Error in Computing the Two-Fold Sumset of a List in the GAP System - gap-system

I am attempting to write a code in the GAP System that will allow me to construct the two-fold sumset of a set with itself. Essentially, this is just the set of elements that can be written as a sum of two elements of a given set. Explicitly, if S is the set (or list) in question, then its two-fold sumset is the set (or list) S + S.
In the GAP System, I have devised the following code to achieve this construction. I am going to provide a test set for demonstrative purposes, but the user should be able to provide the test set in general.
A := [8, 11, 15, 16, 17, 19, 20, 22, 23, 24, 25,
26, 27, 28, 30, 31, 32, 33, 34, 35, 36, 37];
L := [ ];
for i in A do
for j in A do
Add(L, i + j);
od;
od;
I expect this code to add all possible pairs of elements of A and collect them in an (initially empty) list L; however, when I implement the code, the element 22 = 11 + 11 is mysteriously absent from L!
I admit that I am a novice programmer and perhaps this construction could be implemented in a more efficient manner, but this is the first thing that came to mind. I would appreciate any insight or advice on this matter. I thank everyone in advance for their time and consideration.

Actually, 22 is there:
gap> 22 in L;
true
gap> Position(L,22);
24
Depending on the purpose, you might want to use AddSet instead of Add to eliminate duplicates, or at least sort the resulting list L
gap> L1 := [ ];;
gap> for i in A do for j in A do AddSet(L1, i + j); od; od;
gap> L1=Set(L); # just to check
true
Again, depending on the purpose, and commutativity of the operation (are you dealing with lists of integers, or it's just an example, while you may be dealing with some other kinds of objects?), you may also want further optimisation, to avoid calculating b+a after you have already calculated a+b (you said you want "set (or list) S + S" so it's not exactly clear).
gap> L2 := [ ];;
gap> for i in [1..Length(A)] do
> for j in [i..Length(A)] do
> AddSet(L2, A[i] + A[j]);
> od;
> od;
gap> L2=Set(L);
true

Related

Optimal solution for this interview question

Can anyone provide optimal solution with Time Complexity? Very appreciated!
Determine bandwidth required to run prescheduled video streams.
There can be 10s of thousands of streams and all the scheduling data is available at the start.
There may be time intervals when no streams are running
Inputs
int startTime; //start time for the stream
int duration; //how long the stream runs
int bandwidth; // consumed bandwidth from start to end
Output:
list[int] totalBW; // bandwidth needed at every time instant
Example:
input (list may not sorted)
[ [0,2,10], [1,2,10], [2,1,20] ]
output
[10, 20, 30]
Explanation
At time 0: only the first element needs bandwidth 10 => [10, ...]
At time 1: first two elements need bandwidth 10 + 10 => [10, 20, ...]
At time 2: the second and third element need bandwidth 10 + 20 => [10, 20, 30]
The brute force approach using python:
def solution(streams):
_max = max(streams, key=lambda x: (x[0]+x[1]))
_max_time = _max[0] + _max[1]
res = [0] * _max_time
for s, d, bw in streams:
for i in range(d):
res[s+i] += bw
return res
Is there any more efficient approach?
Is there any more efficient approach?
Yes.
The first step would be to transform the original data into a set of "at time = T, bandwidth changes by N" events, sorted in chronological order, and simplified by merging events that happen at the same time.
For your example, if the input is [ [0,2,10], [1,2,10], [2,1,20] ] then it would be broken up into:
** [ [0,2,10] **
At 0, bandwidth += 10
At 2, bandwidth += -10
** [1,2,10] **
At 1, bandwidth += 10
At 3, bandwidth += -10
** [2,1,20] **
At 2, bandwidth += 20
At 3, bandwidth += -20
..then sorted and simplified (merging events that happen at the same time - e.g. bandwidth += -10, bandwidth += 20 becomes a single bandwidth += 10) to get:
At 0, bandwidth += 10
At 1, bandwidth += 10
At 2, bandwidth += 10
At 3, bandwidth += -30
From there it's a simple matter of generating the final array from the sorted list:
10, 20, 30, 0
To understand why this is more efficient, imagine what happens if the time is tracked with higher precision (e.g. maybe milliseconds instead of seconds) and the input is [ [0,2000,10], [1000,2000,10], [2000,1000,20] ] instead. For my approach generating the final array would become an outer loop with 4 iterations and an inner loop that can be a highly optimized memset() (C) or rep stosd (80x86 assembly) or np.full() (Python with NumPy); and for your approach the outer loop needs 30000 iterations where the inner loop wastes a huge amount of time repeating a linear search that (for most iterations of the outer loop) finds the same answer as the previous iteration of the outer loop.

Optimization, time complexity and flowchart (Scilab)

I tried to optimize this code, but it’s impossible to optimize anymore.
Please help with building a flowchart for this algorithm.
A = [-1,0,1,2,3,5,6,8,10,13,19,23,45];
B = [0,1,3,6,7,8,9,12,45];
N1 = length(A);
N2 = length(B);
t = 1;
m = 10;
C = [];
for i=1:N1
for j=1:N2
if A(i)==B(j)
break
else
if j==N2
C(t)=A(i);
t=t+1;
end
end
end
end
disp(C);
N3=length(C);
R = [];
y = 1;
for l=1:N3
if C(l)>m
R(y)=C(l);
y=y+1;
end
end
disp(R);
How to find time complexity of an algorithm
I think it should be O(n).
Dominant (elementary) operation:
comparison A(i)== B(j)
But I am not sure yet.
And I can't do
Complexity function (worst case)
and
Worst Computing Complexity:
𝐹(𝑁)
"Optimization" depends of your goal for exmple you may want to minimize the number of floating point operation or to minimize the number of Scilab instruction or minimize the execution time of the algorithm.
As Scilab is an intepreted langage it is possible to reduce the execution time ans code length applying vectorization.
For example your code
N3=length(C);
R = [];
y = 1;
for l=1:N3
if C(l)>m
R(y)=C(l);
y=y+1;
end
end
may be rewritten:
R=C(C>m)
Here the number of computer operations is more or less the same as in the original code, but the execution time is many times faster:
Let C=rand(1,1000);m=0.5;
--> timer();R=C(C>0.5);timer()
ans =
0.000137
--> timer();
--> N3=length(C);
--> R = [];
--> y = 1;
--> for l=1:N3
> if C(l)>m
> R(y)=C(l);
> y=y+1;
> end
> end
--> timer()
ans =
0.388749
This seems like it's probably homework ;p
As for time complexity, it looks more like it would be O(n²) since you have a for loop, inside another for loop.
I recently started watching this course about Algorithms and data structures on Udemy that I highly recommend. He explains BigO notation quite well :)
Link to course. (No affiliations to the author)
As far as the optimization is concerned you should consider that Scilab (and its fellow mathematical programming languages MATLAB and Octave) are intrinsically vectorized. It means if you are using too many for loops, you should probably go back and read some documentation and tutorials. The canonical version of the code you wrote can be implemented as:
A = [-1, 0, 1, 2, 3, 5, 6, 8, 10, 13, 19, 23, 45];
B = [0, 1, 3, 6, 7, 8, 9, 12, 45];
C = setdiff(A, B);
disp(C);
m = 10;
R = C(C > m);
disp(R);
Result:
-1. 2. 5. 10. 13. 19. 23.
23.

Maximum contigous subsequence sum of x elements

So I came up with a question that I've looked and searched but with no answer found... What's the best (and by saying the best, I mean the fastest) way to get the maximum contigous subsequence sum of x elements?
Imagine that I've: A[] = {2, 4, 1, 10, 40, 50, 22, 1, 24, 12, 40, 11, ...}.
And then I ask:
"What is the maximum contigous subsequence on array A with 3 elements?"
Please imagine this in a array with more than 100000 elements... Can someone help me?
Thank you for your time and you help!
I Googled it and found this:
Using Divide and Conquer approach, we can find the maximum subarray sum in O(nLogn) time. Following is the Divide and Conquer algorithm.
The Kadane’s Algorithm for this problem takes O(n) time. Therefore the Kadane’s algorithm is better than the Divide and Conquer approach
See the code:
Initialize:
max_so_far = 0
max_ending_here = 0
Loop for each element of the array
(a) max_ending_here = max_ending_here + a[i]
(b) if(max_ending_here < 0)
max_ending_here = 0
(c) if(max_so_far < max_ending_here)
max_so_far = max_ending_here
return max_so_far

