day 2 part 2

aoc runner takes part as arg and passes to
init state fn call

refactored day 1 to switch parts dynamically
This commit is contained in:
Caleb Webber 2023-10-28 13:43:18 -04:00
parent 3f047cd890
commit 680929a20c
4 changed files with 91 additions and 46 deletions

View file

@ -3,10 +3,10 @@ defmodule AOCRunner do
(s |> String.trim() |> String.length()) == 0 (s |> String.trim() |> String.length()) == 0
end end
def run(advent) do def run(advent, part) do
{_, state} = IO.stream() |> {_, state} = IO.stream() |>
Enum.reduce_while( Enum.reduce_while(
{nil, advent.init_state()}, {nil, advent.init_state(part)},
fn line, acc -> line fn line, acc -> line
|> then(fn line -> |> then(fn line ->
{u, state} = acc {u, state} = acc

View file

@ -1,11 +1,18 @@
defmodule Day1 do defmodule Day1 do
def get_answer(state) do def get_answer(state) do
elem(state, 1) |> {_, total, part} = state
Enum.reduce(0, fn i, acc -> i + acc end) total |>
then(fn total -> case part do
:part1 -> total
:part2 -> total |> Enum.reduce(0, fn i, acc -> i + acc end)
end end)
end end
def init_state() do def init_state(part) do
{nil, [0, 0, 0]} case part do
:part1 -> {nil, 0, part}
:part2 -> {nil, [0, 0, 0], part}
end
end end
def execute(line, state) do def execute(line, state) do
@ -30,10 +37,10 @@ defmodule Day1 do
end end
defp apply_add(n, state) do defp apply_add(n, state) do
{current, total} = state {current, total, part} = state
new_current = n + if is_nil(current) do 0 else current end new_current = n + if is_nil(current) do 0 else current end
{new_current, total} {new_current, total, part}
end end
defp take_top_three(n, list) do defp take_top_three(n, list) do
@ -43,9 +50,12 @@ defmodule Day1 do
end end
defp apply_reset(state) do defp apply_reset(state) do
{current, total} = state {current, total, part} = state
if !is_nil(current) do if !is_nil(current) do
{nil, take_top_three(current, total)} case part do
:part1 -> {nil, max(total, current), part}
:part2 -> {nil, take_top_three(current, total), part}
end
else else
state state
end end

View file

@ -1,23 +1,70 @@
defmodule Day2 do defmodule Day2 do
def init_state() do def init_state(part) do
score_with_points(0) init_state(0, part)
end end
defp score_with_points(p) do defp init_state(score, part) do
%{score: p} %{score: score, part: part}
end end
defp parse_match(line) do def execute(line, state) do
if line |> String.trim() |> String.length == 0 do
state
else
{_, player, outcome} = parse_moves(line, state.part)
init_state(
state.score +
points_for_move(player) +
points_from_outcome(outcome),
state.part)
end
end
def get_answer(state) do
state.score
end
defp parse_moves(line, part) do
[p1, p2] = String.split(line, " ") |> Enum.map(&String.trim/1) [p1, p2] = String.split(line, " ") |> Enum.map(&String.trim/1)
match = parse_match(p1, p2) parse_moves(p1, p2, part)
match
end end
defp parse_match(left, right) do defp parse_moves(left, right, :part1) do
{parse_move(left, :left), parse_move(right, :right)} match = {parse_move(left, :left), parse_move(right, :right)}
Tuple.append(match, outcome?(match))
end end
defp parse_moves(left, right, :part2) do
left = parse_move(left, :left)
outcome = outcome?(right)
right = plan_move(outcome, left)
{left, right, outcome}
end
defp plan_move(outcome, opposing_move) do
if outcome == :draw do
opposing_move
else
case opposing_move do
:rock -> case outcome do
:win -> :paper
:loss -> :scissors
end
:paper -> case outcome do
:win -> :scissors
:loss -> :rock
end
:scissors -> case outcome do
:win -> :rock
:loss -> :paper
end
end
end
end
defp parse_move(move, side) do defp parse_move(move, side) do
case side do case side do
:left -> case move do :left -> case move do
@ -33,10 +80,8 @@ defmodule Day2 do
end end
end end
defp points_from_player_move(match) do defp points_for_move(move) do
{_, player_move} = match case move do
case player_move do
:rock -> 1 :rock -> 1
:paper -> 2 :paper -> 2
:scissors -> 3 :scissors -> 3
@ -64,7 +109,7 @@ defmodule Day2 do
end end
end end
defp outcome(match) do defp outcome?(match) when is_tuple(match) and tuple_size(match) == 2 do
{opponent, player} = match {opponent, player} = match
case sort_(player, opponent) do case sort_(player, opponent) do
1 -> :win 1 -> :win
@ -73,29 +118,19 @@ defmodule Day2 do
end end
end end
defp points_from_outcome(match) do defp outcome?(plan) do
case outcome(match) do case plan do
"X" -> :loss
"Y" -> :draw
"Z" -> :win
end
end
defp points_from_outcome(outcome) do
case outcome do
:win -> 6 :win -> 6
:draw -> 3 :draw -> 3
:loss -> 0 :loss -> 0
end end
end end
def execute(line, state) do
if line |> String.trim() |> String.length == 0 do
state
else
match = parse_match(line)
score_with_points(
state.score +
points_from_player_move(match) +
points_from_outcome(match))
end
end
def get_answer(state) do
state.score
end
end end

View file

@ -1 +1 @@
AOCRunner.run(Day2) AOCRunner.run(Day2, :part2)