Aetherus

Aetherus

Advent of Code 2020 - Day 13

Hello, guys. I’m back again, but only for the weekends, maybe.

This topic is about Day 13 of the Advent of Code 2020 .

Thanks to @egze, we have a private leaderboard:
https://adventofcode.com/2020/leaderboard/private/view/39276

The join code is:
39276-eeb74f9a

Most Liked

voltone

voltone

My part 2 runs in 64µs:

  def next_sequence(busses) do
    busses
    |> Enum.with_index()
    |> Enum.reduce({0, 1}, &add_to_sequence/2)
    |> elem(0)
  end

  defp add_to_sequence({"x", _index}, state), do: state
  defp add_to_sequence({bus, index}, {t, step}) do
    if Integer.mod(t + index, bus) == 0 do
      {t, lcm(step, bus)}
    else
      add_to_sequence({bus, index}, {t + step, step})
    end
  end

  defp lcm(a, b) do
    div(a * b, Integer.gcd(a, b))
  end
12
Post #6
code-shoily

code-shoily

I am stuck at part 2 of this one, trying to use Chinese Remainder Theorem but for some reason getting the mods messed up, whether to go backwards or something like (v - idx)… ekh, I guess I’m just tired, will try tomorrow :smiley:

Meanwhile, my not so sophisticated part 1:

defmodule AdventOfCode.Y2020.Day13 do
  @moduledoc """
  Problem Link: https://adventofcode.com/2020/day/13
  """
  use AdventOfCode.Helpers.InputReader, year: 2020, day: 13

  def run_1, do: input!() |> process() |> earliest_bus() |> result()
  def run_2, do: {:not_implemented, 2}

  def process(input \\ input!()) do
    [time, ids] = String.split(input, "\n", trim: true)

    {String.to_integer(time),
     ids |> String.split(",") |> Enum.reject(&(&1 == "x")) |> Enum.map(&String.to_integer/1)}
  end

  defp next_departure(id, time) do
    next_departure = (div(time, id) + 1) * id
    {id, next_departure, next_departure - time}
  end

  defp earliest_bus({time, ids}) do
    Enum.min_by(Enum.map(ids, &next_departure(&1, time)), &elem(&1, 2))
  end

  defp result({id, _, diff}), do: id * diff
end
Aetherus

Aetherus

I’m stuck at Part 2, too. Chinese Remainder Theorem looks interesting.

So far, my Part 1 code:

#!/usr/bin/env elixir

[departure, busses] = "day13.txt"
                      |> File.stream!()
                      |> Enum.map(&String.trim/1)

departure = String.to_integer(departure)

id = busses
     |> String.split(",")
     |> Stream.reject(& &1 == "x")
     |> Stream.map(&String.to_integer/1)
     |> Enum.min_by(& &1 - rem(departure, &1))

wait = id - rem(departure, id)

IO.puts(id * wait)
code-shoily

code-shoily

Ekh, I could not sleep without trying out Chinese Remainder Theorem. It works!!! Though I cheated. I did not have the energy to remember the details of algorithm and try to implement in Elixir, so I Rosetta Coded it and the Elixir version there was brute forced, so Nope. So I translated the Erlang version there into Elixir (which in turn was translated from OCaml) and Bam! it worked and performed well. Here’s my CRT:

And the relevant bits of the main code:

defmodule Day13 do
  def run_2, do: input!() |> process_2() |> compute()
  def process_2(input \\ input!()) do
    input
    |> String.split("\n", trim: true)
    |> Enum.at(-1)
    |> String.split(",")
    |> Enum.with_index()
    |> Enum.reject(fn {x, _} -> x == "x" end)
    |> Enum.map(fn {x, y} -> {String.to_integer(x), y} end)
  end

  def compute(list) do
    list
    |> Enum.map(fn {v, idx} -> {v, v - idx} end)
    |> chinese_remainder()
  end
end

Also I realized, my “read Erlang, write Elixir” speed is more than I thought it would be, it’s almost typing speed level :smiley:

stevensonmt

stevensonmt

I too knew LCM was part of the key but was not able to figure out how to utilize it correctly. It doesn’t make any appreciable difference, but I made use of the hint that the answer would be at least 100_000_000_000_000 to start counting from 100000000000000 + rem(100000000000000, first_bus).

