Login
7 branches 0 tags
Ben (Win10) More efficient [array/dup] 02fb583 3 years ago 605 Commits
nujel / tests / slow / day18.nuj
#!/usr/bin/env nujel

[defn snail/read-line [line]
       [read/single [join [split line ","] " . "]]]

[defn snail/parse-list [l d]
       [cond [[nil? l] #nil]
             [[int? l] @[:v l]]
             [#t @[:r [snail/parse-list [cdr l]] :l [snail/parse-list [car l]]]]]]

[defn snail/read [line]
       [snail/parse-list [snail/read-line line]]]

[defn snail/int? [l]
       [and l [ref l :v]]]

[defn snail->str [l]
       [cond [[snail/int? l] [string [ref l :v]]]
             [#t [cat "[" [snail->str [ref l :l]]  "," [snail->str [ref l :r]] "]"]]]]

[defn snail/find [root needle as bs]
       [def last #nil]
       [defn rec [t root needle]

              [cond [[snail/int? t] [set! last t] #f]
                    [[== needle t] last]
                    [#t [or [rec [ref t as] root needle]
                            [rec [ref t bs] root needle]]]]]
       [rec root root needle]]

[defn snail/find/previous [root needle]
       [snail/find root needle :l :r]]

[defn snail/find/next [root needle]
       [snail/find root needle :r :l]]

[defn snail/explode [t root]
       [def p [snail/find/previous root t]]
       [when p [tree/+= p :v [ref [ref t :l] :v]]]
       [def n [snail/find/next root t]]
       [when n [tree/+= n :v [ref [ref t :r] :v]]]
       [-> t
           [tree/set! :v 0]
           [tree/set! :l #nil]
           [tree/set! :r #nil]]]

[defn snail/split [t root]
       [def lv [/ [ref t :v] 2]]
       [-> t
           [tree/set! :l @[:v lv]]
           [tree/set! :r @[:v [- [ref t :v] lv]]]
           [tree/set! :v #nil]]]

[defn snail/explode/maybe [t root d]
       [cond [[snail/int? t] #f]
             [[>= d 4] [snail/explode t root]]
             [[snail/explode/maybe [ref t :l] root [+ 1 d]] #t]
             [#t [snail/explode/maybe [ref t :r] root [+ 1 d]]]]]

[defn snail/split/maybe [t root d]
       [cond [[snail/int? t] [and [>= [ref t :v] 10]
                                  [snail/split t root] #t]]
             [[snail/split/maybe [ref t :l] root [+ 1 d]] #t]
             [#t [snail/split/maybe [ref t :r] root [+ 1 d]]]]]

[defn snail/reduce [t]
       [while [or [snail/explode/maybe t t 0]
                  [snail/split/maybe t t 0]]] t]

[defn snail/add [a b]
       [snail/reduce @[:l a :r b]]]

[defn snail/sum [lines]
       [def vals [map [split lines "\n"] snail/read]]
       [reduce [cdr vals] snail/add [car vals]]]

[defn snail/mag [t]
       [cond [[snail/int? t] [ref t :v]]
             [#t [+ [* [snail/mag [ref t :l]] 3]
                    [* [snail/mag [ref t :r]] 2]]]]]

[defn snail/find-biggest [lines]
      [def vals [apply array/new [split lines "\n"]]]
      [def cmax 0]
      [for [a 0 100]
      [for [b 0 100]
           [when [!= a b]
                 [def cs [snail/add [snail/read [array/ref vals a]] [snail/read [array/ref vals b]]]]
                 [set! cmax [max cmax [snail/mag cs]]]
                 [def cs [snail/add [snail/read [array/ref vals b]] [snail/read [array/ref vals a]]]]
                 [set! cmax [max cmax [snail/mag cs]]]]]]
      cmax]

[def res-p1 [snail/mag [snail/sum [file/read "tests/slow/day18.input"]]]]
[when [!= res-p1 3725]
      [throw [list :wrong-result "Wrong result" res-p1]]]
[def res-p2 [snail/find-biggest [file/read "tests/slow/day18.input"]]]
[when [!= res-p2 4832]
      [throw [list :wrong-result "Wrong result" res-p2]]]