--- /dev/null
+(module net.journcy.aoc2022.common)
+
+(defn inc [n] (+ n 1))
+
+(defn dec [n] (- n 1))
+
+(defn lines [file] (icollect [v (io.lines file)] v))
+
+(defn numbers [file] (icollect [v (io.lines file)] (tonumber v)))
+
+(defn head [tbl] (. tbl 1))
+
+(defn tail [tbl] (icollect [i v (ipairs tbl)] (if (= i 1) nil v)))
+
+(defn last [tbl] (let [n (# tbl)] (. tbl n)))
+
+(defn map [f tbl] (icollect [_ v (ipairs tbl)] (f v)))
+
+(defn add [a b] (+ a b))
+
+(defn gt [a b] (> a b))
+
+(defn accnum [f tbl]
+ (accumulate [acc 0
+ _ v (ipairs tbl)]
+ (f acc v)))
+
+(defn reduce [f tbl]
+ (accumulate [ret (head tbl)
+ _ v (ipairs (tail tbl))]
+ (f ret v)))
+
+(defn take [n tbl]
+ (accumulate [t []
+ i v (ipairs tbl)
+ &until (> i n)]
+ (doto t (table.insert v))))
+
+(defn tsplit [tbl brk]
+ (accumulate [parts [[]]
+ _ v (ipairs tbl)]
+ (do
+ (if (= v brk)
+ (table.insert parts [])
+ (table.insert (last parts) v))
+
+(defn partition [tbl n]
+ (if (or (= (# tbl) 0) (< n 1)) []
+ (accumulate [parts [[]]
+ _ v (ipairs tbl)]
+ (do
+ (if (= n (# (last parts)))
+ (table.insert parts [v])
+ (table.insert (last parts) v))
+ parts))))
+ parts)))
+
+(defn sum [tbl] (accnum add tbl))
+
+(defn sort [tbl f] (do (table.sort tbl f) tbl))
+
+(defn flatten [tbl]
+ (let [ret []]
+ (each [_ v (ipairs tbl)]
+ (each [_ u (ipairs v)]
+ (table.insert ret u)))
+ ret))
+
+(defn split [str sep]
+ (let [ret []]
+ (var beg (if (and (not= (# str) 0) (not= (# sep) 0)) 1 nil))
+ (var mid 0)
+ (var end 0)
+ (while beg
+ (set (mid end) (string.find str sep beg true))
+ (if (= mid nil) (set mid (inc (# str))))
+ (when (not= beg mid) (table.insert ret (string.sub str beg (dec mid))))
+ (set beg (if end (inc end) nil)))
+ (if (= (# sep) 0)
+ (fcollect [i 1 (# str)]
+ (string.sub str i i))
+ ret)))
+
+(defn keys [tbl] (icollect [k _ (pairs tbl)] k))
+
+(defn nil? [v] (= v nil))
+
+(defn swap! [tbl k f] (tset tbl k (f (. tbl k))))
+
+(defn swap!? [tbl k f d]
+ (if (nil? (?. tbl k))
+ (tset tbl k (f d))
+ (swap! tbl k f)))
+
+(defn intersect [A B]
+ (let [one->two #(if (= $1 0) 0 2)
+ join {}]
+ (each [_ a (ipairs A)]
+ (tset join a 1))
+ (each [_ b (ipairs B)]
+ (swap!? join b one->two 0))
+ (icollect [k v (pairs join)]
+ (if (= v 2) k nil))))