added 12022 directory

This commit is contained in:
sejo 2023-12-06 21:10:48 +01:00
parent e5edc774dd
commit 5a24fcb705
66 changed files with 5199 additions and 0 deletions

13
12022/01/01.fnl Normal file
View File

@ -0,0 +1,13 @@
(io.input "input")
(var calories [0])
(each [line (io.lines)]
(if (= line "") (table.insert calories 0)
(let [i (length calories)]
(tset calories i (+ (tonumber line) (. calories i))))))
(table.sort calories (λ [a b] (> a b)))
(print "part 1" (. calories 1))
(print "part 2" (let [c calories] (+ (. c 1) (. c 2) (. c 3))))

47
12022/01/01.lua Normal file
View File

@ -0,0 +1,47 @@
io.input("test")
io.input("input")
calories = {0}
i = #calories
for line in io.lines() do
if line ~= "" then
calories[i] = calories[i] + tonumber(line)
else
table.insert(calories, 0)
i = #calories
end
end
max = 0
maxa, maxb, maxc = 0, 0, 0
for i, c in ipairs(calories) do
if c>max then
max = c
end
if c>maxa then
maxc = maxb
maxb = maxa
maxa = c
elseif c>maxb then
maxc = maxb
maxb = c
elseif c>maxc then
maxc = c
end
-- print(c)
end
part1 = maxa
part2 = maxa+maxb+maxc
assert(part1==71506)
assert(part2==209603)
print("part 1", part1)
print("part 2", part2)
-- using table.sort
table.sort(calories, function(a,b) return (a>b) end)
part1 = calories[1]
part2 = calories[1]+calories[2]+calories[3]
print("part 1", part1)
print("part 2", part2)

22
12022/01/01_copy.fnl Normal file
View File

@ -0,0 +1,22 @@
(io.input "input")
(local n 3)
(var max [0 0 0]) ; greatest is position 1, then 2, last 3
(var calories-sum 0)
(each [line (io.lines)]
(let [num (tonumber line)]
(if (not num)
(let [ s calories-sum
; count to how many "max" the new sum is greater than
greater-than
(accumulate [sum 0 _ m (ipairs max)] (+ sum (if (> s m) 1 0)))]
(set calories-sum 0)
(when (> greater-than 0)
(table.insert max (- (+ n 1) greater-than) s) ; insert new max
(table.remove max))) ; remove last element
(set calories-sum (+ calories-sum num)))))
(print "part 1" (. max 1))
(print "part 2" (accumulate [sum 0 _ m (ipairs max)] (+ sum m)))

14
12022/01/test Normal file
View File

@ -0,0 +1,14 @@
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000

28
12022/02/02.fnl Normal file
View File

@ -0,0 +1,28 @@
(io.input "input")
; rock, paper, scissors
(local own-scores-1 {:X 1 :Y 2 :Z 3})
(local game-scores {:X {:A 3 :B 0 :C 6}
:Y {:A 6 :B 3 :C 0}
:Z {:A 0 :B 6 :C 3}})
; lose, draw, win
(local own-scores-2 {:X 0 :Y 3 :Z 6})
(local game-moves {:X {:A 3 :B 1 :C 2}
:Y {:A 1 :B 2 :C 3}
:Z {:A 2 :B 3 :C 1}})
(var score-1 0)
(var score-2 0)
(each [line (io.lines)]
(let [(other you) (string.match line "(%a+) (%a)")
move-score (. own-scores-1 you)
round-score (. (. game-scores you) other)
own-score-2 (. own-scores-2 you)
move-score-2 (. (. game-moves you) other)]
(set score-1 (+ score-1 move-score round-score))
(set score-2 (+ score-2 own-score-2 move-score-2))))
(print "part 1" score-1)
(print "part 2" score-2)

25
12022/02/02.lua Normal file
View File

@ -0,0 +1,25 @@
io.input("test")
io.input("input")
-- Rock, paper, scisors
own_scores = { X=1, Y=2, Z=3 }
game_scores = { X = { A=3, B=0, C=6},
Y = { A=6, B=3, C=0},
Z = { A=0, B=6, C=3}}
-- lose, draw, win
own_scores_2 = { X=0, Y=3, Z=6 }
game_moves = { X = { A=3, B=1, C=2}, -- lose
Y = { A=1, B=2, C=3}, -- draw
Z = { A=2, B=3, C=1}} -- win
score = 0
score_2 = 0
for line in io.lines() do
other, you = string.match(line, "(%a+) (%a+)")
score = own_scores[you] + game_scores[you][other] + score
score_2 = own_scores_2[you] + game_moves[you][other] + score_2
-- print(you, own_scores[you], game_scores[you][other], other)
-- print(you, own_scores_2[you], game_moves[you][other], other)
end
print("part 1", score)
print("part 2", score_2)

3
12022/02/test Normal file
View File

@ -0,0 +1,3 @@
A Y
B X
C Z

52
12022/03/03.lua Normal file
View File

@ -0,0 +1,52 @@
io.input("test")
io.input("input")
function getPriority(c)
if c>='a' and c<='z' then
return string.byte(c) - string.byte('a') + 1
else
return string.byte(c) - string.byte('A') + 27
end
end
-- for part 1
local sum = 0
local linecount = 0
-- for part 2
local common = {}
local sumBadges = 0
for line in io.lines() do
local h = {}
local i = 0
local repeated = nil
for c in string.gmatch(line, "%a") do
-- part 1
if i<#line/2 then
h[c] = (h[c] or 0) + 1
elseif not repeated and h[c] then
repeated = c
end
i = i + 1
-- part 2
if linecount==0 then
common[c] = 1
elseif common[c] and linecount==1 then
common[c] = 2
elseif common[c]==2 then -- 2
common[c] = 3
sumBadges = sumBadges + getPriority(c)
end
end
-- part 1
local priority = getPriority(repeated)
sum = sum + priority
-- part 2
if linecount==2 then common = {} end
linecount = (linecount + 1)%3
end
print("part 1", sum)
print("part 2", sumBadges)

6
12022/03/test Normal file
View File

@ -0,0 +1,6 @@
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw

19
12022/04/04.fnl Normal file
View File

@ -0,0 +1,19 @@
(io.input "input")
(var sum1 0)
(var sum2 0)
(each [line (io.lines)]
(let [(a b c d) (string.match line "(%d+)-(%d+),(%d+)-(%d+)")
ri1 (tonumber a) rf1 (tonumber b)
ri2 (tonumber c) rf2 (tonumber d)]
(when (or (and (>= ri1 ri2) (<= rf1 rf2))
(and (>= ri2 ri1) (<= rf2 rf1)))
(set sum1 (+ sum1 1)))
(when (and (>= rf1 ri2) (<= ri1 rf2))
(set sum2 (+ sum2 1)))))
; (when (or (and (>= rf1 ri2) (<= ri1 ri2))
; (and (>= rf2 ri1) (<= ri2 ri1)))
; (set sum2 (+ sum2 1)))))
(print "part 1" sum1)
(print "part 2" sum2)

36
12022/04/04.lua Normal file
View File

@ -0,0 +1,36 @@
io.input("test")
io.input("input")
local sum = 0
local sum2 = 0
for line in io.lines() do
local ri1, rf1, ri2, rf2 = string.match(line, "(%d+)-(%d+),(%d+)-(%d+)")
ri1=tonumber(ri1)
rf1=tonumber(rf1)
ri2=tonumber(ri2)
rf2=tonumber(rf2)
--[[
local r = {}
for n in string.gmatch(line,"%d+") do
table.insert(r, tonumber(n))
end
local ri1=r[1]
local rf1=r[2]
local ri2=r[3]
local rf2=r[4]
]]
-- part 1
if (ri1>=ri2 and rf1<=rf2) or (ri2>=ri1 and rf2<=rf1) then
sum = sum + 1
end
-- part 2
if (rf1>=ri2 and ri1<=rf2) then-- or (rf2>=ri1 and ri2<=ri1) then
sum2 = sum2 + 1
-- print(ri1, rf1, ri2, rf2)
end
end
print("part 1", sum)
print("part 2", sum2)