Distribute number over a bell curve

I am looking for a mathematical function that produces something similar to a bell curve ( think). I am very much out of my depth here. I think the Gaussian function might be what I need, but I don't know how to apply it correctly for my purposes.
I will be using the function to animate over a series of objects:
I want to simulate the appearance of acceleration and deceleration of this animation by offsetting each object closer to the previous one, until the midway point, after which the offset increases back to the original value:
Once implemented, I want the function to accept my start and end points on the x-axis, and the number of objects that need to be accommodated. It should then return a series of values that will be the x origin for each object.
For example:
Start: 0
End: 100
Objects: 20
Flat distribution: 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95
Required results: 0, 10, 19, 27, 34, 40, 44, 45, 46, 47, 48, 49, 50, 51, 55, 60, 66, 73, 81, 90
Some control over the profile of the curve would also be nice - for example, my estimated values above are quite a 'flat' bell (items 7-14 have the same offset).
Consider the following cubic polynomial:
f(x,a) = 4ax^3 - 6ax^2 + 2ax + x
evaluated over the domain x in [0:1] with a held constant and chosen from the interval `[0:1]'.
This will generate plot that starts at zero and ends at one. If a==0, you get a straight line. If a==1, you get a deep curve. For a somewhere in between, you get something in between.
Once you've picked a good value for a, you simply evaluate at however many points you want between 0 and 1. Then you scale the values to fit the range that you want.
This screenshot of a spreadsheet gives two examples. Columns A and F hold the value a, columns B and G hold values of x (if you wanted to use the exact values from your flat distribution, you could change every usage of x to be x/100). Columns C and H hold the outcome of f(x,a). Columns D and I hold f(x,a)*100.
Here is a Java implementation for generating a normal deviate:
/** generation of a Gaussian deviates (variants) by the ratio of uniform method */
final public static double generateNormalDeviate( final double mean, final double std_deviation ){
double u, v, x, y, q;
do {
u = random.nextDouble();
v = 1.7156 * ( random.nextDouble() - 0.5 );
x = u - 0.449871;
y = (v < 0 ? v * -1 : v) + 0.386595;
q = x*x + y * (0.19600 * y - 0.25472 * x);
} while( q > 0.27597 &&
(q > 0.27846 || v*v > -4d * Math.log(u) * u*u));
return mean + std_deviation * v / u;
}
See Numeric Recipes by Press for more information and a C version.
IIRC a sum of N independent randoms out of [-1..1] gives a good approximation to a Gaussian curve with the center of 0, I don't remember what's the dispersion.
Edit: Didn't understand the question. You seem to need something that implements this, precisely "inverse error function", you might want its approximation to be implemented in your code, as the function itself is an integral and cannot be evaluated in elementary functions. Once you get the function provide correct approximations to bell curve points, you plainly take a 0-1 number as base (which will define the flatness of the bell curve), name it B, and distribute your N numbers evenly between (-1+B) and (1-B), then take outputs of that function as bell curve positions, then normalize them so the leftmost will be at the start and rightmost at the end.

How to solve Euler Project Prblem 303 faster?

The problem is:
For a positive integer n, define f(n) as the least positive multiple of n that, written in base 10, uses only digits ≤ 2.
Thus f(2)=2, f(3)=12, f(7)=21, f(42)=210, f(89)=1121222.
To solve it in Mathematica, I wrote a function f which calculates f(n)/n :
f[n_] := Module[{i}, i = 1;
While[Mod[FromDigits[IntegerDigits[i, 3]], n] != 0, i = i + 1];
Return[FromDigits[IntegerDigits[i, 3]]/n]]
The principle is simple: enumerate all number with 0, 1, 2 using ternary numeral system until one of those number is divided by n.
It correctly gives 11363107 for 1~100, and I tested for 1~1000 (calculation took roughly a minute, and gives 111427232491), so I started to calculate the answer of the problem.
However, this method is too slow. The computer has been calculating the answer for two hours and hasn't finished computing.
How can I improve my code to calculate faster?
hammar's comment makes it clear that the calculation time is disproportionately spent on values of n that are a multiple of 99. I would suggest finding an algorithm that targets those cases (I have left this as an exercise for the reader) and use Mathematica's pattern matching to direct the calculation to the appropriate one.
f[n_Integer?Positive]/; Mod[n,99]==0 := (* magic here *)
f[n_] := (* case for all other numbers *) Module[{i}, i = 1;
While[Mod[FromDigits[IntegerDigits[i, 3]], n] != 0, i = i + 1];
Return[FromDigits[IntegerDigits[i, 3]]/n]]
Incidentally, you can speed up the fast easy ones by doing it a slightly different way, but that is of course a second-order improvement. You could perhaps set the code up to use ff initially, breaking the While loop if i reaches a certain point, and then switching to the f function you have already provided. (Notice I'm returning n i not i here - that was just for illustrative purposes.)
ff[n_] :=
Module[{i}, i = 1; While[Max[IntegerDigits[n i]] > 2, i++];
Return[n i]]
Table[Timing[ff[n]], {n, 80, 90}]
{{0.000125, 1120}, {0.001151, 21222}, {0.001172, 22222}, {0.00059,
11122}, {0.000124, 2100}, {0.00007, 1020}, {0.000655,
12212}, {0.000125, 2001}, {0.000119, 2112}, {0.04202,
1121222}, {0.004291, 122220}}
This is at least a little faster than your version (reproduced below) for the short cases, but it's much slower for the long cases.
Table[Timing[f[n]], {n, 80, 90}]
{{0.000318, 14}, {0.001225, 262}, {0.001363, 271}, {0.000706,
134}, {0.000358, 25}, {0.000185, 12}, {0.000934, 142}, {0.000316,
23}, {0.000447, 24}, {0.006628, 12598}, {0.002633, 1358}}
A simple thing that you can do to is compile your function to C and make it parallelizable.
Clear[f, fCC]
f[n_Integer] := f[n] = fCC[n]
fCC = Compile[{{n, _Integer}}, Module[{i = 1},
While[Mod[FromDigits[IntegerDigits[i, 3]], n] != 0, i++];
Return[FromDigits[IntegerDigits[i, 3]]]],
Parallelization -> True, CompilationTarget -> "C"];
Total[ParallelTable[f[i]/i, {i, 1, 100}]]
(* Returns 11363107 *)
The problem is that eventually your integers will be larger than a long integer and Mathematica will revert to the non-compiled arbitrary precision arithmetic. (I don't know why the Mathematica compiler does not include a arbitrary precision C library...)
As ShreevatsaR commented, the project Euler problems are often designed to run quickly if you write smart code (and think about the math), but take forever if you want to brute force it. See the about page. Also, spoilers posted on their message boards are removed and it's considered bad form to post spoilers on other sites.
Aside:
You can test that the compiled code is using 32bit longs by running
In[1]:= test = Compile[{{n, _Integer}}, {n + 1, n - 1}];
In[2]:= test[2147483646]
Out[2]= {2147483647, 2147483645}
In[3]:= test[2147483647]
During evaluation of In[53]:= CompiledFunction::cfn: Numerical error encountered at instruction 1; proceeding with uncompiled evaluation. >>
Out[3]= {2147483648, 2147483646}
In[4]:= test[2147483648]
During evaluation of In[52]:= CompiledFunction::cfsa: Argument 2147483648 at position 1 should be a machine-size integer. >>
Out[4]= {2147483649, 2147483647}
and similar for the negative numbers.
I am sure there must be better ways to do this, but this is as far as my inspiration got me.
The following code finds all values of f[n] for n 1-10,000 except the most difficult one, which happens to be n = 9999. I stop the loop when we get there.
ClearAll[f];
i3 = 1;
divNotFound = Range[10000];
While[Length[divNotFound] > 1,
i10 = FromDigits[IntegerDigits[i3++, 3]];
divFound = Pick[divNotFound, Divisible[i10, divNotFound]];
divNotFound = Complement[divNotFound, divFound];
Scan[(f[#] = i10) &, divFound]
] // Timing
Divisible may work on lists for both arguments, and we make good use of that here. The whole routine takes about 8 min.
For 9999 a bit of thinking is necessary. It is not brute-forceable in a reasonable time.
Let P be the factor we are looking for and T (consisting only of 0's, 1's and 2's) the result of multiplication P with 9999, that is,
9999 P = T
then
P(10,000 - 1) = 10,000 P - P = T
==> 10,000 P = P + T
Let P1, ...PL be the digits of P, and Ti the digits of T then we have
The last four zeros in the sum originate of course from the multiplication by 10,000. Hence TL+1,...,TL+4 and PL-3,...,PL are each others complement. Where the former only consists of 0,1,2 the latter allows:
last4 = IntegerDigits[#][[-4 ;; -1]] & /# (10000 - FromDigits /# Tuples[{0, 1, 2}, 4])
==> {{0, 0, 0, 0}, {9, 9, 9, 9}, {9, 9, 9, 8}, {9, 9, 9, 0}, {9, 9, 8, 9},
{9, 9, 8, 8}, {9, 9, 8, 0}, {9, 9, 7, 9}, ..., {7, 7, 7, 9}, {7, 7, 7, 8}}
There are only 81 allowable sets, with 7's, 8's, 9's and 0's (not all possible combinations of them) instead of 10,000 numbers, a speed gain of a factor of 120.
One can see that P1-P4 can only have ternary digits, being the sum of ternary digit and naught. You can see there can be no carry over from the addition of T5 and P1. A further reduction can be gained by realizing that P1 cannot be 0 (the first digit must be something), and if it were a 2 multiplication with 9999 would cause a 8 or 9 (if a carry occurs) in the result for T which is not allowed either. It must be a 1 then. Two's may also be excluded for P2-P4.
Since P5 = P1 + T5 it follows that P5 < 4 as T5 < 3, same for P6-P8.
Since P9 = P5 + T9 it follows that P9 < 6, same for P10-P11
In all these cases the additions don't need to include a carry over as they can't occur (Pi+Ti always < 8). This may not be true for P12 if L = 16. In that case we can have a carry over from the addition of the last 4 digits . So P12 <7. This also excludes P12 from being in the last block of 4 digits. The solution must therefore be at least 16 digits long.
Combining all this we are going to try to find a solution for L=16:
Do[
If[Max[IntegerDigits[
9999 FromDigits[{1, 1, 1, 1, i5, i6, i7, i8, i9, i10, i11, i12}~
Join~l4]]
] < 3,
Return[FromDigits[{1, 1, 1, 1, i5, i6, i7, i8, i9, i10, i11, i12}~Join~l4]]
],
{i5, 0, 3}, {i6, 0, 3}, {i7, 0, 3}, {i8, 0, 3}, {i9, 0, 5},
{i10, 0, 5}, {i11, 0, 5}, {i12, 0, 6}, {l4,last4}
] // Timing
==> {295.372, 1111333355557778}
and indeed 1,111,333,355,557,778 x 9,999 = 11,112,222,222,222,222,222
We could have guessed this as
f[9] = 12,222
f[99] = 1,122,222,222
f[999] = 111,222,222,222,222
The pattern apparently being the number of 1's increasing with 1 each step and the number of consecutive 2's with 4.
With 13 min, this is over the 1 min limit for project Euler. Perhaps I'll look into it some time soon.
Try something smarter.
Build a function F(N) which finds out the smallest number with {0, 1, 2} digits which is divisible by N.
So for a given N the number which we are looking for can be written as SUM = 10^n * dn + 10^(n-1) * dn-1 .... 10^1 * d1 + 1*d0 (where di are the digits of the number).
so you have to find out the digits such that SUM % N == 0
basically each digits contributes to the SUM % N with (10^i * di) % N
I am not giving any more hints, but the next hint would be to use DP. Try to figure out how to use DP to find out the digits.
for all numbers between 1 and 10000 it took under 1sec in C++. (in total)
Good luck.