I've been playing with Clojure lately and I can't get this algorithm to work:
(defn reverse-number [number reversed]
(if (= number 0)
reversed
(reverse-number (/ number 10)
(+ (rem number 10) (* reversed 10)))))
This is how I should call it (reverse-number 123 0) and the result I expect is: 321.
When I run this, the REPL just hangs.
Can someone explain me, please, what is happening, what I did wrong and how to get this function working?
Note: I know I can use string functions to reverse a number. Actually, I already did this, but I'm not interested in this solution. All I want is to make the leap to functional languages. That's why I try multiple approaches.
Using string functions:
(defn reverse-number [n]
(Integer. (clojure.string/reverse (str n))))
(reverse-number 123) ; --> 321
I don't like this version since it feels like cheating by using the string version of reverse.
You should use quot instead of /.
/ in clojure will give you a fraction so number will never be 0 (unless it's 0 from the beginning), while quot will give you "integer division".
Examples:
user=> (/ 123 10)
123/10
user=> (quot 123 10)
12
Related
I am working through the Armstrong Numbers exercise on Exercism's Clojure track. An armstrong number is a number equal to the sum of its digits raised to the power of the number of digits. 153 is an Armstrong number, because: 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153. 154 is not an Armstrong number, because: 154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190.
The test file for this exercise will call the armstrong? function, pass in a number, and expects true if the number is an Armstrong number. I have already solved the problem with this code:
(ns armstrong-numbers)
(defn pow [a b]
(reduce * 1 (repeat b a)))
(defn armstrong? [num]
(->> num
(iterate #(quot % 10))
(take-while pos?)
(map #(mod % 10))
((fn [sq]
(map #(pow % (count sq))
sq)))
(apply +)
(= num)))
but now I am trying to refactor the code. This is what I would like the code to look like:
(ns armstrong-numbers
(:require [swiss.arrows :refer :all]))
(defn pow [a b]
(reduce * 1 (repeat b a)))
(defn armstrong? [num]
(-<>> num
(iterate #(quot % 10))
(take-while pos?)
(map #(mod % 10))
(map #(pow % (count <>))
<>)
(apply +)
(= num)))
A link to the package required above: https://github.com/rplevy/swiss-arrows.
In the first code section, I create an implicit function within the thread-last macro because the sequence returned from the map form is needed in two different places in the second map form. That implicit function works just fine, but I just wanted to make the code sleeker. But when I test the second code block, I get the following error: java.lang.RuntimeException: Unable to resolve symbol: <> in this context.
I get this error whether I use #(), partial , or fn inside the second map form. I have figured out that because all of the preceding are macros (or a special form in fns case), they cannot resolve <> because it's only meaningful to the -<>> macro, which is called at a later point in macroexpansion. But why do #(), partial, and fn attempt to resolve that character at all? As far as I can see, they have no reason to know what the symbol is, or what it's purpose is. All they need to do is return that symbol rearranged into the proper s-expressions. So why does clojure attempt to resolve this (<>) symbol?
The <> symbol is only valid in the topmost level of a clause (plus literals for set, map, vector directly therein). -<> and -<>> do not establish bindings (as in let) for <>, but do code insertion at macro expansion time.
This code insertion is done only at toplevel, because making it work deeper is not only much more complex (you need a so-called code walker), but also raises interesting questions regarding the nesting of arrow forms. This complexity is likely not worth it, for such a simple effect.
If you want a real binding, you can use as-> (from clojure.core).
The documentation for -<>> is quite clear that it doesn't behave the way you wish it did:
"the 'diamond spear': top-level insertion of x in place of single
positional '<>' symbol within the threaded form if present, otherwise
mostly behave as the thread-last macro. Also works with hash literals
and vectors."
It performs replacement:
Of a single symbol
At the top level of the threaded form
Your example wishing to use it for multiple symbols, nested within subforms, will thus not work.
You have made a mistake leaving off the <> symbol in most of your forms in the failing case. Here is a working version (using the similar it-> macro in place of the Swiss Arrows). I also cleaned up the pow a bit.
(defn pow-int [a b] (Math/round (Math/pow a b)))
(defn armstrong? [num]
(it-> num
(iterate #(quot % 10) it)
(take-while pos? it)
(map #(mod % 10) it)
(map #(pow-int % (count it)) it)
(apply + it)
(= it num)))
(armstrong? 153) => true
(armstrong? 154) => false
You can find the docs on it-> here.
If you leave off the (collection) arg to a function like map, it returns a transducer; from the docs:
(map f)(map f coll)(map f c1 c2)(map f c1 c2 c3)(map f c1 c2 c3 & colls)
Returns a lazy sequence consisting of the result of applying f to
the set of first items of each coll, followed by applying f to the
set of second items in each coll, until any one of the colls is
exhausted. Any remaining items in other colls are ignored. Function
f should accept number-of-colls arguments. Returns a transducer when
no collection is provided.
And, always refer to the Clojure CheatSheet!
I am hoping to generate all the multiples of two less than 10 using the following code
(filter #(< % 10) (iterate (partial + 2) 2))
Expected output:
(2 4 6 8)
However, for some reason repl just doesn't give any output?
But, the below code works just fine...
(filter #(< % 10) '(2 4 6 8 10 12 14 16))
I understand one is lazy sequence and one is a regular sequence. That's the reason. But how can I overcome this issue if I wish to filter all the number less than 10 from a lazy sequence...?
(iterate (partial + 2) 2)
is an infinite sequence. filter has no way to know that the number of items for which the predicate is true is finite, so it will keep going forever when you're realizing the sequence (see Mark's answer).
What you want is:
(take-while #(< % 10) (iterate (partial + 2) 2))
I think I should note that Diego Basch's answer is not fully correct in its argumentation:
filter has no way to know that the number of items for which the predicate is true is finite, so it will keep going forever
Why should filter know something about that? Actually filter works fine in this case. One can apply filter on a lazy sequence and get another lazy sequence that represent potentially infinite sequence of filtered numbers:
user> (def my-seq (iterate (partial + 2) 2)) ; REPL won't be able to print this
;; => #'user/my-seq
user> (def filtered (filter #(< % 10) my-seq)) ; filter it without problems
;; => #'user/filtered
user>
Crucial detail here is that one should never try to realize (by printing in OP's case) lazy sequence when actual sequence is not finite for sure (so that Clojure knows that).
Of course, this example is only for demonstration purposes, you should use take-while here, not filter.
I am trying to solving pythonchallenge problem using Clojure:
(java.lang.Math/pow 2 38)
I got
2.74877906944E11
However, I need to turn off this scientific notation. I searched clojure docs, still don't know what to do. Is there a general way to toggle on/off scientific notation in Clojure?
Thanks.
You can use format to control how results are printed.
user> (format "%.0f" (Math/pow 2 38))
"274877906944"
Also, if there is no danger of losing wanted data, you can cast to an exact type:
user> 274877906944.0
2.74877906944E11
user> (long 274877906944.0)
274877906944
There are BigInts for larger inputs
user> (bigint 27487790694400000000.0)
27487790694400000000N
Warning
You can often lose precision by using java.lang.Math/pow to compute an integer power of an integer.
For example
(bigint (java.lang.Math/pow 3 38))
; 1350851717672992000N
whereas
(int-pow 3 38)
; 1350851717672992089
It works with powers of 2 because - if you look at them in binary - there is a single 1 bit with all the rest 0s. So the hex exponent just keeps going up while the solitary 1 bit floats around in the significand. No precision is lost.
By the way, int-pow above is just repeated multiplication:
(defn int-pow [b ^long ex]
(loop [acc 1, ex ex]
(case ex
0 acc
(recur (* acc b) (dec ex)))))
This is more a comment than a solution, but doesn't fit as such.
How do I write modulus syntax in programming language clojure?
For example the symbols money %= money_value.
There are two functions in Clojure you might want to try: mod and rem. They work the same for positive numbers, but differently for negative numbers. Here's an example from the docs:
(mod -10 3) ; => 2
(rem -10 3) ; => -1
Update:
If you really want to convert your code to Clojure, you need to realize that an idiomatic Clojure solution probably won't look anything like your JavaScript solution. Here's a nice solution that I think does roughly what you want:
(defn change [amount]
(zipmap [:quarters :dimes :nickels :pennies]
(reduce (fn [acc x]
(let [amt (peek acc)]
(conj (pop acc)
(quot amt x)
(rem amt x))))
[amount] [25 10 5])))
(change 142)
; => {:pennies 2, :nickels 1, :dimes 1, :quarters 5}
You can look up any of the functions you don't recognize on ClojureDocs. If you just don't understand the style, then you probably need some more experience programming with higher-order functions. I think 4Clojure is a good place to start.
(The following was originally a homework assignment, but I'm trying it in a new language.)
In a short Clojure program, I attempt to generate a lazy sequence of inputs (from the command line) and from them calculate three character values. I would assume that, possibly depending on how Clojure chose to evaluate my let bindings, this ought to produce a prompt series like the following:
$ clj lazy-prompts.clj
Enter value #1: 32
Enter value #3: 162
Enter value #2: 12
Enter value #4: 118
a A 5
Instead, the program begins and hangs infinitely with no prompts. I tried eagerly evaluating the for expression by wrapping it in dorun, but that did not change the outcome.
Why does the following program produce no input prompts?
(use '[clojure.java.io :only (reader)])
(def of-input
(for [value-number [1 2 3 4]]
(dorun
(print (str "Enter encrypted value #" value-number))
(read-line)
)))
(let [value-1 (nth of-input 1)
value-2 (nth of-input 2)
value-3 (nth of-input 3)
value-4 (nth of-input 4)]
(let [a (/ (+ value-1 value-3) 2)
b (/ (+ value-2 value-4) 2)
c (- value-4 b)]
(println (char a) (char b) (char c))))
First, you should replace dorun with do. The former expects a seq as its first or second argument and forces it.
After that change, the code more or less runs correctly. What you observe as "hanging" is actually waiting for your input. One of the problems is, that you don't see the prompts (yet). They actually show, but only after you enter four values. How do you fix that? I don't know, I always thought that having side effects in a lazy sequence is a bad idea, so I never do that.
The other problem is, that read-line returns strings and you're using them as numbers. You'll have to convert them first.
P.S. "for" in clojure is not a for-loop, it is a list comprehension.
print does not flush the output, so you don't see the prompts immediately. Either use println or call flush explicitly, like so:
(def of-input
(for [value-number [1 2 3 4]]
(dorun
(print (str "Enter encrypted value #" value-number))
(flush)
(read-line)
)))