diff --git a/README.md b/README.md index e900774..87f614e 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/day18/README b/day18/README new file mode 100644 index 0000000..f03a9b4 --- /dev/null +++ b/day18/README @@ -0,0 +1,34 @@ +Day 18 Notes + ++--------+ +| Part 1 | ++--------+ + +$ elixir day18part1.exs + + +Thoughts: +Since the order of precedence is the same, we can walk the token list, building up a left operand +and operator as we go, then applying the operator as soon as we get the right operand. For groups, +use recursion to resolve the group, and push the result back onto the beginning of the token list. + + ++--------+ +| Part 2 | ++--------+ + +$ elixir day18part2.exs + +Thoughts: + +Now the order of precedence is relevant, so can no longer just walk the token list, need to know the +full context. +Addition basically becomes implicit brackets. +Will do this part later. + + ++------------------+ +| Overall Thoughts | ++------------------+ + + diff --git a/day18/day18part1.exs b/day18/day18part1.exs new file mode 100644 index 0000000..878a211 --- /dev/null +++ b/day18/day18part1.exs @@ -0,0 +1,39 @@ +defmodule Day18Part1 do + def run do + File.stream!("input") + |> Stream.map(&parse_line/1) + |> Stream.map(&evaluate/1) + |> Enum.sum() + |> IO.puts() + end + + def parse_line(line) do + line + |> String.graphemes() + |> Stream.reject(fn char -> char in [" ", "\n"] end) + |> Enum.map(fn + "*" -> :multiply + "+" -> :add + "(" -> :start_group + ")" -> :end_group + num -> String.to_integer(num) + end) + end + + def evaluate(command), do: evaluate(command, nil, 0) + def evaluate([], nil, acc), do: acc + def evaluate([:multiply | rest], nil, acc), do: evaluate(rest, :multiply, acc) + def evaluate([:add | rest], nil, acc), do: evaluate(rest, :add, acc) + + def evaluate([:start_group | rest], op, acc) do + {remaining, group_result} = evaluate(rest, nil, 0) + evaluate([group_result | remaining], op, acc) + end + + def evaluate([:end_group | rest], _op, acc), do: {rest, acc} + def evaluate([num | rest], :multiply, acc), do: evaluate(rest, nil, acc * num) + def evaluate([num | rest], :add, acc), do: evaluate(rest, nil, acc + num) + def evaluate([num | rest], nil, 0), do: evaluate(rest, nil, num) +end + +Day18Part1.run()