Printing the binary value of a number in clojure - clojure

We can represent the number 12 as 2r001100 in clojure.
Is there a built-in function to print 2r001100 when given the number 12?

java.lang.Integer/toString will print numbers with arbitrary radix:
(Integer/toString 0xf2 2) ==> "11110010"
(Integer/toString 0xf2 16) ==> "f2"
(Integer/toString 0xf2 27) ==> "8q"

see cl-format
user=> (require '[clojure.pprint :refer (cl-format)])
nil
user=> (cl-format nil "2r~6,'0',B" 12)
"2r001100"

These functions generate and print strings using java.util.Formatter.
format
printf
But they don't do binary, so the best I could come up with is:
(fn [i] (str "2r" (Integer/toBinaryString i)))

All of these answers are good, but either won't support two's-complement for negative numbers (cl-format), or won't print out the correct number of bits based on the width of the data itself (e.g., calling Integer/toBinaryString or Integer/toString on a byte will not do what you want, especially for negative numbers).
Here's a solution that will correctly print out the exact bits of the underlying data:
(defn print-bits [b]
(let [class-name (.getName (class b))
is-byte (= "java.lang.Byte" class-name)
num-bits (clojure.lang.Reflector/getStaticField class-name "SIZE")
format-string (str "~" num-bits "'0b")
bin-str-fn #(clojure.lang.Reflector/invokeStaticMethod
(if is-byte "java.lang.Integer" class-name)
"toBinaryString"
(to-array [%]))
bit-string (if is-byte
(str/join (take-last 8 (bin-str-fn (Byte/toUnsignedInt b))))
(bin-str-fn b))]
(println (str (str/join (repeat (- num-bits (count bit-string)) \0))
bit-string))))

Test of extremes here, using (bit-shift-left 1 63), or 1000000000000000000000000000000000000000000000000000000000000000.
The cl-format solution provided gives me an integer overflow.
Integer/toBinaryString gives me Value out of range for int: -9223372036854775808.
But Long/toBinaryString gives me the string that I expected.

Related

Decimal to Binary Clojure

