Code for the Advent of Code event
aoc
advent-of-code
1#!/usr/bin/env ruby
2# frozen_string_literal: true
3
4TYPES = { ?L => :empty, ?. => :floor, ?# => :occupied }.freeze
5SEATS = ARGF.readlines.map { |l| l.chomp.chars.map { TYPES[_1] } }
6
7def count_occupied(grid, x, y)
8 (y - 1..y + 1).flat_map { |y1|
9 (x - 1..x + 1).map { |x1| [x1, y1] }
10 }.reject { |x1, y1|
11 (x1 == x && y1 == y) || x1 < 0 || y1 < 0
12 }.count { |x1, y1| (grid[y1] || [])[x1] == :occupied }
13end
14
15def locate(grid, x, y, dir)
16 return nil if x < 0 || y < 0 || y >= grid.size
17 row = grid[y]
18 return nil if x >= row.size
19 return row[x] unless row[x] == :floor
20 locate grid, x + dir[0], y + dir[1], dir
21end
22
23def count_occupied2(grid, x, y)
24 (y - 1..y + 1).flat_map { |y1|
25 (x - 1..x + 1).map { |x1| [x1, y1] }
26 }.reject { |x1, y1|
27 (x1 == x && y1 == y) || x1 < 0 || y1 < 0
28 }.count { |x1, y1| locate(grid, x1, y1, [x1 - x, y1 - y]) == :occupied }
29end
30
31def copy(grid)
32 grid.map(&:dup)
33end
34
35def transform(grid, threshold, &counter)
36 newgrid = copy grid
37 (0...grid.size).each do |y|
38 (0...grid[y].size).each do |x|
39 occupied = counter.call(grid, x, y)
40 if grid[y][x] == :empty && occupied == 0
41 newgrid[y][x] = :occupied
42 elsif grid[y][x] == :occupied && occupied >= threshold
43 newgrid[y][x] = :empty
44 end
45 end
46 end
47 newgrid
48end
49
50def solve(threshold, &counter)
51 seats_copy = copy SEATS
52
53 loop do
54 hashed = seats_copy.hash
55 seats_copy = transform seats_copy, threshold, &counter
56 break if hashed == seats_copy.hash
57 end
58
59 puts seats_copy.sum { |r| r.count(:occupied) }
60end
61
62solve 4, &method(:count_occupied)
63solve 5, &method(:count_occupied2)