defmodule Day13 do
  @moduledoc false

  @input "1001287
  13,x,x,x,x,x,x,37,x,x,x,x,x,461,x,x,x,x,x,x,x,x,x,x,x,x,x,17,x,x,x,x,19,x,x,x,x,x,x,x,x,x,29,x,739,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,x,x,x,23"

  def process() do
    @input
    |> String.split("\n", parts: 2, trim: true)
    |> Enum.with_index()
    |> Enum.reduce({}, fn {sub, ndx}, acc ->
      case ndx do
        0 ->
          Tuple.append(acc, String.to_integer(sub))

        _ ->
          Tuple.append(
            acc,
            sub
            |> String.trim_leading()
            |> String.split(",")
            |> Enum.filter(&Kernel.!=("x", &1))
            |> Enum.map(&String.to_integer(&1))
          )
      end
    end)
  end

  def shortest_wait(timestamp, bus_list) do
    {bus, wait} =
      bus_list
      |> Enum.map(fn x -> {x, x - rem(timestamp, x)} end)
      |> Enum.min_by(fn {_x, wait} -> wait end)

    bus * wait
  end

  def part_1 do
    {timestamp, bus_list} = process()
    shortest_wait(timestamp, bus_list)
  end

  def process_2 do
    @input
    |> String.split("\n", parts: 2, trim: true)
    |> List.last()
    |> String.trim_leading()
    |> String.split(",")
    |> Enum.with_index()
    |> Enum.reject(fn {c, _ndx} -> c == "x" end)
    |> Enum.map(fn {c, ndx} -> {ndx, String.to_integer(c)} end)
  end

  def timestamp_search([{_ndx, first_bus} | _rest] = buses) do
    min_time = 100_000_000_000_000 + rem(100_000_000_000, first_bus)
    timestamp_search(buses, {min_time, 1})
  end

  def timestamp_search([], {timestamp, _}) do
    timestamp
  end

  def timestamp_search([{ndx, bus} | rest] = buses, {timestamp, step}) do
    if valid_timestamp?(timestamp, bus, ndx) do
      timestamp_search(rest, {timestamp, Day13.MathHelpers.lcm(step, bus)})
    else
      timestamp_search(buses, {timestamp + step, step})
    end
  end

  def valid_timestamp?(timestamp, bus, ndx) do
    rem(timestamp + ndx, bus) == 0
  end

  def part_2 do
    process_2()
    |> timestamp_search()
  end

  defmodule MathHelpers do
    @moduledoc false
    def gcd(a, 0), do: a
    def gcd(0, b), do: b
    def gcd(a, b), do: gcd(b, rem(a, b))

    def lcm(0, 0), do: 0
    def lcm(a, b), do: div(a * b, gcd(a, b))
  end
end

Where Next?

Popular in Challenges Top

bjorng
This topic is about Day 14 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/l...
New
NobbZ
Note by the Moderators: This topic is to talk about the Day 2 of the Advent of Code. For general discussion about the Advent of Code 201...
New
igorb
Today is a brute-force day: advent-of-code-2024/lib/advent_of_code2024/day6.ex at main · ibarakaiev/advent-of-code-2024 · GitHub Takes a...
New
Qqwy
Note by the Moderators: This topic is to talk about Day 6 of the Advent of Code. For general discussion about the Advent of Code 2018 an...
New
sb8244
Note: This topic is to talk about Day 10 of the Advent of Code 2019 . There is a private leaderboard for elixirforum members. You can jo...
New
christhekeele
Continuation of Advent of Code 2022​:christmas_tree:, Day 1: Day 2! Leaderboard:
New
bjorng
Note: This topic is to talk about Day 23 of the Advent of Code. For general discussion about the Advent of Code 2018 and links to topics...
New
bjorng
This topic is about Day 2 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adven...
New
connorlay
Note by the Moderators: This topic is for general discussion about the Advent of Code 2018. To prevent people from being spoiled about s...
New
seeplusplus
Hello all, hopefully I post this before someone else does and I don’t dupe. IMO Day 4 was much easier than Day 3 (yay, I can sleep befor...
New

Other popular topics Top

freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New

We're in Beta

About us Mission Statement