NumberFormatException occurs while solving 4clojure puzzle - clojure

I am trying to solve the 4clojure problem "Product Digits". The problem description is -
Write a function which multiplies two numbers and returns the result
as a sequence of its digits.
(= (__ 1 1) [1])
(= (__ 99 9) [8 9 1])
(= (__ 999 99) [9 8 9 0 1])
Here is my solution -
#(map (fn [x] (Integer/valueOf x)) (clojure.string/split (str (* %1 %2)) #""))
This works perfectly fine in my local. I tested in both lein repl & emacs cider.
But the same solution throws an error in 4clojure site
java.lang.NumberFormatException: For input string: ""
Do they use a different repl? Or am I doing something wrong?

that is probably connected with the older version of clojure in 4clojure.
So clojure.string/split leaves an empty string as an artefact.
There are some differences in that version of clojure with current ones (you would probably run into them in later tasks)
However, you don't even need split here, because mapping internally calls seq on string, making a char sequence of it. So you just need to do this:
#(map (fn [x] (Integer/valueOf (str x))) (str (* %1 %2)))

Related

Good way in clojure to map function on multiple items of coll or seqence

I'm currently learning Clojure, and I'm trying to learn how to do things the best way. Today I'm looking at the basic concept of doing things on a sequence, I know the basics of map, filter and reduce. Now I want to try to do a thing to pairs of elements in a sequence, and I found two ways of doing it. The function I apply is println. The output is simply 12 34 56 7
(def xs [1 2 3 4 5 6 7])
(defn work_on_pairs [xs]
(loop [data xs]
(if (empty? data)
data
(do
(println (str (first data) (second data)))
(recur (drop 2 data))))))
(work_on_pairs xs)
I mean, I could do like this
(map println (zipmap (take-nth 2 xs) (take-nth 2 (drop 1 xs))))
;; prints [1 2] [3 4] [5 6], and we loose the last element because zip.
But it is not really nice.. My background is in Python, where I could just say zip(xs[::2], xs[1::2]) But I guess this is not the Clojure way to do it.
So I'm looking for suggestions on how to do this same thing, in the best Clojure way.
I realize I'm so new to Clojure I don't even know what this kind of operation is called.
Thanks for any input
This can be done with partition-all:
(def xs [1 2 3 4 5 6 7])
(->> xs
(partition-all 2) ; Gives ((1 2) (3 4) (5 6) (7))
(map (partial apply str)) ; or use (map #(apply str %))
(apply println))
12 34 56 7
The map line is just to join the pairs so the "()" don't end up in the output.
If you want each pair printed on its own line, change (apply println) to (run! println). Your expected output seems to disagree with your code, so that's unclear.
If you want to dip into transducers, you can do something similar to the threading (->>) form of the accepted answer, but in a single pass over the data.
Assuming
(def xs [1 2 3 4 5 6 7])
has been evaluated already,
(transduce
(comp
(partition-all 2)
(map #(apply str %)))
conj
[]
xs)
should give you the same output if you wrap it in
(apply println ...)
We supply conj (reducing fn) and [] (initial data structure) to specify how the reduce process inside transduce should build up the result.
I wouldn't use a transducer for a list that small, or a process that simple, but it's good to know what's possible!

How do I evaluate the first step of a Clojure form?

If I have the following string containing a valid Clojure/ClojureScript form:
"(+ 1 (+ 2 (/ 6 3)))"
How would I evaluate the first "step" of this form? In other words, how would I turn the above form into this:
"(+ 1 (+ 2 2))"
and then turn that corresponding form into this:
"(+ 1 4)"
You use recursion.
You need to have a function that evaluates the numbers to themselves but if it's not a number you need to apply the operation on the evaluation of the arguments.. Thus
(evaluate '(+ 1 (+ 2 (/ 6 3))))
This should be treated as:
(+ (evaluate '1) (evaluate '(+ 2 (/ 6 3))))
When it starts doing your first step several steps are waiting for the results to be done as well.
Note I'm using list structure and not strings. With strings you would need to use some function to get it parsed.
The other answers are great if you want to execute code in steps, but I want to mention that this evaluation can also be visualized using a debugger. See below Cider's debugger in action:
By using cider-debug-defun-at-point we add a breakpoint on evaluate. Then when the evaluate definition is evaluated the breakpoint is hit, and we step through the code by pressing next repeatedly.
A debugger is very handy when you want to evaluate "steps" of forms.
Below is a very basic implementation that does what you're looking for. It would be more common to eval the entire form, but since you're wanting to just simplify the innermost expressions, this does it:
(defn leaf?
[x]
(and (list? x)
(symbol? (first x))
(not-any? list? (rest x))))
(defn eval-one
[expr]
(cond
(leaf? expr) (apply (-> (first expr) resolve var-get)
(rest expr))
(list? expr) (apply list (map eval-one expr))
:default expr
))
(read-string "(+ 1 (+ 2 (/ 6 3)))")
=> (+ 1 (+ 2 (/ 6 3)))
(eval-one *1)
=> (+ 1 (+ 2 2))
(eval-one *1)
=> (+ 1 4)
(eval-one *1)
=> 5
This is naive and for illustrative purposes only, so please don't be under the impression that a real eval would work this way.
We define a leaf as a list whose first element is a symbol and which does not contain any other lists which could be evaluated. We then process the form, evaluating leaf expressions, recursively evaluating non-leaf expressions which are lists, and for anything else, we just insert it into the resulting expression. The result is that all innermost expressions which can be evaluated, according to our definition, are evaluated.
To add to the other great answers, here is a simple function that should return the first form to evaluate in a given string:
(defn first-eval [form-str]
(let [form (read-string form-str)
tree-s (tree-seq sequential? identity form)]
(first (filter #(= % (flatten %)) tree-s))))
Usage:
(first-eval "(+ 1 (+ 2 (/ 6 3)))") ;; returns (/ 6 3)
tree-seq is fairly limited in it's ability to evalute ALL form, but it's a start.

How to use reduce and into properly

I'm learning Clojure and actually I'm doing some exercises to practice but I'm stuck in a problem:
I need to make a sum-consecutives function which sums consecutive elements in a array, resulting in a new one, as example:
[1,4,4,4,0,4,3,3,1] ; should return [1,12,0,4,6,1]
I made this function which should work just fine:
(defn sum-consecutives [a]
(reduce #(into %1 (apply + %2)) [] (partition-by identity a)))
But it throws an error:
IllegalArgumentException Don't know how to create ISeq from:
java.lang.Long clojure.lang.RT.seqFrom (RT.java:542)
Can anyone help me see what is wrong with my func? I've already search this error in web but I find no helpful solutions.
You'll likely want to use conj instead of into, as into is expecting its second argument to be a seq:
(defn sum-consecutives [a]
(reduce
#(conj %1 (apply + %2))
[]
(partition-by identity a)))
(sum-consecutives [1,4,4,4,0,4,3,3,1]) ;; [1 12 0 4 6 1]
Alternatively, if you really wanted to use into, you could wrap your call to apply + in a vector literal like so:
(defn sum-consecutives [a]
(reduce
#(into %1 [(apply + %2)])
[]
(partition-by identity a)))
Your approach is sound in starting with partition-by. But let's
walk through the steps to sum each subsequence that it produces.
(let [xs [1 4 4 4 0 4 3 3 1]]
(partition-by identity xs)) ;=> ((1) (4 4 4) (0) (4) (3 3) (1))
To get a sum, you can use reduce (though a simple apply
instead would also work
here); e.g.:
(reduce + [4 4 4]) ;=> 12
Now put it all together to reduce each subsequence from above with map:
(let [xs [1 4 4 4 0 4 3 3 1]]
(map #(reduce + %) (partition-by identity xs))) ;=> (1 12 0 4 6 1)
A few notes...
I'm using xs to represent your vector (as suggested by the
Clojure Style Guide).
The let is sometimes a convenient form for experimenting with some
data building up to eventual functions.
Commas are not needed and are usually distracting, except occasionally
with hash-maps.
So your final function based on all this could look something like:
(defn sum-consecutives [coll]
(map #(reduce + %) (partition-by identity coll)))

Clojure Print the contents of a vector

In Clojure, how do you print the contents of a vector? (I imagine to the console, and usually for debugging purposes). If the answer can be generalized to any Seq that would be good.
Edit:
I should add that it should be a simple function that gives output that looks reasonable, so prints an item per line - so can be easily used for debugging purposes. I'm sure there are libraries that can do it, but using a library really does seem like overkill.
I usually use println. There are several other printing functions that you might want to try. See the "IO" section of the Clojure cheatsheet.
This isn't Java. Just print it, and it will look OK.
You can also use clojure.pprint/pprint to pretty-print it. This can be helpful with large, complex data structures.
These methods work for all of the basic Clojure data structures.
Exception: Don't print infinitely long lazy structures such as what (range) returns--for obvious reasons. For that you may need to code something special.
This works for me:
(defn pr-seq
([seq msg]
(letfn [(lineify-seq [items]
(apply str (interpose "\n" items)))]
(println (str "\n--------start--------\n"
msg "\nCOUNT: " (count seq) "\n"
(lineify-seq seq) "\n---------end---------"))))
([seq]
(pr-seq seq nil)))
Example usages:
(pr-seq [1 2 3])
(pr-seq (take 20 blobs) (str "First 20 of " (count blobs) " Blobs")))
If you want to just print out the elements of the sequence/vector you could just map println to your sequence/vector, but make sure you force map to evaluate using dorun:
(dorun (map println [1 2 3 4]))
This can be applied to sequences too:
(dorun (map println '(1 2 3 4)))
Another way you can do this with apply is to curry map with println and apply it to the sequence/vector:
(apply (partial map println) [[1 2 3 4]])
(apply (partial map println) ['(1 2 3 4)])
Another way you can do this is with doseq:
(doseq [e [1 2 3 4]]
(println e))
(doseq [e '(1 2 3 4)]
(println e))
This one at least stops the text going out too far to the right:
(defn pp
([n x]
(binding [pp/*print-right-margin* n]
(-> x clojure.pprint/pprint)))
([x]
(pp 100 x)))
It is possible to do partials of this function to alter the width.

Clojure recursion and a lazy sequence

Ok, I'm a bit stuck on this one, can I actually do what I'm trying to do with this part of the code below:
(recur (conj (get-links (first links)) (rest links))))
get-links returns a sequence of urls which is fed into the initial process-links call then should recurse.
The first link i feed in works, but then the second link where I'm trying to conj one sequence on to another gives me the following error.
"Clojure.lang.LazySeq#xxxxxxx"
Now I'm wondering, is this conj'ing the reference to the instruction to generate the "rest" (rest links) of the un-evaluated sequence?
(defn process-links
[links]
(if (not (empty? links))
(do
(if (not (is-working (first links)))
(do
(println (str (first links) " is not working"))
(recur (rest links)))
(do
(println (str (first links) " is working"))
(recur (conj (get-links (first links)) (rest links))))))))
If I'm totally wrong in my approach to this, let me know.
conj adds an item to a collection. Using it on two collections creates a nested structure. You probably want to concat the two sequences instead.
To illustrate:
user> (conj [1 2 3] [4 5 6])
[1 2 3 [4 5 6]]
user> (concat [1 2 3] [4 5 6])
(1 2 3 4 5 6)
Regarding the "Clojure.lang.LazySeq#xxxxxxx" thing:
The problem is in this snippet:
(println (str (first links) " is working"))
Here you use the string concatenation function str to glue together (first links), which is not a string in this case, and " is working", which is a string. What does str do with a non-string argument? It calls the .toString method on it. What does .toString do for Clojure data? Not always the thing you'd want.
The solution is to use the pr family of functions. pr writes Clojure data to a stream in a way that is recognized by the clojure reader. Two examples of how the above snipped can be rewritten:
(do (pr (first links))
(println " is working"))
;; Sligtly less efficient since a string must be created
(println (pr-str (first links)) "is working")
Note that if you give multiple arguments to println it will print all items with spaces in between.