aboutsummaryrefslogtreecommitdiffstats
path: root/src/aoc_2022/utils.clj
blob: 4ade901a8485bdc2ecaea5d36653e628d9fcebbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(ns aoc-2022.utils)
(require '[clojure.string :as str])

; Debugging

(def spy #(do (println "DEBUG:" %) %))

; Number parsing

(def to-long #(Long/valueOf %))
(def to-float #(Float/valueOf %))

; Collections

(defn- split-by' [delim acc [x & xs]]
  (condp = x
    nil                       (list (reverse acc))
    delim (cons (reverse acc) (split-by' delim '() xs))
    ; otherwise
    (split-by' delim (cons x acc) xs)))

(def split-by #(split-by' %1 '() %2))

; Advent of Code specific

(defn read-aoc [day]
  (let [slurp-f #(str/split-lines (slurp (format % day)))]
    {:sample (slurp-f "resources/%s_sample.txt")
     :actual (slurp-f "resources/%s_actual.txt")}))

(defn run-aoc
  "Reads input files for `day` and invokes given `task1` and `task2` functions with the contents.
   `task1` and `task2` should take a list of strings as their first argument."
  [day task1 task2]
  (let [{:keys [sample actual]} (read-aoc day)]
    (do
      (println "task1 @ sample:" (task1 sample))
      (println "task1 @ actual:" (task1 actual))
      (println "task2 @ sample:" (task2 sample))
      (println "task2 @ actual:" (task2 actual)))))

; Functions

(defn chain "forward compose: comp fns in reverse order" [& fns]
  (apply comp (reverse fns)))

; Logic

(defmacro nand
  "Logical NAND. `(nand a b c)` is equivalent to `(not (and a b c))`."
  [& args]
  (list 'not (cons 'and args)))

(defmacro nor
  "Logical NOR. `(nor a b c)` is equivalent to `(not (or a b c))`."
  [& args]
  (list 'not (cons 'or args)))