Code for the Advent of Code event
aoc
advent-of-code
1#!/usr/bin/env ruby
2# frozen_string_literal: true
3
4initial, $rules = ARGF.read.split("\n\n")
5
6pots = initial.split(': ')[1].chars.map.with_index { |p, i| p == ?# ? i : nil }.compact
7
8$rules = $rules.lines.to_h { |line|
9 current, result = line.split(' => ').map(&:chomp)
10 result = result == ?#
11 state = current.chars.map.with_index { |c, i| [i - 2, c == ?#] }.to_h
12 [state, result]
13}
14
15def transform(pots)
16 new_pots = []
17 min_i, max_i = pots.minmax
18 min_i -= 2
19 max_i += 2
20 (min_i..max_i).each do |i|
21 rule = $rules.find { |s, _r| s.all? { |d, c| pots.include?(i + d) == c } }
22 new_pots.push(i) if (rule && rule[1]) || pots[i] == true
23 end
24
25 new_pots
26end
27
28final_pots = 20.times.reduce(pots) do |pots, _i|
29 transform(pots)
30end
31
32puts final_pots.sum
33
34delta = nil
35delta_count = 0
36
37_part2_pots = 50_000_000_000.times.reduce(pots) do |pots, i|
38 old_sum = pots.sum
39 new_pots = transform(pots)
40 new_sum = new_pots.sum
41 new_delta = new_sum - old_sum
42 if new_delta == delta
43 delta_count += 1
44 else
45 delta_count = 1
46 end
47 if delta_count == 3
48 remaining = 50_000_000_000 - i - 1
49 final_result = new_sum + (remaining * delta)
50 puts final_result
51 exit
52 end
53
54 delta = new_delta
55 new_pots
56end