Is there any way of optimizing a multiplication loop? - algorithm

Let's say I have to repeat the process of multiplying a variable by a constant and modulus the result by another constant, n times to get my desired result.
the obvious solution is iterating n times, but it's getting time consuming the greater n is.
Code example:
const N = 1000000;
const A = 123;
const B = 456;
var c = 789;
for (var i = 0; i < n; i++)
{
c = (c * a) % b;
}
log("Total: " + c);
Is there any algebraic solution to optimize this loop?

% has two useful properties:
1) (x % b) % b = x % b
2) (c*a) % b = ((c%b) * (a%b))%b
This implies that e.g.
(((c*a)%b)*a) % b = ((((c*a)%b)%b) * (a%b)) % b
= (((c*a) % b) * (a%b)) % b
= (c*a*a) % b
= (c*a^2) % b
Hence, in your case the final c that you compute is equivalent to
(c*a^n)%b
This can be computed efficiently using exponentiation by squaring.
To illustrate this equivalence:
def f(a,b,c,n):
for i in range(n):
c = (c*a)%b
return c
def g(a,b,c,n):
return (c*pow(a,n,b)) % b
a = 123
b = 456
c = 789
n = 10**6
print(f(a,b,c,n),g(a,b,c,n)) #prints 261, 261

First, note that c * A^n is never an exact multiple of B = 456 since the former is always odd and the latter is always even. You can generalize this by considering the prime factorizations of the numbers involved and see that no repetition of the factors of c and A will ever give you something that contains all the factors of B. This means c will never turn into 0 as a result of the iterated multiplication.
There are only 456 possible values for c * a mod B = 456; therefore, if you iterate the loop 456 times, you will see at least value of c repeated. Suppose the first value of c that repeats is c', when i= i'. Say it first saw c' when i=i''. By continuing to iterate the multiplication, we would expect to see c' again:
we saw it at i''
we saw it at i'
we should see it at i' + (i' - i'')
we should see it at i' + k(i' - i'') as well
Once you detect a repeat you know that pattern is going to repeat forever. Therefore, you can compute how many patterns are needed to get to N, and the offset in the repeating pattern that you'd be at for i = N - 1, and then you'd know the answer without actually performing the multiplications.
A simpler example:
A = 2
B = 3
C = 5
c[0] = 5
c[1] = 5 * 2 % 3 = 1
c[2] = 1 * 2 % 3 = 2
c[3] = 2 * 2 % 3 = 1 <= duplicate
i' = 3
i'' = 1
repeating pattern: 1, 2, 1
c[1+3k] = 1
c[2+3k] = 2
c[3+3k] = 1
10,000 = 1 + 3k for k = 3,333
c[10,000] = 1
c[10,001] = 2
c[10,002] = 1

Related

Fastest way to build matrix with concentric "rings" of values

