From 680929a20cfd419987555120bab8ff5996c5d342 Mon Sep 17 00:00:00 2001 From: Caleb Webber Date: Sat, 28 Oct 2023 13:43:18 -0400 Subject: [PATCH] day 2 part 2 aoc runner takes part as arg and passes to init state fn call refactored day 1 to switch parts dynamically --- lib/aoc_runner.ex | 4 +- lib/day1.ex | 26 ++++++++---- lib/day2.ex | 105 ++++++++++++++++++++++++++++++---------------- main.exs | 2 +- 4 files changed, 91 insertions(+), 46 deletions(-) diff --git a/lib/aoc_runner.ex b/lib/aoc_runner.ex index 966fbb4..92e1a40 100644 --- a/lib/aoc_runner.ex +++ b/lib/aoc_runner.ex @@ -3,10 +3,10 @@ defmodule AOCRunner do (s |> String.trim() |> String.length()) == 0 end - def run(advent) do + def run(advent, part) do {_, state} = IO.stream() |> Enum.reduce_while( - {nil, advent.init_state()}, + {nil, advent.init_state(part)}, fn line, acc -> line |> then(fn line -> {u, state} = acc diff --git a/lib/day1.ex b/lib/day1.ex index effcde2..b87989a 100644 --- a/lib/day1.ex +++ b/lib/day1.ex @@ -1,11 +1,18 @@ defmodule Day1 do def get_answer(state) do - elem(state, 1) |> - Enum.reduce(0, fn i, acc -> i + acc end) + {_, total, part} = state + total |> + then(fn total -> case part do + :part1 -> total + :part2 -> total |> Enum.reduce(0, fn i, acc -> i + acc end) + end end) end - def init_state() do - {nil, [0, 0, 0]} + def init_state(part) do + case part do + :part1 -> {nil, 0, part} + :part2 -> {nil, [0, 0, 0], part} + end end def execute(line, state) do @@ -30,10 +37,10 @@ defmodule Day1 do end 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, total} + {new_current, total, part} end defp take_top_three(n, list) do @@ -43,9 +50,12 @@ defmodule Day1 do end defp apply_reset(state) do - {current, total} = state + {current, total, part} = state 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 state end diff --git a/lib/day2.ex b/lib/day2.ex index a113843..bb49139 100644 --- a/lib/day2.ex +++ b/lib/day2.ex @@ -1,23 +1,70 @@ defmodule Day2 do - def init_state() do - score_with_points(0) + def init_state(part) do + init_state(0, part) end - defp score_with_points(p) do - %{score: p} + defp init_state(score, part) do + %{score: score, part: part} 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) - match = parse_match(p1, p2) - - match + parse_moves(p1, p2, part) end - defp parse_match(left, right) do - {parse_move(left, :left), parse_move(right, :right)} + defp parse_moves(left, right, :part1) do + match = {parse_move(left, :left), parse_move(right, :right)} + Tuple.append(match, outcome?(match)) 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 case side do :left -> case move do @@ -33,10 +80,8 @@ defmodule Day2 do end end - defp points_from_player_move(match) do - {_, player_move} = match - - case player_move do + defp points_for_move(move) do + case move do :rock -> 1 :paper -> 2 :scissors -> 3 @@ -64,7 +109,7 @@ defmodule Day2 do end end - defp outcome(match) do + defp outcome?(match) when is_tuple(match) and tuple_size(match) == 2 do {opponent, player} = match case sort_(player, opponent) do 1 -> :win @@ -73,29 +118,19 @@ defmodule Day2 do end end - defp points_from_outcome(match) do - case outcome(match) do + defp outcome?(plan) do + case plan do + "X" -> :loss + "Y" -> :draw + "Z" -> :win + end + end + + defp points_from_outcome(outcome) do + case outcome do :win -> 6 :draw -> 3 :loss -> 0 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 diff --git a/main.exs b/main.exs index c624694..98fd10b 100644 --- a/main.exs +++ b/main.exs @@ -1 +1 @@ -AOCRunner.run(Day2) +AOCRunner.run(Day2, :part2)