Fastest algorithm of getting precise answer (not approximated) when square-rooting - algorithm

Sorry for unclear title, but I don't know how to state it properly (feel free to edit), so I will give example:
sqrt(108) ~ 10.39... BUT I want it to be like this sqrt(108)=6*sqrt(3) so it means expanding into two numbers
So that's my algorithm
i = floor(sqrt(number)) //just in case, floor returns lowest integer value :)
while (i > 0) //in given example number 108
if (number mod (i*i) == 0)
first = i //in given example first is 6
second = number / (i*i) //in given example second is 3
i = 0
i--
Maybe you know better algorithm?
If it matters I will use PHP and of course I will use appropriate syntax

There is no fast algorithm for this. It requires you to find all the square factors. This requires at least some factorizing.
But you can speed up your approach by quite a bit. For a start, you only need to find prime factors up to the cube root of n, and then test whether n itself is a perfect square using the advice from Fastest way to determine if an integer's square root is an integer.
Next speed up, work from the bottom factors up. Every time you find a prime factor, divide n by it repeatedly, accumulating out the squares. As you reduce the size of n, reduce your limit that you'll go to. This lets you take advantage of the fact that most numbers will be divisible by some small numbers, which quickly reduces the size of the number you have left to factor, and lets you cut off your search sooner.
Next performance improvement, start to become smarter about which numbers you do trial divisions by. For instance special case 2, then only test odd numbers. You've just doubled the speed of your algorithm again.
But be aware that, even with all of these speedups, you're just getting more efficient brute force. It is still brute force, and still won't be fast. (Though it will generally be much, much faster than your current idea.)
Here is some pseudocode to make this clear.
integer_sqrt = 1
remainder = 1
# First we special case 2.
while 0 == number % 4:
integer_sqrt *= 2
number /= 4
if 0 == number / 2:
number /= 2
remainder *= 2
# Now we run through the odd numbers up to the cube root.
# Note that beyond the cube root there is no way to factor this into
# prime * prime * product_of_bigger_factors
limit = floor(cube_root(number + 1))
i = 3
while i <= limit:
if 0 == number % i:
while 0 == number % (i*i):
integer_sqrt *= i
number /= i*i
if 0 == number % (i*i):
number /= i
remainder *= i
limit = floor(cube_root(number + 1))
i += 2
# And finally check whether we landed on the square of a prime.
possible_sqrt = floor(sqrt(number + 1))
if number == possible_sqrt * possible_sqrt:
integer_sqrt *= possible_sqrt
else:
remainder *= number
# And the answer is now integer_sqrt * sqrt(remainder)
Note that the various +1s are to avoid problems with the imprecision of floating point numbers.
Running through all of the steps of the algorithm for 2700, here is what happens:
number = 2700
integer_sqrt = 1
remainder = 1
enter while loop
number is divisible by 4
integer_sqrt *= 2 # now 2
number /= 4 # now 675
number is not divisible by 4
exit while loop
number is not divisible by 2
limit = floor(cube_root(number + 1)) # now 8
i = 3
enter while loop
i < =limit # 3 < 8
enter while loop
number is divisible by i*i # 9 divides 675
integer_sqrt *= 3 # now 6
number /= 9 # now 75
number is not divisible by i*i # 9 does not divide 75
exit while loop
i divides number # 3 divides 75
number /= 3 # now 25
remainder *= 3 # now 3
limit = floor(cube_root(number + 1)) # now 2
i += 2 # now 5
i is not <= limit # 5 > 2
exit while loop
possible_sqrt = floor(sqrt(number + 1)) # 5
number == possible_sqrt * possible_sqrt # 25 = 5 * 5
integer_sqrt *= possible_sqrt # now 30
# and now answer is integer_sqrt * sqrt(remainder) ie 30 * sqrt(3)

It's unlikely that there is a fast algorithm for this. See https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness especially https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness/16100#16100

