-
Notifications
You must be signed in to change notification settings - Fork 1
/
day-22-part1.rb
118 lines (89 loc) · 2.2 KB
/
day-22-part1.rb
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
require 'benchmark'
require 'stringio'
require "enumerator"
require 'set'
file_content = File.read(File.join(__dir__, 'input.txt'))
input = file_content.scan(/(on|off) x=(.*),y=(.*),z=(.*)/)
input = input.map{[_1, eval(_2), eval(_3), eval(_4)] }
def combine(a, b)
([a.first, b.first].min..[a.last, b.last].max)
end
def range_within?(range, other)
other.first <= range.last && range.first <=other.last
end
def invert_hash(hash)
hash.each_with_object({}){ |(k, v), o| (o[v]||=[] ) << k }
end
def clamp_range(range, limit)
[range.min, limit.min].max..[range.max, limit.max].min
end
PART1_LIMIT = -50..50
class Cube
attr_accessor :rx, :ry, :rz
def initialize(rx: 0..0, ry:0..0, rz:0..0)
@rx, @ry, @rz = clamp_range(rx, PART1_LIMIT), clamp_range(ry, PART1_LIMIT), clamp_range(rz, PART1_LIMIT)
puts
end
def within?
range_within?(rx, -50..50) &&
range_within?(ry, -50..50) &&
range_within?(rz, -50..50)
end
def size
rx.size * ry.size * rz.size
end
def to_coordinates
coordinates = []
rz.step(1) do |x|
ry.step(1) do |y|
rx.step(1) do |z|
coordinates << [x, y, z]
end
end
end
coordinates
end
end
class CubeRange
attr_accessor :rx, :ry, :rz
def initialize
@rx = @ry = @rz = nil
end
def on(range)
@rx = range.rx if @rx.nil?
@ry = range.ry if @ry.nil?
@rz = range.rz if @rz.nil?
@rx = combine(@rx, range.rx)
@ry = combine(@ry, range.ry)
@rz = combine(@ry, range.rz)
end
def off(exclude)
rr = [@rx.first, exclude.rx.first].max
rr2 = [@rx.last, exclude.rx.last].min
puts
end
end
ON_CUBE = CubeRange.new
result = input.inject(Set.new) do |memo, (state, rx, ry, rz)|
cube = Cube.new(rx: rx, ry: ry, rz: rz)
next memo unless cube.within?
puts "add size #{cube.size}"
#
if state == "on"
memo += cube.to_coordinates
end
if state == "off"
memo -= cube.to_coordinates
end
memo
end
#
# res = result[1].inject([]) do |memo, off_range|
# items = result[0].map do |on_range|
# [off_range.last, on_range.first].max..[off_range.first, on_range.last].max
# end
# memo.push(*items)
# memo
# end
puts "result is #{result.size}"
puts "ok"