Count number of times a letter is in a word - clojure

I have the word describe, and I want to see how many times each letter appears in the word. Eg "e" appears twice, "d" appears once etc
I have tried
(for [letter (map str (seq describe))]
(count (re-seq letter describe)))
But I get the error
ClassCastException java.lang.String cannot be cast to java.util.regex.Pattern clojure.core/re-matcher (core.clj:4667)
Any help would be much appreciated

You can use frequencies to count the frequency at which each character appears in the string, returning a map like this:
(frequencies "ababacdefg")
=> {\a 3, \b 2, \c 1, \d 1, \e 1, \f 1, \g 1}
This works because the string is being treated as a sequence of characters. frequencies can be used on general collections:
(frequencies [1 1 2 3])
=> {1 2, 2 1, 3 1}
The key is the value being counted, and the value is the frequency.

Related

in clojure, why core.match a map inside a vector?

from the sample code of core.match, url:https://github.com/clojure/core.match/wiki/Basic-usage
(let [x {:a 1 :b 1}]
(match [x]
[{:a _ :b 2}] :a0
[{:a 1 :b 1}] :a1
[{:c 3 :d _ :e 4}] :a2
:else nil))
;=> :a1
why we can just match a `x' ? any reason why we can't do that ?
(let [x {:a 1 :b 1}]
(match x
{:a _ :b 2} :a0
{:a 1 :b 1} :a1
{:c 3 :d _ :e 4} :a2
:else nil))
;=> :a1
You can; or at least that's what I'm inferring from reading the source and documentation of match.
The source of match starts with the lines:
(defmacro match
. . .
[vars & clauses]
(let [[vars clauses]
(if (vector? vars) ; If it's a vector...
[vars clauses] ; leave it alone,
[(vector vars) ; else wrap it in a vector
. . .]
The documentation also contains the bit:
. . . Optionally may take a single
var not wrapped in a vector, questions then need not be wrapped in a
vector.
So why are they showing examples with vectors? Likely for consistency of the syntax. That likely help comprehension in a simple, basic overview like that. Switching back and forth between using and not using a vector would necessitate explaining when a vector is necessary, and that would detract from the main point of the page.
Edit: Actually, it does explicitly explain on that page at the top that you can match on an unwrapped value. You can find it by searching for match x on that page.

Why does list* in Clojure only work with a vector in tail position?

I am a clojure newbie. I am trying to play around repl and i see the following as output. And I don't quite understand why each of them behave so differently
(def a (list 1 2 3)) =>#'test.core/a
(list* 4 5 a) =>(4 5 1 2 3)
(list* a 4 5) =>IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:542)
why does the above 2 statements behave the same way in the above 2 statements?
(list* 4 5 [1 2 3]) =>(4 5 1 2 3)
(list* 4 5 [a]) =>(4 5 (1 2 3))
(list* 4 5 (1 2)) =>ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn test.core/eval3837 (form-init633779145118520639.clj:1)
Could someone explain why each of the above statement has a different output?
If you look at the definition and docstring, it'll make sense.
The docs say:
"Creates a new seq containing the items prepended to the rest, the last of which will be treated as a sequence."
Emphasis mine.
In the first block, the last expression fails because 5 is the last argument, but isn't a sequence.
(list* 4 5 [1 2 3]) works for the same reason that (list* 4 5 a) works. The last argument is a sequence, as it's expecting. It just cons onto the last argument as you can see in the definition.
(list* 4 5 [a]) gives different results because you've wrapped the collection a in another collection. It just adds onto the outer collection, leaving the inner one untouched.
The failure of (list* 4 5 (1 2)) isn't really a related problem. Remember, any time you have (...) unquoted, it will attempt to evaluate it, and is expecting that the first element in the list is callable. 1 however isn't callable, thus the error. You need to quote it to treat it as a list literal and not code that you want evaluated.
See the doc string for list*:
Creates a new seq containing the items prepended to the rest, the last
of which will be treated as a sequence.
Note a seq is not a list but lists and vectors and other things can be treated as sequences. Also a seq when output at the repl looks like a list - it is printed within parens.
So in the first case your last argument is a literal vector and it is treated as a sequence and you get an unnested sequence.
In the second case you have the list 'a' as a single element within a literal vector so the vector is treated as a sequence but the inner list is not, your returned sequence is three elements long: 4, 5, and the list a.
In the last case you are tripping up on the function call syntax in lisps being very similar to the list syntax. (1 2) is trying to call the number 1 as if it in a function (with the argument 2). A literal number can not be interpreted as a function.
If you want a list literal not a function call you have to quote it:
(list* 4 5 '(1 2)) => (4 5 1 2)

Clojure sort-by with str and number? keyfunctions

Can anyone explain why sort-by is reacting like this with these keyfunctions?
user=> (sort-by number? [1 2 13 4 "s" 0 "a"])
("s" "a" 1 2 13 4 0)
user=> (sort-by str [1 2 3 4 "s" 0 "a"])
(0 1 2 3 4 "a" "s")
My idea is its dividing the args of the vector into strings and numbers? Is there anything more about what's happening here?
And my second question does sort-by travel through every item of the vector and then returning the result?
number? returns true or false depending on whether the input is a number. false is apparently less than true for comparisons.
str returns a string whose value depends on the input. e.g. (str 1) => "1". String comparison is somewhat complicated, but, in general, numerals are less than uppercase letters are less than lowercase letters and letters are sorted in alphabetical order.
I'm not sure exactly the behavior you're wanting, but it would seem that (sort-by number? ...) did indeed "divide the vector into strings and numbers" by giving you strings at the start of the list and numbers at the end.
If you're wanting to separate strings from numbers, use (group-by number? ...)
As for your second question, sort-by uses the keyfn for comparisons during a merge sort.

How to turn a sequence into a sequence of tuples?

I need to read through a string (which is a sequence) 3 characters at a time. I know of take-while and of take 3 and since take returns nil when there is no more input it seems like the perfect predicate for take-while but I cannot figure out how to wrap the string sequence so that it returns string of the next 3 characters at a time. If this was an object oriented language I'd wrap the sequence's read call or something, but with Clojure I have no idea how to proceed further.
You can use partition or partition-all
(partition 3 "abcdef")
user=> ((\a \b \c) (\d \e \f))
The docs for both are
clojure.core/partition
([n coll] [n step coll] [n step pad coll])
Returns a lazy sequence of lists of n items each, at offsets step
apart. If step is not supplied, defaults to n, i.e. the partitions
do not overlap. If a pad collection is supplied, use its elements as
necessary to complete last partition upto n items. In case there are
not enough padding elements, return a partition with less than n items.
nil
clojure.core/partition-all
([n coll] [n step coll])
Returns a lazy sequence of lists like partition, but may include
partitions with fewer than n items at the end.
nil
If your string is not guaranteed to be of length that is multiple of three, then you should probably use partition-all. The last partition will contain less than 3 elements though. If you want to use partition instead, then to avoid having characters from the string chopped off, you should use step=3, and a padding collection to fill in the holes in the last partition.
To turn every tuple to a string, you can use apply str on every tuple. So you'd want to use map here.
(map (partial apply str) (partition-all 3 "abcdef"))
user=> ("abc" "def")
You can do this without boxing every character:
(re-seq #"..." "Some words to split")
;("Som" "e w" "ord" "s t" "o s" "pli")
If, as your comment on #turingcomplete's answer indicates, you want every other triple,
(take-nth 2 (re-seq #"..." "Some words to split"))
;("Som" "ord" "o s")

Looking to write a spanning function with optional step input

I'm stuck trying to write a Clojure function that takes a span from a collection or vector.
For example I'd like to manipulate a collection such as
(:a :b :c :d :e :f :g :h)
by taking the second element through the fifth in steps of two.
Thus, outputting
(:b :d).
If you haven't figured it out by now, here is a function that does what you want.
(defn take-span
[start end step coll]
(take-nth step (take (- end start) (drop start coll))))
(take-span 1 4 2 '(:a :b :c :d :e :f :g :h))
Hope this helps!
Have a look at (take-nth n coll) function
(take-nth n coll)
Returns a lazy seq of every nth item in coll.
user=> (take-nth 2 (range 10))
(0 2 4 6 8)
It is not an exact match for your question but it is a good starting point for inspiration.
Of course, you can check the source code via:
(source take-nth)