List all prime divisors in increasing order e.g. 2700 = 2*2*3*3*3*5*5. This is the slowest step and requires sqrt(N) operations.
Create an accumulator (start with 1). Scan this list. For every pair of numbers, multiply the accumulator by (one of) them. So after scanning the list above, you get 2*3*5.
Accumulator is your multiplier. The rest remains under square root.

Related

Advanced Algorithms Problems ("Nice Triangle"): Prime number Pyramid where every number depends on numbers above it

I'm currently studying for an advanced algorithms and datastructures exam, and I simply can't seem to solve one of the practice-problems which is the following:
1.14) "Nice Triangle"
A "nice" triangle is defined in the following way:
There are three different numbers which the triangle consists of, namely the first three prime numbers (2, 3 and 5).
Every number depends on the two numbers below it in the following way.
Numbers are the same, resulting number is also the same. (2, 2 => 2)
Numbers are different, resulting number is the remaining number. (2, 3 => 5)
Given an integer N with length L, corresponding to the base of the triangle, determine the last element at the top
For example:
Given N = 25555 (and thus L = 5), the triangle looks like this:
2
3 5
2 5 5
3 5 5 5
2 5 5 5 5
=> 2 is the result of this example
What does the fact that every number is prime have to do with the problem?
By using a naive approach (simply calculating every single row), one obtains a time-complexity of O(L^2).
However, the professor said, it's possible with O(L), but I simply can't find any pattern!!!
I'm not sure why this problem would be used in an advanced algorithms course, but yes, you can do this in O(l) = O(log n) time.
There are a couple ways you can do it, but they both rely on recognizing that:
For the problem statement, it doesn't matter what digits you use. Lets use 0, 1, and 2 instead of 2, 3, and 5. Then
If a and b are the input numbers and c is the output, then c = -(a+b) mod 3
You can build the whole triangle using c = a+b mod 3 instead, and then just negate every second row.
Now the two ways you can do this in O(log n) time are:
For each digit d in the input, calculate the number of times (call it k) that it gets added into the final sum, add up all the kd mod 3, and then negate the result if you started with an even number of digits. That takes constant time per digit. Alternatively:
recognize that you can do arithmetic on n-sized values in constant time. Make a value that is a bit mask of all the digits in n. That takes 2 bits each. Then by using bitwise operations you can calculate each row from the previous one in constant time, for O(log n) time altogether.
Here's an implementation of the 2nd way in python:
def niceTriangle(n):
# a vector of 3-bit integers mod 3
rowvec = 0
# a vector of 1 for each number in the row
onevec = 0
# number of rows remaining
rows = 0
# mapping for digits 0-9
digitmap = [0, 0, 0, 1, 1, 2, 2, 2, 2, 2]
# first convert n into the first row
while n > 0:
digit = digitmap[n % 10]
n = n//10
rows += 1
onevec = (onevec << 3) + 1
rowvec = (rowvec << 3) + digit
if rows%2 == 0:
# we have an even number of rows -- negate everything
rowvec = ((rowvec&onevec)<<1) | ((rowvec>>1)&onevec)
while rows > 1:
# add each number to its neighbor
rowvec += (rowvec >> 3)
# isolate the entries >= 3, by adding 1 to each number and
# getting the 2^2 bit
gt3 = ((rowvec + onevec) >> 2) & onevec
# subtract 3 from all the greater entries
rowvec -= gt3*3
rows -= 1
return [2,3,5][rowvec%4]

Running time/time complexity for while loop with square root

This question looks relatively simple, but I can't seem to find the running time in terms of n.
Here is the problem:
j = n;
while(j >= 2) {
j = j^(1/2)
}
I don't really need the total running time, I just need to know how to calculate the amount of times the second and third lines are hit (they should be the same). I'd like to know if there is some sort of formula for finding this, as well. I can see that the above is the equivalent of:
for(j = n; n >= 2; j = j^(1/2)
Please note that the type of operation doesn't matter, each time a line is executed, it counts as 1 time unit. So line 1 would just be 1 time unit, line 2 would be:
0 time units if n were 1,
1 time unit if n were 2,
2 time units if n were 4,
3 time units if n were 16, etc.
Thanks in advance to anyone who offers help! It is very much appreciated!
Work backwards to get the number of time units for line 2:
time
n n log_2(n) units
1 1 0 0
2 2 1 1
4 4 2 2
16 16 4 3
16^2 256 8 4
(16^2)^2 65536 16 5
((16^2)^2)^2) ... 32 6
In other words, for the number of time units t, n is 2^(2^(t-1)) except for the case t = 0 in which case n = 1.
To reverse this, you have
t = 0 when n < 2
t = log2(log2(n)) + 1 when n >= 2
where log2(x) is known as the binary logarithm of x.

Most efficient way to add individual digits of a number

I am working on an algorithm to determine whether a given number is prime and came across this website. But then I though of trying my own logic. I can easily eliminate numbers ending in 2,4,5,6,8 (and 0 for numbers above 5), so I am left with 1,3,7 and 9 as the possible last digit. Now, if the last digit is 3, I can add up the individual digits to check if it is divisible by 3. I don't want to perform modulus(%) operation and add them. Is there a much more efficient way to sum the digits in a decimal number? Maybe using bitwise operations... ?
% or modulus operator would be faster than adding individul digits. But if you really want to do this, you can unroll your loop partly in such a way that multiples of 3 are escaped automatically.
For ex:
2 is prime
3 is prime
candidate = 5
while(candidate <= limit - 2 * 3) // Unrolling loop for next 2 * 3 number
{
if ( CheckPrime(candidate) ) candidate is prime;
candidate += 2;
if ( CheckPrime(candidate) ) candidate is prime;
candidate += 4; // candidate + 2 is multiple of 3 (9, 15, 21 etc)
}
if(candidate < limit) CheckPrime(candidate);
In above method we are eliminating multiples of 3 instead of checking the divisibility of 3 by adding the digits.
You had a good observation. Incidentally it is called wheel factorization to find prime. I have done for wheel size = 6 (2*3), but you can do the same for larger wheel size also, for ex: 30(2*3*5). The snippet above is also called as all prime number are of type 6N±1.
(because 6N+3 is multiple of 3)
p.s. Not all numbers ending at 2 and 5 are composite. Number 2 and 5 are exceptions.
You might consider the following but i think modulus is fastest way :-
1. 2^n mod 3 = 1 if n is even and = 2 if n is odd
2. odd bits and even bits cancel each out as their sum is zero modulo 3
4. so the absolute difference of odd and even bits is the remainder
5. As difference might be again greater than 3 you need to again calculate modulo 3
6. step 5 can be done recursively
Pseudo code :-
int modulo3(int num) {
if(num<3)
return num;
int odd_bits = cal_odd(num);
int even_bits = cal_even(num);
return module3(abs(even_bits-odd_bits));
}

the number of trailing zeros in a factorial of a given number - Ruby

