Skip to content

Instantly share code, notes, and snippets.

@zerokarmaleft
Created July 31, 2012 18:53
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save zerokarmaleft/3219448 to your computer and use it in GitHub Desktop.
Save zerokarmaleft/3219448 to your computer and use it in GitHub Desktop.
Game of Thrones Challenge #65
AA = Rickard Stark (M) AB = Eddard Stark (M) AC = Catelyn Tully (F)
AD = Brandon Stark (M) AE = Benjen Stark (M) AF = Jon Snow (M)
AG = Robb Stark (M) AH = Sansa Stark (F) AI = Arya Stark (F)
AJ = Bran Stark (M) AK = Rickon Stark (M) AL = Hoster Tully (M)
AM = Minisa Whent (F) AN = Edmure Tully (M) AO = Lysa Tully (F)
AP = Jon Arryn (M) AQ = Robert Arryn (M) AR = Tytos Lannister (M)
AS = Tywin Lannister (M) AT = Joanna Lannister (F) AU = Kevan Lannister (M)
AV = Cersei Lannister (F) AW = Jamie Lannister (M) AX = Tyrion Lannister (M)
AY = Robert Baratheon (M) AZ = Joffrey Baratheon (M) BA = Myrcella Baratheon (F)
BB = Tommen Baratheon (M) BC = Lancel Lannister (M) BD = Steffon Baratheon (M)
BE = Stannis Baratheon (M) BF = Selyse Florent (F) BG = Shireen Baratheon (F)
BH = Renly Baratheon (M) BI = Jaehaerys Targaryen (M) BJ = Aerys Targaryen (M)
BK = Rhaella Targaryen (F) BL = Rhaegar Targaryen (M) BM = Elia Martell (F)
BN = Rhaenys Targaryen (F) BO = Aegon Targaryen (M) BP = Viserys Targaryen (M)
BQ = Daenerys Targaryen (F) BR = Quellon Greyjoy (M) BS = Balon Greyjoy (M)
BT = Euron Greyjoy (M) BU = Victarion Greyjoy (M) BV = Urrigon Greyjoy (M)
BW = Aeron Greyjoy (M) BX = Rodrik Greyjoy (M) BY = Maron Greyjoy (M)
BZ = Asha Greyjoy (F) CA = Theon Greyjoy (M) CB = Alannys Harlaw (F)
---------------------------------------------------------------------------------------
AA->AB, AA->AD, AA->AE, AB->AF, AB->AG, AB->AH, AB->AI, AB->AJ, AB->AK, AC->AG,
AC->AH, AC->AI, AC->AJ, AC->AK, AL->AC, AL->AN, AL->AO, AM->AC, AM->AN, AM->AO,
AO->AQ, AP->AQ, AR->AS, AR->AU, AS->AV, AS->AW, AS->AX, AT->AV, AT->AW, AT->AX,
AU->BC, AV->AZ, AV->BA, AV->BB, AY->AZ, AY->BA, AY->BB, BD->AY, BD->BE, BD->BH,
BE->BG, BF->BG, BI->BJ, BI->BK, BJ->BL, BJ->BP, BJ->BQ, BK->BL, BK->BP, BK->BQ,
BL->BN, BL->BO, BM->BN, BM->BO, BR->BS, BR->BT, BR->BU, BR->BV, BR->BW, BS->BX,
BS->BY, BS->BZ, BS->CA, CB->BX, CB->BY, CB->BZ, CB->CA
(ns familytree.core
(:refer-clojure :exclude [==])
(:use clojure.core.logic))
(defrel parent p c)
(defn child [c p] (parent p c))
(defrel male p)
(defrel female p)
(defn ancestor [x z]
(conde
[(parent x z)]
[(fresh [y]
(parent x y)
(ancestor y z))]))
(defn descendant [x z]
(conde
[(child z x)]
[(fresh [y]
(child y x)
(descendant y z))]))
(defn father [f c]
(all
(parent f c)
(male f)))
(defn mother [m c]
(all
(parent m c)
(female m)))
(defn son [s p]
(all
(child s p)
(male s)))
(defn daughter [d p]
(all
(child d p)
(female d)))
(defn grandfather [gp c]
(fresh [p]
(father gp p)
(parent p c)))
(defn grandmother [gp c]
(fresh [p]
(mother gp p)
(parent p c)))
(defn grandson [gs gp]
(fresh [p]
(child p gp)
(son gs p)))
(defn granddaughter [gd gp]
(fresh [p]
(child p gp)
(daughter gd gp)))
(defn sibling [x y]
(fresh [p]
(parent p x)
(parent p y)
(!= x y)))
(defn brother [b x]
(all
(sibling b x)
(male b)))
(defn sister [s x]
(all
(sibling s x)
(female s)))
(defn uncle [u n]
(fresh [p]
(brother u p)
(parent p n)))
(defn aunt [a n]
(fresh [p]
(sister a p)
(parent p n)))
(defn nephew [n s]
(fresh [p]
(sibling s p)
(child n p)
(male n)))
(defn niece [n s]
(fresh [p]
(sibling s p)
(child n p)
(female n)))
(defn cousin [c x]
(fresh [cp xp]
(parent cp c)
(parent xp x)
(sibling cp xp)))
(defn -main
[& args]
(let [tree-file (slurp "family-trees.txt")
matches (re-seq #"([A-Z][A-Z]) = ([a-zA-Z]+ [a-zA-Z]+) \(([MF])\)"
tree-file)
people (zipmap (map #(nth % 1) matches)
(map #(nth % 2) matches))
relations (->> (re-seq #"([A-Z][A-Z])->([A-Z][A-Z])" tree-file)
(map #(map people %)))]
(doseq [[_ p c] relations] (fact parent p c))
(doseq [[_ _ p g] matches] (fact ({"M" male "F" female} g) p))
(do
(println "The parents of Arya Stark:\n"
(distinct (run* [q] (parent q "Arya Stark"))))
(println "The complete ancestry of Asha Greyjoy:\n"
(distinct (run* [q] (ancestor q "Asha Greyjoy"))))
(println "The complete ancestry of Daenerys Targaryen:\n"
(distinct (run* [q] (ancestor q "Daenerys Targaryen"))))
(println "The children of Jaehaerys Targaryen:\n"
(distinct (run* [q] (child q "Jaehaerys Targaryen"))))
(println "The complete descendants of Jaehaerys Targaryen:\n"
(distinct (run* [q] (descendant "Jaehaerys Targaryen" q))))
(println "The siblings of Arya Stark:\n"
(distinct (run* [q] (sibling "Arya Stark" q))))
(println "The father of Tyrion Lannister:\n"
(distinct (run* [q] (father q "Tyrion Lannister"))))
(println "The children whose mother is Catelyn Tully:\n"
(distinct (run* [q] (mother "Catelyn Tully" q))))
(println "The people whose sister is Cersei Lannister:\n"
(distinct (run* [q] (sister "Cersei Lannister" q))))
(println "The uncles of Joffrey Baratheon:\n"
(distinct (run* [q] (uncle q "Joffrey Baratheon"))))
(println "The aunt of Robb Stark:\n"
(distinct (run* [q] (aunt q "Robb Stark"))))
(println "The cousin of Robb Stark:\n"
(distinct (run* [q] (cousin q "Robb Stark"))))
(println "The nephew of Catelyn Tully:\n"
(distinct (run* [q] (nephew q "Catelyn Tully")))))))
@hlship
Copy link

hlship commented Aug 1, 2012

I love the pragmatism of slurping in the text file and digesting it with regexps.

@mstum
Copy link

mstum commented Aug 1, 2012

I like the simplicity of the rules. Would be interesting to see someone whack up something in Prolog :)

@zerokarmaleft
Copy link
Author

This is a solution for Daily Programmer #65 (without an implementation for the bonus...yet) by way of Brian Taylor's blog.

@netguy204
Copy link

Very nice solution. I'm impressed at how little code it took to ingest the text and build the relations.

@ulsa
Copy link

ulsa commented Aug 2, 2012

Perhaps zipmap can be used instead of the apply hash-map interleave thing?

(zipmap (map #(nth % 1) matches)
        (map #(nth % 2) matches))

@ulsa
Copy link

ulsa commented Aug 2, 2012

And perhaps change the:

flatten
(map people)
(partition 2)

to:

(map #(map people %))

@zerokarmaleft
Copy link
Author

Nice, thanks for the suggestions, Ulsa.

@carlosgaldino
Copy link

You could also change:

(defn sister [s x]
  (fresh []
    (sibling s x)
    (female s)))

to:

(defn sister [s x]
  (all
    (sibling s x)
    (female s)))

and the brother function as well.

all macro doc

@carlosgaldino
Copy link

Basically you can apply the same change I wrote on every function where you create logic variables that are not used. For example, father, mother, etc.

@zerokarmaleft
Copy link
Author

Gist updated. Thanks Carlos!

@antoinelyset
Copy link

I did a try here for Prolog : https://github.com/antoinelyset/GoT_Prolog

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment