Convert nested vector maps in clojure - clojure

I need to collect and transfer :c/name values into nested vector to first level same way.
Input example:
[:a/name "name" :a/vals [{:b/val [{:c/name "one"}{:c/name "two"}]}
{:b/val [{:c/name "three"}]}]]
Output:
[:a/name :a/vals "one, two, three"]

This produces the output from the input, is this what you want?
(defn f [[k1 _ k2 rels]]
[k1 k2
(clojure.string/join ", "
(map :c/name (apply concat (mapcat vals rels))))])

Related

From list of pairs ((3 . #\J) (5 . #\Q)) to list of strings (("3J") (5Q)) in Scheme

I have a list of pairs ((3. #\K) (5 . #\J)) ... and I would like to create a function in scheme that returns the list as this: ("3K", "5J")...
I've beeing trying but I cannot make it.
This is what I have.
; The deckCards will contain the list of pairs;
; The real Deck will contain the empty list.
(define (deck->strings deckCards realDeck)
(let lenOfItem ([n (my-lenght deckCards)])
(if (= 1 n)
(list (card->string (first deckCards)))
(append realDeck (deck->strings (cdr deckCards) realDeck))))
)
I did try doing with cond but for some reason it doesnt return the list and it seems impossible to append the list to the realDeack before calling itself recursively.
I think I found an approach and it worked. Not sure if it good to use it. However, this prints all the strings from top to boottom in a new line... Will this matter? I think its because I have 48 elements.
(map (lambda (i) (card->string i))
clubs)

List definition by repeated entry/iteration

I want to define the Thue-Morse Sequence (or the fair-sharing sequence) in terms of an initial element, 0, and the rule defining the next section of the list in terms of the entire list up until this point. i.e.
fair 0 = [0]
--fair 1 = [0,1]
--fair 2 = [0,1,1,0]
--fair 3 = [0,1,1,0,1,0,0,1]
fair n = fair (n - 1) ++ map (1-) (fair (n - 1))
This works fine to generate the list up to any predefined length, but it seems ineffective to not just define the entire list at once, and use take if I need a predefined amount.
My first attempt at defining the entire list was fair = 0 : map (1-) fair but of course, this populates the list as it goes, so it doesn't ever (need to) reenter the list (and returns [0,1,0,1,0,1...]). What I want is some way to define the list so that when it reaches a not-yet-defined element in the list, it defines the next 'chunk' by reentering the list only until that point, (rather than the computation 'chasing' the new values as they're produced), so the steps in computing the list would be akin to this procedure:
begin with initial list, [0]
map (1-) over the existing list, producing [1]
append this to the existing list, producing [0,1]
map (1-) over the existing list, producing [1,0]
append this to the existing list, producing [0,1,1,0]
map (1-) over the existing list, producing [1,0,0,1]
append this to the existing list, producing [0,1,1,0,1,0,0,1]
The Wikipedia article I linked above has a helpful gif to illustrate this process.
As I presume you can see, this would continue indefinitely as new elements are needed. However, I can't for the life of me find a way to successfully encode this in a recursive function.
I have tried
reenter f xs = reenter f (xs ++ map f xs)
fair = reenter (1-) [0]
But while the logic seems correct, it hangs without producing anything, probably due to the immediate recursive call (though I thought haskell's lazy evaluation might take care of that, despite it being a rather complex case).
As you noted, you can't do the recursive call immediately - you first need to return the next result, and then recursively call, as in your last try:
Prelude> reenter prev_list = inverted_prev_list ++ reenter (prev_list ++ inverted_prev_list) where inverted_prev_list = map (1-) prev_list
Prelude> f = [0] ++ reenter [0]
Prelude> take 20 f
[0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1]
Following is code in Racket, another functional programming language, using the steps listed in the question.
(define (f n)
(define (invert s) ; sub-function to invert the numbers
(list->string
(for/list ((i (string->list s)))
(if (equal? i #\0) #\1 #\0))))
(let loop ((c 1)
(s "0")) ; starting string is "0"
(if (> c n)
s
(loop (add1 c)
(string-append s (invert s))))))
Testing:
(f 1)
(f 2)
(f 3)
(f 4)
(f 5)
Output:
"01"
"0110"
"01101001"
"0110100110010110"
"01101001100101101001011001101001"
For infinite series:
(define (f)
(define (invert s)
(list->string
(for/list ((i (string->list s)))
(if (equal? i #\0) #\1 #\0))))
(let loop ((s "0"))
(define ss (string-append s (invert s)))
(println ss)
(loop ss)))
To run:
(f)
This may give some ideas regarding a Haskell solution to this problem.

Order multiple columns in Incanter for stacked bar chart

I want to order the stack elements (group-by-k) while keeping order in the global bars (col-k).
The $order function doesn't allow ordering multiple columns at once. So the function twice, though, the last sort will not preserve the previous sort. So I can either have the global bars sorted, or the stacked elements of a bar, but not both!
How can I achieve this? I suspect we would need a sorted-map working inside a $fn but not sure how to implement this...
Here the function I've written to attempt multiple ordering.
(require
(incanter '[core :as core]
'[charts :as charts])
(defn sorted-barchart [data col-k & {:keys [group-by-k
order-k
order-sign
order-group-k
order-group-sign
title
x-label
y-label
legend]}]
(core/with-data
(let [d (core/to-dataset data)
d1 (core/$where {group-by-k {:$fn #(not (empty? %))}} d)
d2 (core/$where {col-k {:$fn #(not (empty? %))}} d1)
d3 (core/$rollup :count :counts (if group-by-k [col-k group-by-k] [col-k]) d2)
d4 (core/$order (or order-k col-k) (or order-sign nil) d3)
d5 (core/$order (or order-group-k group-by-k)
(or order-group-sign nil) d4)]
d5)
(let [chart (charts/stacked-bar-chart col-k :counts
:group-by group-by-k
:vertical false
:x-label (or x-label " ")
:y-label (or y-label " ")
:title (or title " ")
:legend (or legend true)
:series-label "Total")]
chart)))
EDIT: this actually works when sorting by col-k and group-by-k. But when you want to first sort by counts it gets trickier to preserve col-k order when sort by count when you also want to get the stack elements sorted.
We can index the counts on main key only (col-k), then sort by index and stacked key (group-by-k).
So, in the sorted-barchart function, we can replace d4 and d5 by the following:
(if
(and group-by-k order-k (not= order-k col-k))
(let [d-count (core/$ col-k
(core/$order :c
:desc
(core/$rollup :count :c [col-k] d2)))
d-index (core/dataset [:index col-k]
(map-indexed vector d-count))
d-join (core/$join [col-k col-k] d-index d3)]
(->> d-join
(core/$order (or order-group-k group-by-k)
(or order-group-sign :asc))
(core/$order :index :asc)))
(let [d-new (if group-by-k
(core/$order (or order-group-k group-by-k)
(or order-group-sign :asc) d3)
d3)]
(core/$order (or order-k col-k) (or order-sign :desc) d-new)))

Clourescript: converting array access

Problem
I am trying to convert the following piece of code: https://github.com/mdn/webgl-examples/blob/gh-pages/tutorial/glUtils.js#L13-L15
The JavaScript code is:
Matrix.Translation = function (v)
{
// ignore length 2 case for simplicty
if (v.elements.length == 3) {
var r = Matrix.I(4);
r.elements[0][3] = v.elements[0];
r.elements[1][3] = v.elements[1];
r.elements[2][3] = v.elements[2];
return r;
}
throw "Invalid length for Translation";
}
Now, I can rewrite it cljs as follows:
(defn translation [x y z]
(let [r (. js/Matrix I 4)]
r[0][3] = x ;; how do I write this?
r[1][3] = y ;; how do I write this?
r[2][3] = z ;; how do I write this?
))
Question
However, how do I write r[0][3] in cljs?
You can use aget and aset to work with Javascript arrays:
(def arr (array (array "a1" "a2") (array "b1" "b2") (array "c1" "c2")))
It creates following nested array:
#js [#js ["a1" "a2"] #js ["b1" "b2"] #js ["c1" "c2"]]
You can access nested elements with aget:
(aget arr 1 0)
;; => "b1"
And update with aset:
(aset arr 1 0 "newb1")
updates arr to:
#js [#js ["a1" "a2"] #js ["newb1" "b2"] #js ["c1" "c2"]]
You might want to take a look at other functions related to Javascript arrays: alength, array, make-array, array?.

How to parse this text into a tree?

I want to take text (sample below) and convert it into a nested data structure that can be walked:
Arbirarchy !
dog, my friend
Bailey the Great
cats, my enemies
Robert the Terrible
Trev the Diner
Gombas the Tasty
Lenny Lion
Alligators
Sadly I have none
Is this the solution?
(defn parse [s]
{(re-find #"(?m)^.+" s)
(map parse (map #(str/replace % #"(?m)^\s{2}" "")
(map first (re-seq #"(?m)(^\s{2}.+(\n\s{4}.+$)*)" s))))})
your string (supposed that "Gombas" is indented):
(def s "hierarchy\n dog\n Bailey\n cats\n Robert\n Trev\n Gombas")
test
(parse s)
-> {"hierarchy" ({"dog" ({"Bailey" ()})}
{"cats" ({"Robert" ()}
{"Trev" ()}
{"Gombas" ()})})}