Say I have a vector Q = [Q1 Q2 .... QN].
I would like to create a matrix A such that the kth "ring" of the matrix is equal to Qk, with the following constraint:
if N is odd, the central patch is composed of one number, which is QN
For Q = [12 3 27] this would be :
A =
12 12 12 12 12
12 3 3 3 12
12 3 27 3 12
12 3 3 3 12
12 12 12 12 12
if N is even, the central patch is a 2x2 patch where QN gets repeated
for Q = [12 3] this would be
A =
12 12 12 12
12 3 3 12
12 3 3 12
12 12 12 12
Two for loops
Two for loops work but it is too slow (~13,3s for 5000x5000 matrices) (Code below) :
%% Two for loops :
% Generate random integer vector Q with unique values
N = 5;
n = 15 * N;
Q = randperm(n,N).';
% Double for loop method
if mod(N,2)==1
mSize = 2*N-1;
else
mSize = 2*N;
end
A = zeros(mSize);
for ii=1:(mSize)
for jj=1:(mSize)
IDX = min([ii,jj,mSize-ii+1,mSize-jj+1]);
A(ii,jj) = Q(IDX);
end
end
Faster approach
I have found a faster approach, which is pretty good (~1.46s for 5000x5000 matrices) but there might still be some room for improvement :
if mod(N,2)==1
mSize = 2*N-1;
I_idx = (1:mSize)-N;
A_fast = Q(end-max(abs(I_idx.'),abs(I_idx)));
else
I_idx = [(N-1):-1:0 0:(N-1)];
A_fast = Q(end-max(I_idx.',I_idx));
end
Any ideas?
The logic of the code is lightly simpler if you follow the advice in Wolfie's comment, and compute only one quadrant that you repeat:
I_idx = 1:N;
B = Q(min(I_idx,I_idx.'));
if mod(N,2)==1
B = [B,B(:,end-1:-1:1)]; % same as [B,fliplr(B(:,1:end-1))]
B = [B;B(end-1:-1:1,:)]; % same as [B;flipud(B(1:end-1,:))]
else
B = [B,fliplr(B)];
B = [B;flipud(B)];
end
This is 2-2.5 times as fast depending on whether Q is even or odd-sized.
Steve's comment suggest building a triangle first, but I don't see that being any faster, due to the complexity of indexing a matrix's upper or lower triangle.
Testing code:
N = 5000;
n = 15 * N;
Q = randperm(n,N).';
tic
if mod(N,2)==1
mSize = 2*N-1;
I_idx = (1:mSize)-N;
A = Q(end-max(abs(I_idx.'),abs(I_idx)));
else
I_idx = [(N-1):-1:0 0:(N-1)];
A = Q(end-max(I_idx.',I_idx));
end
toc
tic
I_idx = 1:N;
B = Q(min(I_idx,I_idx.'));
if mod(N,2)==1
B = [B,B(:,end-1:-1:1)];
B = [B;B(end-1:-1:1,:)];
else
B = [B,fliplr(B)];
B = [B;flipud(B)];
end
toc
isequal(A,B)
I came up with a solution using repmat, then flipping along a diagonal to get a quarter of the solution, finally flipping and reversing twice to get the full output matrix.
function A = flip_it_and_reverse_it(Q)
N = length(Q);
QQ = repmat(Q(:), 1, N);
quarter_A = triu(QQ) + triu(QQ, 1).';
half_A = [quarter_A, quarter_A(:, end-1:-1:1)];
A = [half_A; half_A(end-1:-1:1, :)];
end
There may be improvements that can be made to get faster flips/reverses with some clever transposes.
For the even case in your updated question, the indices in the lines starting half_A and A should be end:-1:1 instead of end-1:-1:1.
Running some quick timings, it looks like my solution is comprable (sometimes slightly slower) to your faster approach:
N = 5000;
n = 15 * N;
Q = randperm(n,N).';
disp('double loop')
tic
double_loop(Q);
disp(toc)
disp('faster approach')
tic
faster_approach(Q);
disp(toc)
disp('flip_it_and_reverse_it')
tic
flip_it_and_reverse_it(Q);
disp(toc)
Results:
double loop
14.4767
faster approach
1.8137
flip_it_and_reverse_it
1.6556
Note: sometimes faster_approach wins, sometimes flip - I've got some other jobs running on my laptop.

Algorithm to finding if the numbers in the list, when added or subtracted, are equal to a mod b

I was doing some interview problems when I ran into an interesting one that I could not think of a solution for. The problems states:
Design a function that takes in an array of integers. The last two numbers
in this array are 'a' and 'b'. The function should find if all of the
numbers in the array, when summed/subtracted in some fashion, are equal to
a mod b, except the last two numbers a and b.
So, for example, let us say we have an array:
array = [5, 4, 3, 3, 1, 3, 5].
I need to find out if there exists any possible "placement" of +/- in this array so that the numbers can equal 3 mod 5. The function should print True for this array because 5+4-3+3-1 = 8 = 3 mod 5.
The "obvious" and easy solution would be to try and add/subtract everything in all possible ways, but that is an egregiously time complex solution, maybe
O(2n).
Is there any way better to do this?
Edit: The question requires the function to use all numbers in the array, not any. Except, of course, the last two.
If there are n numbers, then there is a simple algorithm that runs in O (b * n): For k = 2 to n, calculate the set of integers x such that the sum or difference of the first k numbers is equal to x modulo b.
For k = 2, the set contains (a_0 + a_1) modulo b and (a_0 - a_1) modulo b. For k = 3, 4, ..., n you take the numbers in the previous set, then either add or subtract the next number in the array. And finally check if a is element of the last set.
O(b * n). Let's take your example, [5, 4, 3, 3, 1]. Let m[i][j] represent whether a solution exists for j mod 5 up to index i:
i = 0:
5 = 0 mod 5
m[0][0] = True
i = 1:
0 + 4 = 4 mod 5
m[1][4] = True
but we could also subtract
0 - 4 = 1 mod 5
m[1][1] = True
i = 2:
Examine the previous possibilities:
m[1][4] and m[1][1]
4 + 3 = 7 = 2 mod 5
4 - 3 = 1 = 1 mod 5
1 + 3 = 4 = 4 mod 5
1 - 3 = -2 = 3 mod 5
m[2][1] = True
m[2][2] = True
m[2][3] = True
m[2][4] = True
i = 3:
1 + 3 = 4 mod 5
1 - 3 = 3 mod 5
2 + 3 = 0 mod 5
2 - 3 = 4 mod 5
3 + 3 = 1 mod 5
3 - 3 = 0 mod 5
4 + 3 = 2 mod 5
4 - 3 = 1 mod 5
m[3][0] = True
m[3][1] = True
m[3][2] = True
m[3][3] = True
m[3][4] = True
We could actually stop there, but let's follow a different solution than the one in your example backwards:
i = 4:
m[3][2] True means we had a solution for 2 at i=3
=> 2 + 1 means m[4][3] = True
+ 1
+ 3
+ 3
- 4
(0 - 4 + 3 + 3 + 1) = 3 mod 5
I coded a solution based on the mathematical explanation provided here. I didn't comment the solution, so if you want an explanation, I recommend you read the answer!
def kmodn(l):
k, n = l[-2], l[-1]
A = [0] * n
count = -1
domath(count, A, l[:-2], k, n)
def domath(count, A, l, k, n):
if count == len(l):
boolean = A[k] == 1
print boolean
elif count == -1:
A[0] = 1; # because the empty set is possible
count += 1
domath(count, A, l, k, n)
else:
indices = [i for i, x in enumerate(A) if x == 1]
b = [0] * n
for i in indices:
idx1 = (l[count] + i) % n
idx2 = (i - l[count]) % n
b[idx1], b[idx2] = 1, 1
count += 1
A = b
domath(count, A, l, k, n)

Finding the largest power of a number that divides a factorial in haskell

So I am writing a haskell program to calculate the largest power of a number that divides a factorial.
largestPower :: Int -> Int -> Int
Here largestPower a b has find largest power of b that divides a!.
Now I understand the math behind it, the way to find the answer is to repeatedly divide a (just a) by b, ignore the remainder and finally add all the quotients. So if we have something like
largestPower 10 2
we should get 8 because 10/2=5/2=2/2=1 and we add 5+2+1=8
However, I am unable to figure out how to implement this as a function, do I use arrays or just a simple recursive function.
I am gravitating towards it being just a normal function, though I guess it can be done by storing quotients in an array and adding them.
Recursion without an accumulator
You can simply write a recursive algorithm and sum up the result of each call. Here we have two cases:
a is less than b, in which case the largest power is 0. So:
largestPower a b | a < b = 0
a is greater than or equal to b, in that case we divide a by b, calculate largestPower for that division, and add the division to the result. Like:
| otherwise = d + largestPower d b
where d = (div a b)
Or putting it together:
largestPower a b | a < b = 1
| otherwise = d + largestPower d b
where d = (div a b)
Recursion with an accumuator
You can also use recursion with an accumulator: a variable you pass through the recursion, and update accordingly. At the end, you return that accumulator (or a function called on that accumulator).
Here the accumulator would of course be the running product of divisions, so:
largestPower = largestPower' 0
So we will define a function largestPower' (mind the accent) with an accumulator as first argument that is initialized as 1.
Now in the recursion, there are two cases:
a is less than b, we simply return the accumulator:
largestPower' r a b | a < b = r
otherwise we multiply our accumulator with b, and pass the division to the largestPower' with a recursive call:
| otherwise = largestPower' (d+r) d b
where d = (div a b)
Or the full version:
largestPower = largestPower' 1
largestPower' r a b | a < b = r
| otherwise = largestPower' (d+r) d b
where d = (div a b)
Naive correct algorithm
The algorithm is not correct. A "naive" algorithm would be to simply divide every item and keep decrementing until you reach 1, like:
largestPower 1 _ = 0
largestPower a b = sumPower a + largestPower (a-1) b
where sumPower n | n `mod` b == 0 = 1 + sumPower (div n b)
| otherwise = 0
So this means that for the largestPower 4 2, this can be written as:
largestPower 4 2 = sumPower 4 + sumPower 3 + sumPower 2
and:
sumPower 4 = 1 + sumPower 2
= 1 + 1 + sumPower 1
= 1 + 1 + 0
= 2
sumPower 3 = 0
sumPower 2 = 1 + sumPower 1
= 1 + 0
= 1
So 3.
The algorithm as stated can be implemented quite simply:
largestPower :: Int -> Int -> Int
largestPower 0 b = 0
largestPower a b = d + largestPower d b where d = a `div` b
However, the algorithm is not correct for composite b. For example, largestPower 10 6 with this algorithm yields 1, but in fact the correct answer is 4. The problem is that this algorithm ignores multiples of 2 and 3 that are not multiples of 6. How you fix the algorithm is a completely separate question, though.

Algorithm for checking if number is factorable into a set of prime numbers

I was wondering if there is an algorithm that checks wether a given number is factorable into a set of prime numbers and if no give out the nearest number.
The problem comes always up when I use the FFT.
Thanks a lot for your help guys.
In general this looks like a hard problem, particularly finding the next largest integer that factors into your set of primes. However, if your set of primes isn't too big, one approach would be to turn this into an integer optimization problem by taking the logs. Here is how to find the smallest number > n that factors into a set of primes p_1...p_k
choose integers x_1,...,x_k to minimize (x_1 log p_1 + ... + x_k log p_k - log n)
Subject to:
x_1 log p_1 + ... + x_k log p_k >= log n
x_i >= 0 for all i
The x_i will give you the exponents for the primes. Here is an implementation in R using lpSolve:
minfact<-function(x,p){
sol<-lp("min",log(p),t(log(p)),">=",log(x),all.int=T)
prod(p^sol$solution)
}
> p<-c(2,3,13,31)
> x<-124363183
> y<-minfact(x,p)
> y
[1] 124730112
> factorize(y)
Big Integer ('bigz') object of length 13:
[1] 2 2 2 2 2 2 2 2 3 13 13 31 31
> y-x
[1] 366929
>
Using big integers, this works pretty well even for large numbers:
> p<-c(2,3,13,31,53,79)
> x<-as.bigz("1243631831278461278641361")
> y<-minfact(x,p)
y
>
Big Integer ('bigz') :
[1] 1243634072805560436129792
> factorize(y)
Big Integer ('bigz') object of length 45:
[1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
[26] 2 2 2 2 2 2 2 2 3 3 3 3 13 31 31 31 31 53 53 53
>
Your question is about well-known factorization problem - which could not be resolved with 'fast' (polynomial) time. Lenstra's elliptic algorithm is the most efficient (known) way in common case, but it requires strong knowledge of numbers theory - and it's also sub-exponential (but not polynomial).
Other algorithms are listed in the page by first link in my post, but such things as direct try (brute force) are much more slower, of cause.
Please, note, that under "could not be resolved with polynomial time" - I mean that there's no way to do this now - but not that such way does not exist (at least now, number theory can not provide such solution for this problem)
Here is a brute force method in C++. It returns the factorization of the nearest factorable number. If N has two equidistant factorable neighbours, it returns the smallest one.
GCC 4.7.3: g++ -Wall -Wextra -std=c++0x factorable-neighbour.cpp
#include <iostream>
#include <vector>
using ints = std::vector<int>;
ints factor(int n, const ints& primes) {
ints f(primes.size(), 0);
for (int i = 0; i < primes.size(); ++i) {
while (0< n && !(n % primes[i])) {
n /= primes[i];
++f[i]; } }
// append the "remainder"
f.push_back(n);
return f;
}
ints closest_factorable(int n, const ints& primes) {
int d = 0;
ints r;
while (true) {
r = factor(n + d, primes);
if (r[r.size() - 1] == 1) { break; }
++d;
r = factor(n - d, primes);
if (r[r.size() - 1] == 1) { break; }
}
r.pop_back();
return r; }
int main() {
for (int i = 0; i < 30; ++i) {
for (const auto& f : closest_factorable(i, {2, 3, 5, 7, 11})) {
std::cout << f << " "; }
std::cout << "\n"; }
}
I suppose that you have a (small) set of prime numbers S and an integer n and you want to know is n factors only using number in S. The easiest way seems to be the following:
P <- product of s in S
while P != 1 do
P <- GCD(P, n)
n <- n/P
return n == 1
You compute the GCD using Euclid's algorithm.
The idea is the following: Suppose that S = {p1, p2, ... ,pk}. You can write n uniquely as
n = p1^n1 p2^n2 ... pk^nk * R
where R is coprime wrt the pi. You want to know whether R=1.
Then
GCD(n, P) = prod ( pi such that ni <> 0 ).
Therefore n/p decrease all those non zeros ni by 1 so that they eventually become 0. At the end only R remains.
For example: S = {2,3,5}, n = 5600 = 2^5*5^2*7. Then P = 2*3*5 = 30. One gets GCD(n, p)=10=2*5. And therefore n/GCD(n,p) = 560 = 2^4*5*7.
You are now back to the same problem: You want to know if 560 can be factored using S = {2,5} hence the loop. So the next steps are
GCD(560, 10) = 10. 560/GCD = 56 = 2^3 * 7.
GCD(56, 10) = 2. 56/2 = 28 = 2^2 * 7
GCD(28, 2) = 2. 28/2 = 14 = 2 * 7
GCD(14, 2) = 2. 14/2 = 7
GCD(7, 2) = 1 so that R = 7 ! Your answer if FALSE.
kissfft has a function
int kiss_fft_next_fast_size(int n)
that returns the next largest N that is an aggregate of 2,3,5.
Also related is a kf_factor function that factorizes a number n, pulling out the "nice" FFT primes first (e.g. 4's are pulled out before 2's)

How to decompose an integer in two for grid creation

Given an integer N I want to find two integers A and B that satisfy A × B ≥ N with the following conditions:
The difference between A × B and N is as low as possible.
The difference between A and B is as low as possible (to approach a square).
Example: 23. Possible solutions 3 × 8, 6 × 4, 5 × 5. 6 × 4 is the best since it leaves just one empty space in the grid and is "less" rectangular than 3 × 8.
Another example: 21. Solutions 3 × 7 and 4 × 6. 3 × 7 is the desired one.
A brute force solution is easy. I would like to see if a clever solution is possible.
Easy.
In pseudocode
a = b = floor(sqrt(N))
if (a * b >= N) return (a, b)
a += 1
if (a * b >= N) return (a, b)
return (a, b+1)
and it will always terminate, the distance between a and b at most only 1.
It will be much harder if you relax second constraint, but that's another question.
Edit: as it seems that the first condition is more important, you have to attack the problem
a bit differently. You have to specify some method to measure the badness of not being square enough = 2nd condition, because even prime numbers can be factorized as 1*number, and we fulfill the first condition. Assume we have a badness function (say a >= b && a <= 2 * b), then factorize N and try different combinations to find best one. If there aren't any good enough, try with N+1 and so on.
Edit2: after thinking a bit more I come with this solution, in Python:
from math import sqrt
def isok(a, b):
"""accept difference of five - 2nd rule"""
return a <= b + 5
def improve(a, b, N):
"""improve result:
if a == b:
(a+1)*(b-1) = a^2 - 1 < a*a
otherwise (a - 1 >= b as a is always larger)
(a+1)*(b-1) = a*b - a + b - 1 =< a*b
On each iteration new a*b will be less,
continue until we can, or 2nd condition is still met
"""
while (a+1) * (b-1) >= N and isok(a+1, b-1):
a, b = a + 1, b - 1
return (a, b)
def decomposite(N):
a = int(sqrt(N))
b = a
# N is square, result is ok
if a * b >= N:
return (a, b)
a += 1
if a * b >= N:
return improve(a, b, N)
return improve(a, b+1, N)
def test(N):
(a, b) = decomposite(N)
print "%d decomposed as %d * %d = %d" % (N, a, b, a*b)
[test(x) for x in [99, 100, 101, 20, 21, 22, 23]]
which outputs
99 decomposed as 11 * 9 = 99
100 decomposed as 10 * 10 = 100
101 decomposed as 13 * 8 = 104
20 decomposed as 5 * 4 = 20
21 decomposed as 7 * 3 = 21
22 decomposed as 6 * 4 = 24
23 decomposed as 6 * 4 = 24
I think this may work (your conditions are somewhat ambiguous). this solution is somewhat similar to other one, in basically produces rectangular matrix which is almost square.
you may need to prove that A+2 is not optimal condition
A0 = B0 = ceil (sqrt N)
A1 = A0+1
B1 = B0-1
if A0*B0-N > A1*B1-N: return (A1,B1)
return (A0,B0)
this is solution if first condition is dominant (and second condition is not used)
A0 = B0 = ceil (sqrt N)
if A0*B0==N: return (A0,B0)
return (N,1)
Other conditions variations will be in between
A = B = ceil (sqrt N)

Resources