19
12022/04/04_2.fnl Normal file
View File

@ -0,0 +1,19 @@
(io.input "input")
(var sum1 0)
(var sum2 0)
(each [line (io.lines)]
(let [pattern "(%d+)-(%d+),(%d+)-(%d+)"
[ri1 rf1 ri2 rf2]
(icollect [_ n (-> line (string.match pattern) (table.pack) (ipairs))]
; (-> ...) equivalent to:
; (ipairs (table.pack (string.match line pattern)))]
(tonumber n))]
(when (or (and (>= ri1 ri2) (<= rf1 rf2))
(and (>= ri2 ri1) (<= rf2 rf1)))
(set sum1 (+ sum1 1)))
(when (and (>= rf1 ri2) (<= ri1 rf2))
(set sum2 (+ sum2 1)))))
(print "part 1" sum1)
(print "part 2" sum2)

6
12022/04/test Normal file
View File

@ -0,0 +1,6 @@
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8

74
12022/05/05.lua Normal file
View File

@ -0,0 +1,74 @@
io.input("test")
io.input("input")
stacks = {}
stacks2 = {}
instructions = {}
count = 0
function printStacks()
for i,stack in ipairs(stacks) do
local s = ""
for _,j in ipairs(stack) do
s = s .. j
end
print(i, s)
end
end
-- parsing
for line in io.lines() do
if string.find(line, "%[%a%]") then
local nstacks = #line//4 + 1 -- 1 5 9
for i = 1,nstacks do
if count == 0 then
stacks[i] = {}
stacks2[i] = {}
end
local index = 1 + (i-1)*4 -- 1, 5, 9
local s = string.sub(line, index, index+3)
local t = string.match(s, "%[(%a)%]")
table.insert( stacks[i], 1, t )
table.insert( stacks2[i], 1, t )
end
elseif string.find(line, "^move") then
local pattern = "^move (%d+) from (%d+) to (%d+)$"
local tt = table.pack(string.match(line, pattern))
local t = {}
for j, v in ipairs(tt) do t[j] = tonumber(v) end
table.insert(instructions, t)
end
count = count + 1
end
-- moves
for i, t in ipairs(instructions) do
q, src, dst = table.unpack(t)
-- part 1
for n = 1,q do
local crate = table.remove( stacks[src] )
table.insert( stacks[dst], crate )
end
-- part 2
local crates = {}
for n = 1,q do
crates[q-n+1] = table.remove( stacks2[src] )
end
for n = 1,q do
table.insert( stacks2[dst], crates[n] )
end
end
-- result
local result = ""
for _, stack in ipairs(stacks) do
result = result .. stack[#stack]
end
print("part 1", result)
result = ""
for _, stack in ipairs(stacks2) do
result = result .. stack[#stack]
end
print("part 2", result)

63
12022/05/05_part2.lua Normal file
View File

@ -0,0 +1,63 @@
io.input("test")
io.input("input")
stacks = {}
instructions = {}
count = 0
function printStacks()
for i,stack in ipairs(stacks) do
local s = ""
for _,j in ipairs(stack) do
s = s .. j
end
print(i, s)
end
end
-- parsing
for line in io.lines() do
if string.find(line, "%[%a%]") then
local nstacks = #line//4 + 1 -- 1 5 9
print(nstacks)
for i = 1,nstacks do
if count == 0 then
stacks[i] = {}
end
local index = 1 + (i-1)*4 -- 1, 5, 9
local s = string.sub(line, index, index+3)
local t = string.match(s, "%[(%a)%]")
table.insert( stacks[i], 1, t )
end
elseif string.find(line, "^move") then
local pattern = "^move (%d+) from (%d+) to (%d+)$"
local t = table.pack(string.match(line, pattern))
table.insert(instructions,t)
end
count = count + 1
end
-- moves
for i, t in ipairs(instructions) do
local tt = {}
for j, v in ipairs(t) do tt[j] = tonumber(v) end
q, src, dst = table.unpack(tt)
local crates = {}
for n = 1,q do
crates[q-n+1] = table.remove( stacks[src] )
end
for n = 1,q do
table.insert( stacks[dst], crates[n] )
end
end
printStacks()
-- result
local result = ""
for _, stack in ipairs(stacks) do
result = result .. stack[#stack]
end
print("part 2", result)

9
12022/05/test Normal file
View File

@ -0,0 +1,9 @@
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2

16
12022/06/06.fnl Normal file
View File

@ -0,0 +1,16 @@
(io.input "test")
(λ repeats [s]
(let [chars {}]
(for [i 1 (length s)]
(let [c (string.sub s i i)]
(if (. chars c) true (tset chars c true)))))
false)
(λ end-of-marker [s n]
(for [i 1 (length s)]
(let [window (string.sub s i (+ i (- n 1)))]
(print window))))
(end-of-marker (io.read "a") 4)
(print (repeats "aacd"))

25
12022/06/06.lua Normal file
View File

@ -0,0 +1,25 @@
io.input("test")
io.input("input")
local s = io.read("a")
function endOfMarker( n ) -- n is the window size
local i=1
repeat
local window = string.sub(s,i,i+n-1)
local repeats = false
local chars = {}
for j=1,n do
local c = string.sub(window,j,j)
if chars[c] then
repeats = true
break
else chars[c] = true
end
end
i = i + 1
until not repeats or i>#s
return i+n-2
end
print("part 1", endOfMarker(4))
print("part 2", endOfMarker(14))

1
12022/06/test Normal file
View File

@ -0,0 +1 @@
mjqjpqmgbljsphdztnvjfqwrcgsmlb

92
12022/07/07.lua Normal file
View File

@ -0,0 +1,92 @@
io.input("test")
io.input("input")
function createDir( dirname )
return { name = dirname, children = {}, localsize = 0}
end
function insertDirIntoWD( dirname )
-- if it already exists, return it
for _, d in ipairs( wd.children ) do
if d.name == dirname then return d end
end
-- print("inserting", dirname, "into", wd.name)
-- create it otherwise
local newdir = createDir(dirname)
table.insert( wd.children, newdir )
table.insert( dirs, newdir )
return newdir
end
-- initialize
root = createDir("/")
dirs = {root}
stack = {root}
wd = root -- working directory
local listing = false
for line in io.lines() do
if listing then
if string.find(line, "^%$") then
listing = false
else -- listing
local pattern = "^(.+) (.+)$"
local info, name = string.match( line, pattern )
if info == "dir" then
insertDirIntoWD( name )
else -- file
local size = tonumber(info)
wd.localsize = wd.localsize + size
end
end
end -- if listing
if not listing then
if string.find(line, "^%$ ls") then
listing = true
else -- change directory
local dirname = string.match(line, "^%$ cd (.+)$")
if dirname == "/" then
wd = root
stack = {root}
elseif dirname == ".." then
wd = table.remove( stack ) -- pop from stack
else -- go to named dir
table.insert( stack, wd ) -- push wd into stack
wd = insertDirIntoWD( dirname )
end -- if dirname
end -- if $ ls
end -- if not listing
end -- for line
function totalSize( dir )
local sum = dir.localsize
for i, d in ipairs( dir.children ) do
sum = sum + totalSize( d )
end
return sum
end
-- part 1
local result1 = 0
-- part 2
local total = totalSize(dirs[1])
local unused = 70000000 - total
local needed = 30000000 - unused
local minGreaterThanNeeded = total
for i, d in ipairs(dirs) do
local size = totalSize(d)
-- part 1
if size <= 100000 then
result1 = result1 + size
end
-- part 2
if size >= needed and size < minGreaterThanNeeded then
minGreaterThanNeeded = size
end
end
print("part 1", result1)
print("part 2", minGreaterThanNeeded)

94
12022/07/07_upgrade.lua Normal file
View File

@ -0,0 +1,94 @@
io.input("test")
io.input("input")
function createDir( dirname )
return { name = dirname, children = {}, localsize = 0 }
end
function insertDirIntoWD( dirname )
-- if it already exists, return it
for _, d in ipairs( wd.children ) do
if d.name == dirname then return d end
end
-- print("inserting", dirname, "into", wd.name)
-- create it otherwise
local newdir = createDir(dirname)
table.insert( wd.children, newdir )
table.insert( dirs, newdir )
return newdir
end
-- initialize
root = createDir("/")
dirs = {root}
stack = {root}
wd = root -- working directory
local listing = false
for line in io.lines() do
if listing then
if string.find(line, "^%$") then
listing = false
else -- listing
local pattern = "^(.+) (.+)$"
local info, name = string.match( line, pattern )
if info == "dir" then
insertDirIntoWD( name )
else -- file
local size = tonumber(info)
wd.localsize = wd.localsize + size
end
end
end -- if listing
if not listing then
if string.find(line, "^%$ ls") then
listing = true
else -- change directory
local dirname = string.match(line, "^%$ cd (.+)$")
if dirname == "/" then
wd = root
stack = {root}
elseif dirname == ".." then
wd = table.remove( stack ) -- pop from stack
else -- go to named dir
table.insert( stack, wd ) -- push wd into stack
wd = insertDirIntoWD( dirname )
end -- if dirname
end -- if $ ls
end -- if not listing
end -- for line
function totalSize( dir )
if dir.totalsize then return dir.totalsize end
local sum = dir.localsize
for i, d in ipairs( dir.children ) do
sum = sum + totalSize( d )
end
dir.totalsize = sum
return sum
end
-- part 1
local result1 = 0
-- part 2
local total = totalSize(dirs[1])
local unused = 70000000 - total
local needed = 30000000 - unused
local minGreaterThanNeeded = total
for i, d in ipairs(dirs) do
local size = totalSize(d)
-- part 1
if size <= 100000 then
result1 = result1 + size
end
-- part 2
if size >= needed and size < minGreaterThanNeeded then
minGreaterThanNeeded = size
end
end
print("part 1", result1)
print("part 2", minGreaterThanNeeded)

25
12022/07/test Normal file
View File

@ -0,0 +1,25 @@
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
$ cd ..
$ cd a

98
12022/08/08.lua Normal file
View File

@ -0,0 +1,98 @@
io.input("test")
io.input("input")
function addTree( r, c, height )
local visible = nil
if r==1 or c==1 or r==n or c==n then
visible = true
end
local tree = { h = height, v = visible, s = 1 }
trees[r][c] = tree
return tree
end
trees = {}
n = 0
local row = 1
for line in io.lines() do
n = #line
local col = 1
trees[row] = {}
for height in string.gmatch(line, "%d") do
local tree = addTree( row, col, height )
if row>1 and col>1 then
local allLess = true
local s = 0
for r=row-1,1,-1 do
s = s+1
if trees[r][col].h >= tree.h then
allLess = false
break
end
end
if allLess then tree.v = true end
tree.s = s*tree.s
allLess = true
s = 0
for c=col-1,1,-1 do
s = s + 1
if trees[row][c].h >= tree.h then
allLess = false
break
end
end
if allLess then tree.v = true end
tree.s = s*tree.s
end
col = col + 1
end
row = row + 1
end
-- second pass, other direction
for row = n-1, 2, -1 do
for col = n-1, 2, -1 do
local tree = trees[row][col]
local allLess = true
local s = 0
for r=row+1,n do
s = s + 1
if trees[r][col].h >= tree.h then
allLess = false
break
end
end
if allLess then tree.v = true end
tree.s = tree.s*s
allLess = true
s = 0
for c=col+1,n do
s = s + 1
if trees[row][c].h >= tree.h then
allLess = false
break
end
end
if allLess then tree.v = true end
tree.s = tree.s*s
end
end
local sum = 0
local maxscore = 0
for i, row in ipairs(trees) do
for j, tree in ipairs(row) do
-- part 1
if tree.v then sum = sum + 1 end
-- part 2
if tree.s > maxscore and i>1 and i<n and j>1 and j<n then
maxscore = tree.s
end
end
end
print("part 1", sum )
print("part 2", maxscore )

5
12022/08/test Normal file
View File

@ -0,0 +1,5 @@
30373
25512
65332
33549
35390

56
12022/09/09.lua Normal file
View File

@ -0,0 +1,56 @@
io.input("test")
io.input("input")
function pos2index( pos )
return pos.x*10000 + pos.y
end
function constrain( n, min, max )
local min = min or -1
local max = max or 1
if n < min then return min
elseif n > max then return max
else return n
end
end
local head = { x=1, y=1 }
local tail = { x=1, y=1 }
local visited = { [pos2index(tail)] = true }
for line in io.lines() do
local dir, q = string.match(line, "^(%a) (%d+)$")
q = tonumber(q)
for step = 1,q do
if dir == "R" then
head.x = head.x + 1
elseif dir == "L" then
head.x = head.x - 1
elseif dir == "U" then
head.y = head.y + 1
elseif dir == "D" then
head.y = head.y - 1
end
local dif = { x=head.x-tail.x, y=head.y-tail.y }
if dif.x == 0 and math.abs(dif.y) > 1 then
tail.y = tail.y + constrain(dif.y)
elseif dif.y == 0 and math.abs(dif.x) > 1 then
tail.x = tail.x + constrain(dif.x)
elseif math.abs(dif.x)>1 or math.abs(dif.y)>1 then
tail.y = tail.y + constrain(dif.y)
tail.x = tail.x + constrain(dif.x)
end
print( tail.x, tail.y, head.x, head.y, dif.x, dif.y)
visited[ pos2index(tail) ] = true
end
end
local result = 0
for k, v in pairs(visited) do
print(k)
result = result + 1
end
print("part 1", result)

89
12022/09/09_2.lua Normal file
View File

@ -0,0 +1,89 @@
io.input("test2")
io.input("input")
function pos2index( pos )
return pos.x*10000 + pos.y
end
function constrain( n, min, max )
-- returns converted n, and if it was converted
local min = min or -1
local max = max or 1
if n < min then return min, true
elseif n > max then return max, true
else return n, false
end
end
local head = { x=1, y=1 }
local n = 9
local tail = {}
for i=1,n do tail[i] = { x=1, y=1 } end
local visitedP1 = { [pos2index(tail[1])] = true }
local visitedP2 = { [pos2index(tail[n])] = true }
local resultP1 = 1
local resultP2 = 1
for line in io.lines() do
local dir, q = string.match(line, "^(%a) (%d+)$")
q = tonumber(q)
for step = 1,q do
if dir == "R" then
head.x = head.x + 1
elseif dir == "L" then
head.x = head.x - 1
elseif dir == "U" then
head.y = head.y + 1
elseif dir == "D" then
head.y = head.y - 1
end
-- loop through tails
for i=1,n do
local h = head
if i>1 then h = tail[i-1] end
local t = tail[i]
local dif = { x=h.x-t.x, y=h.y-t.y }
-- gx, gy indicate if the abs diff was greater than 1
local dx, gx = constrain(dif.x)
local dy, gy = constrain(dif.y)
if dif.x == 0 and gy then -- vertical
t.y = t.y + dy
elseif dif.y == 0 and gx then -- horizontal
t.x = t.x + dx
elseif gx or gy then -- diagonal further away
t.y = t.y + dy
t.x = t.x + dx
end
end
-- part 1
local index = pos2index(tail[1])
if not visitedP1[index] then
visitedP1[index] = true
resultP1 = resultP1 + 1
end
-- part 2
local index = pos2index(tail[n])
if not visitedP2[index] then
visitedP2[index] = true
resultP2 = resultP2 + 1
end
-- visitedP1[ pos2index(tail[1]) ] = true
-- visitedP2[ pos2index(tail[n]) ] = true
end
end
print("part 1", resultP1)
print("part 2", resultP2)
local result = 0
for k, v in pairs(visitedP1) do
result = result + 1
end
print("part 1", result, resultP1)
local result = 0
for k, v in pairs(visitedP2) do
result = result + 1
end
print("part 2", result, resultP2)

8
12022/09/test Normal file
View File

@ -0,0 +1,8 @@
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2

8
12022/09/test2 Normal file
View File

@ -0,0 +1,8 @@
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20

28
12022/10/10.lua Normal file
View File

@ -0,0 +1,28 @@
io.input("test2")
io.input("input")
local cycle = 1
local x = 1
local strengths = 0
for line in io.lines() do
local ins, num = string.match(line, "^(%a+) (-?%d+)$")
-- print(cycle, (cycle-19)%40, x)
local period = (cycle-20)%40
if period == 0 then
print(cycle, x)
strengths = strengths + cycle*x
elseif num and period == 39 then
strengths = strengths + (cycle+1)*x
print(cycle, x)
end
if num then -- addx
cycle = cycle + 2
x = x + tonumber(num)
else
cycle = cycle + 1
end
end
print("x", x, "cycle", cycle)
print("part 1", strengths)

41
12022/10/10_2.lua Normal file
View File

@ -0,0 +1,41 @@
io.input("test2")
io.input("input")
-- for part 2
function pixel( cycle, spx )
local cx = (cycle-1)%40
local s = (cx == 0) and "\n" or ""
local ch = (cx>=spx-1) and (cx<=spx+1) and "#" or "."
return s .. ch
end
local cycle = 1
local x = 1
local strengths = 0 -- part 1
local screen = "" -- part 2
-- process
for line in io.lines() do
local ins, num = string.match(line, "^(%a+) (-?%d+)$")
-- part 1
local period = (cycle-20)%40
if period == 0 then
print(cycle,x)
strengths = strengths + cycle*x
elseif num and period == 39 then
--print(cycle,x)
strengths = strengths + (cycle+1)*x
end
-- part 2
screen = screen .. pixel(cycle, x)
if num then -- addx
screen = screen .. pixel(cycle+1, x)
cycle = cycle + 1
x = x + tonumber(num)
end
cycle = cycle + 1
end
print("part 1", strengths)
print("part 2",screen)

3
12022/10/test Normal file
View File

@ -0,0 +1,3 @@
noop
addx 3
addx -5

146
12022/10/test2 Normal file
View File

@ -0,0 +1,146 @@
addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop

77
12022/11/11.lua Normal file
View File

@ -0,0 +1,77 @@
io.input("test")
io.input("input")
local monkeys = {}
local lineIndex = 1
local monkey
-- parsing
for line in io.lines() do
if line=="" then
lineIndex = 1
goto continue
end
if lineIndex == 1 then
local newmonkey = { q = {}, targets ={}, count=0 }
monkey = newmonkey
table.insert(monkeys, newmonkey)
elseif lineIndex == 2 then -- starting items
local q = {}
for item in string.gmatch(line, "%d+") do
table.insert( q, tonumber(item) )
end
monkey.q = q
elseif lineIndex == 3 then -- operation
local sign, value = string.match(line, "([+*]) (.+)$")
local num = tonumber(value)
local f
if sign == "*" then
f = function (x) local v = num or x
return x*v
end
else
f = function (x) local v = num or x
return x+v
end
end
monkey.f = f
elseif lineIndex == 4 then -- divisor
monkey.divisor = tonumber(string.match(line, "%d+$"))
elseif lineIndex == 5 then -- targets
monkey.targets[true] = tonumber(string.match(line, "%d+$"))+1
elseif lineIndex == 6 then -- targets
monkey.targets[false] = tonumber(string.match(line, "%d+$"))+1
end
lineIndex = lineIndex + 1
::continue::
end
for round = 1,20 do
for i, monkey in ipairs(monkeys) do
for _, item in ipairs(monkey.q) do
local worry = monkey.f(item)//3
local divisible = worry%monkey.divisor==0
local target = monkey.targets[divisible]
table.insert( monkeys[target].q, worry )
monkey.count = monkey.count + 1
end
monkey.q = {} -- empty queue
end
-- for debugging
--[[
print("round", round)
for i, monkey in ipairs(monkeys) do
print("monkey", i-1, monkey.count)
local oq =""
for _, item in ipairs(monkey.q) do
oq = oq .. tostring(item) .. ","
end
print(oq)
end
]]
end
table.sort(monkeys, function(a,b) return a.count > b.count end)
print("part 1", monkeys[1].count*monkeys[2].count)

88
12022/11/11_2.lua Normal file
View File

@ -0,0 +1,88 @@
io.input("test")
io.input("input")
local monkeys = {}
local lineIndex = 1
local monkey
-- parsing
for line in io.lines() do
if line=="" then
lineIndex = 1
goto continue
end
if lineIndex == 1 then
local newmonkey = { q = {}, targets ={}, count=0 }
monkey = newmonkey
table.insert(monkeys, newmonkey)
elseif lineIndex == 2 then -- starting items
local q = {}
for item in string.gmatch(line, "%d+") do
table.insert( q, tonumber(item) )
end
monkey.q = q
elseif lineIndex == 3 then -- operation
local sign, value = string.match(line, "([+*]) (.+)$")
local num = tonumber(value)
local f
monkey.sign = sign
monkey.num = num
if sign == "*" then
f = function (x) local v = num or x
return x*v
end
else
f = function (x) local v = num or x
return x+v
end
end
monkey.f = f
elseif lineIndex == 4 then -- divisor
monkey.divisor = tonumber(string.match(line, "%d+$"))
elseif lineIndex == 5 then -- targets
monkey.targets[true] = tonumber(string.match(line, "%d+$"))+1
elseif lineIndex == 6 then -- targets
monkey.targets[false] = tonumber(string.match(line, "%d+$"))+1
end
lineIndex = lineIndex + 1
::continue::
end
local divisors = {}
local period = 1
for _, monkey in ipairs(monkeys) do
table.insert( divisors, monkey.divisor )
period = period * monkey.divisor
end
for round = 1,10000 do
print("round", round)
for i, monkey in ipairs(monkeys) do
for _, item in ipairs(monkey.q) do
local worry = monkey.f(item)%period
local divisible = worry%monkey.divisor==0
local target = monkey.targets[divisible]
table.insert( monkeys[target].q, worry )
monkey.count = monkey.count + 1
end
monkey.q = {} -- empty queue
end
-- for debugging
--[[
for i, monkey in ipairs(monkeys) do
print("monkey", i-1, monkey.count)
local oq =""
for _, item in ipairs(monkey.q) do
oq = oq .. tostring(item) .. ","
end
print(oq)
end
]]
end
print(monkeys[1].count,monkeys[2].count, monkeys[3].count, monkeys[4].count)
table.sort(monkeys, function(a,b) return a.count > b.count end)
local result = monkeys[1].count*monkeys[2].count
print("part 2", result)

27
12022/11/test Normal file
View File

@ -0,0 +1,27 @@
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1

96
12022/12/12.lua Normal file
View File

@ -0,0 +1,96 @@
--io.input("test")
io.input("input")
function loc(x, y)
return { x = x, y = y }
end
local map = { v = {} }
-- parsing
local start, dest
local row = 1
local w, h
for line in io.lines() do
if row==1 then w = #line end
local col = 1
map[row] = {}
map.v[row] = {}
for h in string.gmatch(line,"%a") do
local height = string.byte(h)
if h=='S' then
height = string.byte('a')
start = loc( col, row )
elseif h=='E' then
height = string.byte('z')
dest = loc( col, row )
end
map[row][col] = height
map.v[row][col] = false -- visited
col = col + 1
end
row = row + 1
end
map.cols = w
map.rows = row-1
function map:nextMoves( x, y )
local map = self
local cur = map[y][x]
local leftDif = x>1 and not map.v[y][x-1] and cur-map[y][x-1]<=1
local rightDif = x<map.cols and not map.v[y][x+1] and cur-map[y][x+1]<=1
local upDif = y>1 and not map.v[y-1][x] and cur-map[y-1][x]<=1
local downDif = y<map.rows and not map.v[y+1][x] and cur-map[y+1][x]<=1
local moves = {}
if leftDif then table.insert( moves, loc( x-1, y) ) end
if rightDif then table.insert( moves, loc( x+1, y) ) end
if upDif then table.insert( moves, loc( x, y-1) ) end
if downDif then table.insert( moves, loc( x, y+1) ) end
return moves
end
local tocheck = { loc(dest.x, dest.y) }
map.v[dest.y][dest.x] = true -- visited
local count = 1
local count2
repeat
local checking = {}
for _, p in ipairs(tocheck) do
table.insert( checking, p )
end
tocheck = {}
local found = false
for _, p in ipairs(checking) do
map.v[p.y][p.x] = true
local t = map:nextMoves( p.x, p.y )
for _, move in ipairs(t) do
-- insert move only if not there already
local contains = false
for _, m in ipairs(tocheck) do
if m.x==move.x and m.y==move.y then
contains = true
break
end
end
if not contains then table.insert( tocheck, move ) end
-- part 1
if move.x == start.x and move.y == start.y then
found = true
end
-- part2
if not count2 and map[move.y][move.x]==string.byte('a') then
count2 = count
end
end
end
if not found then count = count + 1 end
until found
print("part 1", count)
print("part 2", count2)

5
12022/12/test Normal file
View File

@ -0,0 +1,5 @@
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi

98
12022/13/13.lua Normal file
View File

@ -0,0 +1,98 @@
--io.input("test")
io.input("input")
function compare(left, right)
local t = { l = type(left), r = type(right) }
if t.l == "number" and t.r == "number" then
if left < right then return true
elseif left > right then return false
else return nil
end
elseif t.l ~= t.r then
if t.l == "number" then
return compare( {left}, right )
else
return compare( left, {right} )
end
elseif t.l and t.r then -- two lists
local i = 1
while i <= #left or i <= #right do
local leftE = left[i]
local rightE = right[i]
if not rightE and leftE then
return false
elseif not leftE and rightE then
return true
end
local isCorrect = compare(leftE, rightE)
if isCorrect == nil then
i = i+1
else return isCorrect
end
end
return nil
end
end
local pair = {}
local index = 1
local count = 0
local packets = { }
for line in io.lines() do
if line == "" then
pair = {}
index = index + 1
goto continue
end
-- hehe, convert to lua table and ingest
local t = line:gsub("%[","{"):gsub("%]","}")
local s = "return " .. t
local packet = load(s)()
table.insert( packets, packet )
if not pair.l then
pair.l = packet
--print("left:", t)
else
pair.r = packet
-- print("right:", t)
local correct = compare( pair.l, pair.r )
--print("pair", index, correct)
if correct then count = count + index end
end
::continue::
end
print("part 1", count)
function tableToString(t)
local s = "{"
for i, v in ipairs(t) do
if type(v)=="table" then
s = s .. tableToString(v)
else
s = s .. tostring(v)
end
if i<#t then s = s .. "," end
end
s = s .. "}"
return s
end
-- part 2
table.insert(packets, {{2}})
table.insert(packets, {{6}})
table.sort( packets, compare )
local d1, d2
for i, p in ipairs(packets) do
local ip = p[1]
if ip and type(ip)=="table" and #ip == 1 and #p == 1 then
if ip[1] == 2 then d1 = i
elseif ip[1] == 6 then d2 = i end
end
end
print("part 2", d1*d2)

23
12022/13/test Normal file
View File

@ -0,0 +1,23 @@
[1,1,3,1,1]
[1,1,5,1,1]
[[1],[2,3,4]]
[[1],4]
[9]
[[8,7,6]]
[[4,4],4,4]
[[4,4],4,4,4]
[7,7,7,7]
[7,7,7]
[]
[3]
[[[]]]
[[]]
[1,[2,[3,[4,[5,6,7]]]],8,9]
[1,[2,[3,[4,[5,6,0]]]],8,9]

128
12022/14/14.lua Normal file
View File

@ -0,0 +1,128 @@
--io.input("test")
io.input("input")
function string2point( s )
local x, y = string.match( s, "(%d+),(%d+)" )
return { x=tonumber(x), y=tonumber(y) }
end
function coord2string( x, y )
return tostring(x) .. "," .. tostring(y)
end
map = {}
map.min = { x=1000, y=1000 }
map.max = { x=1, y=1 }
function map:updateRange( p )
local map = self
if p.x<map.min.x then map.min.x = p.x
elseif p.x>map.max.x then map.max.x = p.x
end
if p.y<map.min.y then map.min.y = p.y
elseif p.y>map.max.y then map.max.y = p.y
end
end
function map:fillWithRock( s1, s2 )
local map = self
local p1 = string2point( s1 )
local p2 = string2point( s2 )
map:updateRange( p1 )
map:updateRange( p2 )
if p1.x == p2.x then
local x = p1.x
local inc = (p1.y > p2.y) and -1 or 1
for y = p1.y, p2.y, inc do
local s = coord2string( x, y )
map[s] = "#"
end
elseif p1.y == p2.y then
local y = p1.y
local inc = (p1.x > p2.x) and -1 or 1
for x = p1.x, p2.x, inc do
local s = coord2string( x, y )
map[s] = "#"
end
end
end
function map:blocked( x, y )
local map = self
local s = coord2string( x, y )
return map[s] or y==map.max.y+2
end
function map:printArea( x1, y1, x2, y2 )
local map = self
print( map.min.x, map.min.y, map.max.x, map.max.y)
for row = y1, y2 do
local rs = ""
for col = x1, x2 do
local cs = coord2string( col, row )
local symbol = map[cs] or "."
rs = rs .. symbol
end
print( row, rs )
end
end
-- parse
for line in io.lines() do
local s1, s2
local i = 1
for point in string.gmatch( line, "(%d+,%d+)" ) do
s2 = point
if s1 then
map:fillWithRock( s1, s2 )
end
s1 = s2
i = i + 1
end
end
local result1, result2
local done = false
local i = 1
while not done do
local unit = { x=500, y=0 }
repeat
local moving = true
local nexty = unit.y+1
-- part 1
if nexty > map.max.y and not result1 then
result1 = i - 1
--done=true
end
if not map:blocked( unit.x, nexty ) then
unit.y = unit.y+1
elseif not map:blocked( unit.x-1, nexty ) then
unit.x = unit.x-1
unit.y = unit.y+1
elseif not map:blocked( unit.x+1, nexty) then
unit.x = unit.x+1
unit.y = unit.y+1
else
local s = coord2string( unit.x, unit.y )
map[s] = "o"
moving = false
-- part 2
if unit.y == 0 then
result2 = i
done = true
end
end
until not moving or done
i = i + 1
end
map:printArea( 490, 0, 503, 11 )
print("part 1", result1)
print("part 2", result2)

3
12022/14/:y:g Normal file
View File

@ -0,0 +1,3 @@
if p.x<map.min.x then map.min.x = p.x
elseif p.x>map.max.x then map.max.x = px
end

2
12022/14/test Normal file
View File

@ -0,0 +1,2 @@
498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9

164
12022/15/15.lua Normal file
View File

@ -0,0 +1,164 @@
--[[
io.input("test")
local targetRow = 10
local maxx, maxy = 20, 20
--]]
--[
io.input("input")
local targetRow = 2000000
local maxx, maxy = 4000000, 4000000
--]]
function abs(x)
return (x>=0) and x or -x
end
function distance(x1, y1, x2, y2)
return abs(x1-x2) + abs(y1-y2)
end
function inRange( x, y, row, targetD )
local startD = abs(row-y)
local dif = targetD - startD
if dif<0 then return nil
else return x-dif, x+dif
end
end
local count = 0
local positions = {}
local beacons = {} -- beacons in row
local data = {}
for line in io.lines() do
local nums = {}
for match in string.gmatch(line, "(-?%d+)") do
table.insert( nums, tonumber(match) )
end
local sx, sy, bx, by = table.unpack(nums)
local d = distance(sx, sy, bx, by)
local r1, r2 = inRange(sx, sy, targetRow, d)
-- print(sx, sy, bx, by, d)
if r1 then
for c = r1,r2 do
positions[c] = true
end
end
if by == targetRow then
beacons[bx] = true
end
-- for part 2
table.insert(data, {sx, sy, bx, by, d})
end
local result1 = 0
local min, max = math.maxinteger, math.mininteger
for x,v in pairs(positions) do
-- print(x, v)
if not beacons[x] then
result1 = result1 + 1
end
end
print("part 1", result1)
-- part 2
function join( r1, r2 )
local mini = (r1.i < r2.i ) and r1.i or r2.i
local maxf = (r1.f > r2.f ) and r1.f or r2.f
if r2.i <= r1.f+1 and r1.i<=r2.i or r1.i <= r2.f+1 and r2.i <= r1.i then
return { i = mini, f = maxf }
else
return r1, r2
end
end
--[[
function cleanUp( ranges )
local i = 2
repeat
local r1, r2 = join( ranges[i], ranges[i-1] )
if not r2 then
ranges[i-1] = r1 -- joined range
table.remove( ranges, i )
else -- don't intersect, try again
i = i + 1
end
until i > #ranges
end
--]]
local found = false
local minx, miny = 0, 0
local beaconX, beaconY
for y = miny, maxy do
if y%500000==0 then print("#"..tostring(y)) end
-- print("#"..tostring(y))
local ranges = {}
local beacons = {} -- beacons in row
for _, t in ipairs(data) do
local sx, sy, bx, by, d = table.unpack(t)
local ri, rf = inRange(sx, sy, y, d)
if ri then
ri = (ri > minx) and ri or minx
rf = (rf < maxx) and rf or maxx
local range = { i=ri, f=rf }
if #ranges == 0 then
table.insert( ranges, range )
else
local i = 1
repeat
local done
local r1, r2 = join( ranges[i], range )
if not r2 then
ranges[i] = r1 -- joined range
done = true
else -- don't intersect, try again
i = i + 1
-- unless there are no more
if i > #ranges then
ranges[i] = range
done = true
end
end
until done
end
end
end
if #ranges > 1 then
-- clean up
local i = 2
repeat
local r1, r2 = join( ranges[i], ranges[i-1] )
if not r2 then
ranges[i-1] = r1 -- joined range
table.remove( ranges, i )
else -- don't intersect, try again
i = i + 1
end
until i > #ranges
end
-- if there are still two ranges, here's the answer
if #ranges > 1 then
local r1, r2 = ranges[1], ranges[2]
local minf = (r1.f>r2.f) and r2.f or r1.f
beaconX = minf+1
beaconY = y
end
if beaconX then break end
end
local result2 = beaconX*4000000 + beaconY
print("part 2", result2)
print(beaconX, beaconY)
-- part 2 12518502636475
-- 3129625 2636475

14
12022/15/test Normal file
View File

@ -0,0 +1,14 @@
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3

99
12022/16/16.lua Normal file
View File

@ -0,0 +1,99 @@
io.input("test")
--io.input("input")
function newValve( r, ids )
return { rate = tonumber(r), ids = ids , open = false, valves = {}, idsAt = {} }
end
local map = {}
for line in io.lines() do
local pat = "(%u%u) [%l ]+=(%d+); [%l ]+([%u, ]+)$"
local valve, rate, list = string.match(line, pat)
local outIds = {}
for v in string.gmatch(list, "(%u%u)") do
table.insert( outIds, v )
end
map[valve] = newValve( rate, outIds )
print(valve, rate, list)
end
-- maybe not needed?
for k, v in pairs(map) do
for _, id in ipairs(v.ids) do
table.insert( v.valves, map[id] )
end
end
function releasedPressure()
local total = 0
for k, valve in pairs(map) do
total = total + ( valve.open and valve.rate or 0 )
end
return total
end
function contains( array, element )
for _, e in ipairs(array) do
if e == element then return true end
end
return false
end
function idsAtSteps( id, steps )
if steps == 1 then
return map[id].ids
else
if map[id].idsAt[steps] then
return map[id].idsAt[steps]
end
local ids = {}
for _, id in ipairs(map[id].ids) do
local idsDeep = idsAtSteps( id, steps-1 )
for _, idD in ipairs(idsDeep) do
if not contains( ids, idD) then
table.insert( ids, idD )
end
end
end
map[id].idsAt[steps] = ids
return ids
end
end
function potentialRateFromAt( id, steps )
local steps = steps or 1
local valve = map[id]
local candidates = {}
for _, v in ipairs( valve.valves ) do
if not v.open then table.insert( candidates, v ) end
end
if #candidates >= 1 then
table.sort( candidates, function (a,b) return a.rate > b.rate end )
return candidates[1].rate
else
return 0
end
end
map["DD"].open = false
map["JJ"].open = false
--print( releasedPressure())
--print(potentialRateFromAt("DD",1))
print("tests")
local actual = "AA"
local bestMove = { p = 0, steps = 0, dest = "" }
for steps = 1,(30) do
local t = idsAtSteps( actual, steps )
print("#",steps)
for _, id in ipairs(t) do
local valve = map[id]
local p = valve.open and 0 or valve.rate*(30-steps-1)
print(id, valve.rate, steps+1, (30-steps-1), valve.rate*(30-steps-1), valve.open, p)
end
end

10
12022/16/test Normal file
View File

@ -0,0 +1,10 @@
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II

189
12022/17/17.lua Normal file
View File

@ -0,0 +1,189 @@
--io.input("test")
io.input("input")
--
--local target = 2022 -- part 1
local target = 1000000000000 -- part 2
local shapes = {
{ w = 4, h = 1, map = { {1, 1, 1, 1} } },
{ w = 3, h = 3, map = { {0, 1, 0}, {1, 1, 1}, {0, 1, 0} } },
{ w = 3, h = 3, map = { {1, 1, 1}, {0, 0, 1}, {0, 0, 1} } },
{ w = 1, h = 4, map = { {1}, {1}, {1}, {1} } },
{ w = 2, h = 2, map = { {1, 1}, {1, 1} } },
}
local f = io.read("a")
local jets = {}
for j in string.gmatch(f,"[<>]") do
table.insert( jets, j)
end
function emptiness()
return {0, 0, 0, 0, 0, 0, 0}
end
local tunnel = {}
function tunnel:print()
for i = #self, 1, -1 do
local s = ""
local row = self[i]
for _, c in ipairs(row) do
s = s .. (c == 1 and "@" or ( c==2 and "#" or "."))
end
print(s)
end
end
function tunnel:drawShape( shape, shX, shY, color)
local tunnel = self
local color = color or 1
for ly = 1, shape.h do
local y = ly + shY - 1
tunnel[y] = tunnel[y] or emptiness()
for lx = 1, shape.w do
local x = lx + shX - 1
tunnel[y][x] = shape.map[ly][lx]==1 and color or tunnel[y][x]
end
end
end
function tunnel:clearShape( shape, shX, shY )
self:drawShape( shape, shX, shY, 0 )
end
function equals( t1, t2 )
for i = 1, #t1 do
if t1[i] ~= t2[i] then return false end
end
return true
end
local shI = 1
local jeI = 1
local erasedRows = 0
local iFound, iPeriod
local i = 1
while i <= target do
local shape = shapes[shI]
local x = 3 -- left
local y = #tunnel + 4 -- bottom
for i = 1, 3 do
table.insert( tunnel, emptiness() )
end
repeat -- moving loop
tunnel:drawShape( shape, x, y )
-- jet
local jet = jets[jeI]
local inc = jet=="<" and -1 or 1
local canMove = false
if (inc == -1 and x > 1 ) or ( inc == 1 and x + shape.w - 1 < 7) then
canMove = true
for lx = 1, shape.w do
local shX = lx + x - 1
for ly = 1, shape.h do
local shY = ly + y - 1
if tunnel[shY][shX+inc] == 2 and shape.map[ly][lx]==1 then
canMove = false
end
end
end
end
if canMove then
tunnel:clearShape( shape, x, y )
x = x + inc
tunnel:drawShape( shape, x, y )
end
jeI = (jeI == #jets) and 1 or (jeI + 1)
-- down
canMove = (y > 1)
if canMove then
for lx = 1, shape.w do
local shX = lx + x - 1
for ly = 1, shape.h do
local shY = ly + y - 1
if tunnel[shY-1][shX] == 2 and shape.map[ly][lx]==1 then
canMove = false
break
end
end
if not canMove then break end
end
end
if canMove then
tunnel:clearShape( shape, x, y )
y = y - 1
tunnel:drawShape( shape, x, y )
end
until not canMove
-- stopped shape
tunnel:drawShape( shape, x, y, 2)
-- clean tunnel
repeat
local emptyRow = true
local ind = #tunnel
for _, c in ipairs( tunnel[ind] ) do
if c > 0 then
emptyRow = false
break
end
end
if emptyRow then
table.remove( tunnel )
end
until not emptyRow or #tunnel == 0
-- check for repetition
local period
for size = 10, #tunnel/2 do
local equal = true
for j = 1, size do
local tail = tunnel[ #tunnel - j + 1 ]
local tail2 = tunnel[ #tunnel - size - j + 1 ]
if not equals(tail, tail2) then
equal = false
break
end
end
if equal then
period = size
for i = 1,period do
table.remove(tunnel)
end
erasedRows = erasedRows + period
if not iFound then
iFound = i
elseif not iPeriod then
iPeriod = i - iFound
-- jump ahead!
local remaining = target - i
local advance = remaining // iPeriod
local outOfIPeriod = remaining % iPeriod
erasedRows = erasedRows + advance*period
i = target - outOfIPeriod
end
-- print(i, iFound, period, iPeriod, #tunnel )
break
end
end
shI = (shI == #shapes) and 1 or (shI + 1)
i = i + 1
end
print("result ", #tunnel + erasedRows)

1
12022/17/test Normal file
View File

@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

1
12022/17/test2 Normal file
View File

@ -0,0 +1 @@
>

53
12022/18/18.lua Normal file
View File

@ -0,0 +1,53 @@
io.input("test")
io.input("input")
function s2p( s )
local nx, ny, nz = string.match(s, "(%d+),(%d+),(%d+)")
return tonumber(nx), tonumber(ny), tonumber(nz)
end
function p2s( x, y, z )
return string.format("%d,%d,%d", x, y, z )
end
local cubes = {}
local potneigh = {}
local ncubes = 0
for line in io.lines() do
local s = line
local x, y, z = s2p(s)
ncubes = ncubes + 1
cubes[ s ] = true
local dirs = {}
table.insert( dirs, p2s( x, y, z+1) )
table.insert( dirs, p2s( x, y, z-1) )
table.insert( dirs, p2s( x, y+1, z) )
table.insert( dirs, p2s( x, y-1, z) )
table.insert( dirs, p2s( x+1, y, z) )
table.insert( dirs, p2s( x-1, y, z) )
for _, d in ipairs(dirs) do
potneigh[d] = (potneigh[d] or 0) + 1
end
end
local neigh = 0
local sub2 = 0
for d, sum in pairs(potneigh) do
if cubes[d] then
neigh = neigh + sum
end
-- part 2
if not cubes[d] and sum == 6 then --trapped
sub2 = sub2 + 6
end
end
local result1 = ncubes*6 - neigh
print("part 1", result1)
-- incomplete (3178, too high)
local result2 = result1 - sub2
print("part 2", result2)

13
12022/18/test Normal file
View File

@ -0,0 +1,13 @@
2,2,2
1,2,2
3,2,2
2,1,2
2,3,2
2,2,1
2,2,3
2,2,4
2,2,6
1,2,5
3,2,5
2,1,5
2,3,5

4
12022/18/test1 Normal file
View File

@ -0,0 +1,4 @@
1,1,1
2,1,1
1,2,1
2,2,1

2
12022/19/test Normal file
View File

@ -0,0 +1,2 @@
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.

97
12022/20/20.lua Normal file
View File

@ -0,0 +1,97 @@
--io.input("test1")
io.input("input")
--local original = {}
--local positions = {}
local mixed = {}
local i = 0
for line in io.lines() do
local num = tonumber(line)
-- table.insert( original, num )
table.insert( mixed, { num = num, pos=i} )
i = i + 1
end
local n = #mixed
function wrap(x)
return ((x+n*10)%n)
end
for i, d in ipairs(mixed) do
if d.num == 0 then goto nextnum end
local newpos = wrap(d.pos+d.num)
--d.num<0 and (d.pos+d.num-1) or (d.pos+d.num)
--newpos = wrap(newpos)
local dir = d.num > 0
local wrapped
if dir then -- moving up
wrapped = math.abs(d.num)>n or newpos < d.pos or newpos == n-1
if wrapped then newpos = wrap(newpos + 1) end
print("checking", d.num, d.pos, newpos)
for j, t in ipairs(mixed) do
if j==i then goto continue end
if wrapped and (t.pos>=newpos and t.pos<d.pos) then
t.pos = t.pos + 1
-- print("updated", t.num, t.pos)
elseif not wrapped and (t.pos > d.pos and t.pos <= newpos) then
t.pos = t.pos - 1
-- print("updated", t.num, t.pos)
end
::continue::
end
else -- moving down
wrapped = math.abs(d.num)>n or newpos > d.pos or newpos==0
if wrapped then newpos = wrap(newpos - 1) end
print("checking", d.num, d.pos, newpos)
for j, t in ipairs(mixed) do
if j==i then goto continue end
if wrapped and (t.pos>d.pos and t.pos<=newpos) then
t.pos = t.pos - 1
-- print("updated", t.num, t.pos)
elseif not wrapped and (t.pos < d.pos and t.pos >= newpos) then
t.pos = t.pos + 1
-- print("updated", t.num, t.pos)
end
::continue::
end
end
print("changed", d.num, d.pos, newpos, dir, wrapped, i)
d.pos = newpos
::nextnum::
end
local pos0
for i, d in ipairs(mixed) do
if d.num == 0 then pos0 = d.pos break end
end
print("pos0", pos0, wrap(pos0+3000))
--[[
-- print list
table.sort(mixed, function (a,b) return a.pos < b.pos end)
local s = ""
for i, d in ipairs(mixed) do
s = s .. tostring(d.num)
if i < #mixed then s = s .. ", " end
end
print(s)
--]]
local sum = 0
for i, d in ipairs(mixed) do
if d.pos == wrap(pos0 + 1000) or d.pos == wrap(pos0+2000) or d.pos == wrap(pos0+3000) then
print(d.num)
sum = sum + d.num
end
end
print("part 1", sum)

84
12022/20/20_2.lua Normal file
View File

@ -0,0 +1,84 @@
--io.input("test")
io.input("input")
local key = 1 -- part 1
local key = 811589153 -- part 2
local mixed = {}
local i = 0
for line in io.lines() do
local num = tonumber(line)*key
table.insert( mixed, { num = num, pos=i} )
i = i + 1
end
local n = #mixed
function wrap(x)
return x%n
end
local pos0 = {}
local it = 1
local nit = 10
local sums = {}
for it = 1,nit do
for i, d in ipairs(mixed) do
if d.num == 0 then goto nextnum end
local ppos = d.num+d.pos
local inc = 0
if ppos >= n or ppos <0 then
inc = ppos//(n-1)
end
local newpos = wrap( ppos + inc )
for j, t in ipairs(mixed) do
if j==i then goto continue end
if newpos < d.pos and t.pos>=newpos and t.pos<d.pos then
t.pos = t.pos + 1
elseif newpos > d.pos and t.pos<=newpos and t.pos>d.pos then
t.pos = t.pos - 1
end
::continue::
end
d.pos = newpos
::nextnum::
end
-- find position of 0
for i, d in ipairs(mixed) do
if d.num == 0 then pos0[it] = d.pos break end
end
print(it, "pos0", pos0[it])
sums[it] = 0
end
for j = 1, nit do
for i, d in ipairs(mixed) do
if d.pos == wrap(pos0[j] + 1000)
or d.pos == wrap(pos0[j]+2000)
or d.pos == wrap(pos0[j]+3000) then
sums[j] = sums[j] + d.num
end
end
end
print("part 1", sums[1])
print("part 2", sums[10])
--[[
-- print list
table.sort(mixed, function (a,b) return a.pos < b.pos end)
local s = ""
for i, d in ipairs(mixed) do
s = s .. tostring(d.num)
if i < #mixed then s = s .. ", " end
end
print(s)
--]]

7
12022/20/test Normal file
View File

@ -0,0 +1,7 @@
1
2
-3
3
-2
0
4

4
12022/20/test1 Normal file
View File

@ -0,0 +1,4 @@
9
-1
0
1

27
12022/21/21.lua Normal file
View File

@ -0,0 +1,27 @@
--io.input("test")
io.input("input")
local m = {}
for line in io.lines() do
local pattern = "^(%a+): (.+)$"
local name, arg = string.match(line, pattern)
local num = tonumber(arg)
if num then
m[name] = function() return num end
else
local pattern = "(%a+) ([%+%-%*%/]) (%a+)"
local a, op, b = string.match(arg, pattern)
if op == "+" then
m[name] = function() return m[a]()+m[b]() end
elseif op == "-" then
m[name] = function() return m[a]()-m[b]() end
elseif op == "*" then
m[name] = function() return m[a]()*m[b]() end
elseif op == "/" then
m[name] = function() return m[a]()//m[b]() end
end
end
end
local result1 = m["root"]()
print("part 1", result1)

48
12022/21/21_2.lua Normal file
View File

@ -0,0 +1,48 @@
--io.input("test")
io.input("input")
local m = {}
for line in io.lines() do
local pattern = "^(%a+): (.+)$"
local name, arg = string.match(line, pattern)
local num = tonumber(arg)
if num then
m[name] = function() return num end
else
local pattern = "(%a+) ([%+%-%*%/]) (%a+)"
local a, op, b = string.match(arg, pattern)
if op == "+" then
m[name] = function() return m[a]()+m[b]() end
-- for part 2
if name == "root" then
m["root2"] = function() return m[a]()-m[b]() end
end
elseif op == "-" then
m[name] = function() return m[a]()-m[b]() end
elseif op == "*" then
m[name] = function() return m[a]()*m[b]() end
elseif op == "/" then
m[name] = function() return m[a]()/m[b]() end
end
end
end
local result1 = m["root"]()
print( string.format("part 1: %d", result1) )
-- part 2
local at = 0
local inc = 10000000000
repeat
repeat
m["humn"] = function() return at end
dif = m["root2"]()
at = at + inc
until dif <= 0
if dif==0 then break end
at = at - 10*inc
inc = inc/10
until inc < 1
local result2 = at - inc
print( string.format("part 2: %d", result2))

15
12022/21/test Normal file
View File

@ -0,0 +1,15 @@
root: pppw + sjmn
dbpl: 5
cczh: sllz + lgvd
zczc: 2
ptdq: humn - dvpt
dvpt: 3
lfqf: 4
humn: 5
ljgn: 2
sjmn: drzm * dbpl
sllz: 4
pppw: cczh / lfqf
lgvd: ljgn * ptdq
drzm: hmdt - zczc
hmdt: 32

157
12022/23/23.lua Normal file
View File

@ -0,0 +1,157 @@
io.input("test")
--io.input("input")
function p2s( x, y )
return string.format("%d,%d", x, y)
end
function s2p( s )
local x, y = string.match(s,"(-?%d+),(-?%d+)")
x = tonumber(x)
y = tonumber(y)
return x, y
end
function neighbors(x, y)
local n = {}
n.NW = p2s( x-1, y-1)
n.N = p2s( x, y-1)
n.NE = p2s( x+1, y-1)
n.E = p2s( x+1, y )
n.SE = p2s(x+1, y+1)
n.S = p2s(x, y+1)
n.SW = p2s(x-1, y+1)
n.W = p2s(x-1, y)
return n
end
local max = {y=0, x=0}
local min = {y=10000, x=10000}
function updateMaxMin( j, i )
if j>max.x then max.x = j
elseif j<min.x then min.x = j end
if i>max.y then max.y = i
elseif i<min.y then min.y = i end
end
local nelves = 0
local elves = {}
-- parse map
local i = 1
for line in io.lines() do
local j = 1
for c in string.gmatch(line, "%g") do
if c=="#" then
elves[ p2s(j,i) ] = true
updateMaxMin(j, i)
nelves = nelves + 1
end
j = j + 1
end
i = i + 1
end
local dirs = {"N", "S", "W", "E"}
local offdirs = 0
local round = 1
local result1
repeat
-- first half
local attempts = {}
for s, e in pairs(elves) do
local x, y = s2p(s)
local alone = true
local n = neighbors(x,y)
for k, ns in pairs(n) do
if elves[ns] then alone = false break end
end
if alone then goto continue end
for i=0,3 do
local idirs = (i+offdirs)%4 + 1
local dir = dirs[idirs]
if dir=="N" and not (elves[n.NW] or elves[n.N] or elves[n.NE]) then
--print("propose north")
if attempts[n.N] == nil then
attempts[n.N] = s
elseif attempts[n.N] then -- attempt
attempts[n.N] = false
end
break
elseif dir=="S" and not (elves[n.SW] or elves[n.S] or elves[n.SE]) then
--print("propose south")
if attempts[n.S] == nil then
attempts[n.S] = s
elseif attempts[n.S] then -- attempt
attempts[n.S] = false
end
break
elseif dir=="W" and not (elves[n.SW] or elves[n.W] or elves[n.NW]) then
--print("propose west")
if attempts[n.W] == nil then
attempts[n.W] = s
elseif attempts[n.W] then -- attempt
attempts[n.W] = false
end
break
elseif dir=="E" and not (elves[n.SE] or elves[n.E] or elves[n.NE]) then
-- print("propose east")
if attempts[n.E] == nil then
attempts[n.E] = s
elseif attempts[n.E] then -- attempt
attempts[n.E] = false
end
break
end
end
::continue::
end
--second half
local count = 0
for k, s in pairs(attempts) do
if s then
elves[s] = nil
elves[k] = true
local nx, ny = s2p(k)
updateMaxMin(nx, ny)
count = count + 1
end
end
--[[
print("moved:",count)
print(min.x, min.y, max.x, max.y)
--]]
offdirs = (offdirs==3) and 0 or (offdirs+1)
if round%100==0 then
print("round", round)
end
if round == 10 then
result1 = (max.y-min.y+1)*(max.x-min.x+1)-nelves
end
if count > 0 then
round = round + 1
end
until count == 0
print("part 1", result1)
print("part 2", round)
-- print map:
for y=min.y,max.y do
local m = ""
for x=min.x,max.x do
local s = p2s(x,y)
m = m .. (elves[s] and "#" or ".")
end
-- print(m)
end

7
12022/23/test Normal file
View File

@ -0,0 +1,7 @@
....#..
..###.#
#...#.#
.#...##
#.###..
##.#.##
.#..#..

6
12022/23/test1 Normal file
View File

@ -0,0 +1,6 @@
.....
..##.
..#..
.....
..##.
.....

46
12022/25/25.lua Normal file
View File

@ -0,0 +1,46 @@
io.input("test")
io.input("input")
function s2d( s )
local b = #s - 1
local num = 0
for i = 1, #s do
local sub = string.sub( s, i, i )
local d = tonumber(sub)
if not d then
if sub=="-" then d=-1
elseif sub=="=" then d=-2 end
end
num = num + d*(5^b)
b = b - 1
end
return num
end
function d2s( num )
local s = ""
repeat
local mod = num % 5
local rest = num // 5
local dif = mod - 5
local digit
if dif >= -2 then
rest = rest + 1
if dif == -2 then digit = "="
elseif dif == -1 then digit = "-" end
else
digit = string.format("%d", mod)
end
s = digit .. s
num = rest
until num == 0
return s
end
local sum = 0
for line in io.lines() do
sum = sum + s2d(line)
end
local result1 = d2s(sum)
print("part1:", result1)

13
12022/25/test Normal file
View File

@ -0,0 +1,13 @@
1=-0-2
12111
2=0=
21
2=01
111
20012
112
1=-1=
1-12
12
1=
122

2420
12022/aoc12022.html Normal file

File diff suppressed because it is too large Load Diff