AdventOfCode-2020/day24.cr

79 lines
1.4 KiB
Crystal

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)