Hi There!

I'm Dan Schlegel, an Associate Professor in the Computer Science Department at SUNY Oswego

Clojure core.logic Example

The following example solves a puzzle gathered from https://logic.puzzlebaron.com/. In order to use this, modify your project.clj file to add the core.logic dependency.

(ns corelogicplay.recipe
  (:require [clojure.core.logic :as l])
  (:require [clojure.core.logic.fd :as fd]))

;Help Grandma Iva write down some of her favorite recipes.
;Determine the baking temperature and time of each recipe.

;1. The dish that cooks at 340 degrees bakes 5 minutes longer than the chicken cutlet.
;2. The dish that cooks at 350 degrees is either the dish that bakes for 35 minutes or the meatloaf.
;3. The mac and cheese bakes 5 minutes longer than the recipe that cooks at 340 degrees.
;4. The dish that bakes for 35 minutes cooks at 400 degrees.

; baking times: 25, 30, 35, 40 minutes
; temperatures: 340, 350, 375, 400
; recipes: candied yams, chicken cutlet, mac and cheese, meatloaf

(defn solve-recipe-puzzle []
  (l/run* [q]
          (l/fresh [yam chicken mac meatloaf
                    yam-temp yam-time
                    chicken-temp chicken-time
                    mac-temp mac-time
                    meatloaf-temp meatloaf-time]

                   (l/== yam [:yam yam-temp yam-time])
                   (l/== chicken [:chicken chicken-temp chicken-time])
                   (l/== mac [:mac mac-temp mac-time])
                   (l/== meatloaf [:meatloaf meatloaf-temp meatloaf-time])

                   (l/membero yam-temp [340 350 375 400])
                   (l/membero chicken-temp [340 350 375 400])
                   (l/membero mac-temp [340 350 375 400])
                   (l/membero meatloaf-temp [340 350 375 400])
                   (l/distincto [yam-temp chicken-temp mac-temp meatloaf-temp])

                   (l/membero yam-time [25 30 35 40])
                   (l/membero chicken-time [25 30 35 40])
                   (l/membero mac-time [25 30 35 40])
                   (l/membero meatloaf-time [25 30 35 40])
                   (l/distincto [yam-time chicken-time mac-time meatloaf-time])

                   ;1. The dish that cooks at 340 degrees bakes 5 minutes longer than the chicken cutlet.
                   ;; What we want to say: whichever one of our recipes that cooks at 340, has time equal to chicken-time + 5
                   (l/fresh [recipe chicken-time-plus-5]
                            (fd/+ chicken-time 5 chicken-time-plus-5)
                            (l/membero [recipe 340 chicken-time-plus-5] [yam chicken mac meatloaf]))

                   ;2. The dish that cooks at 350 degrees is either the dish that bakes for 35 minutes or the meatloaf.
                   (l/fresh [recipe]
                            (l/conde
                              [(l/membero [recipe 350 35] [yam chicken mac meatloaf])]
                              [(l/== meatloaf-temp 350)]))

                   ;3. The mac and cheese bakes 5 minutes longer than the recipe that cooks at 340 degrees.
                   (l/fresh [recipe time-of-340-recipe]
                            (fd/+ time-of-340-recipe 5 mac-time)
                            (l/membero [recipe 340 time-of-340-recipe] [yam chicken mac meatloaf]))

                   ;4. The dish that bakes for 35 minutes cooks at 400 degrees.
                   (l/fresh [recipe]
                            (l/membero [recipe 400 35] [yam chicken mac meatloaf]))


                   (l/== q [yam chicken mac meatloaf]))))

Output:

(solve-recipe-puzzle)
=> ([[:yam 340 30] [:chicken 375 25] [:mac 400 35] [:meatloaf 350 40]])