Skip to content

Instantly share code, notes, and snippets.

@goofansu
Created July 13, 2022 05:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save goofansu/3d7bdb65ada6e0daf2d1bfd4f355b646 to your computer and use it in GitHub Desktop.
Save goofansu/3d7bdb65ada6e0daf2d1bfd4f355b646 to your computer and use it in GitHub Desktop.

Day 2

Mix.install([
  {:finch, "~> 0.12.0"}
])

Helper functions

Finch.start_link(name: MyFinch)
download_fun = fn
  {:status, 200}, acc -> acc
  {:headers, _}, acc -> acc
  {:data, data}, acc -> acc <> data
end

input_stream_fun = fn url ->
  {:ok, data} = Finch.build(:get, url) |> Finch.stream(MyFinch, "", download_fun)
  String.splitter(data, "\n", trim: true)
end

Part 1

What do you get if you multiply your final horizontal position by your final depth?

For example,

forward 5
down 5
forward 8
up 3
down 8
forward 2

After following these instructions, you would have a horizontal position of 15 and a depth of 10. (Multiplying these together produces 150.)

Solution

# This is a list of commands, changing horizontal and vertical position.

# First, parse each line to get the command, then map each command
# to a position, and then reduce to both positions.

input_url =
  "https://gist.githubusercontent.com/goofansu/64d236d2a3904ad2338b7e7f1d36ebfd/raw/cad0df94526099fd9cd8199e481b90e9d40369ed/gistfile1.txt"

reducer = fn
  ["forward", units], acc -> update_in(acc[:horizontal], &(&1 + units))
  ["down", units], acc -> update_in(acc[:depth], &(&1 + units))
  ["up", units], acc -> update_in(acc[:depth], &(&1 - units))
end

input_stream_fun.(input_url)
|> Stream.map(fn line ->
  line
  |> String.split(" ")
  |> List.update_at(1, &String.to_integer/1)
end)
|> Enum.reduce(Map.new(horizontal: 0, depth: 0), reducer)
|> Map.values()
|> Enum.product()

Part 2

What do you get if you multiply your final horizontal position by your final depth?

The commands also mean something entirely different than you first thought:

- down X increases your aim by X units.
- up X decreases your aim by X units.
- forward X does two things:
    - It increases your horizontal position by X units.
    - It increases your depth by your aim multiplied by X.

Now, the above example does something different:

- forward 5 adds 5 to your horizontal position, a total of 5. Because your aim is 0, your depth does not change.
- down 5 adds 5 to your aim, resulting in a value of 5.
- forward 8 adds 8 to your horizontal position, a total of 13. Because your aim is 5, your depth increases by 8*5=40.
- up 3 decreases your aim by 3, resulting in a value of 2.
- down 8 adds 8 to your aim, resulting in a value of 10.
- forward 2 adds 2 to your horizontal position, a total of 15. Because your aim is 10, your depth increases by 2*10=20 to a total of 60.

After following these new instructions, you would have a horizontal position of 15 and a depth of 60. (Multiplying these produces 900.)

Solution

reducer = fn
  ["forward", units], acc ->
    acc = update_in(acc[:horizontal], &(&1 + units))
    update_in(acc[:depth], &(&1 + acc[:aim] * units))

  ["down", units], acc ->
    update_in(acc[:aim], &(&1 + units))

  ["up", units], acc ->
    update_in(acc[:aim], &(&1 - units))
end

input_stream_fun.(input_url)
|> Stream.map(fn line ->
  line
  |> String.split(" ")
  |> List.update_at(1, &String.to_integer/1)
end)
|> Enum.reduce(Map.new(horizontal: 0, depth: 0, aim: 0), reducer)
|> Map.take([:horizontal, :depth])
|> Map.values()
|> Enum.product()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment