How can I make in Clojure functions vector-fold and vector-map from scheme?
To map over a vector and get a vector back you can use mapv.
To fold over a vector you can use regular reduce since vectors are seqable.
To get an index in the function you're iterating with, there's map-indexed or you can use (range):
(mapv (fn [i e] [i e]) [1 2 3] (range))
=> [[1 0] [2 1] [3 2]]
Related
I'm trying to solve the square sum problem, more specifically creating a function that can help with the relations.
"the function should, given a set A of integers, produce a relation that includes tuple [a b],
iff a and b are in A and their sum is a square number"
To my aid, I got a help function square?, that tests whether a passed integer is a squared number.
(defn square?
[n]
(= n (sqr (isqrt n)))
)
I took a shot in dark with this, but honestly I'm lost.
(defn sqr-sum-rel
[A]
(reduce (fn [a b] (
if (square? (a + b))
[a b]
)) A )
)
Testing the function should return something like this:
(test? "test" (sqr-sum-rel (set (range 1 11))) #{[5 4] [2 2] [8 8] [4 5] [7 9] [1 3] [3 6] [6 10] [2 7] [1 8] [8 1] [7 2] [10 6] [6 3] [3 1] [9 7]})
I'm really new to Clojure and even functional programming in general, so any pointers in the right direction are appreciated.
To solve this problem, you can first generate all possible pairs of numbers from the set using for and then filter those pair. Assuming square? is properly implemented, we write a helper function that will be the first argument that we pass to filter:
(defn sum-is-square? [coll]
(square? (apply + coll)))
It takes a collection of numbers as argument and test if their sum is square?. Then we can write the complete function like
(defn sqr-sum-rel [A]
(set (filter sum-is-square? (for [a A
b A]
[a b]))))
that takes as argument a set A and first produces all pairs that can be formed by elements from this set, and then only keep those pairs for which sum-is-square? evaluates to true.
We can test it by passing in a set of numbers:
(sqr-sum-rel (set (range 1 11)))
;; => #{[8 8] [2 2] [7 2] [5 4] [6 3] [1 3] [1 8] [8 1] [7 9] [2 7] [3 6] [10 6] [4 5] [9 7] [3 1] [6 10]}
Added: A briefer implementation as suggested by the original poster uses the :when option of for:
(defn sqr-sum-rel [A]
(set (for [a A
b A :when (square? (+ a b))]
[a b]))))
i would also guess that the the number in set can't form the pair with itself, and also there is no need to compare pair members in reverse order, since we already know they form the relation needed. I would update it like this:
(defn sq-rel [a-set]
(seq (for [[x & t] (take-while seq (iterate rest a-set))
y t
:when (square? (+ x y))]
[x y])))
this one is more or less like an imperative
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++)
if (isSquare(a[i] + a[j])) {
res.push([a[i], a[j]])
}
}
}
in repl:
user> (sq-rel #{1 2 3 4 5 6})
;;=> ([1 3] [4 5] [6 3])
I have a homework problem that requires me to print (in a vector) a specified nth index from a vector of vectors. For examples, if I enter [1 2 3 4] [5 6 7 8] [9 10 11 12] and enter my function specifying the nth index 1, my result has to be [2 6 10].
Very confused, not good at Clojure, just a Java/Python person.
I've already tried using a function that accepts vector and a variable to serve as the nth. But it returns the whole vectors AND the value entered for x.
(defn column [vector x]
(cond
(empty? vector)
nil
:else
(column (nth vector x))))
If I enter:
user ==> column vector 0
Result is this:
[1 2 3 4] [5 6 7 8] [9 10 11 12]
0
Instead of:
[1 5 9]
An idiomatic clojure way of solving this would be with the use of map
(def v [[1 2 3 4] [5 6 7 8] [9 10 11 12]])
(defn column [coll pos]
(map #(nth % pos) coll))
the nth function gives the nth element in the vector. The map function will iterate over each of the inner vectors and call nth on it with the given column value.
The result will be a sequence of value from the required column.
I was surprised to discover that clojure vectors implement the Associative interface.
(associative? [1 2 3]) ; => true
I assume this interface provides optimized indexing by keys. Following this assumption, the interface seems appropriate for map data structures, but odd for vectors, which don't follow a key-value heuristic in my mind.
Is my mental model for Associative or vector's implementation incorrect? What purpose does this design choice serve?
It may not seem intuitive initially, but vectors are keyed by their indices, which allow them to make use of all the standard associative functions. This makes it very easy to do simple operations on them:
(def v [1 2 3])
(assoc v 1 4)
[1 4 3]
(update v 1 inc)
[1 3 3]
(get v 1) ; The same as (v 1)
2
Or, if you have a 2D vector:
(def v [[1 2 3]
[4 5 6]
[7 8 9]])
(assoc-in v [2 1] 0)
[[1 2 3]
[4 5 6]
[7 0 9]]
Without this design choice, an entire separate set of functions would need to be created and used specifically for vectors. Having a standardized interface allows you to write functions that don't care about specifically what structure they're working on.
Think about it this way: Say you wanted to write a function that "replaces" an element of a vector. Would its signature be any different from the existing assoc function; besides specifically expecting a vector?
Clojure vectors associate an index with a value. This means you can do things like this:
(assoc [0 1] 0 2)
(reduce-kv (fn [m idx v]
(assoc m idx v)) {} [0 1 2])
And both are efficient.
Let's say i have the following vector
(def x [[1 2 3] [4 5 6] [7 8]])
and I want to append the number 9 to the last vector (I don't know the index of the vector)
(conj (vec (butlast x)) (conj (last x) 9))
#=> [[1 2 3] [4 5 6] [7 8 9]]
Is there a better/clearer way to do this?
Use the efficient tail access functions
(conj (pop x) (conj (peek x) 9))
But you could also
(update-in x [(dec (count x))] conj 9)
I have two sequences for comparison and I need to keep comparison results in a map, with data in the first sequence serving as keys and second as vals. Here comes sample code that works
(def myAtom (atom {}))
(map #(if (== %1 %2) (swap! myAtom assoc %1 %2 ))
[1 2 3] [4 5 3])
(prn #myAtom) ; ==> {3 3}
However after putting "same" thing above into one let bindings, it doesn't work anymore
(let [ myAtom (atom {})]
(map #(if (== %1 %2) (swap! myAtom assoc %1 %2 ))
[1 2 3] [4 5 3])
(prn #myAtom)) ;;==> {} empty???
So the question is, what happens to myAtom inside let binding? How come is it missing?
map is to generate lazy sequence out of a sequence whereas what you need is to do certain operation (i.e swap) for each item in a sequence, hence you need to use doseq
EDIT: (updated as par #mobyte suggestion)
(let [myAtom (atom {})
a [1 2 3]
b [4 5 3]]
(doseq [[x y] (map vector a b)]
(if (== x y) (swap! myAtom assoc x y )))
(prn #myAtom))
Your first example works because you executed each expression in REPL which made the map operation to execute its lazy operations.
I have seen many people try to use map to do certain operations like this, map should only be used for one purpose i.e mapping a sequence to another sequence without any side-effect operations.
As Ankur mentioned it's better to use doseq for imperative operations:
(let [myAtom (atom {})]
(doseq [[a b] (map vector
[1 2 3]
[4 5 3])]
(when (== a b) (swap! myAtom assoc a b )))
(prn #myAtom))
But you can force evaluation of the map result by using dorun in your original version:
(let [ myAtom (atom {})]
(dorun (map #(when (== %1 %2) (swap! myAtom assoc %1 %2 ))
[1 2 3] [4 5 3]))
(prn #myAtom))
P.S. Ankur's version is not equivalent to original one
doseq:
(doseq [a [1 2 3]
b [4 5 3]]
(println [a b]))
=> [1 4]
[1 5]
[1 3]
[2 4]
[2 5]
[2 3]
[3 4]
[3 5]
[3 3]
map:
(dorun (map #(println [%1 %2])
[1 2 3]
[4 5 3]))
=> [1 4]
[2 5]
[3 3]