count unique values in vector in clojure - clojure

I was wondering if anyone can help me understand how can i do the below code in clojure :
int[] secondArray = new int[500];
for (int i = 0; i < firstArray.length; i++)
{
secondArray[firstArray[i]] += 1;
}

You could probably use the frequencies function:
user=> (frequencies [:foo :bar :baz :foo :foo])
{:foo 3, :bar 1, :baz 1}

Let's walk through a fairly direct translation where we treat the input vector as a sequence and then reduce it into the desired result:
First define some immutable vectors containing our starting states:
boo> (def firstVector (vec (take 30 (repeatedly #(rand-int 10)))))
#'boo/firstVector
boo> firstVector
[9 0 4 5 0 7 3 9 0 0 6 6 5 5 9 4 0 1 3 6 4 9 5 8 8 3 4 6 7 6]
boo> (def secondVector (vec (take 10 (repeat 0))))
#'boo/secondVector
boo> secondVector
[0 0 0 0 0 0 0 0 0 0]
We then want an expression that incs the appropriate element in the second array
boo> (assoc secondVector 4 (inc (secondVector 4)))
[0 0 0 0 1 0 0 0 0 0]
Then we want the result of that to be passed to the frist element in firstVector, followed by the result of that being passed to the second element in firstVector and so forth. The reduce function does this:
boo> (reduce #(assoc %1 %2 (inc (%1 %2))) secondVector firstVector)
[5 1 0 3 4 4 5 2 2 4]
in the reducer function %1 (the first argument) is the current accumulated result, and %2(the second argument) is the current value from the input sequence (firstVector).

Related

Clojure: Same vector values in a row checker

I'm creating an Clojure Tic Tac Toe game, where I have a board variable with 9 numbers (def moves [0 0 0 0 0 0 0 0 0]) . This variable gets filled with 1's en 2's (no "x" or "o" yet). At the end of the game the variable could look like [2 1 2 1 1 1 2 1 2] where 1 owns the second row. Now I need a function to check if there's three in a row. I wanted to start horizontally. Which means I need a function to check if there's after each 3 numbers 3 of the same number are in a row. any ideas how I can create a function like this?
So this is the function so far:
(def moves [0 0 0 0 0 0 0 0 0])
(defn wongame? [playedmoved]
(
(def counter 0)
;action here....
)
)
(won moves) ;gives true/false
Something like this should work:
(defn end-of-game? [moves]
(->> moves
(partition 3)
(remove #(= [0 0 0] %))
(map (partial apply =))
(some identity)))
With your example input of [2 1 2 1 1 1 2 1 2] (partition 3) gives:
((2 1 2) (1 1 1) (2 1 2))
We need to use = with each list. apply is required because = works with individual arguments rather than a list. partial is required because the parameters to apply = are pending. #(apply = %) could have equivalently been used.
(false true false)
some is all about '(at least) one or none'. Here if one of the list it is passed is truthy then that one will be returned.
If you really need the answer to return true/false then put a call to boolean as the last function to the thread last macro (->>). I've left that out because only rarely do you need to actually return true or false in Clojure - you can rely on nil punning.
This same function will work for vertically as well. Start off with a general transpose function that works for a matrix (e.g. [[0 0 0][0 0 0][0 0 0]]):
(defn transpose [matrix]
(apply mapv vector matrix))
Then fashion your input before, and its output after:
(defn transpose-flat [xs]
(->> xs
(partition 3)
transpose
(mapcat identity)))
(def moves [0 0 1 1 0 1 2 2 2]) #_"the game's state in the middle"
At first, if we encounter like this pattern, we need stop the game,
Otherwise we are possible to misjudge the winner of this game
if the moves reaches the state like [2 2 1 1 1 1 2 2 2]. Which is the winner? We need to call this function each turn of the game.
Second, the name "won?" isn't appropriate because this function doesn't tell the winner, but tells the end of game. "won?" function should be renamed like ["end-of-game?" "game-end?" "end?"].
Third, I try to implement "winner" that returns the winner of the game like this:
(defn winner [moves]
(let [pattern-of-end {[1 1 1]:1 [2 2 2]:2}]
(->> moves #_"I use threading macro to explain"
(partition 3) #_"group by each three symbols.
1 line of 9 elements -> 3 lines of 3 elements"
(keep pattern-of-end) #_"If there is some lines that matches
the pattern-of-end ,that will return [1] or [2]"
first #_"Because the previous expression returns lazy-seq
we can get the scalar by calling first"
)))
This tells us the winner of the game.
It would have been easier if you had proper numbers for x's and o's:
(defn the-winner-is [moves]
(let [x 5
o 7]
(->> moves
(partition 3)
(map (partial apply +))
(some #{15 21}))))
This way it even says who is the winner (15 or 21).
(the-winner-is [5 5 7 7 7 0 7 7 7]) ; 21
(the-winner-is [5 5 5 7 7 5 5 7 7]) ; 15
(the-winner-is [5 7 5 7 7 5 5 7 5]) ; nil

Adding sets of numbers up to 16

I have some sets of numbers:
(#{7 1} #{3 5} #{6 3 2 5}
#{0 7 1 8} #{0 4 8} #{7 1 3 5}
#{6 2} #{0 3 5 8} #{4 3 5}
#{4 6 2} #{0 6 2 8} #{4} #{0 8}
#{7 1 6 2} #{7 1 4})
I wish to make each set into a four number vector, such that the sum of all the vectors add up to 16 and they can only come from the set of numbers:
#{7 1} => [1 1 7 7]
#{4 3 5} => [3 4 4 5]
#{4} => [4 4 4 4]
#{0 8} => [0 0 8 8]
Lastly, the vector has to contain all the numbers in the set. It'll be great to solve this for abitrary vector lengths :)
How would the clojure code be written.
With small sets and the originally stated output length of 4
This is easily handled with naive search
(defn bag-sum [s n]
(for [a s, b s, c s, d s
:let [v [a b c d]]
:when (= n (apply + v))
:when (= (set v) s)]
v))
(take 1 (bag-sum #{7 1} 16)) ;=> ([7 7 1 1])
(take 1 (bag-sum #{3 5} 16)) ;=> ([3 3 5 5])
(take 1 (bag-sum #{4 3 5} 16)) ;=> ([4 4 3 5])
Assuming 16 is fixed and all numbers are non-negative
The search space even without the set constraint is tiny.
(require '[clojure.math.combinatorics :refer [partition]])
(count (partitions (repeat 16 1))) ;=> 231
So, again a naive solution is very practical. We'll produce solutions of all lengths, which can be further filtered as desired. If there is a zero in the input set, it can pad any solution.
(defn bag-sum16 [s]
(for [p (partitions (repeat 16 1))
:let [v (mapv (partial apply +) p)]
:when (= (set v) s)]
v))
First example has 2 solutions - length 4 and length 10.
(bag-sum16 #{7 1}) ;=> ([7 7 1 1] [7 1 1 1 1 1 1 1 1 1])
(bag-sum16 #{3 5}) ;=> ([5 5 3 3])
(bag-sum16 #{3 4 5}) ;=> ([5 4 4 3])
Using core.logic finite domains to prune the search space with arbitrary but specified domain set s, output length m, and sum n
This is still fairly naive but prunes the search tree when the target sum is exceeded. I am a novice at core.logic, so this is more an opportunity to practice than an attempt at best representation of the problem. This performs worse than the naive solutions above on small spaces, but enables calculation in some medium size cases.
(defn bag-sum-logic [s m n]
(let [m* (- m (count s))
n* (- n (apply + s))
nums (vec (repeatedly m* lvar))
sums (concat [0] (repeatedly (dec m*) lvar) [n*])
dom (apply fd/domain (sort s))
rng (fd/interval n*)
sol (run 1 [q]
(== q nums)
(everyg #(fd/in % dom) nums)
(everyg #(fd/in % rng) sums)
(everyg #(apply fd/+ %)
(map cons nums (partition 2 1 sums))))]
(when (seq sol) (sort (concat s (first sol))))))
(bag-sum-logic #{7 1} 4 16) ;=> (1 1 7 7)
(bag-sum-logic #{7 1} 10 16) ;=> (1 1 1 1 1 1 1 1 1 7)
(bag-sum-logic #{3 5} 4 16) ;=> (3 3 5 5)
(bag-sum-logic #{3 4 5} 4 16) ;=> (3 4 4 5)
(time (bag-sum-logic #{3 4 5} 30 100))
;=> "Elapsed time: 18.739627 msecs"
;=> (3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 5 5 5 5)
Better algorithms for the general case?
This problem is a linear Diophantine equation, which can be solved with the Extended Euclidean Algorithm via matrix unimodular row reduction, i.e. carry out the Euclidean algorithm in one column while bringing the entire basis row along for the ride.
For example, in the case of #{3 5} and sum 16, you want to solve the equation
3x + 5y = 16
subject to the additional constraints that x > 0, y > 0 and x + y = 4 (your example).
The matrix and reduction steps
[[3 1 0] -> [[3 1 0] -> [[1 2 -1] -> [[1 2 -1]
[5 0 1]] [2 -1 1]] [2 -1 1]] [0 -5 3]]
So the GCD of 3 and 5 is 1, which divides into 16. Therefore there are (infinitely many) solutions before the constraints
x = 16 * 2 - 5k
y = 16 * -1 + 3k
Since we need x + y = 4, 4 = 16 - 2k and therefore k = 6, so
x = 2
y = 2
And we need 2 copies of 3 and 2 copies of 5.
This generalizes to more than 2 variables in the same manner. But whereas for 2 variables the length of the solution fully constrains the single free variable as shown above, more than 3 variables can be underspecified.
Solving linear Diophantine equations can be done in polynomial time. However, once you add the bounds (0, m), finding a solution becomes NP-complete, though a quick perusal of research results suggest there are fairly tractable approaches.
Working on the assumptions that you only want one solution per set and you want the solution ordered ascending as per your example this is what I came up with. There aren't many combinations of sets of 1-4 numbers so the way I initially decomposed the problem was to look at what the pattern of possible solutions might look like.
(def x #{3 5})
(def g 16)
(def y {1 [[0 0 0 0]]
2 [[0 0 0 1][0 0 1 1][0 1 1 1]]
3 [[0 0 1 2][0 1 1 2][0 1 2 2]]
4 [[0 1 2 3]]})
This key of this map indicates the size of the set x that is being evaluated. The values are the possible permutations of indices to the set once it is sorted into a vector. Now we can choose the permutations based on the size of the set and calculate the values of each permutation, stopping as soon as we reach the goal:
(filter #(= g (apply + %))
(for [p (y (count x))]
(mapv #((into [] (sort x)) %) p)))
The values of each key of the map above the permutations form a pattern: the first index is always 0 and the last always is the set size - 1 and all values are either the same as or one above the value to the left. Therefore, the above map can be generalised to:
(defn y2 [m s]
(map (fn [c] (reduce #(conj %1 (+ %2 (peek %1))) [0] c))
(clojure.math.combinatorics/permutations
(mapv #(if (>= % (dec s)) 0 1) (range (dec m))))))
(def y (partial y2 4))
The filter will now work for any number of set items up to s. As the input set is sorted, the search could be optimised to find the right (or no) solution by doing a binary search over the permutations of possible solutions for log2n search time.

Using Clojure vector to model a 7 card poker hand

I have a vector that represents a 7 card poker hand and I want to find the next hand using the following method:
values are from 0 to 12 and are sorted (e.g. [0 0 7 11 11 12 12])
A valid vector has atmost 4 of one value
The first valid vector is [0 0 0 0 1 1 1]
If the values at index and index + 1 are different then increment the value at index and set all the values from 0 to index - 1 to zero
Repeat the last step until the vector is valid
For example, (next-hand [0 0 0 0 1 1 1]) would return [0 0 0 1 1 1 1] directly. However, (next-hand [0 0 0 1 1 1 1]) would loop through,
[0 0 1 1 1 1 1] (invalid)
[0 1 1 1 1 1 1] (invalid)
[1 1 1 1 1 1 1] (invalid)
[0 0 0 0 0 0 2] (invalid)
[0 0 0 0 0 1 2] (invalid)
and return this valid hand:
[0 0 0 0 1 1 2]
Here is the sudo code I have, but need to convert this to clojure. Note how I'm adding a really large integer to the end of the hand to make the last comparison always true. Thus, in the case of [1 1 1 1 1 1 1 99] the first loop would end at i=6 with 1 < 99 == true.
let hand = [hand 99]
while hand is invalid
for i in range(0,6)
if hand[i] < hand[i+1]
increment hand[i]
break
for j in range(0,i-1)
hand[j] = 0
Edit Friday, Mar 29, 2013:
In order for the select solution to work with the poker hand model I added an is-valid function like so:
(defn is-valid [v]
(let [distinct-ranks (partition-by identity v)
count-distinct (map count distinct-ranks)
max-count (apply max count-distinct)]
(<= max-count 4)))
and updated to (filter #(is-valid %) in next-hand.
One possible solution:
(defn next [v]
(let [i (->> (map < v (rest v))
(map-indexed vector)
(filter #(% 1))
first)
index (if i (i 0) 6)]
(for [[i x] (map-indexed vector v)]
(cond (= i index) (inc x)
(< i index) 0
:else x))))
(defn next-hand [v]
(->> (iterate next (next v))
(filter #(= 4 (apply + %)))
first
vec))
(next-hand [0 0 0 1 1 1 1])

How to count the number of ones in a vector, given an upper limit

Given a vector of ones and zeros, I would like to count the number of entries with a value one. However, the vector may be very long and I only care to know if the vector has zero, one, or more entries with a value o f one.
Using the approach given here, I can count the number of ones in the vector.
(count (filter #{1} [1 0 1 0 0 1 1]))
Can I limit filter (or use some other approach) to avoid visiting any more than three elements of the vector, in this case?
Filter is lazy, so will only do as much work as required. Since you only care about having no 1's, one 1's or two or more ones, you only need to examine up to two elements of the filtered sequence of 1's, so just take 2 before you count:
user=> (count (take 2 (filter #{1} [1 0 1 0 0 1 1])))
2
user=> (count (take 2 (filter #{1} [0 0 0 0 0 0 0])))
0
user=> (count (take 2 (filter #{1} [0 0 0 0 0 0 1])))
1
user=> (def rare (repeatedly #(if (< (rand) 0.0001) 1 0)))
#'user/rare
user=> (take 10 rare)
(0 0 0 0 0 0 0 0 0 0)
user=> (count (take 2 (filter #{1} rare)))
2

How can I update an item in a vector in Clojure?

If I have a Vector:
[1 2 3 4 5 6 7 8 9]
: and I want to replace the 5 with a 0 to give:
[1 2 3 4 0 6 7 8 9]
How can I do this when I only know the index as being 4?
Something like:
(replace-in-vec [1 2 3 4 5 6 7 8 9] 4 0)
assoc works with vectors too!
Usage: (assoc map key val)
(assoc map key val & kvs)
assoc[iate]. When applied to a map,
returns a new map of the same
(hashed/sorted) type, that contains
the mapping of key(s) to val(s). When
applied to a vector, returns a new
vector that contains val at index.
Note - index must be <= (count
vector).
(assoc [1 2 3] 1 :a)
=> [1 :a 3]
You want assoc: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/assoc