(vec) vs [ ] vector literal - recursion

I've got two functions here that I though would return the same thing but they don't. I can't for the life of me figure out why. Any ideas?
user=> (defn foo [x] (when (> x 0) (conj (vec (foo (dec x))) x)))
#'user/foo
user=> (defn bar [x] (when (> x 0) (conj [(bar (dec x))] x)))
#'user/bar
user=> (foo 5)
[1 2 3 4 5]
user=> (bar 5)
[[[[[nil 1] 2] 3] 4] 5]

[xs] creates a one-element vector, containing the single item xs. In contrast, (vec xs) does not create a one-element vector containing the item xs. Instead, it creates an n-element vector, containing each item in xs separately. A function which does the former is vector: (vector x y z) is conceptually the same as [x y z]. Compare to (list x) and (seq x): the former creates a one-element sequence containing its input, while the latter converts its input to a sequence.
Of course, if you are going to conj onto the result of vector you might as well just build the 2-element vector directly: instead of (conj (vector x) y), write [x y].

Related

Scheme Make list of all pair permutations of elements in two equal length lists

I am trying to combine two lists of x coordinates and y coordinates into pairs in scheme, and I am close, but can't get a list of pairs returned.
The following can match up all the pairs using nested loops, but I'm not sure the best way to out put them, right now I am just displaying them to console.
(define X (list 1 2 3 4 5))
(define Y (list 6 7 8 9 10))
(define (map2d X Y)
(do ((a 0 (+ a 1))) ; Count a upwards from 0
((= a (length X) ) ) ; Stop when a = length of list
(do ((b 0 (+ b 1))) ; Count b upwards from 0
((= b (length Y) ) ) ; Stop when b = length of second list
(display (cons (list-ref X a) (list-ref Y b))) (newline)
))
)
(map2d X Y)
I am looking to have this function output
((1 . 6) (1 . 7) (1 . 8) ... (2 . 6) (2 . 7) ... (5 . 10))
I will then use map to feed this list into another function that takes pairs.
Bonus points if you can help me make this more recursive (do isn't 'pure' functional, right?), this is my first time using functional programming and the recursion has not been easy to grasp. Thanks!
The solutions of Óscar López are correct and elegant, and address you to the “right” way of programming in a functional language. However, since you are starting to study recursion, I will propose a simple recursive solution, without high-level functions:
(define (prepend-to-all value y)
(if (null? y)
'()
(cons (cons value (car y)) (prepend-to-all value (cdr y)))))
(define (map2d x y)
(if (null? x)
'()
(append (prepend-to-all (car x) y) (map2d (cdr x) y))))
The function map2d recurs on the first list: if it is empty, then the cartesian product will be empty; otherwise, it will collect all the pairs obtained by prepending the first element of x to all the elements of y, with all the pairs obtained by applying itself to the rest of x and all the elements of y.
The function prepend-to-all, will produce all the pairs built from a single value, value and all the elements of the list y. It recurs on the second parameter, the list. When y is empty the result is the empty list of pairs, otherwise, it builds a pair with value and the first element of y, and “conses” it on the result of prepending value to all the remaining elements of y.
When you will master the recursion, you can pass to the next step, by learning tail-recursion, in which the call to the function is not contained in some other “building” form, but is the first one of the recursive call. Such form has the advantage that the compiler can transform it into a (much) more efficient iterative program. Here is an example of this technique applied to your problem:
(define (map2d x y)
(define (prepend-to-all value y pairs)
(if (null? y)
pairs
(prepend-to-all value (cdr y) (cons (cons value (car y)) pairs))))
(define (cross-product x y all-pairs)
(if (null? x)
(reverse all-pairs)
(cross-product (cdr x) y (prepend-to-all (car x) y all-pairs))))
(cross-product x y '()))
The key idea is to define an helper function with a new parameter that “accumulates” the result while it is built. This “accumulator”, which is initialized with () in the call of the helper function, will be returned as result in the terminal case of the recursion. In this case the situation is more complex since there are two functions, but you can study the new version of prepend-to-all to see how this works. Note that, to return all the pairs in the natural order, at the end of the cross-product function the result is reversed. If you do not need this order, you can omit the reverse to make the function more efficient.
Using do isn't very idiomatic. You can try nesting maps instead, this is more in the spirit of Scheme - using built-in higher-order procedures is the way to go!
; this is required to flatten the list
(define (flatmap proc seq)
(fold-right append '() (map proc seq)))
(define (map2d X Y)
(flatmap
(lambda (i)
(map (lambda (j)
(cons i j))
Y))
X))
It's a shame you're not using Racket, this would have been nicer:
(define (map2d X Y)
(for*/list ([i X] [j Y])
(cons i j)))

Returning positions of an element Clojure

I am trying to find a solution to a problem i am facing at the moment, i have tried and tried to get this working but to no avail. I am trying to scan a list containing data and then returning the position of the data if found.
For example if i ran this:
(ind 'p '(l m n o p o p))
Then i would get a return value of....
==> 4 6
As it has found the data in those positions.
I have come close i think to what i want with this solution before, but i cannot get it to run. Can anyone help me figure out whats up with my function?? As far as i can see it should work, but i cant figure out why it isnt?
(defn ind
([choice list emptylist x]
(let [x (count list)])
(if (= (x) 0)
nil)
(if (= (first list) item)
(ind item (rest list) (cons x emptylist) (dec x))
(ind item (rest list) emptylist (dec x))
)
)
)
What i have tried to do is loop through the list until it hits a value and add it to the empty list and once it has looped through return the empty list.
I found that there is a built-in function called keep-indexed in Clojure.
So you can simply do this:
(keep-indexed (fn [idx elm] (if (= 'p elm) idx)) '(l m n o p o p))
; return (4 6)
Here is a solution which I think is a bit simpler:
(defn find-index
"Returns a seq of the indexes of the supplied collection."
[values target]
(let [indexes (range (count values))
val-idx-tuples (map vector values indexes)
found-tuples (filter #(= target (first %)) val-idx-tuples)
found-indexes (vec (map second found-tuples)) ]
found-indexes))
(println (find-index '(l m n o p o p) 'p ))
;=> [4 6]
Though I prefer #chanal's approach, you can write the function you want as follows:
(defn ind [x coll]
(loop [ans [], coll coll, n 0]
(if-let [[y & ys] (seq coll)]
(recur (if (= x y) (conj ans n) ans) ys (inc n))
ans)))
(ind 'p '(l m n o p o p))
;[4 6]
This uses several idioms to make it concise:
if-let comprises if inside let.
The destructuring form [y & ys] comprises calls to first and rest.
Pushing the if form down into the recur avoids repetition.

clojure recursion conj a list

((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5)
For this code, the result is [5 4 3 2 1]
Why isn't is [1,2,3,4,5]?
I see we do conf from result of recursive foo call with a value.
For I thought it should be 1 2 3 4 5?
Need help to understand this.
Thanks.
From the documentation of conj:
clojure.core/conj
([coll x] [coll x & xs])
conj[oin]. Returns a new collection with the xs
'added'. (conj nil item) returns (item). The 'addition' may
happen at different 'places' depending on the concrete type.
The termination condition of your function yields nil, because the test is a when. So the deepest conj call will be:
(conj nil 1)
(1) <-- a list
The next one:
(conj (conj nil 1) 2)
(2 1)
So your result will be in decreasing order because conj appends at the front for lists. If you want it in increasing order, start with an empty vector like this:
((fn foo [x] (if (> x 0) (conj (foo (dec x)) x) [])) 5)
[1 2 3 4 5]
The recursive call expands to
(conj (conj (conj (conj (conj nil 1) 2) 3) 4) 5)
;(5 4 3 2 1)
The implicit nil returned by (foo 0) puns to ().

Clojure Variable assignment

Iam another Clojure-newbi!
How can i assign a vector containing some values to another one?
I want to do:
[a b] >>> [b (+ a b)]
so that afterwards b has the value of (a+b) and a that of b.
It looks like you're trying to do a fibonacci sequence.
user=> (def fibseq (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
#'user/fibseq
user=> (take 10 fibseq)
(1 1 2 3 5 8 13 21 34 55)
What you've got to remember in clojure is immutability, so you don't change a and b to be the new values. So something like:
user=> (defn next-fib [[a b]]
(let [na b
nb (+ a b)]
[na nb]))
user=> (next-fib [1 2])
[2 3]
would produce a function next-fib that would return the next 2 values from your input. During the function, a and b cannot be changed, they are immutable, hence assignment to new values.
Here, i'm using destructuring to immediately break the elements of the input vector into values a and b, which are then used to calculate the next element, and is the same as how the 1 liner at the top of my answer works.
Or if you're doing looping, you can recur with values that get substitute over their previous iteration, this is not changing a and b (during any iteration their values are fixed and still immutable), but redoing the entire stack with new values in their place, subtle difference. See articles on tail recursion.
user=> (loop [a 1 b 1]
(if (< a 20)
(recur b (+ a b))
[a b]))
[21 34]
Here's a simple version of the Fibonacci Sequence using recur, it returns the first n numbers.
(defn fib-recur [n]
(loop [fib [] x n a 0 b 1]
(if (zero? x)
fib
(recur (conj fib b) (dec x) b (+ a b)))))
It works by starting with an empty array of numbers it's building, then recurs by decrementing the counter (x) from n to 0, each iteration changes a and b to be new values as part of the recursion, and it adds the latest number to the array fib returning that when the counter gets to zero.

Clojure, comparing vectors of integers: why "longer" vector is always "greater"? Is there a remedy?

It works like this:
pcc.core=> (compare [4] [2 2])
-1
pcc.core=> (compare [4 0] [2 2])
1
I want a vector comparator with "string semantics":
pcc.core=> (compare-like-strings [4] [2 2])
1 ;; or 2, for that matter
pcc.core=> (compare-like-strings [4 0] [2 2])
1
Is there a lightweigt, nice way to get what I want?
How about:
(defn compare-like-strings [[x & xs] [y & ys]]
(let [c (compare x y)]
(if (and (zero? c) (or xs ys))
(recur xs ys)
c)))
So far it's
(defn cmpv-int
"Compare vectors of integers using 'string semantics'"
[vx vy]
(let [res (first (drop-while zero? (map compare vx vy)))
diffenence (- (count vx) (count vy))]
(if res res diffenence)
)
)
based on Fabian approach.
Why not use subvec?
(defn compare-like-strings
[vec1 vec2]
(let [len (min (count vec1) (count vec2))]
(compare (subvec vec1 0 len)
(subvec vec2 0 len))))
Comparison seems to work if both vectors are the same length, so let me offer this:
(defn compare-vectors
[a b]
(compare
(reduce conj a (map #{} b))
(reduce conj b (map #{} a))))
This is basically padding the inputs with as many nils as necessary before running the comparison. I like how it looks (and it should fit your requirements perfectly) but I'm not particularly sure I'd recommend it to anyone. ;)
(compare-vectors [2 2] [2 2]) ;; => 0
(compare-vectors [4 2] [2 2]) ;; => 1
(compare-vectors [2 2] [4 2]) ;; => -1
(compare-vectors [4] [2 2]) ;; => 1
EDIT: I probably wouldn't - it's terribly inefficient.
As I said in the comments on Diego's answer, I think the least creative approach is best here: just write a loop, enumerate all the cases, and slog through it. As a bonus, this approach also works for arbitrary sequences, possibly lazy, because we don't need to rely on any vector-specific tricks.
(defn lexicographic-compare
([xs ys]
(lexicographic-compare compare xs ys))
([compare xs ys]
(loop [xs (seq xs) ys (seq ys)]
(if xs
(if ys
(let [c (compare (first xs) (first ys))]
(if (not (zero? c))
c
(recur (next xs), (next ys))))
1)
(if ys
-1
0)))))
Maybe like this?
(defn compare-like-strings [a b]
(let [res (first (drop-while zero? (map compare a b)))]
(if (nil? res)
0
res)))
The idea would be to do a pairwise comparison, returning a seq of -1, 0, or 1s and then drop all leading 0s. The first non-zero element is the first element that differs.

Resources