conj not adding to end of vector when called via recur - clojure

Why does this keep asking Jack if he wants a cup of tea and not the other fathers.
(defn tea-anyone
"Ask 'fathers' if they would like some tea"
[fathers]
(loop [asks 0 to-ask fathers]
(let [[father & others] to-ask]
(println (str "Cup of tea " father "? "))
(if (> asks 6)
(println (str father ": All right then!"))
(recur (inc asks) (conj others father))))))
(tea-anyone ["Jack" "Ted" "Dougle"])

Because others isn't a vector. See for yourself:
(let [[f & o :as a] [1 2 3 4]]
(println f)
(println o)
(println a)
(println (type f))
(println (type o))
(println (type a))
(println (type (conj o 5)))
(println (type (conj a 5))))
To achieve the effect you want, you could use cycle.

Try this:
(recur (inc asks) (conj (vec others) father))

Related

Lazy Sequence Clojure

I was trying to modify a vector of vector but ended up with lazy-seq inside. I am new to clojure. Can someone help me to get this correctly?
(require '[clojure.string :as str])
;;READ CUST.TXT
(def my_str(slurp "cust.txt"))
(defn esplit [x] (str/split x #"\|" ))
(def cust (vec (sort-by first (vec (map esplit (vec (str/split my_str #"\n")))))))
;;func to print
(for [i cust] (do (println (str (subs (str i) 2 3) ": [" (subs (str i) 5 (count (str i)))))))
;;CODE TO SEARCH CUST
(defn cust_find [x] (for [i cust :when (= (first i) x )] (do (nth i 1))))
(type (cust_find "2"))
;;READ PROD.TXT
(def my_str(slurp "prod.txt"))
(def prod (vec (sort-by first (vec (map esplit (vec (str/split my_str #"\n")))))))
;;func to print
(for [i prod] (do (println (str (subs (str i) 2 3) ": [" (subs (str i) 5 (count (str i)))))))
;;CODE TO SEARCH PROD
(defn prod_find [x y] (for [i prod :when (= (first i) x )] (nth i y)))
(prod_find "2" 1)
(def my_str(slurp "sales.txt"))
(def sales (vec (sort-by first (vec (map esplit (vec (str/split my_str #"\n")))))))
; (for [i (range(count sales))] (cust_find (nth (nth sales i) 1)))
; (defn fill_sales_1 [x]
; (assoc x 1
; (cust_find (nth x 1))))
; (def sales(map fill_sales_1 (sales)))
(def sales (vec (for [i (range(count sales))] (assoc (nth sales i) 1 (str (cust_find (nth (nth sales i) 1)))))))
; (for [i (range(count sales))] (assoc (nth sales i) 2 (str (prod_find (nth (nth sales i) 2) 1))))
(for [i sales] (println i))
When I print sales vector I get
[1 clojure.lang.LazySeq#10ae5ccd 1 3]
[2 clojure.lang.LazySeq#a5d0ddf9 2 3]
[3 clojure.lang.LazySeq#a5d0ddf9 1 1]
[4 clojure.lang.LazySeq#d80cb028 3 4]
If you need the text files I will upload them as well.
In Clojure, for and map, as well as other functions and macros working with sequences, generate a lazy sequence instead of a vector.
In the REPL, lazy sequences are usually fully computed when printing - to have it printed, it's enough to remove the str in your second to last line:
(def sales (vec (for [i (range(count sales))] (assoc (nth sales i) 1 (cust_find (nth (nth sales i) 1))))))
Just in case, note that your code can be prettified / simplified to convey the meaning better. For example, you are just iterating over a sequence of sales - you don't need to iterate over the indices and then get each item using nth:
(def sales
(vec (for [rec sales])
(assoc rec 1 (cust_find (nth rec 1)))))
Second, you can replace nth ... 1 with second - it will be easier to understand:
(def sales
(vec (for [rec sales])
(assoc rec 1 (cust_find (second rec))))
Or, alternatively, you can just use update instead of assoc:
(def sales
(vec (for [rec sales])
(update rec 1 cust_find)))
And, do you really need the outer vec here? You can do most of what you intend without it:
(def sales
(for [rec sales])
(update rec 1 cust_find))
Also, using underscores in Clojure function names is considered bad style: dashes (as in cust-find instead of cust_find) are easier to read and easier to type.
(for [i sales] (println (doall i)))
doall realizes a lazy sequence. Bare in mind that if the sequence is huge, you might not want to do this.

How can I improve my solution to the Hackerrank Maximum Element challenge to avoid timeouts?

I am trying to complete the Hackerrank Maximum Element challenge found here: https://www.hackerrank.com/challenges/maximum-element/problem
My solution produces the correct output, but times out on the final test cases beginning with #17.
Initially, I used a list and loop/recur to get my answer:
(defn get-query []
(map #(Integer/parseInt %) (clojure.string/split (read-line) #" ")))
(defn stack-stepper [query stack]
(condp = (first query)
1 (conj stack (second query))
2 (rest stack)
3 (do (println (apply max stack)) stack)))
(loop [stack '()
queries-left (Integer/parseInt (read-line))]
(if (> queries-left 0)
(recur (stack-stepper (get-query) stack) (dec queries-left))))
After some research and feedback from other channels, I tried a vector instead of a list, and reduce instead of loop/recur, but the results were the same.
(defn get-query []
(map #(Integer/parseInt %) (clojure.string/split (read-line) #" ")))
(defn get-queries []
(loop [queries []
queries-left (Integer/parseInt (read-line))]
(if (= queries-left 0)
queries
(recur (conj queries (get-query)) (dec queries-left)))))
(defn stack-stepper [stack query]
(condp = (first query)
1 (conj stack (second query))
2 (pop stack)
3 (do (println (apply max stack)) stack)))
(reduce stack-stepper [] (get-queries))
I am still new to FP and Clojure and I would really like to understand what I am missing. I greatly appreciate your time and help!
HackerRank problems are often very demanding from a performance point of view.
The obvious thing to try first is using a transient vector so see if that helps. I tried this:
(let [in (clojure.string/split (slurp *in*) #"\s")
tests (first in)
input-data (map #(Integer/parseInt %) (rest in))]
(loop [v (transient [])
d input-data]
(when (seq d)
(condp = (first d)
1 (recur (conj! v (second d)) (drop 2 d))
2 (recur (pop! v) (rest d))
3 (let [pv (persistent! v)] (println (apply max pv)) (recur (transient pv) (rest d)))))))
If failed at the same point as your solution. Clearly they're looking for something cleverer than that.
The obvious bottleneck is the calculation of the max value on the current stack, which gets re-calculated each time. We can instead save the previous max value on the stack, and recover it as the current max value when we pop the stack:
(defn peek! [tvec] (get tvec (dec (count tvec))))
(let [in (clojure.string/split (slurp *in*) #"\s")
tests (first in)
input-data (map #(Integer/parseInt %) (rest in))]
(loop [v (transient [])
m 0
d input-data]
(when (seq d)
(condp = (first d)
1 (let [snd (second d)
max-now (max m snd)]
(recur (conj! v {:val snd :max-prev m}) max-now (drop 2 d)))
2 (let [popped (peek! v)
max (if popped (:max-prev popped) 0)]
(recur (pop! v) max (rest d)))
3 (do
(println m)
(recur v m (rest d)))))))
Which puts me at rank 1 on the leaderboard :)

Sleeping barber in Clojure

I'm implementing Sleeping barber using core.async. My current code is:
(def workingtime 10000)
(defn barber [in waiting-room]
(go-loop [served-customers 0]
(let [[v] (alts! [waiting-room in])]
(if (= v :close)
served-customers
(do (Thread/sleep 20)
(recur (inc served-customers)))))))
(defn customers [in waiting-room]
(go-loop [customers-overall 0]
(let [customer-arrival-interval (timeout (+ 10 (rand-int 20)))
[v] (alts! [in customer-arrival-interval])]
(if (= v :close)
customers-overall
(do (>! waiting-room :customer)
(recur (inc customers-overall)))))))
(defn -main [& args]
(let [in (chan)
waiting-room (chan (dropping-buffer 3))
barber-ch (barber in waiting-room)
customers-ch (customers in waiting-room)]
(println "opening the shop for 10 seconds...")
(Thread/sleep workingtime)
(>!! in :close)
(>!! in :close)
(println "closing the shop...")
(println (str "Served " (<!! barber-ch) " customers"))
(println (str "Overall " (<!! customers-ch) " customers came"))))
Is it a correct solution? Can it be improved to make it more Clojure-like?
I wanted to use alt! instead of alts! which makes code easier to read:
(defn barber [in]
(go-loop [served-customers 0]
(alt!
waiting-room (do (Thread/sleep 20)
(recur (inc served-customers)))
in served-customers)))
Runtime throws an exception: Can only recur from tail position. Can I still use alt!?
You could solve the alt!/recur problem by rewriting to:
(defn barber [in]
(go-loop [served-customers 0]
(if (= :waiting-room
(a/alt!
waiting-room ([result] :waiting-room) ;; you could also use result if needed
in ([result] :in))) ;; same here
(do (Thread/sleep 20)
(recur (inc served-customers)))
served-customers)))

Strange error when using atoms inside deftype

I have the following code, defining a type that has an atom in there.
(defprotocol IDeck
(vec-* [dk] "Output to a persistent vector")
(count-* [dk] "Number of elements in the deck")
(conj1-* [dk & es] "Adding multiple elements to the deck"))
(deftype ADeck [#^clojure.lang.Atom val]
IDeck
(vec-* [dk] (->> (.val dk) deref (map deref) vec))
(count-* [dk] (-> (.val dk) deref count))
(conj1-* [dk & es]
(try
(loop [esi es]
(let [e (first esi)]
(cond
(nil? e) dk
:else
(do
(swap! (.val dk) #(conj % (atom e)))
(recur (rest esi))))))
(catch Throwable t (println t)))))
(defn new-*adeck
([] (ADeck. (atom [])))
([v] (ADeck. (atom (vec (map atom v))))))
(defn conj2-* [dk & es]
(try
(loop [esi es]
(let [e (first esi)]
(cond
(nil? e) dk
:else
(do
(swap! (.val dk) #(conj % (atom e)))
(recur (rest esi))))))
(catch Throwable t (println t))))
;; Usage
(def a (new-*adeck [1 2 3 4]))
(count-* a)
;=> 4
(vec-* a)
;=> [1 2 3 4]
(conj1-* a 1 2) ;; The deftype case
;=> IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long
(vec-* a)
;=> [1 2 3 4]
(conj2-* a 1 2) ;; The defn case
(vec-* a)
;=> [1 2 3 4 1 2]
Even though the two conj-* methods are exactly the same, except that one is in a deftype and the other is a normal defn, the first gives an error while the second succeeds. Why is this?
This is because protocols doesn't support variable number of arguments.
What you can do is make:
(conj1-* [dk & es] "Adding multiple elements to the deck"))
into
(conj1-* [dk es] "Adding multiple elements to the deck"))
such that the es param will be vector and called like:
(conj1-* a [1 2])

How to launch two threads and wait for them

I can launch two threads and they work, but synchronously. What am I missing to get these threads independently launched?
main, thread, and output
(defn -main
[& args]
(do
(let [grid-dim-in [0 5]
mr1-pos [\N 2 4]
mr2-pos [\N 1 5]
mr1-movs "LMLMMRMM"
mr2-movs "RMRMMMLM"]
(reset! grid-dim grid-dim-in)
(reset! mr1-id {:mr1 mr1-pos})
(reset! mr2-id {:mr2 mr2-pos})
(.start (Thread. (rover-thread mr1-id mr1-movs update-work-block)))
(.start (Thread. (rover-thread mr2-id mr2-movs update-work-block))))))
(defn rover-thread [id movs update-ref]
(let [id-key (keys #id)
id-vals (vals #id)]
(doseq [mov movs]
(println "Rover " id-key " is moving ")
(let [new-mov (determine-rover-move (first id-vals) mov)]
(move-rover id new-mov update-ref)
(print "Rover ")
(print (first id-key))
(print " is at ")
(println new-mov)
(Thread/sleep (rand 1000)))))
Rover :mr1 is at [E 2 4]
Rover (:mr1) is moving
Rover :mr1 is at [N 2 5]
Rover (:mr1) is moving
Rover :mr1 is at [N 2 5]
Finished on Thread[main,5,main]
Rover (:mr2) is moving
Rover :mr2 is at [E 1 5]
Rover (:mr2) is moving
Rover :mr2 is at [N 1 6]
Take a close look at these two lines:
(.start (Thread. (rover-thread mr1-id mr1-movs update-work-block)))
(.start (Thread. (rover-thread mr2-id mr2-movs update-work-block))))))
This code evaluates the (rover-thread mr1-id mr1-movs update-work-block) first, and passes the result of that to the constructor of Thread, which is not what you want.
Here's a simple function to illustrate the principle. This doesn't work, because the (f ...) is evaluated before its result it passed to the Thread constructor:
(defn run-thread-thing-wrong []
(let [f (fn [n s]
(doseq [i (range n)]
(prn s i)
(Thread/sleep (rand 1000))))]
(.start (Thread. (f 10 "A")))
(.start (Thread. (f 10 "B"))))
nil)
Here's a version that does work. A function is passed to the Thread constructor instead:
(defn run-thread-thing []
(let [f (fn [n s]
(doseq [i (range n)]
(prn s i)
(Thread/sleep (rand 1000))))]
(.start (Thread. (fn [] (f 10 "A"))))
(.start (Thread. (fn [] (f 10 "B")))))
nil)
Note: instead of (fn [] ....) you can use the short form #(....) for anonymous functions.
Here's another version that does the same, but with a future instead of manually creating threads:
(defn run-thread-thing []
(let [f (fn [n s]
(doseq [i (range n)]
(prn s i)
(Thread/sleep (rand 1000))))]
(future (f 10 "A"))
(future (f 10 "B")))
nil)
Note that in this case, you pass a form to future instead of a function.
This seems like a really good place to use Clojure's agent feature. I am not qualified to fully explain how to use them, but a really good example of their usage can be found here. Starting threads using agents is dead-easy, and I think it is more idiomatic.
The code would look something like,
(def rover1 (agent [mr1-posn mr1-movs mr1-id]))
(def rover2 (agent [mr2-posn mr2-movs mr2-id]))
(defn rover-behave [[posn movs id]]
(send-off *agent* #'rover-behave)
(. Thread (sleep 1000))
(let [new-mov (determine-rover-move posn movs id)
new-posn (posn-after-move posn new-mov)]
;return value updates state of agent
[new-posn movs id]
)
)
(send-off rover1 rover-behave)
(send-off rover2 rover-behave)