1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
require "set"

rocks = <<~ROCKS.split("\n\n")
  ####

  .#.
  ###
  .#.

  ..#
  ..#
  ###

  #
  #
  #
  #

  ##
  ##
ROCKS
rocks = rocks
  .map {|rock| rock.lines(chomp: true).reverse.map(&:chars) }
  .map {|rock|
    rock.each.with_index.with_object(Set.new) {|(row, y), rocks|
      row.each.with_index do |c, x|
        rocks << [x, y] if c == ?#
      end
    }
  }
rocks = rocks.cycle

jet_pattern = ARGF.read.strip.chars
jet_pattern = jet_pattern.cycle

chamber = Hash.new {|_,(x,y)| !(0...7).cover?(x) || y.negative? }

def move_rock(chamber, rock, dx, dy)
  next_rock = rock.map {|x,y| [x+dx, y+dy] }

  if next_rock.any? {|x,y| chamber[[x, y]] }
    rock
  else
    next_rock
  end
end

def debug(chamber, rock)
  max_y = [chamber.keys.map(&:last).max || 0, rock.map(&:last).max || 0].max

  puts
  puts max_y.downto(0).map {|y|
    (0...7).map {|x|
      (chamber[[x,y]] || rock.include?([x,y])) ? ?# : ?.
    }.join
  }.join("\n")
end

2022.times do
  rock = rocks.next

  y = chamber.empty? ? 3 : chamber.keys.map(&:last).max + 4
  x = 2
  rock = move_rock(chamber, rock, x, y)

  loop do
    rock = case jet = jet_pattern.next
           when ?< then move_rock(chamber, rock, -1, 0)
           when ?> then move_rock(chamber, rock,  1, 0)
           else fail "invalid jet pattern: #{jet}"
           end

    next_rock = move_rock(chamber, rock, 0, -1)
    break if rock == next_rock
    rock = next_rock
  end

  chamber.merge!(rock.to_h { [_1, true] })
end

# debug(chamber, Set.new)
max_y = chamber.keys.map(&:last).max + 1
p max_y

candidates = (0..max_y).select {|y| (0...7).count {|x| chamber[[x,y]] } == 6 }
# max_delta = candidates.each_cons(2).map { _2 - _1 }.max
candidates.
p candidates
p max_delta