Aetherus

Aetherus

Advent of Code 2020 - Day 3

This topic is about Day 3 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

adamu

adamu

I used:

  • Stream.cycle/1 to handle the repeating horizontal values
  • Enum.take_every/2 to handle skipping the downward slope.
  • The input wasn’t very long, so I just brute forced the horizontal value with Enum.at/2.
  def slope(v_x, v_y) do
    {_, trees} =
      File.read!("input")
      |> String.trim()
      |> String.split("\n")
      |> Enum.take_every(v_y)
      |> Enum.map(&String.to_charlist/1)
      |> Enum.reduce({0, 0}, fn row, {x, trees} ->
        trees =
          case Stream.cycle(row) |> Enum.at(x) do
            ?# -> trees + 1
            ?. -> trees
          end

        {x + v_x, trees}
      end)

    trees
  end
kwando

kwando

I see I’m not the first one to find the Stream.cycle function :slight_smile:
My version:

defmodule Aoc2020.Day03 do
  def part1(input) do
    count_trees(input, {3, 1})
  end

  def part2(input) do
    slopes = [
      {1, 1},
      {3, 1},
      {5, 1},
      {7, 1},
      {1, 2}
    ]

    for slope <- slopes, reduce: 1 do
      product -> product * count_trees(input, slope)
    end
  end

  def count_trees(input, {dx, dy}) do
    input
    |> Stream.take_every(dy)
    |> Stream.map(&Stream.cycle/1)
    |> Enum.reduce({0, 0}, fn
      row, {trees, shift} ->
        row
        |> Stream.drop(shift)
        |> Enum.at(0)
        |> case do
          ?. ->
            {trees, shift + dx}

          ?# ->
            {trees + 1, shift + dx}
        end
    end)
    |> elem(0)
  end

  def input_stream(path) do
    File.stream!(path)
    |> Stream.map(&parse/1)
  end

  defp parse(line) do
    line
    |> String.trim()
    |> String.to_charlist()
  end
end

input = Aoc2020.Day03.input_stream("input.txt")

input
|> Aoc2020.Day03.part1()
|> IO.inspect(label: "part1")

input
|> Aoc2020.Day03.part2()
|> IO.inspect(label: "part2")
Damirados

Damirados

My solution with streams keeping only 1 line of map in memory at any given time.

defmodule Event3 do
  def run do
    part1_ruleset = [{3, 1}]
    part2_ruleset = [{1, 1}, {3, 1}, {5, 1}, {7, 1}, {1, 2}]
    IO.puts("Test part1: #{solver("input/event3/test.txt", part1_ruleset)}")
    IO.puts("Puzzle part1: #{solver("input/event3/puzzle.txt", part1_ruleset)}")
    IO.puts("Test part2: #{solver("input/event3/test.txt", part2_ruleset)}")
    IO.puts("Puzzle part2: #{solver("input/event3/puzzle.txt", part2_ruleset)}")
  end

  def solver(path, ruleset) do
    accs = Enum.map(ruleset, &rule_to_acc/1)

    input_stream(path)
    |> Stream.drop(1)
    |> Stream.transform(accs, &step_all/2)
    |> Stream.take(-length(ruleset))
    |> Stream.flat_map(& &1)
    |> Enum.reduce(&(&1 * &2))
  end

  def input_stream(path), do: path |> File.stream!() |> Stream.map(&parse_input/1)

  def parse_input(input), do: String.trim(input) |> String.graphemes() |> Enum.map(&(&1 == "#"))

  def step_all(input, acc), do: Enum.map(acc, &step(input, &1)) |> Enum.unzip()

  def step(input, {count, index, step, step_down, step_down}) do
    width = length(input)
    count = count + ((Enum.at(input, index) && 1) || 0)
    {[count], {count, rem(index + step, width), step, step_down, 1}}
  end

  def step(_input, {count, index, step, step_down, down_counter}),
    do: {[count], {count, index, step, step_down, down_counter + 1}}

  def rule_to_acc({right, down}), do: {0, right, right, down, 1}
end

aaronnamba

aaronnamba

Might not be the most efficient solution, but fairly straightforward:

Day 3 Notes

  • Took a bit longer than it should to build the data structure, then got hung up for several minutes on a row vs. col mixup when accessing it (forgot that I need to get_in(map, [y, x]) instead of [x, y]).
  • Still pretty straightforward, my initial solution worked as expected for both parts (once I got it implemented properly). Part 2 did not add a new twist this time, which was unusual. (Unless of course, you assumed that you would always move down by one…)
LostKobrakai

LostKobrakai

This was a fun one. I build a map of %{{x :: non_neg_integer, y :: non_neg_integer} => type :: :tree | :space} from the input. For the horizontal repeating I simply used rem(x, max_x) to preprocess the coordinates before checking the map. For building the path through the map I used Stream.unfold to build a stream of types at the coordinates following the trajectory from the start.

Where Next?

Popular in Challenges Top

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
stevensonmt
Trying to get more facility with dynamic programming concepts on Leetcode and having an issue I can’t find a way around. It’s a chutes an...
New
Aetherus
This topic is about the Advent of Code 2021 - Day 4. Thanks to @bjorng , we now have a new Private Leaderboard. The entry code is: 370...
New
Aetherus
Don’t know why the regex ~r/[\W && [^\.]]/x does not work in Elixir. It works pretty well in Ruby. Anyway, here is my solution:
New
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 1 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adven...
New
cblavier
Hey there :wave: No magic or algorithmic finesse today, I just finished the challenge and I my code is quite slow (1sec for part1, 3se...
New
bjorng
Note: This topic is to talk about Day 18 of the Advent of Code 2019. There is a private leaderboard for elixirforum members. You can joi...
New
bjorng
Here is my solution for day 1 of Advent of Code: defmodule Day01 do def part1(input) do all = parse(input) {first, second} = E...
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
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement