My beginner’s solution, Day 3 part 1.
My focus was on readability. How I did?
defmodule Day03 do
def part1(input) do
# " 467..
# ...*.
# ..35 "
schematic = input
|> String.split("\n")
|> Enum.map(&String.graphemes/1)
# [ ["4", "6", "7", ".", "."],
# [".", ".", ".", "*", "."],
# [".", ".", "3", "5", "."] ]
matrix_of_positions_adjecent_to_symbols(schematic)
# [ [false, false, true, true, true],
# [false, false, true, false, true],
# [false, false, true, true, true] ]
|> Enum.zip(schematic)
|> Enum.map(fn {m, s} -> Enum.zip(s, m) end)
# [ [{"4", false}, {"6", false}, {"7", true}, {".", true}, {".", true}],
# [{".", false}, {".", false}, {".", true}, {"*", false}, {".", true}],
# [{".", false}, {".", false}, {".", true}, {"3", true}, {"5", true}] ]
|> Enum.map(&extract_valid_numbers_from_zipped_row/1)
|> List.flatten
|> Enum.sum
end
def matrix_of_positions_adjecent_to_symbols(schematic) do
blank_matrix = List.duplicate(false, 140)
|> List.duplicate(140)
# [ [false, false, false, false, false],
# [false, false, false, false, false],
# [false, false, false, false, false] ]
schematic
|> Enum.map(&Enum.with_index/1)
|> Enum.with_index
# [ {[{"4", 0}, {"6", 1}, {"7", 2}, {".", 3}, {".", 4}], 0},
# {[{".", 0}, {".", 1}, {".", 2}, {"*", 3}, {".", 4}], 1},
# {[{".", 0}, {".", 1}, {".", 2}, {"3", 3}, {"5", 4}], 2} ]
|> Enum.reduce(blank_matrix,
fn {row, row_index}, acc ->
Enum.reduce(row, acc,
fn {p, index}, acc ->
cond do
is_symbol?(p) -> encrircle_with_true_at(acc, row_index, index)
true -> acc
end
end)
end)
# [ [false, false, true, true, true],
# [false, false, true, false, true],
# [false, false, true, true, true] ]
end
def is_symbol?(grapheme) do
["*", "&", "@", "/", "+", "-", "%", "$", "=", "#"]
|> Enum.member?(grapheme)
end
def is_digit?(grapheme) do
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|> Enum.member?(grapheme)
end
def encrircle_with_true_at(matrix, row, pos) do
matrix
|> replace_with_true_at(row-1, pos-1)
|> replace_with_true_at(row-1, pos)
|> replace_with_true_at(row-1, pos+1)
|> replace_with_true_at(row, pos-1)
|> replace_with_true_at(row, pos+1)
|> replace_with_true_at(row+1, pos-1)
|> replace_with_true_at(row+1, pos)
|> replace_with_true_at(row+1, pos+1)
end
def replace_with_true_at(matrix, row, position) do
matrix
|> List.pop_at(row)
|> elem(0)
|> List.replace_at(position, true)
|> then(&List.replace_at(matrix, row, &1))
end
def extract_valid_numbers_from_zipped_row(row) do
# [{"4", false}, {"6", false}, {"7", true}, {".", true}, {".", true}]
row
|> Enum.chunk_by(fn {n, _} -> is_digit?(n) end)
|> Enum.filter(fn x -> x |> List.first |> elem(0) |> is_digit? end)
|> Enum.map(&Enum.unzip/1)
# [{["4", "6", "7"], [false, false, true]}, {[...],[...]}, ...]
|> Enum.filter(fn {_, truth_list} -> Enum.any?(truth_list) end)
|> Enum.map(fn x -> x
|> elem(0)
|> Enum.join
|> String.to_integer
end)
end
end






















