Output with println in clojure on Hackerrank - clojure

Hi I am starting to write clojure code and practicing Hackerrank questions.
The problem requires me to take input as
2
RGRG
BGYG
where 2 is number of test cases followed by 2 strings.
I have written following code to take input and print the output of it where fullballs? is my function :
(defn Start [FuncToCall inputParse outputParse]
(let [lines (line-seq (java.io.BufferedReader. *in*))
input (rest lines)
times (first lines)]
(for [i (range (Integer. times))]
(outputParse (FuncToCall (inputParse (nth input i)))))
))
(Start fullballs?
(fn [x] x)
(fn [x]
(if x
(println "True")
(println "False"))
x))
However, Hackerrank says that nothing gets printed on the stdout.
Also when i am trying it int cider repl it is not something like usual
(False
False
false false)
for my two test cases..
Is this problem with for or where is my code wrong ?

for is lazy. This means that unless and until you force evaluation of the result, side effects will not be executed.
The reason this works in your REPL is that it tries to print out the result of your function. This forces evaluation of the lazy sequence produced by for.
Use doseq instead.
For further reading.
I don't understand the second half of your question: "It is not something like usual for my two test cases."

Related

Printing inside a for loop

I was practicing one Clojure tutorial and had to ensure that a for loop was executed so I put a println command there, but it did not display messages.
So now I have got the question...
This code prints Tom's name:
(ns tutorial.core)
(defn -main []
(println 'Jane)
(for [a ['Tom]]
(println a))
;; 'Kate
)
tutorial.core> (-main)
Jane
Tom
(nil)
tutorial.core>
but this not:
(ns tutorial.core)
(defn -main []
(println 'Jane)
(for [a ['Tom]]
(println a))
'Kate
)
tutorial.core> (-main)
Jane
Kate
tutorial.core>
Why? In which cases can we expect that println will not print texts?
for is not a loop, it is a sequence comprehension which returns a lazy sequence. Your for expression will therefore only execute its side-effects (calls to println) when the returned sequence is evaluated. The REPL evaluates the values returned from your calls to -main so it can print them.
Your first example returns a lazy sequence which is evaluted by the REPL causing the (println 'Tom) call to be evaluated. Since println returns nil, the resulting sequence contains a single nil value - this is the (nil) you see in the output.
Your second example creates the same sequence but does not evaluate it, instead 'Kate is returned from the function and the REPL prints that.
If you want an imperative for loop you should use doseq:
(defn -main []
(println 'Jane)
(doseq [a ['Tom]]
(println a))
'Kate)
As Lee says, if you only want side effects like printing, a doseq is the best solution as it never returns a value other than nil.
If you do want to use a for loop, you can remove the laziness by wrapping it inside a (vec ...) expression, which will force the for loop to run immediately. Thus we get:
(println :start)
(vec
(for [a [1 2 3]]
(println a)))
(println :end)
with result:
:start
1
2
3
:end
Without the vec, we get the behavior you saw:
(println :start)
(for [a [1 2 3]]
(println a))
(println :end)
with result:
:start
:end
I almost never want a lazy result, as the uncertainty over when a computation occurs can make debugging difficult. I use the above construct so often that I wrote a small macro forv that always returns a vector result, similar to the mapv function.

Beginner in clojure: Tokenizing lists of different characters

So I know this isn't the best method of solving this issue, but I'm trying to go through a list of lines from an input file, which end up being expressions. I've got a list of expressions, and each expression has it's own list thanks to the split-the-list function. My next step is to replace characters with id, ints with int, and + or - with addop. I've got the regexes to find whether or not my symbols match any of those, but when I try and replace them, I can only get the last for loop I call to leave any lasting results. I know what it stems down to is the way functional programming works, but I can't wrap my head around the trace of this program, and how to replace each separate type of input and keep the results all in one list.
(def reint #"\d++")
(def reid #"[a-zA-Z]+")
(def readdop #"\+|\-")
(def lines (into () (into () (clojure.string/split-lines (slurp "input.txt")) )))
(defn split-the-line [line] (clojure.string/split line #" " ))
(defn split-the-list [] (for [x (into [] lines)] (split-the-line x)))
(defn tokenize-the-line [line]
(for [x line] (clojure.string/replace x reid "id"))
(for [x line] (clojure.string/replace x reint "int"))
(for [x line] (clojure.string/replace x readdop "addop")))
(defn tokenize-the-list [] (for [x (into [] (split-the-list) )] (tokenize-the-line x)))
And as you can probably tell, I'm pretty new to functional programming, so any advice is welcome!
You're using a do block, which evaluates several expressions (normally for side effects) and then returns the last one. You can't see it because fn (and hence defn) implicitly contain one. As such, the lines
(for [x line] (clojure.string/replace x reid "id"))
(for [x line] (clojure.string/replace x reint "int"))
are evaluated (into two different lazy sequences) and then thrown away.
In order for them to affect the return value, you have to capture their return values and use them in the next round of replacements.
In this case, I think the most natural way to compose your replacements is the threading macro ->:
(for [x line]
(-> x
(clojure.string/replace reid "id")
(clojure.string/replace reint "int")
(clojure.string/replace readdop "addop")))
This creates code which does the reid replace with x as the first argument, then does the reint replace with the result of that as the first argument and so on.
Alternatively you could do this by using comp to compose anonymous functions like (fn [s] (clojure.string/replace s reid "id") (partial application of replace). In the imperative world we get pretty used to running several procedures that "bash the data in place" - in the functional world you more often combine several functions together to do all the operations and then run the result.

Error in recur call in Clojure

I am trying to read numbers from input and printing them back in Clojure till I read the number 42. A really basic thing to make sure I know how to read input. Taken from codechef
I have written this program. Might not be good clojure.
(defn universe
[]
(let [num (line-seq (java.io.BufferedReader. *in*))]
(if (not= num 42)
(do
(println num)
(recur (universe))
)
)
)
)
My understanding is that line-seq lazily evaluates from whatever reader is given. In this case the standard input.
So I have let it be num. Then if num is not 42 I print it and then recursively call universe. But it throws exception
Mismatched argument count to recur, expected: 0 args, got: 1,
I have seen an example and recur does take an argument. Looking at the official documentation I couldn't see the syntax for this. So why am I getting this error?
recur does not take the name of the location to recur to. Instead the recur special form jumps back up to the closest function or loop expression, whichever is closer. It then passes it different arguments. This lets you go through the same block of code repeatedly as you work through the data, and there is no function call overhead.
In your case it's recurring up to the function call:
(defn universe [] ...
and trying to pass it an argument, which fails because universe, the function, does not accept any arguments. perhaps you intended to put a loop expression around the if?
user> (defn universe
[]
(let [numbers (line-seq (java.io.BufferedReader. *in*))]
(loop [numbers numbers]
(let [num (first numbers)]
(if (not= (Integer/parseInt num) 42)
(do
(println num)
(recur (rest numbers))))))))
#'user/universe
user> (universe)
3 ;; typed 3
nil ;; typed 42
or where you intending to recur back to the top of the function, in which case just call (recur) instead of (recur universe)

why can't I call a println after a while in defn body in Clojure?

I have a function that looks like,
(defn app [server]
(println "before while...."))
(while test
while-body)
(println "...after while."))
However when I call the fn I just see the "before while" at the REPL, and then when the while fails its test, "nil".
If I write a test foo at the repl like
(defn foo []
(println "testing before")
(loop [i 100]
(when (> i 10)
(prn i)
(recur (- i 2))))
(println "after..."))
It works as I'd expect.
I've put the actual code up in a paste here, https://www.refheap.com/paste/12147 , if it helps.
What explains the difference in behavior here?
edit
Apologies for not trying this before, but this does work at the REPL:
(defn bar []
(let [i (atom 100)]
(println "before...")
(while (> #i 10)
(swap! i dec))
(println "after...")))
So there's something else going on.
edit #2
Testing more at the repl, if I comment out the while loop, the println before and after will print. I was mistaken before about the 'nil', this is the return value of a different function called after the while was called. So it seems to have something to do with the while loop.
I noticed that if I change the while to this
(loop []
(if test
(do things and recur...)
(println "test failed")))
The "test failed" never prints to the repl.
You've got an extranious ) at the end of the first println.
(defn app [server]
(println "before while....")
(while test
while-body)
(println "...after while."))
But since this is obviously example code that you didn't run, I expect the problem to be in the code that you did run. Please copy & paste that code exactly as is if this doesn't fix the problem.
The problem wasn't what I thought it was. I was blocking on a select call (called in the while loop) and that was causing problems with my shutdown function which ended the while loop. Adding a timeout to the select fixes it.
In Clojure function definitions, the last thing to be evaluated is what's returned, and (println ...) returns nil

How can I lazily evaluate read-line to gather input?

(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)
)))