Compare commits
6 Commits
19f704f4ee
...
069a32cc82
Author | SHA1 | Date |
---|---|---|
sejo | 069a32cc82 | |
sejo | 4833d1593a | |
sejo | 80822c8d5f | |
sejo | 8864dea301 | |
sejo | 96bcfd7553 | |
sejo | e5edc774dd |
|
@ -0,0 +1 @@
|
|||
*/*/input
|
|
@ -0,0 +1,51 @@
|
|||
# awk aoc 2021
|
||||
|
||||
got caught in the thrill of wanting to solve the puzzles fast :)
|
||||
|
||||
[advent of code 2021: awk](https://compudanzas.net/advent_of_code_2021.html)
|
||||
|
||||
the `NUM.awk` and `NUM_2.awk` files are the original ones written under pressure. the `*_new.awk` files are improved versions written afterwards.
|
||||
|
||||
you can see the puzzles and get the input files at [advent of code 2021](https://adventofcode.com/2021/)
|
||||
|
||||
# run
|
||||
|
||||
to run a program, e.g. `01.awk`:
|
||||
|
||||
```
|
||||
awk -f 01.awk inputfile
|
||||
```
|
||||
|
||||
if using gawk, you should be able to use compatibility/traditional mode (except for day 03, and 09)
|
||||
|
||||
```
|
||||
awk -c -f 01.awk inputfile
|
||||
```
|
||||
|
||||
# stats
|
||||
|
||||
```
|
||||
-------Part 1-------- -------Part 2--------
|
||||
Day Time Rank Score Time Rank Score
|
||||
22 00:19:18 1596 0 - - -
|
||||
21 00:29:17 3064 0 - - -
|
||||
20 12:59:28 11947 0 13:14:02 11669 0 --- same as 18
|
||||
18 >24h 16659 0 >24h 16484 0 --- solved it afterwards
|
||||
17 00:41:03 2839 0 00:56:57 2841 0
|
||||
16 00:34:15 550 0 02:21:09 3657 0
|
||||
15 16:52:00 24420 0 17:30:02 20656 0 --- thanks alderwick for your help!
|
||||
14 00:27:53 4878 0 01:07:47 3311 0
|
||||
13 02:02:33 9507 0 02:19:53 9225 0 --- started late
|
||||
12 01:57:59 7241 0 02:16:49 6447 0
|
||||
11 00:46:21 4284 0 00:49:55 4145 0
|
||||
10 00:19:04 4202 0 00:28:32 3347 0
|
||||
9 00:12:52 2598 0 00:55:08 4504 0
|
||||
8 00:06:26 580 0 01:02:03 2196 0
|
||||
7 00:06:50 2657 0 00:12:29 2665 0
|
||||
6 00:10:35 3339 0 00:36:30 4445 0
|
||||
5 00:08:39 464 0 00:19:44 917 0
|
||||
4 00:42:46 4241 0 00:45:01 3008 0
|
||||
3 00:12:37 4213 0 00:38:29 3758 0
|
||||
2 00:02:08 324 0 00:06:30 1842 0
|
||||
1 00:03:11 1556 0 00:08:18 1774 0
|
||||
```
|
|
@ -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))))
|
|
@ -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)
|
||||
|
|
@ -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)))
|
|
@ -0,0 +1,14 @@
|
|||
1000
|
||||
2000
|
||||
3000
|
||||
|
||||
4000
|
||||
|
||||
5000
|
||||
6000
|
||||
|
||||
7000
|
||||
8000
|
||||
9000
|
||||
|
||||
10000
|
|
@ -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)
|
|
@ -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)
|
|
@ -0,0 +1,3 @@
|
|||
A Y
|
||||
B X
|
||||
C Z
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
|||
vJrwpWtwJgWrhcsFMMfFFhFp
|
||||
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||
PmmdzqPrVvPwwTWBwg
|
||||
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||
ttgJtRGJQctTZtZT
|
||||
CrZsJsPPZsGzwwsLwLmpwMDw
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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"))
|
|
@ -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))
|
|
@ -0,0 +1 @@
|
|||
mjqjpqmgbljsphdztnvjfqwrcgsmlb
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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 )
|
|
@ -0,0 +1,5 @@
|
|||
30373
|
||||
25512
|
||||
65332
|
||||
33549
|
||||
35390
|
|
@ -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)
|
|
@ -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)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue