Hi I just starting with Clojure and I cannot manage to reverse a vector of integers.
;generate a vector of random integers
(defn generate-rands
[x]
(vector (take x (repeatedly #(rand-int 100))))
)
;vector of integers
(def my-vector (generate-rands 10))
;reverse the vector of integers
(def my-vector-reversed (reverse my-vector))
;main
(defn main-app
[]
(println "My Vector: \t\t\t" my-vector)
(println "My Vector Reversed: \t" my-vector-reversed))
The output is
=> (main-app)
My Vector: [(14 49 29 3 66 7 60 60 34 19)]
My Vector Reversed: [((14 49 29 3 66 7 60 60 34 19))]
nil
#'startingclojure.app/main-app
=> (vector? my-vector-reversed)
false
Can someone kindly explain me why my-vector-reversed is not a vector? And how can I reverse the content of 'my-vector'?
Thanks
Also, it's preferable to use rseq instead of reverse when you work with vector or sorted-map. It has constant time, because they are indexed and can be efficiently walked in either direction.
from reverse's doc:
Returns a seq of the items in coll in reverse order. Not lazy.
reverse turns anything into a seq, meaning, a list. in order to get back a vector you should turn it into a vector:
(into [] (reverse [1 2 3 4])) ; =>[4 3 2 1]
In your case, look at your "my-vector": [(14 49 29 3 66 7 60 60 34 19)] - its a vector containing a single element - a seq. so reversing it wouldnt change anything. you should use the same technique to turn your seq into a vector:
(defn generate-rands
[x]
(into [] (take x (repeatedly #(rand-int 100)))))
reverse function returns always a seq, not a vector. You can again convert the result into a vector with something like: (apply vector (reverse [1 2 3]))
Related
In Clojure, is there some general purpose function (similar to higher order functions map, filter, reduce, where one starts, say, with a vector with one element, applies function f to the element, add the element to the vector, and apply the function to the new element, and continue as such until some condition is met.
Example: I have vector [1], function double, and the function I am after, call it f, and, something like:
(take-while some-pred (f double 1))
which produces: [1 2 4 8 16 32 . . .]
i guess you're talking about iterate:
(take-while #(< % 1000) (iterate #(* 2 %) 1))
;;=> (1 2 4 8 16 32 64 128 256 512)
if you need vector, you can also use transducer:
(into [] (take-while #(< % 1000)) (iterate #(* 2 %) 1))
;; [1 2 4 8 16 32 64 128 256 512]
I am writing an assignment in Clojure which should display a list of prime numbers between 2 inputs: from and to. I managed to do that with this function:
(defn print-top-primes [ from to ]
(doseq
[ i (prime-seq from to) ] ;;prime-seq returns a range of numbers
(println i)
)
)
Which gives the output:
(print-top-primes 50 100)
53
59
61
67
71
73
79
83
89
97
=> nil
However, the assignment specifies that i need the numbers to be printed like this:
(print-top-primes 50 100)
97
89
83
79
73
71
67
61
59
53
Total=732
=> nil
I cannot manage to use doseq to print the numbers from top to bottom.
I also need to add the total of all the primes but I am not sure how this would work as the doseq function does not hold each value of i.
Perhaps I am using the wrong function, however the example in the assignment outputs a:
=> nil
...suggesting that it is a doseq function?
Any help would be really appreciated.
Thanks
Thank you jas,
Looking at your answer helped me come up with an even easier way i think, this is the way i have been taught so i should probably implement it like this:
(defn print-top-primes [ from to ]
(doseq [i (reverse (prime-seq from to))]
(println i))
(printf "Total = %d\n" (reduce + (prime-seq from to)))
)
Giving the correct output!
I am wondering now is there a way to just output the first 10 largest primes, given there was a large number of primes?
One straightforward way would be like:
(defn print-top-primes [from to]
(let [top-primes (reverse (prime-seq from to))
total (apply + top-primes)]
(doseq [i top-primes]
(println i))
(printf "Total = %d\n" total)))
=> (print-top-primes 50 100)
97
89
83
79
73
71
67
61
59
53
Total = 732
nil
If you really want to avoid making three passes through the list of primes (one for reverse, one for apply +, and one for printing), you can try something like:
(defn print-top-primes [from to]
(loop [primes (prime-seq from to)
total 0]
(let [p (last primes)]
(if p
(do (println p)
(recur (butlast primes) (+ total p)))
(printf "Total = %d\n" total)))))
But you would want to verify that it's enough of a performance gain to justify the increased complexity.
Maybe your course is going to mention it next, but in any case I would not use doseq here but loop and recur:
(loop [elements (reverse (range 10))
sum 0]
(if (empty? elements)
sum
(let [[head & tail] elements]
(println head)
(recur tail (+ sum head)))))
Prints:
9
8
7
6
5
4
3
2
1
0
Returns:
45
Instead of returning the value, you can easily write the required Total line and return nil.
The loop macro allows to define accumulators (like sum). I use the [head & tail] notation to destructure the sequence of elements in two parts. The reversed sequence is traversed only once.
[returns nil] ...suggesting that it is a doseq function?
First, doseq is a macro, and second, there are so many ways to return nil that you cannot guess if the example you have is using doseq or not. Whether you have to use doseq or not should be told by the assignment, maybe you are under no obligation to use it.
I´m new to clojure and am trying to break through some of the walls I keep running into. The code in question is the function v3 which should accept 4 arguments:
a min and a max integer, mi and ma, to use with the
random-numbers function to find numbers within a certain range,
another integer,cnt, to signify how many numbers I want in my
final list, and
tones, which is a list of integers that the randomized numbers have
to match once I've calculated modulo 12 of said numbers.
The function should run until o is a list of length cnt containing random numbers that are also in the tones list.
My document compiles just fine but when I want to run the function itself in a repl, for example using something like (v3 58 52 15 '(0 2 4 5 7 9)) I get the following error:
ClassCastException clojure.langLazySeq cannot be cast to java.lang.Number clojure.langNumbers.reminder (Numbers.java:173)
Here's my code
(defn random-numbers [start end n]
(repeatedly n #(+ (rand-int (- end start)) start)))
(defn m12 [input]
(mod input 12))
(defn in? [coll elm]
(some #(= elm %) coll))
(defn v3 [ma mi cnt tones]
(let [o '()]
(loop []
(when(< (count o) cnt)
(let [a (m12 (random-numbers mi ma 1))]
(if (in? tones a)
(conj o a)))))
(println o)))
First of all, it is more idiomatic Clojure to type the parentheses on the same line, and not in the "Java"-way.
When I debug your code I see it fails at the call to m12: random-numbers returns a sequence and the call to mod in m12 expects a number.
You can fix this issue by for example taking the first element from the sequence returned by random-numbers:
(defn v3
[ma mi cnt tones]
(let [o '()]
(loop []
(when (< (count o) cnt)
(let [a (m12 (first (random-numbers mi ma 1)))]
(if (in? tones a)
(conj o a)))))
(println o)))
/edit
I am not sure what your code is supposed to be doing, but this did not stop me to make some more changes. If you use a loop, you usually also see a recur to "recur" back to the loop target. Otherwise it does not do much. I added the following things:
a recur to the loop.
The let statement added to the loop vector (starting value).
println statements in the false clause of the if-statement.
Removed the first if-statement that checked the count
Changed list to vector. You would use a list over a vector when you create code structures structure (for example while writing macros).
See:
(defn v3
[ma mi cnt tones]
(loop [o []]
(if (< (count o) cnt)
(let [a (m12 (first (random-numbers mi ma 1)))]
(if (in? tones a)
(recur (conj o a))
(println "a not in tones, o:" o)))
(println "already " cnt "tones generated"))))
If you run (v3 58 52 4 [0 2 4 5 7 9]) (note I changed your 15 for cnt to 4 and changed the list to a vector) a few times you get for example the following output:
a not in tones, o: [4 4]
a not in tones, o: [9 5 5]
a not in tones, o: []
already 4 tones generated
a not in tones, o: [7]
Hope this helps.
I think I see what you are trying to do.
This is an exercise in automatic composition. Your v3 function is intended to generate a sequence of tones
in a range given by min and max.
with tone class drawn from a given set of tone classes (tones)
The m12 function returns the tone class of a tone, so let's call it that:
(defn tone-class [tone]
(mod tone 12))
While we're about it, I think your random-number function is easier to read if we add the numbers the other way round:
(defn random-number [start end]
(+ start (rand-int (- end start))))
Notice that the possible values include start but not end, just as the standard range does.
Apart from your various offences against clojure semantics, as described by #Erwin, there is a problem with the algorithm underlying v3. Were we to repair it (we will), it would generate a sequence of tone classes, not tones. Interpreted as tones, these do not move beyond the base octave, however wide the specified tone range.
A repaired v3
(defn v3 [mi ma cnt tones]
(let [tone-set (set tones)]
(loop [o '()]
(if (< (count o) cnt)
(let [a (tone-class (random-number mi ma))]
(recur (if (tone-set a) (conj o a) o)))
o))))
For a start, I've switched the order of mi and ma to conform with
range and the like.
We turn tones into a set, which therefore works as a
membership function.
Then we loop until the resulting sequence, o, is big enough.
We return the result rather than print it.
Within the loop, we recur on the same o if the candidate a doesn't fit, but on (conj o a) if it does. Let's try it!
(v3 52 58 15 '(0 2 4 5 7 9))
;(4 5 9 7 7 5 7 7 9 7 5 7 4 9 7)
Notice that neither 0 nor 2 appears, though they are in tones. That's because the tone range 52 to 58 maps into tone class range 4 to 10.
Now let's accumulate tones instead of tone classes. We need to move conversion inside the test, replacing ...
(let [a (tone-class (random-number mi ma))]
(recur (if (tone-set a) (conj o a) o)))
... with ...
(let [a (random-number mi ma)]
(recur (if (tone-set (tone-class a)) (conj o a) o)))
This gives us, for example,
(v3 52 58 15 '(0 2 4 5 7 9))
;(53 52 52 52 55 55 55 53 52 55 53 57 52 53 57)
An idiomatic v3
An idiomatic version would use the sequence library:
(defn v3 [mi ma cnt tones]
(let [tone-set (set tones)
numbers (repeatedly #(random-number mi ma))
in-tones (filter (comp tone-set tone-class) numbers)]
(take cnt in-tones)))
This generates the sequence front first. Though you can't tell by looking at the outcome, the repaired version above generates it back to front.
An alternative idiomatic v3
Using the ->> threading macro to capture the cascade of function calls:
(defn v3 [mi ma cnt tones]
(->> (repeatedly #(random-number mi ma))
(filter (comp (set tones) tone-class))
(take cnt)))
I want to create a sequence, however to create its every element I need access to the two previous elements. What is the generic way to do such things in clojure ?
So two slightly diff cases -
a) seq is (a b c) when I am processing c I want to have access to a and b ....
b) and having such ability to create the sequence itself by always being able to access th two previous elements.
Thanks,
Murtaza
partition gives you this nearly for free:
(partition-all 3 1 (range 100))
((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) ... )
then you can map your function over the sequence of partitions:
(map my-func (partition-all 3 1 (range 100)))
you just need to make your function aware of the fact that the last segment may have less than three elements if your seq is not a multiple of three. if you want to just drop any extras use partition instead of partition-all
Well, here is one way to do it. Assume you have a function g that takes the last two values as input and produces the next value.
(defn f [g x0 x1]
(let [s (g x0 x1)]
[s (fn [] (f g x1 s))]))
Given g and two consecutive values in the sequence, f returns a pair consisting of the next value and a function that will return the value after that. You can use f as follows to generate an infinite sequence of such pairs:
(iterate (fn [[v h]] (h)) (f g x0 x1))
To extract just the sequence values, do this:
(map first (iterate (fn [[v h]] (h)) (f g x0 x1)))
For example:
user=> (take 10 (map first (iterate (fn [[v h]] (h)) (f + 0 1))))
(1 2 3 5 8 13 21 34 55 89)
You can iterate using a vector of two elements and then take the first of the resulting sequence.
For example, to create the fibonacci series:
user=> (def fib (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
#'user/fib
user=> (take 10 fib)
(1 1 2 3 5 8 13 21 34 55)
I have the following code to try to remove non-numbers froma string:
(apply str
(flatten
(map
(fn[x]
(if (number? x) x))
"ij443kj"
)
)
)
But it always returns an empty string instead of "443". Does anyone know what I am doing wrong here and how I can get the desired result?
number? doesn't work that way. It checks the type. If you pass it a character, you'll get back false every time, no matter what the character is.
I'd probably use a regular expression for this, but if you want to keep the same idea of the program, you could do something like
(apply str (filter #(#{\0,\1,\2,\3,\4,\5,\6,\7,\8,\9} %) "abc123def"))
or even better
(apply str (filter #(Character/isDigit %) myString))
There is an even simpler way, use a regular expression:
(.replaceAll "ij443kj" "[^0-9]" "")
get the char's int values...
(map int (apply vector "0123456789"))
-> (48 49 50 51 52 53 54 55 56 57)
then fix it:
(defn my-int
[char]
(- (int char) 48))
now let's try this again, shall we?
(map my-int (apply vector "0123456789"))
-> (0 1 2 3 4 5 6 7 8 9)
and just to get a warm-and-fuzzy that they're integers...
(map #(* % 10) (map my-int (apply vector "0123456789")))
-> (0 10 20 30 40 50 60 70 80 90)
(reduce + (map my-int (apply vector "0123456789")))
-> 45
in case you will handling decimal
#(re-seq #"[0-9\.]+" "ij443kj")