Having a little trouble trying calculate the number of trailing zeros in a factorial of a given number. This is one of the challenges from Codewars- can't get mine to pass.
zeros(12) = 2 #=> 1 * 2 * 3 .. 12 = 479001600
I think I'm on the wrong path here and there is probably a more elegant ruby way. This is what I have down so far.
def zeros(n)
x = (1..n).reduce(:*).to_s.scan(/[^0]/)
return 0 if x == []
return x[-1].length if x != []
end
This is more of a math question. And you're right, you are off on a wrong path. (I mean the path you are on is going to lead to a very inefficient solution)
Try to reduce the problem mathematically first. (BTW you are shooting for a log N order algorithm.)
In my answer I will try to skip a few steps, because it seems like a homework question.
The number of trailing zeros is going to be equal to the total power of 5s in the multiplication of the series.
the numbers between 1 and n will have n/5, n/25, n/125 numbers which are multiples of 5s, 25s, 125s respectively... and so on.
Try to take these hints and come up with an algorithm to count how many powers of 10 will be crammed in to that factorial.
Spoilers Ahead
I've decided to explain in detail below so if you want to try and solve it yourself then stop reading, try to think about it and then come back here.
Here is a step by step reduction of the problem
1.
The number of trailing zeros in a number is equivalent to the power of 10 in the factor of that number
e.g.
40 = 4 * 10^1 and it has 1 trailing zero
12 = 3 * 4 * 10^0 so it has 0 trailing zeros
1500 = 3 * 5 * 10^2 so it has 2 trailing zeros
2.
The number power of 10 in the factors is the same as the minimum of the power of 2 and power of 5 in the factors
e.g.
50 = 2^1 * 5^2 so the minimum power is 1
300 = 3^1 * 2^2 * 5^2 so the minimum is 2 (we are only concerned with the minimum of the powers of 2 and 5, so ignore powers of 3 and all other prime factors)
3.
In any factorial there will be many more powers of 2 than the powers of 5
e.g.
5! = 2^3 * 3^1 * 5^1
10! = 2^8 * 3^4 * 5^2 * 7^1
As you can see the power of 2 is going to start increasing much faster so the power of 5 will be the minimum of the two.
Hence all we need to do is count the power of 5 in the factorial.
4.
Now lets focus on the power of 5 in any n!
4! ~ 5^0
5! ~ 5^1 (up to 9!)
10! ~ 5^2 (up to 14!)
15! ~ 5^3 (up to `19!)
20! ~ 5^4 (up to 24!)
25! ~ 5^6 (notice the jump from 5^4 to 5^6 because the number 25 adds two powers of 5)
5.
The way I'd like to count the total power of five in a factorial is... count all the multiples of 5, they all add one power of 5. Then count all the multiples of 25, they all add an extra power of 5. Notice how 25 added two powers of 5, so I can put that as, one power because it's a multiple of 5 and one extra power because it's a multiple of 25. Then count all the multiple of 125 (5^3) in the factorial multiplication, they add another extra power of 5... and so on.
6.
So how'd you put that as an algorithm ?
lets say the number is n. So...
pow1 = n/5 (rounded down to an integer)
pow2 = n/25
pow3 = n/125
and so on...
Now the total power pow = pow1 + pow2 + pow3 ...
7.
Now can you express that as a loop?
So, now that #Spunden has so artfully let the cat out of the bag, here's one way to implement it.
Code
def zeros(n)
return 0 if n.zero?
k = (Math.log(n)/Math.log(5)).to_i
m = 5**k
n*(m-1)/(4*m)
end
Examples
zeros(3) #=> 0
zeros(5) #=> 1
zeros(12) #=> 2
zeros(15) #=> 3
zeros(20) #=> 4
zeros(25) #=> 6
zeros(70) #=> 16
zeros(75) #=> 18
zeros(120) #=> 28
zeros(125) #=> 31
Explanation
Suppose n = 128.
Then each number between one and 128 (inclusive) that is divisible by 5^1=>5 provides at least one factor, and there are 128/5 => 25 such numbers. Of these, the only ones that provide more than one factor are those divisible by 5^2=>25, of which there are 128/25 => 5 (25, 50, 75, 100, 125). Of those, there is but 128/125 => 1 that provides more than two factors, and since 125/(5^4) => 0, no numbers contribute more than three divisors. Hence, the total number of five divisors is:
128/5 + 128/25 + 128/125 #=> 31
(Note that, for 125, which has three divisors of 5, one is counted in each of these three terms; for 25, 50, etc., which each have two factors of 5, one is counted in each of the first terms.)
For arbitrary n, we first compute the highest power k for which:
5**k <= n
which is:
k <= Math.log(n)/Math.log(5)
so the largest such value is:
k = (Math.log(n)/Math.log(5)).to_i
As #spundun noted, you could also calculate k by simply iterating, e.g.,
last = 1
(0..1.0/0).find { |i| (last *= 5) > n }
The total number of factors of five is therefore
(n/5) + (n/25) +...+ (n/5**k)
Defining:
r = 1/5,
this sum is seen to be:
n * s
where
s = r + r**2 +...+ r**k
The value of s is the sum of the terms of a geometric series. I forget the formula for that, but recall how it's derived:
s = r + r**2 +...+ r**k
sr = r**2 +...+ r**(k+1)
s-sr = r*(1-r**k)
s = r*(1-r**k)/(1-r)
I then did some rearrangement so that only only integer arithmetic would be used to calculate the result.
def zeros(n)
zeros = 0
zeros += n /= 5 while n >= 1
zeros
end
If N is a number then number of trailing zeroes in N! is
N/5 + N/5^2 + N/5^3 ..... N/5^(m-1) WHERE (N/5^m)<1
You can learn here how this formula comes.
Here's a solution that is easier to read:
def zeros(num)
char_array = num.to_s.split('')
count = 0
while char_array.pop == "0"
count += 1
end
count
end
Let me know what you think and feel free to edit if you see an improvement!
The article A Note on Factorial and its Trailing Zeros in GanitCharcha is insightful and has explained the Mathematics behind this well. Take a look.
http://www.ganitcharcha.com/view-article-A-Note-on-Factorial-and-it's-Trailing-Zeros.html
My solution
def zeros(n)
trailing_zeros = []
fact = (1..n).inject(:*)
fact.to_s.split('').reverse.select {|x| break if (x.to_i != 0); trailing_zeros << x}
return trailing_zeros.count
end
n = int (raw_input())
count = 0
num = 1
for i in xrange(n+1):
if i != 0:
num = num * i
while(num >= 10):
if num%10 == 0:
count+=1
num = num/10
else:
break
print count
As per the explanation given by #spundan and apart from #cary's code you can find number of trailing zero by just very simple and efficient way..see below code..
def zeros(n)
ret = 0
while n > 0 do
ret += n / 5
n = n/5
end
ret
end
For example zeros(100000000) this will give you output -> 24999999
With the time Time Elapsed -> 5.0453e-05(Just See 5.0453e-05 )
This is the part of even milliseconds.
n=int(input())
j=5
c=int(0)
while int(n/j)>0:
c=c+int(n/j)
j=j*5
print(c)
count = 0
i =5
n = 100
k = n
while(n/i!=0):
count+=(n/i)
i=i*5
n = k
print count
def zeros(n)
n < 5 ? 0 : (n / 5) + zeros(n / 5)
end

No of numbers less than a given number with no repeating digits

How can we find the number of numbers less than a given number with no repeating digits in it?
For example the number of such numbers less than 100 is 90. (11, 22, 33,44, 55,66,77,88,99 have repeating digits so are excluded).
Similarly for less than 1000, digits like 101, 110, 122, 202 etc have to be excluded.
Here is a way to make it quicker. Notice that there is a correlation between the number of digits in the max number and the solution (number of numbers which I will call NON)
100 (3 digits) => NON = 10 * 9
1000 (4 digits) => NON = 10 * 9 * 8
10000 (5 digits) => NON = 10 * 9 * 8 * 7
...
10000000000 (11 digits) => NON = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
after one billion you're bound to repeat a digit
You can consider two cases:
numbers shorter than the limit
numbers that that differ from the limit at some digit
The count of d-digit numbers is 9*9*8*... = 9*9!/(9-d)! (the first digit may not be zero). The count of all numbers shorter than d is the count of 0-digit numbers + .. count of d-1-digit numbers. These sums may be precomputed (or even hard-coded).
The count of d-digit numbers with f first digits given is (10-f)*...*(10-(d-1)) = (10-f)!/(10-d)!. You can precomupte the factorials as well.
Pseudocode :
To precompute fac:
- fac = int[10];
- fac[0] = 1;
- for i in 1..10:
- fac[i] = fac[i-1] * i;
To precompute count_shorter:
- cs = int[10];
- cs[0] = 0;
- cs[1] = 1; // if zero is allowed
- for i in 1..10:
- cs[i+1] = cs[i] + 9 * fac[9] / fac[10-i]
- count_shorter = cs;
To determine the count of numbers smaller than d:
- sl = strlen(d)
- if sl > 10
- return count_shorter[11]
- else
- sum = 0
account for shorter numbers:
- sum += count_shorter[sl]
account for same-length numbers; len=count of digits shared with the limit:
- sum += 9* fac[9] / fac[10-sl];
- for every len in 1..{sl-1}:
count the unused digits less than d[len]; credits to #MvG for noting:
- first_opts = d[len]-1;
- for every i in 0..{len-1}:
- if d[i] < d[len]
- first_opts -= 1;
- sum += first_opts * fac[9-len] / fac[10-sl]
- return sum
Here is some code that does this. Comments in the code. The basic idea is that you iterate over the digits of the last counted number one at a time, and for every digit position you can count the numbers that have the same digits prior to that position but a smaller digit at that current position. The functions build upon one another, so the cntSmaller function at the very end is the one you'd actually call, and also the one with the most detailed comments. I've checked that this agrees with a brute-force implementation for all arguments up to 30000. I've done extensive comparisons against alternate implementations, so I'm fairly confident that this code is correct.
from math import factorial
def take(n, r):
"""Count ways to choose r elements from a set of n without
duplicates, taking order into account"""
return factorial(n)/factorial(n - r)
def forLength(length, numDigits, numFirst):
"""Count ways to form numbers with length non-repeating digits
that take their digits from a set of numDigits possible digits,
with numFirst of these as possible choices for the first digit."""
return numFirst * take(numDigits - 1, length - 1)
def noRepeated(digits, i):
"""Given a string of digits, recursively compute the digits for a
number which is no larger than the input and has no repeated
digits. Recursion starts at i=0."""
if i == len(digits):
return True
while digits[i] in digits[:i] or not noRepeated(digits, i + 1):
digits[i] -= 1
for j in range(i + 1, len(digits)):
digits[j] = 9
if digits[i] < 0:
digits[i] = 9
return False
return True
def lastCounted(n):
"""Compute the digits of the last number that is smaller than n
and has no repeated digits."""
digits = [int(i) for i in str(n - 1)]
while not noRepeated(digits, 0):
digits = [9]*(len(digits) - 1)
while digits[0] == 0:
digits = digits[1:]
assert len(digits) == len(set(digits))
return digits
def cntSmaller(n):
if n < 2:
return 0
digits = lastCounted(n)
cnt = 1 # the one from lastCounted is guaranteed to get counted
l = len(digits)
for i in range(1, l):
# count all numbers with less digits
# first digit non-zero, rest all other digits
cnt += forLength(i, 10, 9)
firstDigits = set(range(10))
for i, d in enumerate(digits):
# count numbers which are equal to lastCounted up to position
# i but have a smaller digit at position i
firstHere = firstDigits & set(range(d)) # smaller but not duplicate
if i == 0: # this is the first digit
firstHere.discard(0) # must not start with a zero
cnt += forLength(l - i, 10 - i, len(firstHere))
firstDigits.discard(d)
return cnt
Edit: cntSmaller(9876543211) returns 8877690 which is the maximum number of numbers you can form with non-repeating digits. The fact that this is more than 10!=3628800 had me confused for a while, but this is correct: when you consider your sequences padded to length 10, then sequences of leading zeros are allowed in addition to a zero somewhere in the number. This increases the count above that of the pure permutations.

Resources