Day 13 Part 1 and WIP Part 2

This commit is contained in:
Adam Millerchip 2020-12-13 22:17:33 +09:00
parent d6c713ed24
commit c245b18028
4 changed files with 115 additions and 1 deletions

View file

@ -2,7 +2,7 @@
My (attempted) solutions to [Advent of Code 2020](https://adventofcode.com/2020) in Elixir.
<img width="975" alt="image" src="https://user-images.githubusercontent.com/498229/101977622-1a5b1280-3c92-11eb-8dc5-73c0998623e0.png">
<img width="979" alt="image" src="https://user-images.githubusercontent.com/498229/102020090-57222900-3dba-11eb-9916-4b90c0107dfa.png">
## Strategy

52
day13/README Normal file
View file

@ -0,0 +1,52 @@
Day 13 Notes
+--------+
| Part 1 |
+--------+
$ elixir day13part1.exs
<will add later>
Thoughts:
Pretty easy.
Filter out the x items, divide the current time by the bus ID, and the remainder is how many
minutes to wait. Take the minimum.
+--------+
| Part 2 |
+--------+
$ elixir day13part2.exs
*runs forever*
Thoughts:
Another one that's impossible to brute force. Currently stuck.
Have created a correct algorithm that produces the correct answer for the examples.
However, it will never complete for the real input.
There must be some other relationship that I'm missing. Maybe something to do with common factors?
Attempted to improve by starting with the multiple of all the ids and searching downwards, but
that doesn't complete either (I'm not interested in brute-force, so won't let it run for a long
time).
Wondering if the fact that three of the examples use the same IDs and differ only in offset
is important.
Going to come back to this later with a clear mind. Not sure I'll get it without a hint.
Seems like I have a knowledge gap.
+------------------+
| Overall Thoughts |
+------------------+
Doesn't really feel like a "coding" problem, because I implemented the algorithm but there's
obviously another trick. But will judge that once I know the answer.
Working out things from first principles is hard! But I think the thought process is more
valuable than just getting the right answer. So far I've been a bit competitive due to the
private leaderboards, but I guess that ends now.

19
day13/day13part1.exs Normal file
View file

@ -0,0 +1,19 @@
defmodule Day13Part1 do
def run do
File.read!("input")
|> String.split(["\n", ","], trim: true)
|> Enum.reject(&(&1 == "x"))
|> Enum.map(&String.to_integer/1)
|> earliest_bus()
|> (fn {id, time} -> id * time end).()
|> IO.puts()
end
def earliest_bus([now | busses]) do
busses
|> Enum.map(fn bus -> {bus, bus - rem(now, bus)} end)
|> Enum.min(fn {_, time1}, {_, time2} -> time1 <= time2 end)
end
end
Day13Part1.run()

43
day13/day13part2.exs Normal file
View file

@ -0,0 +1,43 @@
defmodule Day13Part2 do
def run do
schedule =
File.read!("input")
|> String.split(["\n", ","], trim: true)
|> Enum.drop(1)
|> Enum.map(&parse_schedule/1)
|> Enum.with_index()
|> Enum.reject(&match?({:any, _}, &1))
|> IO.inspect()
{max_id, max_offset} =
Enum.max(schedule, fn {id1, _}, {id2, _} -> id1 >= id2 end)
|> IO.inspect()
start_time =
Enum.reduce(schedule, 1, fn {id, _}, acc -> id * acc end)
|> Kernel.-(max_offset)
|> IO.inspect(label: "start time")
find_sequential_departures(start_time, schedule, max_id)
|> IO.inspect()
end
def parse_schedule(id) do
case Integer.parse(id) do
{id, ""} -> id
_ -> :any
end
end
def find_sequential_departures(t, busses, period) do
if Enum.all?(busses, fn {id, offset} -> departs_at_offset?(t, id, offset) end) do
t
else
find_sequential_departures(t - period, busses, period)
end
end
def departs_at_offset?(t, id, offset), do: rem(t + offset, id) == 0
end
Day13Part2.run()