diff --git a/day24.cr b/day24.cr new file mode 100644 index 0000000..fdf9b5c --- /dev/null +++ b/day24.cr @@ -0,0 +1,78 @@ +require "advent" + +INPUT = input(2020, 24).lines.map &.tiles.map { |t| MATCHES[t] } +MATCHES = { "se" => {0.5, -1.0}, "sw" => {-0.5, -1.0}, "ne" => {0.5, 1.0}, "nw" => {-0.5, 1.0}, "e" => {1.0, 0.0}, "w" => {-1.0, 0.0} } + +class String + def tiles + i = 0 + tiles = [] of String + while i < size + if self[i] == 's' || self[i] == 'n' + tiles << self[i..i+1] + i += 2 + else + tiles << self[i..i] + i += 1 + end + end + tiles + end +end + +class Array(T) + def pos + curr = {0.0, 0.0} + each do |c| + curr = curr.add c + end + curr + end +end + +def part1(input) + counts = Hash({Float64,Float64}, Int32).new(0) + input.each do |i| + counts[i.pos] += 1 + end + counts.count &.[1].%(2).==(1) +end + +struct Tuple(*T) + def neighbors + MATCHES.values.map &.add(self) + end +end + +def part2(input) + state = Hash({Float64,Float64}, Bool).new(false) + counts = Hash({Float64,Float64}, Int32).new(0) + + input.each do |i| + state[i.pos] ^= true + end + + 100.times do |i| + counts.clear + state.each do |t, f| + next unless f + t.neighbors.each do |n| + counts[n] += 1 + end + end + + new_state = state.clone.clear + state.each do |k, v| + next unless v + new_state[k] = !(counts[k] == 0 || (counts[k] > 2)) + end + counts.each do |k, v| + new_state[k] = true if (!state[k]) && v == 2 + end + state = new_state + end + state.count &.[1] +end + +puts part1(INPUT.clone) +puts part2(INPUT.clone)