Skip to content

Instantly share code, notes, and snippets.

@riffraff

riffraff/7.ex Secret

Created December 7, 2024 06:33
defmodule Day do
def today() do
String.replace(__ENV__.file, ".ex", ".input")
end
def daily_input do
File.stream!(today()) |> parse()
end
def test_input do
"""
190: 10 19
3267: 81 40 27
83: 17 5
156: 15 6
7290: 6 8 6 15
161011: 16 10 13
192: 17 8 14
21037: 9 7 18 13
292: 11 6 16 20
"""
|> String.split("\n", trim: true)
|> parse()
end
def parse(stream) do
stream
|> Enum.map(&line_to_ints/1)
end
def main(_args) do
test_input() |> Day.Easy.solve() |> IO.inspect(label: "test easy 3749")
daily_input() |> Day.Easy.solve() |> IO.inspect(label: "easy 3119088655389")
test_input() |> Day.Hard.solve() |> IO.inspect(label: "test hard 11387")
daily_input() |> Day.Hard.solve() |> IO.inspect(label: "hard 264184041398847")
end
def line_to_ints(line) do
String.split(line, ~r/\W+/, trim: true) |> Enum.map(&String.to_integer/1)
end
def test_value(target, array, use_concat) do
do_test_value(target, 0, array, use_concat)
end
def do_test_value(target, current, array, use_concat) do
cond do
current > target ->
false
Enum.empty?(array) ->
current == target
[top | rest] = array ->
do_test_value(target, current + top, rest, use_concat) ||
do_test_value(target, current * top, rest, use_concat) ||
(use_concat && do_test_value(target, String.to_integer("#{current}#{top}"), rest, use_concat))
end
end
def line_value([target | rest], use_concat) do
if test_value(target, rest, use_concat) do
target
else
0
end
end
def solve_async(list, use_concat) do
list
|> Task.async_stream(Day, :line_value, [use_concat])
|> Enum.reduce(0, fn {:ok, value}, acc -> acc + value end)
end
defmodule Easy do
def solve(list) do
Day.solve_async(list, false)
end
end
defmodule Hard do
def solve(list) do
Day.solve_async(list, true)
end
end
end
Day.main(System.argv())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment