I am making poker game in clojure I have a function like:
(sort (map rank straight-hand))
that returns rank of the hand in sort order let say
(2 3 4 5 6)
how to check that the difference of preceding number and current number in the sequence is 1
(every? #{1} (map - (rest hand) hand))
This verifies that every result of subtracting an item from the following in your hand is in the set #{1}
Use (partition 2 1 <seq>) to break your sorted sequence into overlapping groups of two, then get the difference of each group of two, then test that each difference is -1:
(defn incrementing?
[xs]
(every? #(= % -1) (map #(apply - %) (partition 2 1 xs))))
Here's another way: you want to check that what you have is a range. So compare it to the range between the first and the last element of your list.
(= xs (range (first xs)
(inc (last xs))))
Related
I am new to clojure
I am trying to find whether a vector in clojure has consecutive elements:
in python its simple using numpy
(np.diff(np.sort(np.array(numbers))))
But I am lost trying to find similar methods:
My strategy was to
subtract a vector with itself
make it a set and see if it contains first element as 1 and the length of set is 1
for example
(def x `(5 7 3 6 4))
Output would be (1 1 1 1)
I am confused how to work on this.
Try something like this:
(defn diff [vals]
(map - (next vals) vals))
This returns a list of differences between each pair of consecutive elements are equal. It works because next simply offsets the sequence of values by one element.
Example usage:
(diff [1 2 2 3])
=> (1 0 1)
To test whether consecutive numbers exist, you simply need to check for the presence of the value 1 in this list.
Following your idea of getting the differences, after sorting you can use partition to get all the consecutive pairs and than use map to get all the differences. (Here it seemed more natural to get the reverse of the numpy diff, so the check is that every element is -1 instead of 1.)
(defn contains-consecutive? [xs]
(let [sorted (sort xs)
differences (map #(apply - %) (partition 2 1 sorted))]
(every? #(= -1 %) differences)))
user> (contains-consecutive? [])
true
user> (contains-consecutive? [1])
true
user> (contains-consecutive? [1 3 2])
true
user> (contains-consecutive? [1 3 4])
false
user> (contains-consecutive? '(5 7 3 6 4))
true
Clojure has a built-in dedupe function so an easy (but not particularly fast) answer is to dedupe and compare equals.
(defn consecutive?
[coll]
(not= coll (dedupe coll)))
(consecutive? [1 2 2 3]) ;; true
(consecutive? [1 2 3]) ;; false
Please see this list of documentation, especially the Clojure CheatSheet. You are looking for the function partition. You can use it like this:
(ns tst.demo.core
(:use tupelo.test))
(defn pair-delta
[pair]
(let [[a b] pair]
(- b a)))
(defn consectives?
[v]
(let [pairs (partition 2 1 (sort v))
deltas (mapv pair-delta pairs)
result (= #{1} (set deltas))]
result))
(dotest
(let [pos [1 2 3 6 5 4]
neg [1 2 3 6 5 ]]
(is= true (consectives? pos))
(is= false (consectives? neg))))
The template project shows how I like to set up a project, and includes my favorite helper functions.
I am learning clojure. While solving one of the problem, I had to use first + filter. I noted that the filter is running unnecessarily for all the inputs.
How can I make the filter to run lazily so that it need not apply the predicate for the whole input.
The below is an example showing that it is not lazy,
(defn filter-even
[n]
(println n)
(= (mod n 2) 0))
(first (filter filter-even (range 1 4)))
The above code prints
1
2
3
Whereas it need not go beyond 2. How can we make it lazy?
This happens because range is a chunked sequence:
(chunked-seq? (range 1))
=> true
And it will actually take the first 32 elements if available:
(first (filter filter-even (range 1 100)))
1
2
. . .
30
31
32
=> 2
This overview shows an unchunk function that prevents this from happening. Unfortunately, it isn't standard:
(defn unchunk [s]
(when (seq s)
(lazy-seq
(cons (first s)
(unchunk (next s))))))
(first (filter filter-even (unchunk (range 1 100))))
2
=> 2
Or, you could apply list to it since lists aren't chunked:
(first (filter filter-even (apply list (range 1 100))))
2
=> 2
But then obviously, the entire collection needs to be realized pre-filtering.
This honestly isn't something that I've ever been too concerned about though. The filtering function usually isn't too expensive, and 32 element chunks aren't that big in the grand scheme of things.
I have the following bit of code that produces the correct results:
(ns scratch.core
(require [clojure.string :as str :only (split-lines join split)]))
(defn numberify [str]
(vec (map read-string (str/split str #" "))))
(defn process [acc sticks]
(let [smallest (apply min sticks)
cuts (filter #(> % 0) (map #(- % smallest) sticks))]
(if (empty? cuts)
acc
(process (conj acc (count cuts)) cuts))))
(defn print-result [[x & xs]]
(prn x)
(if (seq xs)
(recur xs)))
(let [input "8\n1 2 3 4 3 3 2 1"
lines (str/split-lines input)
length (read-string (first lines))
inputs (first (rest lines))]
(print-result (process [length] (numberify inputs))))
The process function above recursively calls itself until the sequence sticks is empty?.
I am curious to know if I could have used something like take-while or some other technique to make the code more succinct?
If ever I need to do some work on a sequence until it is empty then I use recursion but I can't help thinking there is a better way.
Your core problem can be described as
stop if count of sticks is zero
accumulate count of sticks
subtract the smallest stick from each of sticks
filter positive sticks
go back to 1.
Identify the smallest sub-problem as steps 3 and 4 and put a box around it
(defn cuts [sticks]
(let [smallest (apply min sticks)]
(filter pos? (map #(- % smallest) sticks))))
Notice that sticks don't change between steps 5 and 3, that cuts is a fn sticks->sticks, so use iterate to put a box around that:
(defn process [sticks]
(->> (iterate cuts sticks)
;; ----- 8< -------------------
This gives an infinite seq of sticks, (cuts sticks), (cuts (cuts sticks)) and so on
Incorporate step 1 and 2
(defn process [sticks]
(->> (iterate cuts sticks)
(map count) ;; count each sticks
(take-while pos?))) ;; accumulate while counts are positive
(process [1 2 3 4 3 3 2 1])
;-> (8 6 4 1)
Behind the scene this algorithm hardly differs from the one you posted, since lazy seqs are a delayed implementation of recursion. It is more idiomatic though, more modular, uses take-while for cancellation which adds to its expressiveness. Also it doesn't require one to pass the initial count and does the right thing if sticks is empty. I hope it is what you were looking for.
I think the way your code is written is a very lispy way of doing it. Certainly there are many many examples in The Little Schema that follow this format of reduction/recursion.
To replace recursion, I usually look for a solution that involves using higher order functions, in this case reduce. It replaces the min calls each iteration with a single sort at the start.
(defn process [sticks]
(drop-last (reduce (fn [a i]
(let [n (- (last a) (count i))]
(conj a n)))
[(count sticks)]
(partition-by identity (sort sticks)))))
(process [1 2 3 4 3 3 2 1])
=> (8 6 4 1)
I've changed the algorithm to fit reduce by grouping the same numbers after sorting, and then counting each group and reducing the count size.
I have a higher order predicate
(defn not-factor-of-x? [x]
(fn [n]
(cond
(= n x) true
(zero? (rem n x)) false
:else true)))
which returns a predicate that checks if the given argument n is not a factor of x.
Now I want to filter a list of numbers and find which are not factors of say '(2 3). One way to do this would be :
(filter (not-factor-of-x? 3) (filter (not-factor-of-x? 2) (range 2 100)))
But one can only type so much. In order to do this dynamically I tried function composition :
(comp (partial filter (not-factor-of-x? 2)) (partial filter (not-factor-of-x? 3)))
And it works. So I tried reducing the filters, like this:
(defn compose-filters [fn1 fn2]
(comp (partial filter fn1) (partial filter fn2)))
(def composed-filter (reduce compose-filters (map not-factor-of-x? '(2 3 5 7 11))))
(composed-filter (range 2 122)) ; returns (2 3 4 5 6 7 8 9 10 .......)
So, why the filter composition is not working as intended ?
There are many ways to compose functions and/or improve your code. Here's one:
(defn factor? [n x]
(and (not= n x) (zero? (rem n x))))
(->> (range 2 100)
(remove #(factor? % 2))
(remove #(factor? % 3)))
;; the same as the above
(->> (range 2 100)
(remove (fn [n] (some #(factor? n %) [2 3]))))
To see your problem with (reduce compose-filters ... let's look a bit at what that actually does. First, it uses filter on the first two predicates and composes them.. The result of that is a new function from sequences to sequences. The next iteration then calls filter on that function, when filter expects a predicate. Every sequence is a truthy value, so that new filter will now never remove any values because it's using a "predicate" which always returns truthy values. So in the end, only the very last filter actually does any filtering - in my REPL your code removes the numbers 22, 33, 44 and so on because 11 is a factor in them. I think the reduce you want to do here is more like
(reduce comp (map (comp (partial partial filter) not-factor-of-x?) '(2 3 5 7 11)))
Note how because we only want to call (partial filter) once per number, you can move that into the mapping step of the mapreduce. As to how I'd do this, considering that you produce all your predicates together:
(map not-factor-of-x? '(2 3 5 7 11))
it seems more natural to me to just combine the predicates at that point using every-pred
(apply every-pred (map not-factor-of-x? '(2 3 5 7 11)))
and use one filter on that predicate. It seems to communicate the intent a little more clearly ("I want values satisfying every one of these preds") and unlike composition of (partial filter ...) it avoids making an intermediate sequence for each predicate.
(In Clojure 1.7+ you can also avoid this by composing the transducer version of filter).
Like the title says, I'm looking for a function in Clojure that returns me the index of the first element in a map to satisfy a condition, I know how to do it, but if something is already available in the API I would like to us it.
Example:
(strange-fn #(even? %) '(1 3 5 7 9 4))
=> 5
You provided a list rather than a map in your example, so I assume you mean any sequence.
One simple way to do it is to just count the number of items returned from take-while:
(defn strange-fn [f coll]
(count (take-while (complement f) coll)))
(strange-fn #(even? %) '(1 3 5 7 9 4))
;=> 5
It's easy enough to do, but beware that most of the time if you're writing code that works with indices of things (especially lazy-seqs), it's usually possible to do the whole thing much more tidily by just working with sequences. However, if you're certain you want to deal in indices, it's as simple as (fn [pred coll] (first (keep-indexed (fn [i x] (when (pred x) i)) coll))).