79 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Crystal
		
	
	
	
	
	
		
		
			
		
	
	
			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) |