Skip to content

Latest commit

 

History

History
146 lines (108 loc) · 5.19 KB

README.md

File metadata and controls

146 lines (108 loc) · 5.19 KB
Time:      7  15   30
Distance:  9  40  200

This document describes three races:

  • The first race lasts 7 milliseconds. The record distance in this race is 9 millimeters.
  • The second race lasts 15 milliseconds. The record distance in this race is 40 millimeters.
  • The third race lasts 30 milliseconds. The record distance in this race is 200 millimeters.

Your toy boat has a starting speed of zero millimeters per millisecond. For each whole millisecond you spend at the beginning of the race holding down the button , the boat's speed increases by one millimeter per millisecond.

So, because the first race lasts 7 milliseconds, you only have a few options:

  • Don't hold the button at all (that is, hold it for 0 milliseconds) at the start of the race. The boat won't move; it will have traveled 0 millimeters by the end of the race.
  • Hold the button for 1 millisecond at the start of the race. Then, the boat will travel at a speed of 1 millimeter per millisecond for 6 milliseconds, reaching a total distance traveled of 6 millimeters.
  • Hold the button for 2 milliseconds, giving the boat a speed of 2 millimeters per millisecond. It will then get 5 milliseconds to move, reaching a total distance of 10 millimeters.
  • Hold the button for 3 milliseconds. After its remaining 4 milliseconds of travel time, the boat will have gone 12 millimeters.
  • Hold the button for 4 milliseconds. After its remaining 3 milliseconds of travel time, the boat will have gone 12 millimeters.
  • Hold the button for 5 milliseconds, causing the boat to travel a total of 10 millimeters.
  • Hold the button for 6 milliseconds, causing the boat to travel a total of 6 millimeters.
  • Hold the button for 7 milliseconds. That's the entire duration of the race. You never let go of the button. The boat can't move until you let go of the button. Please make sure you let go of the button so the boat gets to move. 0 millimeters.

Since the current record for this race is 9 millimeters, there are actually 4 different ways you could win: you could hold the button for 2, 3, 4, or 5 milliseconds at the start of the race.

In the second race, you could hold the button for at least 4 milliseconds and at most 11 milliseconds and beat the record, a total of 8 different ways to win.

In the third race, you could hold the button for at least 11 milliseconds and no more than 19 milliseconds and still beat the record, a total of 9 ways you could win.

To see how much margin of error you have, determine the number of ways you can beat the record in each race; in this example, if you multiply these values together, you get 288 (4 _ 8 _ 9).

Determine the number of ways you could beat the record in each race. What do you get if you multiply these numbers together?

Part 1

Start by parsing the input

def part1(input \\ @input) do
  input |> parse_input()

  ...
end

Here is the parse_input function

Here we turn this: "Time: 7 15 30\nDistance: 9 40 200" into this: [{7, 9}, {15, 40}, {30, 200}]

def parse_input(input) do
  [times | [dist | []]] =
    input
    |> String.split("\n", trim: true)
    |> Enum.map(&(String.split(&1, ":", trim: true) |> Enum.at(1) |> String.split()))
    |> Enum.map(fn list -> Enum.map(list, &String.to_integer/1) end)

  Enum.zip(times, dist)
end

In the count_ways_to_win function we are trying every length of time of holding the button down and checking if it beats the record, if it does count it.

  def count_ways_to_win({time, dist}) do
    0..time
    |> Enum.reduce(fn held, acc ->
      if (time - held) * held > dist do
        acc + 1
      else
        acc
      end
    end)
  end

Put it all together

def part1(input \\ @input) do
  input
  |> parse_input()
  |> Enum.map(&count_ways_to_win/1)
  |> Enum.reduce(&Kernel.*/2)
end

Part 2

As the race is about to start, you realize the piece of paper with race times and record distances you got earlier actually just has very bad kerning. There's really only one race - ignore the spaces between the numbers on each line.

So, the example from before:

Time:      7  15   30
Distance:  9  40  200

...now instead means this:

Time:      71530
Distance:  940200

Now, you have to figure out how many ways there are to win this single race. In this example, the race lasts for 71530 milliseconds and the record distance you need to beat is 940200 millimeters. You could hold the button anywhere from 14 to 71516 milliseconds and beat the record, a total of 71503 ways!

How many ways can you beat the record in this one much longer race?


All we need to do is modify the parse_input function

The parse_input2 function turns this: "Time: 7 15 30\nDistance: 9 40 200" into this: {71530, 940200}

def parse_input2(input) do
  input
  |> String.split("\n", trim: true)
  |> Enum.map(&(String.split(&1, ":", trim: true) |> Enum.at(1) |> String.split()))
  |> Enum.map(fn list -> Enum.join(list) |> String.to_integer() end)
  |> List.to_tuple()
end

Put it all together with the new parse_input2 function

def part2(input \\ @input) do
    input
    |> parse_input2()
    |> count_ways_to_win()
end