diff --git a/day7/main.exs b/day7/main.exs index 55ef88b..7780f80 100644 --- a/day7/main.exs +++ b/day7/main.exs @@ -1,35 +1,31 @@ defmodule Day7 do def run do lines = - File.read!("test.txt") + File.read!("data.txt") |> String.trim() |> String.split("\n") |> Enum.map(fn l -> String.split(l, ~r{\D+}) |> Enum.map(&String.to_integer(&1)) end) |> Enum.map(fn [head | tail] -> {head, tail} end) - [part1, part2] = - Enum.map([1, 2], fn part -> - # filter valid lines for parts 1 and 2, grab their targets, and sum them - Enum.filter(lines, &valid?(&1, part)) |> Enum.map(&elem(&1, 0)) |> Enum.sum() - end) - - dbg({part1, part2}) + [ + [&*/2, &+/2], # part 1's operatons: * and + + [&*/2, &+/2, &("#{&1}#{&2}" |> String.to_integer())] # part 2's operatons: *, +, and concat + ] + |> Enum.map(fn ops -> + # filter valid lines for parts 1 and 2, grab their targets, and sum them + Enum.filter(lines, &valid?(&1, ops)) |> Enum.map(&elem(&1, 0)) |> Enum.sum() + end) + |> Enum.map(&dbg(&1)) end - defp valid?({total, [a, b | rest]}, part) do - # if we're in part 1, just check a * b and a + b. in part 2, we'll also check a <> b - branches = if part == 1, do: [a * b, a + b], else: [a * b, a + b, concat(a, b)] - - case [a, b | rest] do - # base case is 2 elements. if any succeed, return true - [_, _] -> Enum.any?(branches, fn n -> n == total end) - # recurse by trying each branch, subbing the first 2 elements with the new combined element - [_, _ | _] -> Enum.any?(branches, &valid?({total, [&1 | rest]}, part)) - end + # base case, when there are 2 operands. returns true if applying any of the ops returns the target + defp valid?({total, [a, b]}, ops) do + Enum.any?(ops, fn op -> op.(a, b) == total end) end - defp concat(a, b) do - "#{a}#{b}" |> String.to_integer() + # apply each operation to the first two operands, prepend and recurse + defp valid?({total, [a, b | rest]}, ops) do + Enum.any?(ops, &valid?({total, [&1.(a, b) | rest]}, ops)) end end