I'm following this pseudo code to convert decimal to binary recursively.
findBinary(decimal)
if (decimal == 0)
binary = 0
else
binary = decimal % 2 + 10 * (findBinary(decimal / 2)
This is what I have tried:
(defn binary [n]
(loop [res 0]
(if (= n 0)
res
(recur (res (* (+ (mod n 2) 10) (binary (quot n 2)))) )
)
)
)
But I get this error :
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn user/binary (form-init9002795692676588773.clj:6)
Any ideas how to fix the code to complete the task?
I realize, that this is about the journey and not the result. But to
have it mentioned: Long/toString can give you a string from a number with a wide
variety of radixes.
(Long/toString 123 2)
; → "1111011"
Here's a slightly different approach which allows recur to be used:
(defn find-binary [d]
(loop [ decimal d
digits '() ]
(if (= decimal 0)
(Integer. (clojure.string/join (map str digits)))
(recur (quot decimal 2) (conj digits (mod decimal 2))))))
In the loop we build up a collection of binary digits, adding each new digit at the beginning of the list so that we end up with the digits in the desired order left-to-right in the list. When the terminating condition is reached we convert the collection-of-digits to a collection-of-strings, join the collection of strings together into single string, and convert the string back to an integer.
Your psuedo code can be expressed pretty directly in clojure:
(defn find-binary [decimal]
(if (= decimal 0)
0
(+ (mod decimal 2) (* 10 (find-binary (quot decimal 2))))))
Examples:
user=> (find-binary 1)
1
user=> (find-binary 2)
10
user=> (find-binary 25)
11001
user=> (find-binary 255)
11111111
The error in your version is here:
(recur (res (* (+ (mod n 2) 10) (binary (quot n 2))))
Specifically, the complaint is that you are trying to use res (which has the value 0) as a function.
To be honest, I'm not sure how to do this with loop-recur. When I try it complains about recur not being from the tail position. Perhaps another answer can enlighten us!
Using recur:
;; returns a binary number string of the given decimal number
(defn find-binary [decimal]
(loop [n decimal
res ""]
(if (= n 0)
res
(recur (quot n 2)
(str (mod n 2) res)))))
But without loop:
(defn find-binary [decimal & {:keys [acc] :or {acc ""}}]
(if (= decimal 0)
acc
(find-binary (quot decimal 2) :acc (str (mod decimal 2) acc))))
The original attempt was the following, but it can't go far in the size of decimal:
(defn find-binary [decimal]
(loop [n decimal ;; number to be binarized
res '() ;; collector list
pos 0] ;; position of binary number
(if (= n 0)
(reduce #'+ res) ;; sum up collector list
(recur (quot n 2)
(cons (* (int (Math/pow 10 pos))
(mod n 2))
res)
(+ 1 pos)))))
For large numbers use:

Decrease list values by ratio in Clojure

I have a little programming issue that I'm trying to resolve in Clojure.
Say, I have a list with Integer values (they also include zeros). These values have a sum, which I want to decrease by a certain value. To get to this lower sum, I want to decrease the values in the list by ratio.
Say, I have the following list: [0, 10, 30, 40, 20, 0]. The sum is 100, and I want to decrease the sum to 90. I want to decrease the values by ratio, so the new list will be [0, 9, 27, 36, 18, 0].
However, this gets problematic when the numbers turn into fractions. When you round numbers (either with round, floor or ceil), you can end up with a sum that's off by 1 or 2. I can't seem to find an elegant solution. Everything I get consists of going through all the values once, and then going back to repair the offset. Any ideas?
Edit
To clarify the behaviour I want to see, the way it rounds doesn't really matter to me, as long as the sum is correct and the ratios of the numbers are approximately the same. I don't care care whether the total error is the smallest or that most are rounded down.
Additional requirements are that numbers are only allowed to stay equal or get lower, numbers should be >= 0, and the resulting list of numbers should be integers.
We can specify the function's requirements with clojure.spec. If we want the function to support integers w/arbitrary precision, sequences that sum to zero, empty sequences, etc., we could write this function spec:
(s/def ::natural-integer (s/and integer? (comp not neg?)))
(s/fdef dec-sum-int
:args (s/and (s/cat :new-sum ::natural-integer
:nums (s/coll-of ::natural-integer))
#(<= (:new-sum %) (apply +' (:nums %))))
:ret (s/coll-of ::natural-integer)
:fn (fn [{:keys [args ret]}]
(and (= (count (:nums args)) (count ret))
;; each output <= corresponding input
(every? true? (map <= ret (:nums args)))
(or (empty? ret)
(= (:new-sum args) (apply + ret))))))
Then st/check the original answer below to see failing examples, or see example invocations with s/exercise-fn.
Here's a version that satisfies the spec for your updated requirements. Most of the complexity is to ensure each output <= input when adjusting for rounding error:
(defn dec-sum-int [new-sum nums]
(let [sum (apply +' nums)
ratio (if (zero? sum) 1 (/ new-sum sum))
nums' (map #(bigint (*' % ratio)) nums)
err (- new-sum (apply + nums'))]
(loop [nums nums
nums' nums'
out []
err err]
(cond
(zero? err)
(into out nums')
(seq nums')
(let [[num & more] nums
[num' & more'] nums']
(if (pos? num)
(let [num'' (min num (+ num' err))]
(recur more more'
(conj out num'')
(- err (- num'' num'))))
(recur more more' (conj out num') err)))
:else out))))
(st/summarize-results (st/check `dec-sum-int))
{:sym playground.so/dec-sum-int}
=> {:total 1, :check-passed 1}
Original Answer
Here's a function to multiply each number in a collection by a ratio to reach some desired sum:
(defn adjust-sum [new-sum nums]
(let [sum (apply + nums)]
(map #(* % (/ new-sum sum))
nums)))
(adjust-sum 90 [0 10 30 40 20 0])
=> (0N 9N 27N 36N 18N 0N)
(map int *1)
=> (0 9 27 36 18 0)
For your example the results naturally come out as big integers. This is the only given example, but this problem lends itself well to property-based, generative testing. We can define properties that should hold for all examples and use test.check to test the function against many random examples we may not have imagined:
(tc/quick-check 10000
(prop/for-all [new-sum gen/int
nums (->> (gen/vector gen/int)
;; current approach fails for inputs that sum to zero
(gen/such-that #(not (zero? (apply + %)))))]
(= new-sum (apply + (adjust-sum new-sum nums)))))
=> {:result true, :num-tests 10000, :seed 1552170880184}
See updates above for handling examples with rounding error, or prior edits for handling negative numbers.
I don't think there is way to solve it without going through the list a second time to fix the rounding. Here is one solution using Largest Remainder Method:
(defn adj-seq
[input ratio rounding]
(let [;;
;; function to apply ratio to a number
;;
mul-ratio (partial * ratio)
;;
;; function to apply ratio and rounding to a number
;;
mul-ratio-r (comp rounding mul-ratio)
;;
;; sort oirignal input with largest remainder first
;; then applies ratio and rounding to each number
;;
rounded-list (->> input
(sort-by #(- (mul-ratio-r %)
(mul-ratio %)))
(map mul-ratio-r))
;;
;; sum of original numbers
;;
sum-input (reduce + input)
;;
;; calculate the delta between the expected sum and sum of all rounded numbers
;;
delta (- (mul-ratio-r sum-input) (reduce + rounded-list))]
;;
;; distribute delta to the rounded numbers in largest remainder order
;;
(->> rounded-list
(reductions (fn [[remain _] e]
;; increment number by 1 if remaining delta is >1
(if (pos? remain)
[(dec remain) (inc e)]
;; otherwise returns the rounded number as is
[0 e]))
;; delta is the initial value to feed to the reducing function
[delta])
;;
;; ignore the first output from the reducing function - which is the original delta
;;
rest
;;
;; get the adjusted number: ratio + rounding + delta-adj
;;
(map last))))
And a sample run:
(def input [0 10 30 40 20 0])
(def ratio 0.83)
(def rounding int)
(reduce + input)
;; => 100
(* ratio *1)
;; => 83.0
(adj-seq input ratio rounding)
;; => (25 17 8 33 0 0)
(reduce + *1)
;; => 83
Is this what you need?
(defn scale-vector
"Given `s`, a sequence of numbers, and `t`, a target value for the sum of
the sequence, return a sequence like `s` but with each number scaled
appropriately."
[s t]
(let [ratio (/ (reduce + (filter number? s)) t)]
(map #(if (number? %) (/ % ratio) %) s)))
(scale-vector [10 20 :foo 30 45.3 0 27/3] 21)
=> (1.837270341207349 3.674540682414698 :foo 5.511811023622047 8.32283464566929 0.0 1.6535433070866141)
(reduce + (filter number? (scale-vector [10 20 :foo 30 45.3 0 27/3] 21)))
=> 21.0
What's going on here:
We're assuming that s is a sequence of numbers; but it isn't necessarily an error if some element is not a number. Filtering for numbers allows us to cope gracefully is some elements are non-numeric; I've chosen to preserve non-numeric elements, but you could equally drop them.
I've done nothing special to exclude rational numbers from the output, and I can't see why you'd need to; but if you wanted to do that you could use (map double [1 1/2 22/7]) => (1.0 0.5 3.142857142857143).
But idiomatically, in Clojure, a number is just a number. Any function that accepts numbers should accept numbers. Rational numbers - what you are referring to as 'fractions' - are just numbers like any other numbers. Don't worry about them.

clojure: Compute Factorial of number using defmulti and defmethod

I tried to compute factorial through defmulti and defmethod.
(defmulti factorial identity)
(defmethod factorial 0 [_] 1)
(defmethod factorial :default [num]
(* num (factorial (dec num))))
It works fine for small numbers
(-> 10 factorial) ;;3628800
(-> 2 factorial) ;; 2
it shows Integer Overflow Exception for factorial 40
(-> 40 factorial)
ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow
My curiosity is
How can we compute factorial for Big Numbers using defmulti and defmethod?
Clojure's implementation of number types builds on the host platform's number types. Your solution works when you define the arbitrary size flag N, because the underlying number type changes on the JVM.
(type 10) ;=> java.lang.Long
(type 10N) ;=> clojure.lang.BigInt
clojure.lang.BigInt uses either java.math.BigInteger or a Java long as the underlying type, depending on the bit size of the number.
On a different host, the Javascript engine of a browser, both types are JavaScript's native Numbers. The factorial function gives a result up to 170 in ClojureScript. It does not throw when overflowing, but returns the JavaScript number value Infinity:
(factorial 170) ; => 7.257415615307994e+306
(factorial 170N) ; => 7.257415615307994e+306
(factorial 171N) ; => Infinity
Update: This answer (pointed out by #cske) gives a neat solution to use the *' operator, which bumps up the number type in case it would overflow:
(defmethod factorial :default [num]
(*' num (factorial (dec num))))
(factorial 40) ; => 815915283247897734345611269596115894272000000000N
I have solved it
(-> 40N factorial) ;;815915283247897734345611269596115894272000000000N

how to Replace an Integer with string 20 percent of the time Clojure

I need to replace an integer with a string in clojure but only for 20% of the outputted integers.
(defn factor5 [x]
(if (= (mod x 3) (mod x 5) 0) "BuzzFizz"
(if (= (mod x 5) 0) "buzz"
(if (= (mod x 3) 0) "fizz" x))))
here i have a fizzbuzz program which prints out "fizz" if the number is a multiple of 3 or "buzz" if it is a multiple of 5 and "BuzzFizz" is printed if is a multiple of both. if an integer is neither of the above multiplies the integer gets printed. What i need is to print "Boom" instead of the integer but only for 20% of the integers.
some pseudo code
if(x == int){
print out Boom instead of x only for 20% }
else{
print out x}
I have very limited exprience in clojure as my pseudocode is java based
Please see the Clojure Cheatsheet for a comprehensive listing of functions.
The one you want is rand, and a test like:
(if (< (rand) 0.2) ....)
if you want the decision made randomly you could use one of the rand runctions in an if statement like so:
user> (defn x20% [x]
(if (rand-nth [true false false false false])
"Boom"
x))
#'user/x20%
user> (x20% 5)
5
user> (x20% 5)
5
user> (x20% 5)
"Boom"
user> (x20% 5)
5
there are also rand and rand-int. which you use is somewhat a matter of style and the specifics of your function:
user> (> 2 (rand-int 10))
true
user> (> 2 (rand-int 10))
true
user> (> 2 (rand-int 10))
false
user> (> 0.2 (rand))
true
user> (> 0.2 (rand))
(defn factor-5 [x]
(if (and (number? x) (zero? (rem x 1)))
(if (zero? (rand-int 5))
"Boom"
x)))
This returns the required value rather than printing it.
It tests that its argument is numeric, and - if so - that it is a
whole number value, which could be byte, short, int, ... .
(rand-int 5) chooses randomly from 0, 1, ... 4.

Building a lazy, impure id generator

I'd like to know how to create an infinite, impure sequence of unique values in Clojure.
(def generator ...) ; def, not defn
(take 4 generator) ; => (1 2 3 4)
(take 4 generator) ; => (5 6 7 8). note the generator's impurity.
I think that such a design could be more convenient than e.g. wrapping a single integer value into a reference type and increment it from its consumers, as:
The proposed approach reduces the implementation details to a single point of change: the generator. Otherwise all the consumers would have to care about both the reference type (atom), and the concrete function that provides the next value (inc)
Sequences can take advantage many clojure.core functions. 'Manually' building a list of ids out of an atom would be a bit bulky: (take 4 (repeatedly #(swap! _ inc)))
I couldn't come up with a working implementation. Is it possible at all?
You can wrap a lazy sequence around an impure class (like a java.util.concurrent.atomic.AtomicLong) to create an id sequence:
(def id-counter (java.util.concurrent.atomic.AtomicLong.))
(defn id-gen []
(cons
(.getAndIncrement id-counter)
(lazy-seq
(id-gen))))
This works, but only if you don't save the head of the sequence. If you create a var that captures the head:
(def id-seq (id-gen))
Then call it repeatedly, it will return ids from the beginning of the sequence, because you've held onto the head of the sequence:
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
If you re-create the sequence though, you'll get fresh values because of the impurity:
(take 3 (id-gen))
;; (3 4 5)
(take 3 (id-gen))
;; (6 7 8)
(take 3 (id-gen))
;; (9 10 11)
I only recommend doing the following for educational purposes (not production code), but you can create your own instance of ISeq which implements the impurity more directly:
(def custom-seq
(reify clojure.lang.ISeq
(first [this] (.getAndIncrement id-counter))
(next [this] (.getAndIncrement id-counter))
(cons [this thing]
(cons thing this))
(more [this] (cons
(.getAndIncrement id-counter)
this))
(count [this] (throw (RuntimeException. "count: not supported")))
(empty [this] (throw (RuntimeException. "empty: not supported")))
(equiv [this obj] (throw (RuntimeException. "equiv: not supported")))
(seq [this] this)))
(take 3 custom-seq)
;; (12 13 14)
(take 3 custom-seq)
;; (15 16 17)
I had a fun time discovering something during answering your question. The first thing that occured to me was that perhaps, for whatever ultimate goal you need these IDs for, the gensym function might be helpful.
Then, I thought "well hey, that seems to increment some impure counter to generate new IDs" and "well hey, what's in the source code for that?" Which led me to this:
(. clojure.lang.RT (nextID))
Which seems to do what you need. Cool! If you want to use it the way you suggest, then I would probably make it a function:
(defn generate-id []
(. clojure.lang.RT (nextID)))
Then you can do:
user> (repeatedly 5 generate-id)
=> (372 373 374 375 376)
I haven't yet tested whether this will produce always unique values "globally"--I'm not sure about terminology, but I'm talking about when you might be using this generate-id function from within different threads, but want to still be sure that it's producing unique values.
this is another solution, maybe:
user=> (defn positive-numbers
([] (positive-numbers 1))
([n] (cons n (lazy-seq (positive-numbers (inc n))))))
#'user/positive-numbers
user=> (take 4 (positive-numbers))
(1 2 3 4)
user=> (take 4 (positive-numbers 5))
(5 6 7 8)
A way that would be more idiomatic, thread-safe, and invites no weirdness over head references would be to use a closure over one of clojures built in mutable references. Here is a quick sample I worked up since I was having the same issue. It simply closes over a ref.
(def id-generator (let [counter (ref 0)]
(fn [] (dosync (let [cur-val #counter]
(do (alter counter + 1)
cur-val))))))
Every time you call (id-generator) you will get the next number in the sequence.
Here's another quick way:
user> (defn make-generator [& [ii init]]
(let [a (atom (or ii 0 ))
f #(swap! a inc)]
#(repeatedly f)))
#'user/make-generator
user> (def g (make-generator))
#'user/g
user> (take 3 (g))
(1 2 3)
user> (take 3 (g))
(4 5 6)
user> (take 3 (g))
(7 8 9)
This is hack but it works and it is extremely simple
; there be dragons !
(defn id-gen [n] (repeatedly n (fn [] (hash #()))))
(id-gen 3) ; (2133991908 877609209 1060288067 442239263 274390974)
Basically clojure creates an 'anonymous' function but since clojure itselfs needs a name for that, it uses uniques impure ids to avoid collitions. If you hash a unique name then you should get a unique number.
Hope it helps
Creating identifiers from an arbitrary collection of seed identifiers:
(defonce ^:private counter (volatile! 0))
(defn- next-int []
(vswap! counter inc))
(defn- char-range
[a b]
(mapv char
(range (int a) (int b))))
(defn- unique-id-gen
"Generates a sequence of unique identifiers seeded with ids sequence"
[ids]
;; Laziness ftw:
(apply concat
(iterate (fn [xs]
(for [x xs
y ids]
(str x y)))
(map str ids))))
(def inf-ids-seq (unique-id-gen (concat (char-range \a \z)
(char-range \A \Z)
(char-range \0 \9)
[\_ \-])))
(defn- new-class
"Returns an unused new classname"
[]
(nth inf-ids-seq (next-int)))
(repeatedly 10 new-class)
Demonstration:
(take 16 (unique-id-gen [\a 8 \c]))
;; => ("a" "8" "c" "aa" "a8" "ac" "8a" "88" "8c" "ca" "c8" "cc" "aaa" "aa8" "aac" "a8a")