about summary refs log tree commit diff
path: root/users/sterni/exercises/aoc/2022
diff options
context:
space:
mode:
Diffstat (limited to 'users/sterni/exercises/aoc/2022')
-rw-r--r--users/sterni/exercises/aoc/2022/.skip-subtree1
-rw-r--r--users/sterni/exercises/aoc/2022/01/1.bqn7
-rw-r--r--users/sterni/exercises/aoc/2022/01/1.k1
-rw-r--r--users/sterni/exercises/aoc/2022/02/2.bqn7
-rw-r--r--users/sterni/exercises/aoc/2022/02/2.k1
-rw-r--r--users/sterni/exercises/aoc/2022/03/3.bqn8
-rw-r--r--users/sterni/exercises/aoc/2022/03/3.k1
-rw-r--r--users/sterni/exercises/aoc/2022/04/4.bqn11
-rw-r--r--users/sterni/exercises/aoc/2022/05/5.bqn18
-rw-r--r--users/sterni/exercises/aoc/2022/06/6.bqn4
-rw-r--r--users/sterni/exercises/aoc/2022/06/6.k1
-rw-r--r--users/sterni/exercises/aoc/2022/07/7.bqn24
-rw-r--r--users/sterni/exercises/aoc/2022/08/8.bqn15
-rw-r--r--users/sterni/exercises/aoc/2022/09/9.bqn17
-rw-r--r--users/sterni/exercises/aoc/2022/10/10.bqn25
-rw-r--r--users/sterni/exercises/aoc/2022/11/11.bqn41
-rw-r--r--users/sterni/exercises/aoc/2022/12/12.bqn16
-rw-r--r--users/sterni/exercises/aoc/2022/13/13.bqn14
-rw-r--r--users/sterni/exercises/aoc/2022/15/15.bqn18
-rw-r--r--users/sterni/exercises/aoc/2022/16/16.k21
-rw-r--r--users/sterni/exercises/aoc/2022/17/17.bqn51
-rw-r--r--users/sterni/exercises/aoc/2022/18/18.bqn14
-rw-r--r--users/sterni/exercises/aoc/2022/20/20.bqn13
-rw-r--r--users/sterni/exercises/aoc/2022/21/21.bqn25
-rw-r--r--users/sterni/exercises/aoc/2022/25/25.bqn4
-rw-r--r--users/sterni/exercises/aoc/2022/25/25.k1
-rw-r--r--users/sterni/exercises/aoc/2022/README.md8
-rw-r--r--users/sterni/exercises/aoc/2022/default.nix53
28 files changed, 420 insertions, 0 deletions
diff --git a/users/sterni/exercises/aoc/2022/.skip-subtree b/users/sterni/exercises/aoc/2022/.skip-subtree
new file mode 100644
index 0000000000..39d1894495
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/.skip-subtree
@@ -0,0 +1 @@
+nix solutions don't use readTree and the rest is non-nix
diff --git a/users/sterni/exercises/aoc/2022/01/1.bqn b/users/sterni/exercises/aoc/2022/01/1.bqn
new file mode 100644
index 0000000000..022b476aa9
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/01/1.bqn
@@ -0,0 +1,7 @@
+lib ← •Import •path∾"/../../lib.bqn"
+input ← lib.ReadDec¨¨ (<"") lib.SplitOn •FLines •path∾"/input"
+
+a‿·‿b ← +`3↑∨+´¨ input
+
+•Out "day01.1: "∾•Fmt a
+•Out "day01.2: "∾•Fmt b
diff --git a/users/sterni/exercises/aoc/2022/01/1.k b/users/sterni/exercises/aoc/2022/01/1.k
new file mode 100644
index 0000000000..42d64dfb6c
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/01/1.k
@@ -0,0 +1 @@
+(+\e@3#>e:(+/.'1_)'(&0=#'i)_i:0:"input")_1
diff --git a/users/sterni/exercises/aoc/2022/02/2.bqn b/users/sterni/exercises/aoc/2022/02/2.bqn
new file mode 100644
index 0000000000..65e3c817bb
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/02/2.bqn
@@ -0,0 +1,7 @@
+lib ← •Import •path∾"/../../lib.bqn"
+i ← 3|"ABCXYZ"⊸⊐¨ ' ' ⊑¨∘lib.SplitOn¨ •FLines •path∾"/input"
+S1 ← {1+𝕩+3×3|1+𝕩-𝕨}
+S2 ← {𝕨 S1 3|𝕨+𝕩-1}
+
+•Out "day02.1: "∾•Fmt +´S1´¨i
+•Out "day02.2: "∾•Fmt +´S2´¨i
diff --git a/users/sterni/exercises/aoc/2022/02/2.k b/users/sterni/exercises/aoc/2022/02/2.k
new file mode 100644
index 0000000000..9b6d10058d
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/02/2.k
@@ -0,0 +1 @@
++/{{y+1+3*3!1+y-x}[x]'y,3!x+y-1}.'3!"ABCXYZ"?(0:"input")_'1
diff --git a/users/sterni/exercises/aoc/2022/03/3.bqn b/users/sterni/exercises/aoc/2022/03/3.bqn
new file mode 100644
index 0000000000..642fccd450
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/03/3.bqn
@@ -0,0 +1,8 @@
+i ← •FLines •path∾"/input"
+c ← ∾(↕26)⊸+¨"aA"
+P ← {1+⊑c⊐⊑𝕩}
+S ← (∊/⊣)
+G ← ((⊣/(↕÷˜⟜≠))⊔⊢)
+
+•Out "day03.1: "∾•Fmt +´(P S˝)¨2‿∘⊸⥊¨i
+•Out "day03.2: "∾•Fmt +´3(P S´)¨∘G i
diff --git a/users/sterni/exercises/aoc/2022/03/3.k b/users/sterni/exercises/aoc/2022/03/3.k
new file mode 100644
index 0000000000..3e31f5f32c
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/03/3.k
@@ -0,0 +1 @@
++/'(58*r<1)+r:-96+(,/{?y@&~^x?y}/')'((2 0N#)';0N 3#)@\:0:"input"
diff --git a/users/sterni/exercises/aoc/2022/04/4.bqn b/users/sterni/exercises/aoc/2022/04/4.bqn
new file mode 100644
index 0000000000..0b8f1b4500
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/04/4.bqn
@@ -0,0 +1,11 @@
+⟨SplitOn, ReadDec⟩ ← •Import "../../lib.bqn"
+
+Sections ← {
+  a‿b ← ReadDec¨ (<'-') SplitOn 𝕩
+  ↕⌾(-⟜a) 1+b
+}
+i ← ∘‿2⥊Sections¨ ∾(<',') SplitOn¨ •FLines "input"
+Is ← ∊´∘((⍋≠¨)⊏⊢)
+
+•Out "day04.1: "∾•Fmt +´(∧´Is)˘ i
+•Out "day04.2: "∾•Fmt +´(∨´Is)˘ i
diff --git a/users/sterni/exercises/aoc/2022/05/5.bqn b/users/sterni/exercises/aoc/2022/05/5.bqn
new file mode 100644
index 0000000000..15b0dfc805
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/05/5.bqn
@@ -0,0 +1,18 @@
+⟨ReadDec, SplitOn, IsAsciiNum⟩ ← •Import "../../lib.bqn"
+rs‿rc ← (<"") SplitOn •FLines "../05/input"
+
+stacks ← {
+  count ← '0'-˜⊑⌽' ' (≠/⊢) ⊑⌽rs
+  ' ' (≠/⊢)¨<˘ (count×4) ((»∘(0⊸=)∘(4⊸|)∘↕⊣)/↑) ⍉> (-1)↓rs
+}
+
+cmds ← {0‿1‿1-˜ ReadDec¨ ((∧´IsAsciiNum)¨/⊢) (<' ') SplitOn 𝕩}¨ rc
+
+_ApplyCmd ← {
+  s Fn _self c‿f‿t :
+  m‿k ← 2↑ c ((≤⟜(↕≠))⊔⊢) f⊑s
+  (Fn m)⊸∾⌾(t⊸⊑) k˙⌾(f⊸⊑) s
+}
+
+•Out "day05.1: "∾⊑¨stacks ⌽_ApplyCmd˜´ ⌽ cmds
+•Out "day05.2: "∾⊑¨stacks ⊢_ApplyCmd˜´ ⌽ cmds
diff --git a/users/sterni/exercises/aoc/2022/06/6.bqn b/users/sterni/exercises/aoc/2022/06/6.bqn
new file mode 100644
index 0000000000..041a2e9100
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/06/6.bqn
@@ -0,0 +1,4 @@
+i ← ⊑•FLines "input"
+FirstMarker ← {𝕩+⊑/(∧´∘¬⊒)˘𝕩↕i}
+•Out "day06.1: "∾•Fmt FirstMarker 4
+•Out "day06.2: "∾•Fmt FirstMarker 14
diff --git a/users/sterni/exercises/aoc/2022/06/6.k b/users/sterni/exercises/aoc/2022/06/6.k
new file mode 100644
index 0000000000..3dc0de0a3e
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/06/6.k
@@ -0,0 +1 @@
+4 14{x+*&x=#'?'x':y}\:1:"input"
diff --git a/users/sterni/exercises/aoc/2022/07/7.bqn b/users/sterni/exercises/aoc/2022/07/7.bqn
new file mode 100644
index 0000000000..2fc387f340
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/07/7.bqn
@@ -0,0 +1,24 @@
+lib ← •Import "../../lib.bqn"
+cmds ← 1↓ '$' ((+`= ⟜(⊑¨))⊔⊢) •FLines "input"
+paths ← (<⟨⟩) {
+  𝕨 𝕊 "$ ls": 𝕨;
+  𝕨 𝕊 "$ cd /": ⟨⟩;
+  𝕨 𝕊 "$ cd ..": (-1)↓𝕨;
+  𝕨 𝕊 𝕩: 𝕨∾<5↓𝕩 # "$ cd …"
+}` ⊑¨cmds
+ParseLs ← {
+  dirs‿files ← 2↑((lib.IsAsciiNum∘⊑∘⊑)¨⊔⊢) ((<' ')⊸lib.SplitOn)¨ 1↓𝕩
+  (1⊑¨dirs)⋈(lib.ReadDec 0⊸⊑)¨files
+}
+dirlists ← ParseLs⌾(1⊸⊑)¨⥊⋈˘(("$ cd"⊸≢⟜(4⊸↑)∘⊑¨)∘(1⊸⊏)˘/⊢) (⍒≠¨paths)⊏⍉paths≍cmds
+DirSize ← {⊑𝕨 (⊑∘(1⊸⊑¨∘⊣⊐⊢)⊑⊣) <𝕩}
+DirName ← ∾'/'⊸∾¨
+dirsizes ← ⊑¨ ⟨⟩ {
+  szs 𝕊 ⟨dir, subdirs‿files⟩:
+  Canon ← DirName dir⊸∾⟜⋈
+  sz ← +´files∾szs⊸DirSize∘Canon¨ subdirs
+  szs∾<sz⋈DirName dir
+}˜´ ⌽dirlists
+
+•Out "day07.1: "∾•Fmt +´ 100000 (≥/⊢) dirsizes
+•Out "day07.2: "∾•Fmt (30000000-70000000-⌈´dirsizes) ⌊´∘(≤/⊢) dirsizes
diff --git a/users/sterni/exercises/aoc/2022/08/8.bqn b/users/sterni/exercises/aoc/2022/08/8.bqn
new file mode 100644
index 0000000000..91a16d9573
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/08/8.bqn
@@ -0,0 +1,15 @@
+i ← >'0'-˜•FLines "input"
+Visible ← {
+  _vis ← {(⌈`∘(¯1⊸»˘⌾⍉)<⊢)⌾𝕏 𝕗}
+  ∨´𝕩 _vis¨ ⟨⊢,⌽,⍉,⌽⍉⟩
+}
+
+•Out "day08.1: "∾•Fmt +´⥊Visible i
+
+ViewingDistances ← {
+  DirView ← {≠1(»⟜(∧`(⊑𝕩)⊸>)/⊢) 1↓𝕩}
+  _spliceDir ← {! =´≢𝕗 ⋄ 𝕏⁼(⊢↓(⊏⟜(𝕏𝕗))∘⊣)´¨ ⋈⌜˜↕≠𝕗}
+  ×´ DirView¨¨ 𝕩 _spliceDir¨ ⟨⊢, ⌽˘, ⍉, ⌽˘⍉⟩
+}
+
+•Out "day08.2: "∾•Fmt ⌈´⥊ViewingDistances i
diff --git a/users/sterni/exercises/aoc/2022/09/9.bqn b/users/sterni/exercises/aoc/2022/09/9.bqn
new file mode 100644
index 0000000000..fff38b5913
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/09/9.bqn
@@ -0,0 +1,17 @@
+⟨SplitOn,ReadDec⟩ ← •Import "../../lib.bqn"
+i ← ReadDec⌾(1⊸⊑)¨ (<' ')⊸SplitOn¨ •FLines "input"
+
+UnitDelta ← (⊢÷(|+0⊸=))
+ExpandStep ← {
+  𝕊 "L"‿l: 𝕊 (-l)‿0;
+  𝕊 "R"‿r: 𝕊 r‿0;
+  𝕊 "U"‿u: 𝕊 0‿u;
+  𝕊 "D"‿d: 𝕊 0‿(-d);
+  𝕊 delta: ((⌈´|)⥊<∘UnitDelta) delta
+}
+
+Step ← {knots 𝕊 delta: {h 𝕊 t: (UnitDelta h-t) +⍟(1<⌈´|h-t) t}` (delta⊸+)⌾⊑ knots}
+Visited ← {+´0=⊒(¯1⊸⊑)¨(<𝕨⥊<0‿0) Step` ∾ExpandStep¨ 𝕩}
+
+•Out "day09.1: "∾•Fmt  2 Visited i
+•Out "day09.2: "∾•Fmt 10 Visited i
diff --git a/users/sterni/exercises/aoc/2022/10/10.bqn b/users/sterni/exercises/aoc/2022/10/10.bqn
new file mode 100644
index 0000000000..04e3d6a8e5
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/10/10.bqn
@@ -0,0 +1,25 @@
+⟨SplitOn,ReadDec⟩ ← •Import "../../lib.bqn"
+# Instead of implementing the VM described in the problem, translate the
+# program to instructions with equivalent timing for a similar VM that
+# only needs 1 cycle for every instruction.
+is ← ∾{"noop": <"noop"; 𝕩: (<"noop")∾<ReadDec⌾(1⊸⊑) (<' ') SplitOn 𝕩}¨ •FLines "input"
+
+Op ← {x 𝕊 "noop": x;x 𝕊 "addx"‿i: x+i}
+Draw ← {𝕊 c‿x‿pic: pic∨(↕240)((c-1)⊸=∘⊣∧∊)(⌊⌾(÷⟜40)c)+¯1+x+↕3}
+_vm ← {
+  is _self s: (⊑s)≥≠is? s;
+  is _self prev‿sum‿x‿pic:
+  cycle ← prev+1
+  is _self ⟨
+    cycle,
+    sum+x×cycle×⊑cycle∊20‿60‿100‿140‿180‿220,
+    x Op (¯1+cycle)⊑is,
+    Draw cycle‿x‿pic
+  ⟩
+}
+
+·‿sum‿·‿pic ← is _vm 1‿0‿1‿(240⥊0)
+
+•Out "day10.1: "∾•Fmt sum
+•Out "day10.2:"
+•Show ".#" ⊏˜ ∘‿40⥊pic
diff --git a/users/sterni/exercises/aoc/2022/11/11.bqn b/users/sterni/exercises/aoc/2022/11/11.bqn
new file mode 100644
index 0000000000..12b9b5097a
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/11/11.bqn
@@ -0,0 +1,41 @@
+# needs export BQNLIBS=/path/to/mlochbaum/bqn-libs
+⟨ReadDec,ImportBqnLibs⟩ ← •Import "../../lib.bqn"
+⟨Split⟩ ← ImportBqnLibs "strings.bqn"
+MakeOp ← {
+  𝕊 a‿"+"‿b: 𝕊 a‿+‿b;
+  𝕊 a‿"*"‿b: 𝕊 a‿×‿b;
+  𝕊 a‿op‿b:
+  is‿xs ← (<"old") (≡¨⊔⊢) a‿b
+  {op´ (𝕩⋆≠xs) ∾ReadDec¨ is}
+}
+ParseMonkey ← {
+  ·‿items‿op‿if‿then‿else:
+  {
+    initial ⇐ ReadDec¨ ", " Split 18↓items
+    op ⇐ MakeOp " " Split 19↓op
+    if ⇐ ReadDec 21↓if
+    then ⇐ ReadDec 29↓then
+    else ⇐ ReadDec 30↓else
+  }
+}
+monkeys ← ParseMonkey¨ 1↓' '((+`(≠⟜⊑)¨)⊔⊢)0(≠⟜≠¨/⊢)•FLines "input"
+items ← {𝕩.initial}¨ monkeys
+lim ← ×´{𝕩.if}¨ monkeys
+
+Sim ← {
+  div 𝕊 len:
+  Turn ← {
+    items 𝕊 turnidx:
+    i ← (≠monkeys)|turnidx
+    m ← i⊑monkeys
+
+    worry ← lim|⌊div÷˜ m.Op¨ i⊑items
+    else‿then ← 2↑0 (=⟜(m.if⊸|)⊔⊢) worry
+
+    ⟨then, else⟩⊸(∾˜¨)⌾(m.then‿m.else⊸⊏) ⟨⟩˙⌾(i⊸⊑) items
+  }
+  ×´2↑∨+˝(<items) ((≠⊑)⊸(>((↕⊣)=|)¨)×(≠¨˘)∘>∘(⊣»Turn`)) ↕len×≠items
+}
+
+•Out "day11.1: "∾•Fmt 3 Sim 20
+•Out "day11.2: "∾•Fmt 1 Sim 10000
diff --git a/users/sterni/exercises/aoc/2022/12/12.bqn b/users/sterni/exercises/aoc/2022/12/12.bqn
new file mode 100644
index 0000000000..cf42f6f899
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/12/12.bqn
@@ -0,0 +1,16 @@
+⟨ImportBqnLibs,_fix⟩ ← •Import "../../lib.bqn"
+⟨ReplaceAll⟩ ← ImportBqnLibs "strings.bqn"
+i ← >•FLines "input"
+
+elevation ← 'a'-˜⟨"S","E"⟩‿⟨"a","z"⟩ ReplaceAll⌾⥊ i
+starts ← (⊏⟜∞‿0)¨⟨'S'=i,0=elevation⟩
+end ← 'E'=i
+
+Step ← {
+  𝕊 steps:
+  Go ← {𝕏⁼((⊢∾¨↕∘≢)(≤⟜(∞⊸»˘∘+⟜1))˜𝕏elevation)⊑>((⥊⟜∞)∘≢⊸⋈)˜∞⊸»˘1+𝕏steps}
+  steps⌊´Go¨⟨⊢,⌽˘,⍉,⍉⌽⟩
+}
+Shortest ← {⊑end/⊸⊏○⥊Step _fix 𝕩}
+
+•Out¨ "day12.1: "‿"day12.2: "∾¨ •Fmt∘Shortest¨ starts
diff --git a/users/sterni/exercises/aoc/2022/13/13.bqn b/users/sterni/exercises/aoc/2022/13/13.bqn
new file mode 100644
index 0000000000..0242cc5093
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/13/13.bqn
@@ -0,0 +1,14 @@
+lib ← •Import "../../lib.bqn"
+str ← lib.ImportBqnLibs "strings.bqn"
+i ← >⟨"[","]"⟩‿⟨"⟨","⟩"⟩⊸(•BQN str.ReplaceAll)¨¨0((⟨⟩⊸≡¨¯1˙⍟⊣¨(+`(=⟜≠)¨))⊔⊢)•FLines "input"
+
+Ord ← {
+  i1 𝕊 i2: 1‿1≡•Type¨ i1‿i2? ¯1‿1‿0⊑˜i1(=+≤)i2;
+  i1 𝕊 l2: 1‿0≡•Type¨ i1‿l2? l2 Ord˜ ⋈i1;
+  l1 𝕊 i2: 0‿1≡•Type¨ l1‿i2? l1 Ord ⋈i2;
+  l1 𝕊 l2: 0‿0≡•Type¨ l1‿l2?
+  ⊑1↑0(≠/⊢)l1 Ord¨○((l1⌈○≠l2)⊸(↑⌾(+⟜1))) l2
+}
+
+•Out "day13.1: "∾•Fmt +´1+/(1⊸=Ord´)˘i
+•Out "day13.2: "∾•Fmt ×´1‿2++´˘¯1=⟨⟨2⟩⟩‿⟨⟨6⟩⟩Ord⌜⥊i
diff --git a/users/sterni/exercises/aoc/2022/15/15.bqn b/users/sterni/exercises/aoc/2022/15/15.bqn
new file mode 100644
index 0000000000..e47355856b
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/15/15.bqn
@@ -0,0 +1,18 @@
+lib ← •Import "../../lib.bqn"
+
+F ← ¬∘('-'⊸=∨lib.IsAsciiNum)
+i ← ⌽˘˘∘‿2‿2⥊lib.ReadDec¨>(0⊸<⟜≠¨/⊢)∘((F ¯1˙⍟⊣¨(+`F))⊔⊢)¨ •FLines "input"
+
+ssp ← 4000000
+
+sds ← (⊏˘∾˘(+´˘(|(-˝))˘)) i
+
+# _fix is needed to deal with e.g. ⟨0‿15, 5‿8, 12‿23⟩
+MergeRanges ← ((⊑∾⊑∘⌽)∘∧∘∾)¨∘(+`∘((<∞‿∞)⊸»{<´1‿2⊏𝕨∾𝕩}¨⊢)⊔⊢) lib._fix
+
+Range ← {cky 𝕊 y‿x‿d: x+¯1‿1×d-|cky-y}
+RangesY ← {<˘∧𝕩(⊣Range˘({cky 𝕊 y‿·‿d: d≥|y-cky}˘/⊢))sds}
+OutRangeY ← {(1<≠)◶⟨0˙,𝕩⊸+∘(ssp⊸×⟜(+⟜1))∘(1⊸⊑)∘∾⟩ MergeRanges ssp⌊0⌈RangesY 𝕩}
+
+•Out "day15.1: "∾•Fmt +´-˜´¨MergeRanges RangesY 2÷˜ssp
+•Out "day15.2: "∾•Fmt +´OutRangeY¨↕ssp
diff --git a/users/sterni/exercises/aoc/2022/16/16.k b/users/sterni/exercises/aoc/2022/16/16.k
new file mode 100644
index 0000000000..40d5ace60e
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/16/16.k
@@ -0,0 +1,21 @@
+/ parsing
+(f;r;t):+{x[1 4],,9_x^'","}'" "\' 0:"input"
+(f;t):`s$''(f;t)
+r:f!{`I$x[&(x<58)&47<x]}' r
+g:f!t
+
+/ total flow scoring
+tf: {+/+\{x,(30-#x)#0}((r.)'x)*`XX=':x}
+
+/ valves to open
+vto: f^(=r).0;
+
+/ paths to keep after each step
+best: {x[(1000&#x)#>tf'x]}
+
+p:{[n;ps]
+  ms:ps[&~fin:(#vto)={#?x[&`X=':x]}'ps];
+  rt: best[ps[&fin],(ms[w],'(,*|)'ms[w:&{(0|/vto=l)&~|/0&':x=l:*|x}'ms]),,/{x,/:,'g[*|x]}' ms];
+  $[n>1;o[n-1;rt];rt]}
+
+*tf'p[29;,,`AA]
diff --git a/users/sterni/exercises/aoc/2022/17/17.bqn b/users/sterni/exercises/aoc/2022/17/17.bqn
new file mode 100644
index 0000000000..21b94221aa
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/17/17.bqn
@@ -0,0 +1,51 @@
+jets ← '>'= "<>" (∊˜/⊢) •FChars "input"
+pieces ← >¨⟨1‿1‿1‿1⟩‿⟨0‿1‿0,1‿1‿1,0‿1‿0⟩‿⟨0‿0‿1,0‿0‿1,1‿1‿1⟩‿⟨⋈1,⋈1,⋈1,⋈1⟩‿⟨1‿1,1‿1⟩
+w ← 7
+initial ← 0‿w⥊0
+
+# Warning: mutated global!
+ji ← 0
+_try ← {(⊢ 𝕩˙⍟(≠○(+´∘⥊∘∨⟜𝕨)) 𝔽) 𝕩}
+Fall ← {
+  pushed ← 𝕨 ((ji⊑jets)◶«‿»)˘ _try 𝕩
+  ji ↩ (≠jets)|ji+1
+  fallen ← 𝕨 » _try pushed
+  𝕨 𝕊⍟(pushed≢fallen) fallen
+}
+Height ← ≠∘(∨´˘/⊢)
+ThrowPiece ← {
+  piece ← 𝕩 (|˜⟜≠⊑⊢) pieces
+  chamber ← (((3+≠piece)⊸+∘⊑∘(1⊸↑)∘⌽∘(1⊸+)∘/∨´˘)↑⊢)⌾⌽𝕨
+  falling ← (≠chamber)↑(»⍟2 w⊸↑)˘piece
+  chamber (⊣∨Fall) falling
+}
+
+•Out "day17.1: "∾•Fmt Height initial ThrowPiece˜´ ⌽↕2022
+
+# https://mlochbaum.github.io/BQN/doc/control.html#while
+While ← {𝕩{𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}𝕨@}´
+{
+  target ← 1000000000000
+  ji ↩ 0 ⋄ i ← 0 ⋄ res ← @
+
+  chamber ← initial
+  cycles ← ⟨≠pieces,≠jets⟩⥊<⟨⟩
+
+  While {𝕤⋄res=@}‿{𝕤
+    chamber ↩ chamber ThrowPiece i
+    i +↩ 1
+
+    t ← i|˜≠pieces
+    cycles ↩ {
+      new ← 𝕩∾<i⋈Height chamber
+      res ↩ {𝕊 𝕩:
+        ⟨pl,hl⟩‿· ← chk ← ¯2↑new
+        pd‿hd ← -´⌽chk
+        @˙⍟(0≠pd|target-pl) hl+hd×pd÷˜target-pl
+      }⍟(1<≠new) @
+      new
+    }⌾(t‿ji⊸⊑) cycles
+  }
+
+  •Out "day17.2: "∾•Fmt res
+}
diff --git a/users/sterni/exercises/aoc/2022/18/18.bqn b/users/sterni/exercises/aoc/2022/18/18.bqn
new file mode 100644
index 0000000000..76ec569fed
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/18/18.bqn
@@ -0,0 +1,14 @@
+lib ← •Import "../../lib.bqn"
+
+i ← (lib.ReadDec¨(<',')⊸lib.SplitOn)¨ •FLines "input"
+dim ← 1+⌈´i
+cubes ← i∊˜↕dim
+
+views ← ⟨0‿1‿2, 1‿2‿0, 2‿0‿1⟩
+Exposed ← {(6×+´⥊𝕩)-2×+´views{+´⥊(∧˝˘)2↕𝕨⍉𝕩}¨<𝕩}
+Interior ← {(¬𝕩)∧´views{((lib.Xor`∘((∊∧⊢)∨»∘(∊⌾⌽∧⊢)))⎉1)⌾(𝕨⊸⍉)𝕩}¨<𝕩}
+Displace ← {⌈´(⥊⊢‿⌽⋈⌜views){F‿a 𝕊 𝕩:((-∘¬∘(»((0⊸=⊣)∧>)⊢)⌈⊢)⎉1)⌾(F a⊸⍉)𝕩}¨<𝕩}
+Exterior ← (⊢-○Exposed ¯1⊸=∘(Displace lib._fix)∘(-∘Interior+⊢))
+
+•Out "day18.1: "∾•Fmt Exposed cubes
+•Out "day18.2: "∾•Fmt Exterior cubes
diff --git a/users/sterni/exercises/aoc/2022/20/20.bqn b/users/sterni/exercises/aoc/2022/20/20.bqn
new file mode 100644
index 0000000000..8d4c905e87
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/20/20.bqn
@@ -0,0 +1,13 @@
+⟨ReadDec⟩ ← •Import "../../lib.bqn"
+enc ← ReadDec¨ •FLines "input"
+
+CoordSum ← +´∘(1000‿2000‿3000⊸((⊢≠⊸|+⟜(⊑∘(/=⟜0)∘⊢))⊏⊢))
+Mix ← {
+  M ← {m 𝕊 i:
+    l ← ≠m
+    i {n ← (l-1)|(𝕩⊑m)+⊑/𝕩=𝕨 ⋄ (n⊸↑(∾⟜𝕩)⊸∾n⊸↓) 𝕩(≠/⊢)𝕨}˜´ ⌽↕l
+  }
+  CoordSum ((⊢M⍟𝕨↕∘≠)⊏⊢) 𝕩
+}
+•Out "day20.1: "∾•Fmt 1 Mix enc
+•Out "day20.2: "∾•Fmt 10 Mix 811589153×enc
diff --git a/users/sterni/exercises/aoc/2022/21/21.bqn b/users/sterni/exercises/aoc/2022/21/21.bqn
new file mode 100644
index 0000000000..2f91f55d44
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/21/21.bqn
@@ -0,0 +1,25 @@
+⟨ImportBqnLibs, IsAsciiNum, ReadDec⟩ ← •Import "../../lib.bqn"
+⟨ReplaceAll, Split⟩ ← ImportBqnLibs "strings.bqn"
+
+i ← ": "⊸Split¨ •FLines "input"
+ReplaceInts ← {
+  𝕊 𝕩: 𝕊´ 2↑(¬∘(∧´IsAsciiNum∘⊑∘⌽)¨⊔⊢) 𝕩;
+  # TODO: Efficient replace on tokens
+  is 𝕊 es: (((•Fmt⍟(0⊸≠•Type))¨⌾(1⊸⊑) <˘⍉>is)⊸ReplaceAll⌾(1⊸⊑))¨ es
+}
+
+c ← 0
+CanEval ← (IsAsciiNum∨∊⟜"+-/* ")
+Eval ← {
+  a‿s‿b ← " " Split 𝕩
+  f ← ⊑+‿-‿×‿÷⊏˜"+-*/"⊐s
+  a F○ReadDec b
+}
+EvalExprs ← {
+  p‿e ← 2↑((∧´CanEval∘⊑∘⌽)¨⊔⊢) 𝕩
+  ev ← (Eval⌾(⊑⌽))¨ e
+  c +↩1
+  (⊑(⊑¨ev)∊˜<"root")◶⟨EvalExprs∘(ReplaceInts⟜p),1⊸⊑⊑⟩ ev
+}
+
+•Show EvalExprs ReplaceInts i
diff --git a/users/sterni/exercises/aoc/2022/25/25.bqn b/users/sterni/exercises/aoc/2022/25/25.bqn
new file mode 100644
index 0000000000..921099141f
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/25/25.bqn
@@ -0,0 +1,4 @@
+c ← "=-012"
+F ← +´∘(⊢×(5⊸⋆)∘⌽∘↕∘≠)∘(-⟜2)∘(c⊸⊐)
+T ← {c⊏˜5|2+𝕩 {(⌊5÷˜𝕨+2) (𝕊⟜(𝕨⊸∾))⍟(0<𝕨) 𝕩} ⟨⟩}
+•Out "day25.1: "∾T +´F¨ •FLines "input"
diff --git a/users/sterni/exercises/aoc/2022/25/25.k b/users/sterni/exercises/aoc/2022/25/25.k
new file mode 100644
index 0000000000..df956f002f
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/25/25.k
@@ -0,0 +1 @@
+c@2+{(1_o,0)+x+-5*o:2<x}/5\+/{5/x-2}'(c:"=-012")?0:"input"
diff --git a/users/sterni/exercises/aoc/2022/README.md b/users/sterni/exercises/aoc/2022/README.md
new file mode 100644
index 0000000000..65d51dd21f
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/README.md
@@ -0,0 +1,8 @@
+# sterni's [Advent of Code 2022](adventofcode.com/2022)
+
+I'm trying to do it in BQN again to redeem myself for my unfinished [AoC 2021](../2021),
+but will allow myself falling back to another language if I get stuck, so I actually
+complete this one.
+~~I also plan to write additional solutions in Nix (when I have the time) in order to
+throw `//tvix/eval` against some new problems.~~
+We'll see how it goes, as my December promises to be quite busy.
diff --git a/users/sterni/exercises/aoc/2022/default.nix b/users/sterni/exercises/aoc/2022/default.nix
new file mode 100644
index 0000000000..01134d1306
--- /dev/null
+++ b/users/sterni/exercises/aoc/2022/default.nix
@@ -0,0 +1,53 @@
+{ depot, pkgs, lib, ... }:
+
+let
+  inherit (pkgs.buildPackages) cbqn ngn-k;
+
+  # input files are not checked in
+  meta.ci.skip = true;
+
+  BQNLIBS = pkgs.fetchFromGitHub {
+    owner = "mlochbaum";
+    repo = "bqn-libs";
+    rev = "d56d8ea0b8c294fac7274678d9ab112553a03f42";
+    sha256 = "1c1bkqj62v8m13jgaa32ridy0fk5iqysq5b2qwxbqxhky5zwnk9h";
+  };
+in
+
+depot.nix.readTree.drvTargets {
+  shell = pkgs.mkShell {
+    name = "aoc-2022-shell";
+    packages = [
+      cbqn
+      ngn-k
+    ];
+
+    inherit BQNLIBS;
+  };
+
+  bqn = pkgs.runCommand "bqn-aoc-2022"
+    {
+      nativeBuildInputs = [
+        cbqn
+      ];
+
+      aoc = builtins.path {
+        name = "bqn-aoc-2022";
+        path = ./../.;
+        # Need lib.bqn from ../ and all inputs as well as bqn files from ./*
+        filter = path: type:
+          lib.hasSuffix ".bqn" path || (
+            lib.hasPrefix (toString ./.) path
+            && (
+              type == "directory"
+              || lib.hasSuffix "/input" path
+            )
+          );
+      };
+
+      inherit meta BQNLIBS;
+    }
+    ''
+      find "$aoc/2022" -name '*.bqn' -exec BQN {} \; | tee "$out"
+    '';
+}