Fork me on GitHub
#core-logic
<
2019-12-25
>
erwinrooijakkers00:12:45

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

erwinrooijakkers00:12:26

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

erwinrooijakkers00:12:44

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

erwinrooijakkers00:12:57

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

erwinrooijakkers00:12:07

Any pointers on how to do this?

erwinrooijakkers00:12:52

What type of features can I use?

erwinrooijakkers00:12:17

Any examples that solve a similar problem?

erwinrooijakkers00:12:21

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"])}

erwinrooijakkers00:12:01

Hope someone can give me some pointers! Merry Christmas

hiredman02:12:59

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

hiredman02:12:18

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

hiredman02:12:34

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

hiredman02:12:08

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

erwinrooijakkers12:12:13

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)