0
votes

I am learning Clojure and Functional Programming and I am facing another problem that I am stuck and I have no idea how to deal with it. Here is the problem:

I have a vector of vectors:

[[a b][b c][c d][d e][e f][f g][f h][b i][d j][j l][l m][a n][a o][o p]]

And I need to establish a relationship between some of the items. The relationship rules are:

1 - Every item that has the same value as the first column has a direct relationship.

2 - If there is any item with the first column equals the second column from the rule 1, there is also a relationship, but an indirect one.

In our scenario the relationship would be:

Relationship for a (rule 1):

[[a b][a n][a o]]

Relationship for a (rule 2):

[[b c][o p]]

After that I also need to calculate, but I can't figure out how to do this the Functional Programming style with clojure. I have been working with O.O. Programming since 2008 and this is the first time I am learning functional programming.

Any ideas?

Thanks in advance.

1
second relationship should be [[b c] [b i] [o p]] - leetwinski

1 Answers

3
votes

ok. the first one is easy:

(def data '[[a b][b c][c d][d e][e f][f g][f h]
            [b i][d j][j l][l m][a n][a o][o p]])

(defn rel1 [x data] (filter #(= (first %) x) data))

(rel1 'a data)
;; => ([a b] [a n] [a o])

you just keep all the pairs, whose first item is the one you need

the second one is slightly more complicated. You have to find first level relations for all the first level relations. e.g: when the first level relations for a are [[a b][a n][a o]], you have to find first level relations for b, n, and o, and concatenate them:

(defn rel2 [x data] 
  (mapcat (fn [[_ k]] (rel1 k data)) 
          (rel1 x data)))

(rel2 'a data)
;; => ([b c] [b i] [o p])

as a bonus: you can make up a function to compute any nth relation of this kind:

if you already have rel1:

(defn rel1 [x data] (filter #(= (first %) x) data))

(defn rel-n [x data n]
  (when (pos? n)
    (nth (iterate #(mapcat (fn [[_ k]] (rel1 k data)) %)
                  [[nil x]])
         n)))

in repl:

user> (rel-n 'a data 0)
nil

user> (rel-n 'a data 1)
([a b] [a n] [a o])

user> (rel-n 'a data 2)
([b c] [b i] [o p])

user> (rel-n 'a data 3)
([c d])

user> (rel-n 'a data 4)
([d e] [d j])

user> (rel-n 'a data 5)
([e f] [j l])

user> (rel-n 'a data 6)
([f g] [f h] [l m])

user> (rel-n 'a data 7)
()