Optimisation of the number of divisors of a number - algorithm

I am using the below code to get the number of divisors for the given number as per this answer https://stackoverflow.com/a/110365/2610955. I calculate the number of times a prime factor is repeated and then increment each of them and make a product out of them. But the algorithm seems too slow. Is there a way to optimise the program. I tried with type hints but they don't have any use. Is there something wrong with the algorithm or am I missing any optimisation here?
(defn prime-factors
[^Integer n]
(loop [num n
divisors {}
limit (-> n Math/sqrt Math/ceil Math/round inc)
init 2]
(cond
(or (>= init limit) (zero? num)) divisors
(zero? (rem num init)) (recur (quot num init) (update divisors init #(if (nil? %) 1 (inc %))) limit init)
:else (recur num divisors limit (inc init)))))
(prime-factors 6)
(set! *unchecked-math* true)
(dotimes [_ 10] (->> (reduce *' (range 30 40))
prime-factors
vals
(map inc)
(reduce *' 1)
time))
Edit : Removed rem as its not needed in the final output

Minor thing: use int or long instead of Integer as #leetwinski mentioned.
Major reason:
It seems that you loop from 2 to sqrt(n), which will loop over unnecessary numbers.
Take a look at the code below: (This is just a dirty patch)
(defn prime-factors
[n]
(loop [num n
divisors {}
limit (-> n Math/sqrt int)
init 2]
(cond
(or (>= init limit) (zero? num)) divisors
(zero? (rem num init)) (recur (quot num init) (update divisors init #(if (nil? %) 1 (inc %))) limit init)
:else (recur num divisors limit (if (= 2 init ) (inc init) (+ 2 init))))))
I just replace (inc init) with (if (= 2 init ) (inc init) (+ 2 init)). This will loop over 2 and odd numbers. If you run it, you will notice that the execution time reduced almost half of the original version. Because it skip the even numbers (except 2).
If you loop over only prime numbers, it will be much faster than this. You can get the sequence of primes from clojure.contrib.lazy-seqs/primes. Though this contrib namespace has deprecated, you can still use it.
This is my approach:
(ns util
(:require [clojure.contrib.lazy-seqs :refer (primes)]))
(defn factorize
"Returns a sequence of pairs of prime factor and its exponent."
[n]
(loop [n n, ps primes, acc []]
(let [p (first ps)]
(if (<= p n)
(if (= 0 (mod n p))
(recur (quot n p) ps (conj acc p))
(recur n (rest ps) acc))
(->> (group-by identity acc)
(map (fn [[k v]] [k (count v)])))))))
Then you can use this function like this:
(dotimes [_ 10] (->> (reduce *' (range 30 40))
factorize
(map second)
(map inc)
(reduce *' 1)
time))

you can increase the performance by using primitive int in loop. Just replace (loop [num n... with (loop [num (int n)...
for me it works 4 to 5 times faster
another variant (which is in fact the same) is to change the type hint in the function signature to ^long.
The problem is that the ^Integer type hint doesn't affect the performance in your case (as far as i know). This kind of hint just helps to avoid reflection overhead when you call some methods of the object (which you don't), and primitive type hint (only ^long and ^double are accepted) actually converts value to the primitive type.

Related

How to decrement a value in Scheme?

I have a procedure that can find the n smallest primes larger than from
(define (primes_range from to n)
(for ([i (in-range from to)])
(if (> n 0)
(cond ((prime? i) (display i)
(- n 1)))
false)))
I add a parameter n to the procedure primes_range and decrement it during the execution only if a prime was found.
But n not changed. How to fix that?
The idiomatic Scheme way to write this function is to use recursion:
(define (primes-range from to n)
(cond ((>= from to) '())
((<= n 0) '())
((prime? from) (cons from (primes-range (+ from 1) to (- n 1))))
(else (primes-range (+ from 1) to n))))
You can easily spell this out in English:
Base cases:
A prime range where the from is equal or greater to to is empty.
A prime range where n is 0 or less is empty.
Recursive cases:
If from is a prime, then the prime range is from, prepended to the result of calling primes-range starting from (+ from 1) and with (- n 1) elements.
Otherwise, the result is calling primes-range starting from (+ from 1) (still with n elements).

How to go about composing core functions, rather then using imperative style?

I have translated this code, the snippet below, from Python to Clojure. I replaced Python's while construct with Clojure's loop-recur here. But this doesn't look idiomatic.
(loop [d 2 [n & more] (list 256)]
(if (> n 1)
(recur (inc d)
(loop [x n sublist more]
(if (= (rem x d) 0)
(recur (/ x d) (conj sublist d))
(conj sublist x))))
(sort more)))
This routine gives me (3 3 31), that is prime factors of 279. For 256, it gives, (2 2 2 2 2 2 2 2), that means, 2^8.
Moreover, it performs worse for large values, say 987654123987546 instead of 279; whereas Python's counterpart works like charm.
How to start composing core functions, rather then translating imperative code as is? And specifically, how to improve this bit?
Thanks.
[Edited]
Here is the python code, I referred above,
def prime_factors(n):
factors = []
d = 2
while n > 1:
while n % d == 0:
factors.append(d)
n /= d
d = d + 1
return factors
A straight translation of the Python code in Clojure would be:
(defn prime-factors [n]
(let [n (atom n) ;; The Python code makes use of mutability which
factors (atom []) ;; isn't idiomatic in Clojure, but can be emulated
d (atom 2)] ;; using atoms
(loop []
(when (< 1 #n)
(loop []
(when (== (rem #n #d) 0)
(swap! factors conj #d)
(swap! n quot #d)
(recur)))
(swap! d inc)
(recur)))
#factors))
(prime-factors 279) ;; => [3 3 31]
(prime-factors 987654123987546) ;; => [2 3 41 14389 279022459]
(time (prime-factors 987654123987546)) ;; "Elapsed time: 13993.984 msecs"
;; same performance on my machine
;; as the Rosetta Code solution
You can improve this code to make it more idiomatic:
from nested loops to a single loop:
(loop []
(cond
(<= #n 1) #factors
(not= (rem #n #d) 0) (do (swap! d inc)
(recur))
:else (do (swap! factors conj #d)
(swap! n quot #d)
(recur))))))
get rid of the atoms:
(defn prime-factors [n]
(loop [n n
factors []
d 2]
(cond
(<= n 1) factors
(not= (rem n d) 0) (recur n factors (inc d))
:else (recur (quot n d) (conj factors d) d))))
replace == 0 by zero?:
(not (zero? (rem n d))) (recur n factors (inc d))
You can also overhaul it completely to make a lazy version of it:
(defn prime-factors [n]
((fn step [n d]
(lazy-seq
(when (< 1 n)
(cond
(zero? (rem n d)) (cons d (step (quot n d) d))
:else (recur n (inc d)))))
n 2))
I planned to have a section on optimization here, but I'm no specialist. The only thing I can say is that you can trivially make this code faster by interrupting the loop when d is greater than the square root of n:
(defn prime-factors [n]
(if (< 1 n)
(loop [n n
factors []
d 2]
(let [q (quot n d)]
(cond
(< q d) (conj factors n)
(zero? (rem n d)) (recur q (conj factors d) d)
:else (recur n factors (inc d)))))
[]))
(time (prime-factors 987654123987546)) ;; "Elapsed time: 7.124 msecs"
Not every loop unrolls cleanly into an elegant "functional" decomposition.
The Rosetta Code solution suggested by #edbond is pretty simple and concise; I would say it's idiomatic since no obvious "functional" solution is apparent. That solution runs noticeably faster on my machine than your Python version for 987654123987546.
More generally, if you're looking to expand your understanding of functional idioms, Bedra and Halloway's "Programming Clojure" (pp.90-95) presents an excellent comparison of different versions of the Fibonacci sequence, using loop, lazy seqs, and an elegant "functional" version. Chouser and Fogus's "Joy of Clojure" (MEAP version) also has a nice section on function composition.

Reversing an integer

I am trying to write a function which takes an input number and outputs the number in reverse order.
Ie:
Input -> 25
Output -> 52
Input -> 125
Output -> 521
I am new to lisp, if its helpful here is the working function in c++
function.cpp
int revs(int rev, int n)
{
if (n <= 0)
return rev;
return revs((rev * 10) + (n % 10), n/10);
}
I have written it in Racket as follows:
(define (revs rev n)
(if (<= n 0)
rev
(revs (+ (* rev 10) (modulo n 10)) (/ n 10))))
But when I run it with (revs 0 125) I get this error:
modulo: contract violation
expected: integer?
given: 25/2
argument position: 1st
other arguments...:
10
Certainly I am doing something incorrect here, but I am unsure of what I am missing.
The division operator / doesn't do integer division, but general division, so when you call, e.g., (/ 25 2), you don't get 12 or 13, but rather the rational 25/2. I think you'd want quotient instead, about which the documentation has:
procedure (quotient n m) → integer?
n : integer?
m : integer?
Returns (truncate (/ n m)). Examples:
> (quotient 10 3)
3
> (quotient -10.0 3)
-3.0
> (quotient +inf.0 3)
quotient: contract violation
expected: integer?
given: +inf.0
argument position: 1st
other arguments...:
3
Treating the operation lexicographically:
#lang racket
(define (lexicographic-reverse x)
(string->number
(list->string
(reverse
(string->list
(number->string x))))))
Works[1] for any of Racket's numerical types.
[edit 1] "Works," I realized, is context dependent and with a bit of testing shows the implicit assumptions of the operation. My naive lexicographic approach makes a mess of negative integers, e.g. (lexicographic-reverse -47) will produce an error.
However, getting an error rather than -74 might be better when if I am reversing numbers for lexicographic reasons rather than numerical ones because it illuminates the fact that the definition of "reversing a number" is arbitrary. The reverse of 47 could just as well be -74 as 74 because reversing is not a mathematical concept - even though it might remind me of XOR permutation.
How the sign is handled is by a particular reversing function is arbitrary.
#lang racket
;; Reversing a number retains the sign
(define (arbitrary1 x)
(define (f n)
(string->number
(list->string
(reverse
(string->list
(number->string n))))))
(if (>= x 0)
(f x)
(- (f (abs x)))))
;; Reversing a number reverses the sign
(define (arbitrary2 x)
(define (f n)
(string->number
(list->string
(reverse
(string->list
(number->string n))))))
(if (>= x 0)
(- (f x))
(f (abs x))))
The same considerations extend to Racket's other numerical type notations; decisions about reversing exact, inexact, complex, are likewise arbitrary - e.g. what is the reverse of IEEE +inf.0 or +nan.0?
Here is my solution for this problem
(define (reverseInt number)
(define (loop number reversedNumber)
(if (= number 0)
reversedNumber
(let ((lastDigit (modulo number 10)))
(loop (/ (- number lastDigit) 10) (+ (* reversedNumber 10) lastDigit)))))
(loop number 0))
Each time we multiply the reversed number by 10 and add the last digit of number.
I hope it makes sense.
A R6RS version (will work with R7RS with a little effort)
#!r6rs
(import (rnrs)
(srfi :8))
(define (numeric-reverse n)
(let loop ((acc 0) (n n))
(if (zero? n)
acc
(receive (q r) (div-and-mod n 10)
(loop (+ (* acc 10) r) q)))))
A Racket implementation:
#!racket
(require srfi/8)
(define (numeric-reverse n)
(let loop ((acc 0) (n n))
(if (zero? n)
acc
(receive (q r) (quotient/remainder n 10)
(loop (+ (* acc 10) r) q)))))
With recursion, you can do something like:
#lang racket
(define (reverse-num n)
(let f ([acc 0]
[n n])
(cond
[(zero? n) acc]
[else (f (+ (* acc 10) (modulo n 10)) (quotient n 10))])))

how to write a scheme program consumes n and sum as parameters, and show all the numbers(from 1 to n) that could sum the sum?

How to write a scheme program consumes n and sum as parameters, and show all the numbers(from 1 to n) that could sum the sum? Like this:
(find 10 10)
((10)
(9 , 1)
(8 , 2)
(7 , 3)
(7 ,2 , 1)
(6 ,4)
(6 , 3, 1)
(5 , 4 , 1)
(5 , 3 , 2)
(4 ,3 ,2 ,1))
I found one:
(define (find n sum)
(cond ((<= sum 0) (list '()))
((<= n 0) '())
(else (append
(find (- n 1) sum)
(map (lambda (x) (cons n x))
(find (- n 1) (- sum n)))))))
But it's inefficient,and i want a better one. Thank you.
The algorithm you are looking for is known as an integer partition. I have a couple of implementations at my blog.
EDIT: Oscar properly chastized me for my incomplete answer. As penance, I offer this answer, which will hopefully clarify a few things.
I like Oscar's use of streams -- as the author of SRFI-41 I should. But expanding the powerset only to discard most of the results seems a backward way of solving the problem. And I like the simplicity of GoZoner's answer, but not its inefficiency.
Let's start with GoZoner's answer, which I reproduce below with a few small changes:
(define (fs n s)
(if (or (<= n 0) (<= s 0)) (list)
(append (if (= n s) (list (list n))
(map (lambda (xs) (cons n xs))
(fs (- n 1) (- s n))))
(fs (- n 1) s))))
This produces a list of the output sets:
> (fs 10 10)
((10) (9 1) (8 2) (7 3) (7 2 1) (6 4) (6 3 1) (5 4 1) (5 3 2) (4 3 2 1))
A simple variant of that function produces the count instead of a list of sets, which shall be the focus of the rest of this answer:
(define (f n s)
(if (or (<= s 0) (<= n 0)) 0
(+ (if (= n s) 1
(f (- n 1) (- s n)))
(f (- n 1) s))))
And here is a sample run of the function, including timings on my ancient and slow home computer:
> (f 10 10)
10
> (time (f 100 100)
(time (f 100 ...))
no collections
1254 ms elapsed cpu time
1435 ms elapsed real time
0 bytes allocated
444793
That's quite slow; although it is fine for small inputs, it would be intolerable to evaluate (f 1000 1000), as the algorithm is exponential. The problem is the same as with the naive fibonacci algorithm; the same sub-problems are re-computed again and again.
A common solution to that problem is memoization. Fortunately, we are programming in Scheme, which makes it easy to encapsulate memoization in a macro:
(define-syntax define-memoized
(syntax-rules ()
((_ (f args ...) body ...)
(define f
(let ((results (make-hash hash equal? #f 997)))
(lambda (args ...)
(let ((result (results 'lookup (list args ...))))
(or result
(let ((result (begin body ...)))
(results 'insert (list args ...) result)
result)))))))))
We use hash tables from my Standard Prelude and the universal hash function from my blog. Then it is a simple matter to write the memoized version of the function:
(define-memoized (f n s)
(if (or (<= s 0) (<= n 0)) 0
(+ (if (= n s) 1
(f (- n 1) (- s n)))
(f (- n 1) s))))
Isn't that pretty? The only change is the addition of -memoized in the definition of the function; all of the parameters and the body of the function are the same. But the performance improves greatly:
> (time (f 100 100))
(time (f 100 ...))
no collections
62 ms elapsed cpu time
104 ms elapsed real time
1028376 bytes allocated
444793
That's an order-of-magnitude improvement with virtually no effort.
But that's not all. Since we know that the problem has "optimal substructure" we can use dynamic programming. Memoization works top-down, and must suspend the current level of recursion, compute (either directly or by lookup) the lower-level solution, then resume computation in the current level of recursion. Dynamic programming, on the other hand, works bottom-up, so sub-solutions are always available when they are needed. Here's the dynamic programming version of our function:
(define (f n s)
(let ((fs (make-matrix (+ n 1) (+ s 1) 0)))
(do ((i 1 (+ i 1))) ((< n i))
(do ((j 1 (+ j 1))) ((< s j))
(matrix-set! fs i j
(+ (if (= i j)
1
(matrix-ref fs (- i 1) (max (- j i) 0)))
(matrix-ref fs (- i 1) j)))))
(matrix-ref fs n s)))
We used the matrix functions of my Standard Prelude. That's more work than just adding -memoized to an existing function, but the payoff is another order-of-magnitude reduction in run time:
> (time (f 100 100))
(time (f 100 ...))
no collections
4 ms elapsed cpu time
4 ms elapsed real time
41624 bytes allocated
444793
> (time (f 1000 1000))
(time (f 1000 ...))
3 collections
649 ms elapsed cpu time, including 103 ms collecting
698 ms elapsed real time, including 132 ms collecting
15982928 bytes allocated, including 10846336 bytes reclaimed
8635565795744155161506
We’ve gone from 1254ms to 4ms, which is a rather astonishing range of improvement; the final program is O(ns) in both time and space. You can run the program at http://programmingpraxis.codepad.org/Y70sHPc0, which includes all the library code from my blog.
As a special bonus, here is another version of the define-memoized macro. It uses a-lists rather than hash tables, so it's very much slower than the version given above, but when the underlying computation is time-consuming, and you just want a simple way to improve it, this may be just what you need:
(define-syntax define-memoized
(syntax-rules ()
((define-memoized (f arg ...) body ...)
(define f
(let ((cache (list)))
(lambda (arg ...)
(cond ((assoc `(,arg ...) cache) => cdr)
(else (let ((val (begin body ...)))
(set! cache (cons (cons `(,arg ...) val) cache))
val)))))))))
This is a good use of quasi-quotation and the => operator in a cond clause for those who are just learning Scheme. I can't remember when I wrote that function -- I've had it laying around for years -- but it has saved me many times when I just needed a quick-and-dirty memoization and didn't care to worry about hash tables and universal hash functions.
This answer will appear tomorrow at my blog. Please drop in and have a look around.
This is similar to, but not exactly like, the integer partition problem or the subset sum problem. It's not the integer partition problem, because an integer partition allows for repeated numbers (here we're only allowing for a single occurrence of each number in the range).
And although it's more similar to the subset sum problem (which can be solved more-or-less efficiently by means of dynamic programming), the solution would need to be adapted to generate all possible subsets of numbers that add to the given number, not just one subset as in the original formulation of that problem. It's possible to implement a dynamic programming solution using Scheme, but it'll be a bit cumbersome, unless a matrix library or something similar is used for implementing a mutable table.
Here's another possible solution, this time generating the power set of the range [1, n] and checking each subset in turn to see if the sum adds to the expected value. It's still a brute-force approach, though:
; helper procedure for generating a list of numbers in the range [start, end]
(define (range start end)
(let loop ((acc '())
(i end))
(if (< i start)
acc
(loop (cons i acc) (sub1 i)))))
; helper procedure for generating the power set of a given list
(define (powerset set)
(if (null? set)
'(())
(let ((rest (powerset (cdr set))))
(append (map (lambda (element) (cons (car set) element))
rest)
rest))))
; the solution is simple using the above procedures
(define (find n sum)
(filter (lambda (s) (= sum (apply + s)))
(powerset (range 1 n))))
; test it, it works!
(find 10 10)
=> '((1 2 3 4) (1 2 7) (1 3 6) (1 4 5) (1 9) (2 3 5) (2 8) (3 7) (4 6) (10))
UPDATE
The previous solution will produce correct results, but it's inefficient in memory usage because it generates the whole list of the power set, even though we're interested only in some of the subsets. In Racket Scheme we can do a lot better and generate only the values as needed if we use lazy sequences, like this (but be aware - the first solution is still faster!):
; it's the same power set algorithm, but using lazy streams
(define (powerset set)
(if (stream-empty? set)
(stream '())
(let ((rest (powerset (stream-rest set))))
(stream-append
(stream-map (lambda (e) (cons (stream-first set) e))
rest)
rest))))
; same algorithm as before, but using lazy streams
(define (find n sum)
(stream-filter (lambda (s) (= sum (apply + s)))
(powerset (in-range 1 (add1 n)))))
; convert the resulting stream into a list, for displaying purposes
(stream->list (find 10 10))
=> '((1 2 3 4) (1 2 7) (1 3 6) (1 4 5) (1 9) (2 3 5) (2 8) (3 7) (4 6) (10))
Your solution is generally correct except you don't handle the (= n s) case. Here is a solution:
(define (find n s)
(cond ((or (<= s 0) (<= n 0)) '())
(else (append (if (= n s)
(list (list n))
(map (lambda (rest) (cons n rest))
(find (- n 1) (- s n))))
(find (- n 1) s)))))
> (find 10 10)
((10) (9 1) (8 2) (7 3) (7 2 1) (6 4) (6 3 1) (5 4 1) (5 3 2) (4 3 2 1))
I wouldn't claim this as particularly efficient - it is not tail recursive nor does it memoize results. Here is a performance result:
> (time (length (find 100 100)))
running stats for (length (find 100 100)):
10 collections
766 ms elapsed cpu time, including 263 ms collecting
770 ms elapsed real time, including 263 ms collecting
345788912 bytes allocated
444793
>

Performance of function in Clojure 1.3

I was wondering if someone could help me with the performance of this code snippet in Clojure 1.3. I am trying to implement a simple function that takes two vectors and does a sum of products.
So let's say the vectors are X (size 10,000 elements) and B (size 3 elements), and the sum of products are stored in a vector Y, mathematically it looks like this:
Y0 = B0*X2 + B1*X1 + B2*X0
Y1 = B0*X3 + B1*X2 + B2*X1
Y2 = B0*X4 + B1*X3 + B2*X2
and so on ...
For this example, the size of Y will end up being 9997, which corresponds to (10,000 - 3). I've set up the function to accept any size of X and B.
Here's the code: It basically takes (count b) elements at a time from X, reverses it, maps * onto B and sums the contents of the resulting sequence to produce an element of Y.
(defn filt [b-vec x-vec]
(loop [n 0 sig x-vec result []]
(if (= n (- (count x-vec) (count b-vec)))
result
(recur (inc n) (rest sig) (conj result (->> sig
(take (count b-vec))
(reverse)
(map * b-vec)
(apply +)))))))
Upon letting X be (vec (range 1 10001)) and B being [1 2 3], this function takes approximately 6 seconds to run. I was hoping someone could suggest improvements to the run time, whether it be algorithmic, or perhaps a language detail I might be abusing.
Thanks!
P.S. I have done (set! *warn-on-reflection* true) but don't get any reflection warning messages.
You are using count many times unnecessary. Below code calculate count one time only
(defn filt [b-vec x-vec]
(let [bc (count b-vec) xc (count x-vec)]
(loop [n 0 sig x-vec result []]
(if (= n (- xc bc))
result
(recur (inc n) (rest sig) (conj result (->> sig
(take bc)
(reverse)
(map * b-vec)
(apply +))))))))
(time (def b (filt [1 2 3] (range 10000))))
=> "Elapsed time: 50.892536 msecs"
If you really want top performance for this kind of calculation, you should use arrays rather than vectors. Arrays have a number of performance advantages:
They support O(1) indexed lookup and writes - marginally better than vectors which are O(log32 n)
They are mutable, so you don't need to construct new arrays all the time - you can just create a single array to serve as the output buffer
They are represented as Java arrays under the hood, so benefit from the various array optimisations built into the JVM
You can use primitive arrays (e.g. of Java doubles) which are much faster than if you use boxed number objects
Code would be something like:
(defn filt [^doubles b-arr
^doubles x-arr]
(let [bc (count b-arr)
xc (count x-arr)
rc (inc (- xc bc))
result ^doubles (double-array rc)]
(dotimes [i rc]
(dotimes [j bc]
(aset result i (+ (aget result i) (* (aget x-arr (+ i j)) (aget b-arr j))))))
result))
To follow on to Ankur's excellent answer, you can also avoid repeated calls to the reverse function, which gets us even a little more performance.
(defn filt [b-vec x-vec]
(let [bc (count b-vec) xc (count x-vec) bb-vec (reverse b-vec)]
(loop [n 0 sig x-vec result []]
(if (= n (- xc bc))
result
(recur (inc n) (rest sig) (conj result (->> sig
(take bc)
(map * bb-vec)
(apply +))))))))

Resources