From c245b1802856992672a37d66614a9a6571c82b3a Mon Sep 17 00:00:00 2001 From: Adam Millerchip Date: Sun, 13 Dec 2020 22:17:33 +0900 Subject: [PATCH] Day 13 Part 1 and WIP Part 2 --- README.md | 2 +- day13/README | 52 ++++++++++++++++++++++++++++++++++++++++++++ day13/day13part1.exs | 19 ++++++++++++++++ day13/day13part2.exs | 43 ++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 day13/README create mode 100644 day13/day13part1.exs create mode 100644 day13/day13part2.exs diff --git a/README.md b/README.md index bb03303..8400499 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ My (attempted) solutions to [Advent of Code 2020](https://adventofcode.com/2020) in Elixir. -image +image ## Strategy diff --git a/day13/README b/day13/README new file mode 100644 index 0000000..399ba4d --- /dev/null +++ b/day13/README @@ -0,0 +1,52 @@ +Day 13 Notes + ++--------+ +| Part 1 | ++--------+ + +$ elixir day13part1.exs + + +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. diff --git a/day13/day13part1.exs b/day13/day13part1.exs new file mode 100644 index 0000000..2b8b96e --- /dev/null +++ b/day13/day13part1.exs @@ -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() diff --git a/day13/day13part2.exs b/day13/day13part2.exs new file mode 100644 index 0000000..1c170a8 --- /dev/null +++ b/day13/day13part2.exs @@ -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()