65 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Crystal
		
	
	
	
	
	
		
		
			
		
	
	
			65 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Crystal
		
	
	
	
	
	
|  | require "advent" | ||
|  | INPUT = input(2020, 11).lines.map(&.chars)  | ||
|  | 
 | ||
|  | abstract class Search | ||
|  |   def search(current, x, y, dx, dy) | ||
|  |     x, y = x + dx, y + dy | ||
|  |     return 0 if y < 0 || y >= current.size | ||
|  |     return 0 if x < 0 || x >= current[y].size | ||
|  |     search_impl(current,x,y,dx,dy) | ||
|  |   end | ||
|  | 
 | ||
|  |   abstract def search_impl(current, x, y, dx, dy) | ||
|  | end | ||
|  | 
 | ||
|  | class FirstSearch < Search | ||
|  |   def search_impl(current, x, y, dx, dy) | ||
|  |     return current[y][x] == '#' ? 1 : 0
 | ||
|  |   end | ||
|  | end | ||
|  | 
 | ||
|  | class SecondSearch < Search | ||
|  |   def search_impl(current, x, y, dx, dy) | ||
|  |     return 1 if current[y][x] == '#' | ||
|  |     return 0 if current[y][x] == 'L' | ||
|  |     return search(current, x, y, dx, dy) | ||
|  |   end | ||
|  | end | ||
|  | 
 | ||
|  | DIRS = [{-1,-1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1,1}] | ||
|  | 
 | ||
|  | def step(current, step, check, n) | ||
|  |   current.each_with_index do |row, y| | ||
|  |     row.each_with_index do |seat, x| | ||
|  |       step[y][x] = current[y][x] | ||
|  |       count = DIRS.sum do |dx, dy| | ||
|  |         check.search(current, x, y, dx, dy) | ||
|  |       end | ||
|  |       step[y][x] = 'L' if seat == '#' && count >= n | ||
|  |       step[y][x] = '#' if seat == 'L' && count == 0
 | ||
|  |     end | ||
|  |   end | ||
|  |   {step, current} | ||
|  | end | ||
|  | 
 | ||
|  | def run(input, search, n) | ||
|  |   current = input | ||
|  |   step = input.clone | ||
|  |   loop do | ||
|  |     current, step = step(current, step, search, n) | ||
|  |     break if current.zip_with(step) { |l, r| l == r }.all? | ||
|  |   end | ||
|  |   current.sum(&.count(&.==('#'))) | ||
|  | end | ||
|  | 
 | ||
|  | def part1(input) | ||
|  |   run(input, FirstSearch.new, 4) | ||
|  | end | ||
|  | 
 | ||
|  | def part2(input) | ||
|  |   run(input, SecondSearch.new, 5) | ||
|  | end | ||
|  | 
 | ||
|  | puts part1(INPUT.clone) | ||
|  | puts part2(INPUT.clone) |