-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday-3.lua
89 lines (78 loc) · 3.34 KB
/
day-3.lua
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 "lua-string"
local linq = require("lazylualinq")
local client = require("client")
return {
schematic = {},
init = function(self, day)
local rawSchematic = client:getDayInput(day):trim():split("\n")
self.schematic = linq(rawSchematic)
:selectMany(function(line, id)
local candidates = setmetatable({}, table)
local endIndex = 0
while true do
local startIndex, number
startIndex, endIndex, number = line:find("(%d+)", endIndex + 1)
if startIndex == nil then
break
end
candidates:insert({
line = id,
first = startIndex,
last = endIndex,
number = tonumber(number),
})
end
return candidates
end)
:select(function(partNumberCandidate)
for y = partNumberCandidate.line - 1, partNumberCandidate.line + 1 do
for x = partNumberCandidate.first - 1, partNumberCandidate.last + 1 do
local intersectsNumber = y == partNumberCandidate.line
and x >= partNumberCandidate.first
and x <= partNumberCandidate.last
if y >= 1 and y <= #rawSchematic and not intersectsNumber then
local char = rawSchematic[y]:sub(x, x)
if #char > 0 and char ~= "." then
return {
line = partNumberCandidate.line,
start = partNumberCandidate.first,
last = partNumberCandidate.last,
number = partNumberCandidate.number,
part = {
x = x,
y = y,
type = char
}
}
end
end
end
end
return partNumberCandidate
end)
:where(function(partCandidate) return partCandidate.part ~= nil end)
:toArray()
end,
puzzle1 = function(self)
return linq(self.schematic)
:sum(function(partNumber) return partNumber.number end)
end,
puzzle2 = function(self)
local gearTypeCandidates = {}
for _, part in pairs(self.schematic) do
if part.part.type == "*" then
local key = ("%d-%d"):format(part.part.x, part.part.y)
local candidate = gearTypeCandidates[key]
if candidate == nil then
candidate = {}
gearTypeCandidates[key] = candidate
end
table.insert(candidate, part)
end
end
return linq(gearTypeCandidates)
:where(function(candidate) return #candidate == 2 end)
:select(function(partNumbers) return partNumbers[1].number * partNumbers[2].number end)
:sum()
end,
}