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")
Related
I'm working through the 4clojure problems. I came across this answer for #120, which I would have totally never thought of on my own:
(fn sum-square [coll]
(let [digits (fn [n] (map #(- (int %) 48) (str n)))
square #(* % %)
sum-digits (fn [n] (reduce + (map square (digits n))))]
(count (filter #(< % (sum-digits %)) coll))))
The part I'm really trying to understand is how the digits part of it works.
(fn [n] (map #(- (int %) 48) (str n))
I'm really confused about how
(map #(- (int %) 48) "10")
returns
(1 0)
Can you please explain how this works? I'm confused about why n has to be turned into a string, and why it's then turned back into an integer, and why it has 48 subtracted. I'm sure there must be some really neat trick I'm missing.
Thanks!
"10" in the context of map can be treated as a seq of chars(in this case \1 and \0)
then int converts say \1 to ascii 49, and \0 to ascii 48
then - 48 converts 49 to 1 and 48 to 0
I am currently implementing solution for one of Project Euler problems, namely Sieve of Eratosthenes (https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes), in Clojure. Here's my code:
(defn cross-first-element [coll]
(filter #(not (zero? (rem % (first coll)))) coll))
(println
(last
(map first
(take-while
(fn [[primes sieve]] (not (empty? sieve)))
(iterate
(fn [[primes sieve]] [(conj primes (first sieve)) (cross-first-element sieve)])
[[] (range 2 2000001)])))))
The basic idea is to have two collections - primes already retrieved from the sieve, and the remaining sieve itself. We start with empty primes, and until the sieve is empty, we pick its first element and append it to primes, and then we cross out the multiples of it from the sieve. When it's exhausted, we know we have all prime numbers from below two millions in the primes.
Unfortunately, as good as it works for small upper bound of sieve (say 1000), it causes java.lang.StackOverflowError with a long stacktrace with repeating sequence of:
...
clojure.lang.RT.seq (RT.java:531)
clojure.core$seq__5387.invokeStatic (core.clj:137)
clojure.core$filter$fn__5878.invoke (core.clj:2809)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:51)
...
Where is the conceptual error in my solution? How to fix it?
the reason for this is the following: since the filter function in your cross-first-element is lazy, it doesn't actually filter your collection on every iterate step, rather it 'stacks' filter function calls. This leads to the situation that when you are going to actually need the resulting element, the whole load of test functions would be executed, roughly like this:
(#(not (zero? (rem % (first coll1))))
(#(not (zero? (rem % (first coll2))))
(#(not (zero? (rem % (first coll3))))
;; and 2000000 more calls
leading to stack overflow.
the simplest solution in your case is to make filtering eager. You can do it by simply using filterv instead of filter, or wrap it into (doall (filter ...
But still your solution is really slow. I would rather use loop and native arrays for that.
You have (re-)discovered that having nested lazy sequences can sometimes be problematic. Here is one example of what can go wrong (it is non-intuitive).
If you don't mind using a library, the problem is much simpler with a single lazy wrapper around an imperative loop. That is what lazy-gen and yield give you (a la "generators" in Python):
(ns tst.demo.core
(:use demo.core tupelo.test)
(:require [tupelo.core :as t]))
(defn unprime? [primes-so-far candidate]
(t/has-some? #(zero? (rem candidate %)) primes-so-far))
(defn primes-generator []
(let [primes-so-far (atom [2])]
(t/lazy-gen
(t/yield 2)
(doseq [candidate (drop 3 (range))] ; 3..inf
(when-not (unprime? #primes-so-far candidate)
(t/yield candidate)
(swap! primes-so-far conj candidate))))))
(def primes (primes-generator))
(dotest
(is= (take 33 primes)
[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 ])
; first prime over 10,000
(is= 10007 (first (drop-while #(< % 10000) primes)))
; the 10,000'th prime (https://primes.utm.edu/lists/small/10000.txt)
(is= 104729 (nth primes 9999)) ; about 12 sec to compute
)
We could also use loop/recur to control the loop, but it's easier to read with an atom to hold the state.
Unless you really, really need a lazy & infinite solution, the imperative solution is so much simpler:
(defn primes-upto [limit]
(let [primes-so-far (atom [2])]
(doseq [candidate (t/thru 3 limit)]
(when-not (unprime? #primes-so-far candidate)
(swap! primes-so-far conj candidate)))
#primes-so-far))
(dotest
(is= (primes-upto 100)
[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]) )
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.
Hi i am new to clojure i have written this function and there are few errors in it. i have got one function called 'checkFunction' it basically gets one paramtere and returns either true or false.
(defn getList [number1 number2]
(loop for x from number1 to number2
(recur (inc num) (if (checkFunction? x) (concat p [num]) p))))
i want the function above to take two paramters for example if i say 'get List 15 20' it should call check function with 15 16 17 18 19 20 and if checkFunction returns true it should put that number in the vector and return it or print it. so far i have got onto this but i am struggling a bit.
Any help or right direction would be very thankful.
If I understand your question, you're trying to filter a range of numbers according to some predicate. (For the sake of the example I set your check-function? to return true for odd numbers.)
(defn check-function? [n]
(odd? n))
(defn get-list [n1 n2]
(filter check-function? (range n1 (+ 1 n2))))
> (get-list 15 20)
(15 17 19)
If you are also interested in how the loop-recur works, here's a version more like what you were trying to do originally. But I will say that one of the nicest things about clojure is that you rarely have to do this!
(defn get-list-2 [n1 n2]
(loop [src (range n1 (+ 1 n2)) dest []]
(if (empty? src)
dest
(let [n (first src)
src (rest src)
dest (if (check-function? n) (conj dest n) dest)]
(recur src dest)))))
> (get-list-2 15 20)
[15 17 19]
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]))