Fork me on GitHub
#datascript
<
2023-12-10
>
Alex15:12:59

Hi! I'm a total beginner in Datascript (and Datalog). Trying to figure it out by doing this years Advent of Code. 🙂 The task in the https://adventofcode.com/2023/day/2 seemed like a good fit to apply it. I got a DB in the form of tuples like this: [game-id draw-order cube-color cubes-number], e.g. [1 0 :red 4]. I am able to make a single Datascript query to remove all rows that contain impossible draws (more cubes of the given color than total provided). I can also easily show all impossible draws with a single query:

(d/q '[:find   ?gid ?ord ?col ?num   ?total
        :keys    gid  ord  col  num    total
        :in   [[?gid ?ord ?col ?num]] ?total-cubes
        :where
        [(?total-cubes ?col) ?total]
        [(> ?num ?total)]]
      db
      total-cubes)
Do you see a way to give the Part I's answer in a single query (i.e. sum of all possible game IDs )? It feels like I should try to use not-join, but I couldn't make it work yet...

Alex15:12:40

PS: my current working solution in plain Clojure requires use of every? at two levels of data structure nesting to keep only the legal games: https://github.com/a1exsh/advent-of-clerk/blob/main/src/advent_of_clerk/year_2023/day_02.clj#L48-L60

dvingo19:12:14

I can't think of a way around needing to make two queries - pretty sure if you need to build up an intermediate set and not individual values then a second query will be needed:

(d/q '[:find [?valid-gid ...]
       :in ?row ?totals
       :where
       [(datalevin.core/q
          [:find ?gid
           :in [[?gid ?ord ?col ?num]] ?total-cubes
           :where [(?total-cubes ?col) ?total]
                  [(> ?num ?total)]]
          ?row ?totals)
        [[?out-gid]]]
       [(identity ?row) [[?valid-gid]]]
       [(not= ?valid-gid ?out-gid)] ]
  [[0 0 :red 4]
   [0 0 :green 12]

   [1 0 :red 4]
   [1 0 :green 10]

   [2 0 :red 4]
   [2 0 :green 18]]
  {:red 12 :blue 14 :green 13})
=> [0 1]

Alex20:12:01

Interesting, thanks. It still looks like a "single" query, even with a sub-query to me, so maybe that's good enough. Why datalevin? Doesn't Datascript supports sub-queries?

dvingo21:12:40

it's a db built with datascript for its query interface https://github.com/juji-io/datalevin I just had it setup and not datascript locally to test your query out

Alex18:12:52

Actually, back to where I've seen a use for logical programming in this task: I wanted to be able to ask the system, when it gives some answer, how and from which given facts did it derive that answer. Is this something that Datalog / Datascript can do or should I be looking for actual Prolog implementations?

delaguardo10:12:35

have you seen meander? https://github.com/noprompt/meander it is logic programming in clojure. Not really Prolog implementation but still can help in many usecases

👀 1