core-logic

erwinrooijakkers 2019-12-25T00:23:25.000400Z

Hi all

erwinrooijakkers 2019-12-25T00:23:45.000800Z

I am trying to solve Advent of Code day 14 using core.logic

erwinrooijakkers 2019-12-25T00:24:26.001500Z

Day 14 is about “Stoichemetry” and minimizing reactants. It has constraints like this:

10 ORE => 10 A
1 ORE => 1 B
7 A, 1 B => 1 C
7 A, 1 C => 1 D
7 A, 1 D => 1 E
7 A, 1 E => 1 FUEL

erwinrooijakkers 2019-12-25T00:24:44.001900Z

This means 1 FUEL can be made of 7A and 1E

erwinrooijakkers 2019-12-25T00:24:57.002300Z

The goal is to find how much ORE is needed for 1 FUEL

erwinrooijakkers 2019-12-25T00:25:07.002600Z

Any pointers on how to do this?

erwinrooijakkers 2019-12-25T00:25:52.003Z

What type of features can I use?

erwinrooijakkers 2019-12-25T00:26:17.003500Z

Any examples that solve a similar problem?

erwinrooijakkers 2019-12-25T00:30:48.004100Z

I’ll watch these videos: • https://www.youtube.com/watch?v=irjP8BO1B8Yhttps://www.youtube.com/watch?v=lzCIyvFgUVk

erwinrooijakkers 2019-12-25T00:33:21.004800Z

I have the input now as a hash map from output to inputs:

{[1 "D"] ([7 "A"] [1 "C"]),
 [1 "FUEL"] ([7 "A"] [1 "E"]),
 [10 "A"] ([10 "ORE"]),
 [1 "C"] ([7 "A"] [1 "B"]),
 [1 "B"] ([1 "ORE"]),
 [1 "E"] ([7 "A"] [1 "D"])}

erwinrooijakkers 2019-12-25T00:34:01.005100Z

Hope someone can give me some pointers! Merry Christmas

2019-12-25T02:29:59.008Z

I think key is representation, you'll want to use a map of thing to count of thing instead of those pairs of thing and count

2019-12-25T02:34:18.014800Z

And write a relation, call it reduco that takes an input map and an output map, and it has a bunch of conde clauses that do things like constrain the fuel count of output to be one less them the input, and the count of a to be 7 more, and the count of e to be 1 one, using the fd namespace

2019-12-25T02:47:34.016100Z

so something like

(require '[clojure.core.logic :as l]
         '[clojure.core.logic.fd :as fd])

(defn reduco [input output]
  (l/conde
   [(fd/> (get input "FUEL") 0)
    (fd/- (get input "FUEL") 1 (get output "FUEL"))
    (fd/+ (get input "A") 7 (get output "A"))
    (fd/+ (get input "E") 1 (get output "E"))
    ;;
    (l/== (get input "ORE") (get output "ORE"))
    (l/== (get input "B") (get output "B"))
    (l/== (get input "C") (get output "C"))
    (l/== (get input "D") (get output "D"))
    ]))


(l/run 1 [output]
  (l/fresh [ore a b c d e fuel]
    (l/== output {"FUEL" fuel
                  "ORE" ore
                  "A" a
                  "B" b
                  "C" c
                  "D" d
                  "E" e})
    (reduco {"FUEL" 1
             "ORE" 0
             "A" 0
             "B" 0
             "C" 0
             "D" 0
             "E" 0}
            {"FUEL" fuel
                  "ORE" ore
                  "A" a
                  "B" b
                  "C" c
                  "D" d
                  "E" e})))
but with reduco fleshed out with the rest of the reduction rules and then with some driving goal that recursively calls reduco until you get back a map with nothing but ore in it

2019-12-25T02:48:08.016700Z

the tricky thing with mixing maps and core.logic is map stuff will be non-relational, so just watch out for it

erwinrooijakkers 2019-12-25T10:11:23.017100Z

Thanks!!!

erwinrooijakkers 2019-12-25T12:22:13.018300Z

Why doesn’t this find negative values?

(defn sqrts [n]
  (l/run 2 [x]
    (fd/in x (fd/interval (- n) n))
    (fd/* x x n)))

(sqrts 4)
;; => (2)

(sqrts 25)
;; => (5)