Hello everyone,
I’m continuing my journey of learning Clojure - fantastic language and great community!
I’ve started with simple examples and I’m currently trying to understand Bulls and cows example: https://www.rosettacode.org/wiki/Bulls_and_cows#Clojure
I understand the logic of (defn bulls) function, but I don’t of understanding the logic of (defn cows) function:
We filter the user’s guess input (a sequence of numbers) to see if the solution contains a number the user guessed. These are either bulls or cows, depending on their position.
This invocation of filter uses (set solution) as its predicate function to filter the sequence. In clojure, most collections have a function implementation for convenience. It is idiomatic to use sets as filters, since a set - applied as a function to a single argument, like (#{:a :b :c} :a), will return the arg if the set contains it, or nil. Since the function filter expects as a predicate only needs to return a “truthy” value (e.g. “any” value that is neither nil nor false), then using the set as a function is straightforward. The solution is coerced to a persistent set via clojure.core/set, which returns a set derived from the input sequence. So it’s a set of all the values in the solution, which is used to filter the user’s guess to determine which elements - if any - they correctly guessed at all (either bulls or cows).
If we rewrite this a bit maybe it’s clearer:
(defn cows [guess solution]
(let [number-of-bulls-and-cows (count (filter (set solution) guess))] ;;count of any matching entries
(- number-of-bulls-and-cows (bulls guess solution))) ;;derive cows by subtracting bulls count
To determine the cows, we use the bulls function to compute the actual exact positional matches where the user’s guess is = to the solution’s entries.