Sorting lists in Clojure - sorting

I'm trying to sort a Clojure list (or seq, if that's what it's called) in a specific way. I would like it sorted in the priority of last item in decending order, then first item in ascending order. An example:
(def pnts '((1 2)
(2 4)
(3 2)
(4 10)
(5 3)
(6 1)
(7 2)))
(sort-by last > pnts)
;; ((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))
;; Notice how (1 2), (3 2), (7 2) are sorted. This
;; is correct and is what I want.
The (sort-by last) seems to be doing the trick, although this might be because the points are initially sorted by the first item. The way I am implementing the ASCII/CLI graphing script that I am writing the points will always be ordered like pnts was. My question is what is a command that can guarantee such a sorting preference?
PS I tried doing (sort-by (juxt last first) (juxt > <) pnts) but to no avail.

I think you were on the right track using juxt. Assuming that your points are all numbers, you can just compose last and - to emulate a descending natural order on the last component.
user=> (sort-by (juxt (comp - last) first) (shuffle pnts))
((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))

Sort uses Java's sort, which is stable, so you can also just sort twice
(def pnts (shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))
(->> pnts (sort-by first <) (sort-by last >))
;=> ((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))

I have shuffled the input to ensure that the result is stable for arbitrary input order:
(sort #(or (> (last %1) (last %2))
(and (= (last %1) (last %2))
(< (first %1) (first %2))))
(shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))
=> ((4 10) (2 4) (5 3) (1 2) (3 2) (7 2) (6 1))
Here we verify, even with 1000 reorderings of the input, there is only one ordering of the output:
(count (into #{}
(repeatedly
1000
(fn [] (sort #(or (> (last %1) (last %2))
(and (= (last %1) (last %2))
(< (first %1) (first %2))))
(shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2))))))))
=> 1
Here we show that shuffle produces a large variety of orderings:
(count (into #{}
(repeatedly
1000
(fn [] (shuffle '((1 2) (2 4) (3 2) (4 10) (5 3) (6 1) (7 2)))))))
=> 899
(of course since shuffle is randomized the results will vary, but the count seems to be typically in the 850 - 950 range)

Related

Round robin distribution in Clojure

I was wondering if anyone has any resources regarding round robin distribution in Clojure?
I have a function which splits the passed data into separate maps, like so:
(defn round-robin
"Divides the dataset into distinct maps using
round robin distribution"
[data sets split]
(partition split data)
)
My problem is that I'm not certain how to distribute these maps into the amount of "sets" defined. I'm thinking I could create the maps before hand with something like this:
(defn create-map-set
"Creates a set of (count) maps"
[count set]
(if(= count 0) set (recur (- count 1) (conj set
'())))
)
but as I can't reference indexes it becomes harder to merge data with the specific map.
Here's what I'm expecting:
Input: ((2 5) (3 2) (7 3) (1 4) (3 7) (4 2))
Output: ((2 5 1 4) (3 2 3 7) (7 3 4 2))
I'm essentially going 1 2 3, 1 2 3 when adding data to maps.
I will indicate how I go about such a problem. Clojure is quite conducive to this sort of experimentation. (leetwinski effectively gave this answer in his comment.)
Start off with the data.
'((2 5) (3 2) (7 3) (1 4) (3 7) (4 2))
Drop that inside a thread macro
(->> '((2 5) (3 2) (7 3) (1 4) (3 7) (4 2))) ===> ((2 5) (3 2) (7 3) (1 4) (3 7) (4 2))
Partition halfway
(->> '((2 5) (3 2) (7 3) (1 4) (3 7) (4 2))
(partition 3)) ===> (((2 5) (3 2) (7 3)) ((1 4) (3 7) (4 2)))
At this point, we get two elements (always). If we can pass these into map, and then concatenate each two elements, we are done. So,
(->> '((2 5) (3 2) (7 3) (1 4) (3 7) (4 2))
(partition 3)
(apply map concat)) ===> ((2 5 1 4) (3 2 3 7) (7 3 4 2))
Now, remove the hard-coded stuff:
(defn round-robin [s]
(let [half-len (quot (count s) 2)]
(->> s
(partition half-len)
(apply map concat))))
Note that if the input is odd-length, function disregards the last element.
My experience is that any time you want to do some transformations on some data, it pays to just push the data into a thread-last macro (->>) and keep whacking at it. This problem is quite simple, but the method works for complex transformations also.

Cons the first element of every sublist?

I'm writing a function to get me the children nodes of a parent, my code is:
(define (children elem tree)
(if (eqv? tree '())
'()
(if (= elem (car tree))
(getchilds (cdr tree))
(children elem (cdr tree)))))
(define (getchilds childNodes)
(cond ((null? childNodes) '())
(else (cons (caar childNodes) (getchilds (cdr childNodes))))))
This half works.
(children 10 '(10 (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6)))
outputs (2 5 6) which is what I expect
but (children 2 '(10 (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6))) fails.
I get a
=: contract violation
expected: number?
given: (2 (4 (9 (3)) (12 (1 (2))) (16)))
argument position: 2nd
other arguments...:
I think it's because (= elem (car tree) expect a number as a second parameter, but if I do
(car '(2 (4 (9 (3)) (12 (1 (2))) (16))))
output is 2
So I'm not quite sure where my logic fails. Anybody got an idea?
Consider your input list of (10 (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6)) (called tree in your code).
When you recurse with (cdr tree) (as you do in (children elem (cdr tree))), the new tree (in the recursive call) becomes ((2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6)). That means (car tree) is (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6). That's not a number.

Counting adjacent duplicates in scheme and prolog

I am new to scheme and prolog and have done only a few basic problems.
I need to write a function in scheme and prolog for counting adjacent recurrences in a list.
Example: (Count '(1, 1, 1, 2, 3, 3, 1)) gives ((3 1) (1 2) (2 3) (1 1))
I do not want the code as this is homework but any hints or how to think about this problem would be appreciated as I don't know where to start.
Let's look at a hypothetical function loop:
(loop todo done)
that rewrites the list in todo to you wanted format
and done contains the part already handled.
(loop '(1 1 1 2 3 3 1) '())
(loop '(1 1 2 3 3 1) '((1 1))
(loop '(1 2 3 3 1) '((1 2))
(loop '(2 3 3 1) '((1 3))
(loop '(3 3 1) '((2 1) (1 3))
(loop '(3 1) '((3 1) (2 1) (1 3))
(loop '(1) '((3 2) (2 1) (1 3))
(loop '() '((1 1) (3 2) (2 1) (1 3))
'((1 1) (3 2) (2 1) (1 3)
Given such a function loop you can write
(define (count xs)
(reverse loop xs '())
Now in order to implement loop you need to consider these cases:
1) todo is empty
2) done is empty
3) the first element of todo is different from the first element of done
3) the first element of todo is the same as the first element of done

printing pairs from a list in scheme

I'm trying to print pairs from one list kinda like a subset in scheme but with two elements just like this
(1 2 3 4 5)
((1 2) (1 3) (1 4) (1 5) (2 3) (2 4) (2 5) (3 4) (3 5) (4 5))
the code I wrote doesn't work
(define (subset x)
(if ( null? x) x
(map cons x (subset (cdr x)))))
this just return an empty list
I prefer to write the lambdas explicitly, makes it easier to understand what arguments are passed:
(define subset
(lambda (lst)
(if (null? lst)
lst
(append (map (lambda (el) (cons (car lst) el)) (cdr lst))
(subset (cdr lst)))
)))
(subset '(1 2 3 4 5))
=> ((1 . 2) (1 . 3) (1 . 4) (1 . 5) (2 . 3) (2 . 4) (2 . 5) (3 . 4) (3 . 5) (4 . 5))
EDIT: The explanation about map below is only valid in some versions of scheme, read Sylwester's comment to this answer.
map traverses n lists supplied to it and applies proc to the n elements in the same position in the lists. This means it can apply proc no more times than the length of the shortest list, but you keep giving it an empty list (from the last recursive call backwards).
(BTW this is in plain scheme)
In #lang racket that is very easy since we have combinations:
(combinations '(1 2 3 4 5) 2)
; ==> ((1 2) (1 3) (2 3) (1 4) (2 4) (3 4) (1 5) (2 5) (3 5) (4 5))
Now this does not print anything. To get it print to the terminal you can use displayln:
(displayln (combinations '(1 2 3 4 5) 2))
; ==> #<void>, ((1 2) (1 3) (2 3) (1 4) (2 4) (3 4) (1 5) (2 5) (3 5) (4 5)) printed to terminal as side effect
If order of items is also important, following can be used:
(define (subsets l)
(let loop ((n 0) ; run a loop for each item
(ol '())) ; start with blank output list
(cond
[(= n (length l)) (reverse ol)] ; output ol when last item reached;
[else
(let* ((x (list-ref l n)) ; get one item
(jl (for/list ((i l) ; get remaining list
(j (in-naturals))
#:unless (= j n))
i))
(kl (for/list ((i jl)) ; make combinations with each of remaining list
(list x i))))
(loop (add1 n) (cons kl ol)))])))
Testing:
(subsets '(1 2 3 4 5))
Output:
'(((1 2) (1 3) (1 4) (1 5))
((2 1) (2 3) (2 4) (2 5))
((3 1) (3 2) (3 4) (3 5))
((4 1) (4 2) (4 3) (4 5))
((5 1) (5 2) (5 3) (5 4)))

Lisp: How to get all possible combinations of the elements from lists contained on a list?

I need to write a function in Common-Lisp that takes a list of lists and returns a list containing all the possible combinations of the elements from the sublists.
So, for example calling the function on a list such as ((1 2) (1 2)) should return a list like ((1 1) (1 2) (2 1) (2 2)). The input list can be of any length and the sublists are not guaranted to have the same length.
I know how to get this with paired elements from the sublists ( inputtting ((1 2) (1 2)) returns ((1 1) (2 2)), but that's not good enough for the arc-consistency algorithm I'm trying to write, and I'm stuck.
Thank you.
If you don't want to use a library, here's code to do the same thing, and works with any number of lists:
(defun combinations (&rest lists)
(if (endp lists)
(list nil)
(mapcan (lambda (inner-val)
(mapcar (lambda (outer-val)
(cons outer-val
inner-val))
(car lists)))
(apply #'combinations (cdr lists)))))
[2]> (combinations '(1 2))
((1) (2))
[3]> (combinations '(1 2) '(3 4))
((1 3) (2 3) (1 4) (2 4))
[4]> (combinations '(1 2) '(3 4) '(5 6))
((1 3 5) (2 3 5) (1 4 5) (2 4 5) (1 3 6) (2 3 6) (1 4 6) (2 4 6))
wvxvw removed their answer that pointed to a function from Alexandria, but it does provide a very similarly named function that actually does what you want. Instead of alexandria:map-combinations, you need alexandria:map-product, e.g.
(apply #'alexandria:map-product #'list '((1 2) (1 2)))
evaluates to
((1 1) (1 2) (2 1) (2 2))

Resources