From 5fa6263c32546ad3d92f50422ae95ea830e49d8e Mon Sep 17 00:00:00 2001 From: Noah Over Date: Tue, 19 Dec 2023 13:11:01 -0500 Subject: [PATCH] 2023 Day 1 Part 2 --- .../{day1_example.txt => day1_example1.txt} | 0 noahover/aoc23/input/day1_example2.txt | 7 + noahover/aoc23/lib/day1.ex | 160 +++++++++++++++++- noahover/aoc23/test/day1_test.exs | 22 ++- 4 files changed, 179 insertions(+), 10 deletions(-) rename noahover/aoc23/input/{day1_example.txt => day1_example1.txt} (100%) create mode 100644 noahover/aoc23/input/day1_example2.txt diff --git a/noahover/aoc23/input/day1_example.txt b/noahover/aoc23/input/day1_example1.txt similarity index 100% rename from noahover/aoc23/input/day1_example.txt rename to noahover/aoc23/input/day1_example1.txt diff --git a/noahover/aoc23/input/day1_example2.txt b/noahover/aoc23/input/day1_example2.txt new file mode 100644 index 0000000..41aa89c --- /dev/null +++ b/noahover/aoc23/input/day1_example2.txt @@ -0,0 +1,7 @@ +two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen diff --git a/noahover/aoc23/lib/day1.ex b/noahover/aoc23/lib/day1.ex index 567eb94..fc708aa 100644 --- a/noahover/aoc23/lib/day1.ex +++ b/noahover/aoc23/lib/day1.ex @@ -6,12 +6,6 @@ defmodule Day1 do def parse_input(input) do input |> String.split("\n", trim: true) - |> Enum.map(fn x -> - x - |> String.to_charlist() - |> Enum.map(fn x -> x - 48 end) - |> Enum.filter(fn x -> x >= 0 && x <= 9 end) - end) end @doc """ @@ -20,8 +14,21 @@ defmodule Day1 do Sum the calibration values which are the first numeral in each line as the first digit and the last numeral in each line as the second digit. """ - def sum_calibration_values(digits) do - digits + def sum_calibration_values(rows) do + rows + |> Enum.map(fn x -> numerals_from_string(x) end) + |> sum_from_numerals() + end + + defp numerals_from_string(row) do + row + |> String.to_charlist() + |> Enum.map(fn x -> x - 48 end) + |> Enum.filter(fn x -> x >= 0 && x <= 9 end) + end + + defp sum_from_numerals(numerals) do + numerals |> Enum.map(fn x -> first_digit = hd(x) last_digit = List.last(x) @@ -30,4 +37,141 @@ defmodule Day1 do end) |> Enum.sum() end + + @doc """ + Day 1 Part 2 + + Sum the calibration values which are the first numeral or spelled out + numeral in each line as the first digit and the last numeral or spelled + out numeral in each line as the second digit. + """ + def sum_calibration_values_with_words(rows) do + rows + |> Enum.map(fn x -> words_to_calibration_value(x) end) + |> Enum.sum() + end + + defp words_to_calibration_value(row) do + first_digit = find_first_digit(row) + last_digit = find_last_digit(row) + + first_digit * 10 + last_digit + end + + defp find_first_digit(row) do + valid_digits = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine" + ] + + valid_digits + |> Enum.reduce(%{}, fn x, acc -> + case :binary.match(row, x) do + {index, _length} -> + Map.put(acc, x, index) + + _ -> + acc + end + end) + |> Map.to_list() + |> Enum.sort(fn {_k1, v1}, {_k2, v2} -> v1 < v2 end) + |> hd() + |> elem(0) + |> convert_text_to_number() + end + + defp convert_text_to_number(s) do + case s do + "one" -> + 1 + + "two" -> + 2 + + "three" -> + 3 + + "four" -> + 4 + + "five" -> + 5 + + "six" -> + 6 + + "seven" -> + 7 + + "eight" -> + 8 + + "nine" -> + 9 + + _ -> + String.to_integer(s) + end + end + + defp find_last_digit(row) do + valid_digits = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "eno", + "owt", + "eerht", + "ruof", + "evif", + "xis", + "neves", + "thgie", + "enin" + ] + + backwards_row = String.reverse(row) + + valid_digits + |> Enum.reduce(%{}, fn x, acc -> + case :binary.match(backwards_row, x) do + {index, _length} -> + Map.put(acc, x, index) + + _ -> + acc + end + end) + |> Map.to_list() + |> Enum.sort(fn {_k1, v1}, {_k2, v2} -> v1 < v2 end) + |> hd() + |> elem(0) + |> String.reverse() + |> convert_text_to_number() + end end diff --git a/noahover/aoc23/test/day1_test.exs b/noahover/aoc23/test/day1_test.exs index 2ff3bb9..5142cd3 100644 --- a/noahover/aoc23/test/day1_test.exs +++ b/noahover/aoc23/test/day1_test.exs @@ -4,9 +4,9 @@ defmodule Day1Test do import Day1 - test "day 1 part 1 example - sum calibration values" do + test "day 1 part 1 example 1 - sum calibration values" do answer = - File.read!("input/day1_example.txt") + File.read!("input/day1_example1.txt") |> parse_input() |> sum_calibration_values() @@ -21,4 +21,22 @@ defmodule Day1Test do assert answer == 54450 end + + test "day 1 part 2 example 2 - sum calibration values with words" do + answer = + File.read!("input/day1_example2.txt") + |> parse_input() + |> sum_calibration_values_with_words() + + assert answer == 281 + end + + test "day 1 part 2 - sum calibration values with words" do + answer = + File.read!("input/day1.txt") + |> parse_input() + |> sum_calibration_values_with_words() + + assert answer == 54265 + end end