Large array indexes scala - arrays

(Language: scala)
I have a problem where I want to iterate over 1 million numbers, but for some reason I get an arrayindexOutofbounds exception. The function I am using works perfectly for 100 000 numbers, but I get the exception if I add a zero.
There cannot be a problem with the array size, because I have built a sort of flex-array, where the array is about 1000 elements and each element consists of a list of elements.
So the problem looks something like this:
for (x <- 1 to 1000000) {
// Do a thing
}
Can for loops only handle a certain number of elements?
I have tried running the program with the "extra-space-flag"
I include the whole code below for reference, in case it makes a difference
object Problem14 {
class FlexArray (n : Int){
var array = new Array[List[Tuple2[Int, Int]]](n)
val size = n
for(x <- 0 until size) {
array(x) = List()
}
def insert (n : Int, value : Int) {
if (find(n) != -1) {
val i = n % size
array(i) = (n, value) :: array(i)
}
}
def read (i : Int) : List[Tuple2[Int, Int]] = {
(array(i))
}
def findAux (list : List[Tuple2[Int, Int]], n : Int) : Int = {
if (list == Nil) {
-1
} else {
val (num, value) = list.head
if (n == num) {
value
} else {
findAux(list.tail, n)
}
}
}
def find (n : Int) : Int = {
val i = n % size
findAux(array(i), n)
}
}
var accArray = new FlexArray(10000)
// denna funktion bör kallas med 1 som andra argument
def chainLength (n : Int, acc : Int) : Int = {
if (n == 1)
acc
else {
val value = accArray.find(n)
if (value != -1)
acc + value
else if (n % 2 == 0)
chainLength(n/2, acc+1)
else
chainLength(3*n+1, acc+1)
}
}
def main(args: Array[String]) {
var max = 0
var maxnum = 0
for (x <- 1 to 1000000) {
var value = chainLength(x, 1)
accArray.insert(x, value)
if (max < value) {
max = value
maxnum = x
}
println(maxnum + ": " + max)
}
}

The problem isn't with array indexes, scala functions just like java and will go to Int.MaxValue 2,147,483,647. The problem is with this line of in your chainLength function:
chainLength(3 * n + 1, acc + 1)
Since chainLength is recursive on itself switching between n/2 and n * 3 + 1 you run into this with numbers larger than 113383. It leads to integer overflow so you end up with a negative value passed to the array index which throws your error. I'm guessing you'll need to add some integer overflow handling to your function.
Full output of calls to chainLength in chainLength(113383, 1) (it ends with overflow at the bottom):
Starting at 113383
3 * 113383 + 1 = 340150
340150 / 2 = 170075
3 * 170075 + 1 = 510226
510226 / 2 = 255113
3 * 255113 + 1 = 765340
765340 / 2 = 382670
382670 / 2 = 191335
3 * 191335 + 1 = 574006
574006 / 2 = 287003
3 * 287003 + 1 = 861010
861010 / 2 = 430505
3 * 430505 + 1 = 1291516
1291516 / 2 = 645758
645758 / 2 = 322879
3 * 322879 + 1 = 968638
968638 / 2 = 484319
3 * 484319 + 1 = 1452958
1452958 / 2 = 726479
3 * 726479 + 1 = 2179438
2179438 / 2 = 1089719
3 * 1089719 + 1 = 3269158
3269158 / 2 = 1634579
3 * 1634579 + 1 = 4903738
4903738 / 2 = 2451869
3 * 2451869 + 1 = 7355608
7355608 / 2 = 3677804
3677804 / 2 = 1838902
1838902 / 2 = 919451
3 * 919451 + 1 = 2758354
2758354 / 2 = 1379177
3 * 1379177 + 1 = 4137532
4137532 / 2 = 2068766
2068766 / 2 = 1034383
3 * 1034383 + 1 = 3103150
3103150 / 2 = 1551575
3 * 1551575 + 1 = 4654726
4654726 / 2 = 2327363
3 * 2327363 + 1 = 6982090
6982090 / 2 = 3491045
3 * 3491045 + 1 = 10473136
10473136 / 2 = 5236568
5236568 / 2 = 2618284
2618284 / 2 = 1309142
1309142 / 2 = 654571
3 * 654571 + 1 = 1963714
1963714 / 2 = 981857
3 * 981857 + 1 = 2945572
2945572 / 2 = 1472786
1472786 / 2 = 736393
3 * 736393 + 1 = 2209180
2209180 / 2 = 1104590
1104590 / 2 = 552295
3 * 552295 + 1 = 1656886
1656886 / 2 = 828443
3 * 828443 + 1 = 2485330
2485330 / 2 = 1242665
3 * 1242665 + 1 = 3727996
3727996 / 2 = 1863998
1863998 / 2 = 931999
3 * 931999 + 1 = 2795998
2795998 / 2 = 1397999
3 * 1397999 + 1 = 4193998
4193998 / 2 = 2096999
3 * 2096999 + 1 = 6290998
6290998 / 2 = 3145499
3 * 3145499 + 1 = 9436498
9436498 / 2 = 4718249
3 * 4718249 + 1 = 14154748
14154748 / 2 = 7077374
7077374 / 2 = 3538687
3 * 3538687 + 1 = 10616062
10616062 / 2 = 5308031
3 * 5308031 + 1 = 15924094
15924094 / 2 = 7962047
3 * 7962047 + 1 = 23886142
23886142 / 2 = 11943071
3 * 11943071 + 1 = 35829214
35829214 / 2 = 17914607
3 * 17914607 + 1 = 53743822
53743822 / 2 = 26871911
3 * 26871911 + 1 = 80615734
80615734 / 2 = 40307867
3 * 40307867 + 1 = 120923602
120923602 / 2 = 60461801
3 * 60461801 + 1 = 181385404
181385404 / 2 = 90692702
90692702 / 2 = 45346351
3 * 45346351 + 1 = 136039054
136039054 / 2 = 68019527
3 * 68019527 + 1 = 204058582
204058582 / 2 = 102029291
3 * 102029291 + 1 = 306087874
306087874 / 2 = 153043937
3 * 153043937 + 1 = 459131812
459131812 / 2 = 229565906
229565906 / 2 = 114782953
3 * 114782953 + 1 = 344348860
344348860 / 2 = 172174430
172174430 / 2 = 86087215
3 * 86087215 + 1 = 258261646
258261646 / 2 = 129130823
3 * 129130823 + 1 = 387392470
387392470 / 2 = 193696235
3 * 193696235 + 1 = 581088706
581088706 / 2 = 290544353
3 * 290544353 + 1 = 871633060
871633060 / 2 = 435816530
435816530 / 2 = 217908265
3 * 217908265 + 1 = 653724796
653724796 / 2 = 326862398
326862398 / 2 = 163431199
3 * 163431199 + 1 = 490293598
490293598 / 2 = 245146799
3 * 245146799 + 1 = 735440398
735440398 / 2 = 367720199
3 * 367720199 + 1 = 1103160598
1103160598 / 2 = 551580299
3 * 551580299 + 1 = 1654740898
1654740898 / 2 = 827370449
3 * 827370449 + 1 = -1812855948

Related

Application.Transpose 2D array assigment

For example I have 2d array
tKey(0, 0) = 1
tKey(1, 0) = 2
tKey(2, 0) = 3
So
testArray = Application.Transpose(tKey)
assign like 1D array
testArray(1) = 1
testArray(2) = 2
testArray(3) = 3
Instead of expected
testArray(1,1) = 1
testArray(1,2) = 2
testArray(1,3) = 3
But if tKey
tKey(0, 0) = 1
tKey(1, 0) = 2
tKey(2, 0) = 3
tKey(0, 1) = 1
tKey(1, 1) = 2
tKey(2, 1) = 3
then
testArray = Application.Transpose(tKey)
assign like 2D array, like expected
testArray(1,1) = 1
testArray(1,2) = 2
testArray(1,3) = 3
testArray(2,1) = 1
testArray(2,2) = 2
testArray(2,3) = 3
test code
Sub testss()
Dim tKey(0 To 2, 0 To 0) As Variant
tKey(0, 0) = 1
tKey(1, 0) = 2
tKey(2, 0) = 3
testArray1 = Application.Transpose(tKey) ' wrong assignment
Dim tKey2(0 To 2, 0 To 1) As Variant
tKey2(0, 0) = 1
tKey2(1, 0) = 2
tKey2(2, 0) = 3
tKey2(0, 1) = 1
tKey2(1, 1) = 2
tKey2(2, 1) = 3
testArray2 = Application.Transpose(tKey2) ' good assignment
Stop
End Sub
Is that a bug? How to assign correct one value to 2d array using Application.Transpose?

Exponentiation complexity

Based on this code:
int poow(int x,int y)
{
if(y==0)
return 1;
if(y%2!= 0)
return poow(x,y-1)*x;
return poow(x,y/2)*poow(x,y/2); //this line
}
I tried to see the complexity: We suppose that we have n=2^k
we have T(0)=1
T(n)=2*T(n/2)+C
T(n)=2^i * T(n/2^i)+i*c
for i=k we have T(n)=2^k * T(n/2^k) + k * c
T(n)=2^k * T(1) + k*c
T(n)=2^k * c2 + k * c
I am stuck here ? How can I continue the computation of complexity and what is the difference when changing this line:
return poow(x,y/2)*poow(x,y/2); //this line
with
int p=poow(x,y/2);
return p*p;
in term of complexity !
Start off with a proper recurrence. The complexity is solely based on y, so we can write the recurrence as
T(0) = 1
T(y) = y is even: 2 * T(y / 2)
y is odd: T(y - 1) + 1
Worst-case would be that every division by 2 leaves us with a odd number, which would lead to the complexity of
T(2^n-1) = 1 + 2 * (1 + 2 * (1 + 2 * ( ... * T(1)))) =
= 2 ^ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 3 + ... + 2 ^ (n - 1) + 2 ^ (n - 1) =
= 2 ^ n - 1 + 2 ^(n - 1) = 3 * 2 ^ (n - 1) - 1
T(y) = O(y)
Best-case would be a power of 2:
T(2^n) = 2 * 2 * ... * 2 * T(1) = 2 ^ n * (1 + 1) = 2 ^ (n + 1) = 2 * 2 ^ n
T(y) = O(y)
Now what if we optimized the whole function?
T'(0) = 1
T'(y) = y is even: T(y / 2) + 1
y is odd: T(y - 1) + 1
Worst case:
T'(2^n - 1) = T(2^n - 2) + 1 = T(2^(n - 1) - 1) + 1 + 1 = ... =
= T(1) + 1 + 1 + 1 + ... =
= 2 + 1 + 1 + 1 + ... =
= 1 + ln(2^n) / ln(2) * 2 =
= 1 + 2 * n
T'(y) = O(log y)
Best case:
T'(2 ^ n) = T(1) + 1 + 1 + ... =
= 2 + 1 + 1 + ... =
= 2 + ln(2^n) / ln(2)
= n + 2
T'(y) = O(log y)
So the optimized version is definitely faster (linear vs logarithmic complexity).
Sometime code analysis focuses on the theory and not the actual.
Code has a bug.
if(y%2!= 0)
return poow(x,y-1)*x;
// should be
if(y%2!= 0)
return poow(x,y-y%2)*x;
// better alternative, use
unsigned poow(unsigned x, unsigned y)
Without the fix, calling poow(1,-1) causes infinite recursion and likely stack-overflow. So O(∞) regardless in the last line is return poow(x,y/2)*poow(x,y/2); or int p=poow(x,y/2);
return p*p;.

Is this a bug in Arduino modulo or is it me?

I created the following simple sketch for my Arduino Due (running 1.6.1) using the modulo operator:
int count = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print("Count: ");
Serial.println(count);
Serial.print("Count / 4 = ");
Serial.println(count / 4);
Serial.print("Remainder = ");
Serial.println(count & 4);
Serial.println();
count++;
if (count == 50) {
delay(86400000);
} else {
delay(1000);
}
}
The output looks like this:
Count: 0
Count / 4 = 0
Remainder = 0
Count: 1
Count / 4 = 0
Remainder = 0
Count: 2
Count / 4 = 0
Remainder = 0
Count: 3
Count / 4 = 0
Remainder = 0
Count: 4
Count / 4 = 1
Remainder = 4
Count: 5
Count / 4 = 1
Remainder = 4
Count: 6
Count / 4 = 1
Remainder = 4
Count: 7
Count / 4 = 1
Remainder = 4
Count: 8
Count / 4 = 2
Remainder = 0
Count: 9
Count / 4 = 2
Remainder = 0
Count: 10
Count / 4 = 2
Remainder = 0
Count: 11
Count / 4 = 2
Remainder = 0
Count: 12
Count / 4 = 3
Remainder = 4
Count: 13
Count / 4 = 3
Remainder = 4
Count: 14
Count / 4 = 3
Remainder = 4
Count: 15
Count / 4 = 3
Remainder = 4
Count: 16
Count / 4 = 4
Remainder = 0
My expectation would be that the remainder value would count up from 0 to 3 again and again. Instead it alternates between 0 for four times and 4 for four times.
I'm completely open to the idea of me doing something wrong, but I can't figure out what it is.
I fail to see a modulo operator (%). I see & instead.

Nested loops result

I really don't know how to find out the result of nested loops.
For example in the following pseudo-code, I can't sort out what will be given at the end of execution. I'll be so glad if anyone gives me a simple solution.
r <- 0
for i <- 1 to n do
for j <- 1 to i do
for k <- j to i+j do
r <- r + 1
return r
Question is:
What is the result of the code and give the result r in terms of n?
I write it but every time I get confused.
In your pseudo-code, Inner most loop, k <- j to i+j can be written as k <- 0 to i (this is by removing j). Hence your code can be simplified as follows:
r <- 0
for i <- 1 to n do
for j <- 1 to i do
for k <- 0 to i do // notice here `j` removed
r <- r + 1
return r
Based on this pseudo-code, I have written a C program(as below) to generate sequence for N = 1 to 10. (you originally tagged question as java but I am writing c code because what you wants is independent of language constraints)
#include<stdio.h>
int main(){
int i =0, k =0, j =0, n =0;
int N =0;
int r =0;
N =10;
for (n=1; n <= N; n++){
// unindented code here
r =0;
for (i=1; i<=n; i++)
for (j=1; j<=i; j++)
for (k=0; k<=i; k++)
r++;
printf("\n N=%d result = %d",n, r);
}
printf("\n");
}
Output of this program is something like:
$ ./a.out
N=1 result = 2
N=2 result = 8
N=3 result = 20
N=4 result = 40
N=5 result = 70
N=6 result = 112
N=7 result = 168
N=8 result = 240
N=9 result = 330
N=10 result = 440
Then, Tried to explore, How does it work? with some diagrams:
Execution Tree For N=1:
1<=i<=1, (i=1)
|
1<=j<=i, (j=1)
/ \
0<=k<=i, (K=0) (K=1)
| |
r=0 r++ r++ => r = 2
( 1 + 1 )
That is (1*2) = 2
Tree For N=2:
1<=i<=2, (i=1)-----------------------(i=2)
| |---------|------|
1<=j<=i, (j=1) (j=1) (j=2)
/ \ / | \ / | \
0<=k<=i, (K=0) (K=1) (K=0)(K=1)(k=2) (K=0)(K=1)(k=2)
| | | | | | | |
r=0 r++ r++ r++ r++ r++ r++ r++ r++ => 8
-------------- ---------------------------------
( 1 + 1) ( 3 + 3 )
That is (1 + 1) + (3 + 3) = 8
Similarly I drawn a tree for N=3:
1<=i<=3, (i=1)-----------------------(i=2)--------------------------------------------(i=3)
| |---------|------| |----------------------|----------------------|
1<=j<=3, (j=1) (j=1) (j=2) ( j=1 ) ( j=2 ) ( j=3 )
/ \ / | \ / | \ / | | \ / | | \ / | | \
0<=k<=i, (K=0) (K=1) (K=0)(K=1)(k=2) (K=0)(K=1)(k=2) / | | \ / | | \ / | | \
| | | | | | | | (K=0)(K=1)(k=2)(k=3) (K=0)(K=1)(k=2)(k=3) (K=0)(K=1)(k=2)(k=3)
r=0 r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++ r++
That is (1 + 1) + (3 + 3) + (4 + 4+ 4)= 20
N = 1, (1 + 1) = 2
N = 2, (1 + 1) + (3 + 3) = 8
N = 3, (1 + 1) + (3 + 3) + (4 + 4 + 4)= 20
N = 4, (1 + 1) + (3 + 3) + (4 + 4 + 4) + (5 + 5 + 5 + 5) = 40
N = 5, (1 + 1) + (3 + 3) + (4 + 4 + 4) + (5 + 5 + 5 + 5) + (6 + 6 + 6 + 6 + 6) = 70
N = 6, (1 + 1) + (3 + 3) + (4 + 4 + 4) + (5 + 5 + 5 + 5) + (6 + 6 + 6 + 6 + 6) + (7 + 7 + 7 + 7 + 7 + 7)= 112
For N=6 we can also be write above sequence as:
(1*2) + (2*3) + (3*4) + (4*5) + (5*6) + (6*7)
Finally, I could understand that sum of N in three loop is:
(1*2) + (2*3) + (3*4) + (4*5) + (5*6) + ... + (N * (N+1))
With help from math.stackexchange.com, I could simplify this equation:
I asked here: How to simplify summation equation in terms of N?
So as I commented to your question, Result in term of N is ( ((N) * (N+1) * (N+2)) / 3 ).
And, I think its correct. I cross checked it as follows:
N = 1, (1 * 2 * 3)/3 = 2
N = 2, (2 * 3 * 4)/3 = 8
N = 3, (3 * 4 * 5)/3 = 20
N = 4, (4 * 5 * 6)/3 = 40
N = 5, (5 * 6 * 7)/3 = 70
Try using some code like this to work it out... i.e. code up what it is and what you think it should be and test it.
EDIT: updated based on comment above.
public class CountLoop{
public static void main(String[] args){
for(int i=1;i<=10;i++)
System.out.println("It's "+run(i)+" and I think "+guess(i));;
}
public static int run(int n){
int r = 0;
for(int i=1;i<=n;i++)
for(int j=1; j <= i;j++)
for(int k=j; k <= i+j; k++)
r += 1;
return r;
}
public static int guess(int n){
// taken from the comments
int r = ((n * (n+1) * (n+2)) /3);
return r;
}
}
Running this gets
It's 2 and I think 2
It's 8 and I think 8
It's 20 and I think 20
It's 40 and I think 40
It's 70 and I think 70
It's 112 and I think 112
It's 168 and I think 168
It's 240 and I think 240
It's 330 and I think 330
It's 440 and I think 440
so we're happy.
I am getting it something like this :
n = 1: r = 2
n = 2: r = 8
n = 3: r = 20
n = 4: r = 40
n = 5: r = 70
n = 6: r = 112
n = 7: r = 168
n = 8: r = 240
n = 9: r = 330
n = 10: r = 440
lets say for n = 10,
r = 2 + 6 + 12 + 20 + 30 + 42 + 56 + 72 + 90 + 110 = 440
=> r = 2(1 + 3 + 6 + 10 + 15 + 21 + 28 + 36 + 45 + 55)
Intuitively, I think
n = sum(n-1) + n * (n + 1).
where
sum(n-1) = value of r for n-1

A puzzle related to nested loops

For a given input N, how many times does the enclosed statement executes?
for i in 1 … N loop
for j in 1 … i loop
for k in 1 … j loop
sum = sum + i ;
end loop;
end loop;
end loop;
Can anyone figure out an easy way or a formula to do this in general. Please explain.
First, I written a C code to generate sum:
int main(){
int i =0, k =0, j =0, n =0;
int N =0;
int sum =0;
N =10;
for (n=1; n <= N; n++){
// unindented code here
sum =0;
for (i=1; i<=n; i++)
for (j=1; j<=i; j++)
for (k=1; k<=j; k++)
sum++;
printf("\n N=%d sum = %d",n, sum);
}
printf("\n");
}
Simple compile and generate result for N=1 to N=10 :
$ gcc sum.c
$ ./a.out
N=1 sum = 1
N=2 sum = 4
N=3 sum = 10
N=4 sum = 20
N=5 sum = 35
N=6 sum = 56
N=7 sum = 84
N=8 sum = 120
N=9 sum = 165
N=10 sum = 220
Then, Tried to explore How this works? with some diagrams:
For, N=1:
i<=N, (i=1)
|
j<=i, (j=1)
|
k<=j, (K=1)
|
sum=0. sum++ ---> sum = 1
That is (1) = 1
For, N=2:
i<=N, (i=1)-------(i=2)
| |-----|-----|
j<=i, (j=1) (j=1) (j=2)
| | |----|----|
k<=j, (K=1) (K=1) (K=1) (K=2)
| | | |
sum=0, sum++ sum++ sum++ sum++ --> sum = 4
That is (1) + (1 + 2) = 4
For, N=3:
i<=N, (i=1)-------(i=2)--------------------(i=3)
| |-----|-----| |---------|-------------|
j<=i, (j=1) (j=1) (j=2) (j=1) (j=2) (j=3)
| | |----|----| | |----|----| |-----|-----|
k<=j, (K=1) (K=1) (K=1) (K=2) (K=1) (K=1) (K=2) (K=1) (K=2) (K=3)
| | | | | | | | | |
sum=0, sum++ sum++ sum++ sum++ sum++ sum++ sum++ sum++ sum++ sum++
--> sum = 10
That is (1) + (1 + 2) + ( 1 + 2 + 3 ) = 10
N = 1, (1) = 1
N = 2, (1) + (1 + 2) = 4
N = 3, (1) + (1 + 2) + (1 + 2 + 3) = 10
N = 4, (1) + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) = 20
N = 5, (1) + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) + (1 + 2 + 3 + 4 + 5) = 35
Finally, I could understood that sum of N in three loop is:
(1) + (sum 0f 1 to 2) + ... + (sum of 1 to (N-2)) + (sum of 1 to (N-1) ) + (sum of 1 to N)
or we can write it as:
=> (1) + (1 + 2) + ...+ (1 + 2 +....+ i) + ... + (1 + 2 + ....+ N-1) + (1 + 2 + ....+ N)
=> ( N * 1 ) + ( (N-1) * 2) + ( (N-2) * 3) +...+ ( (N -i+1) * i ) +... + ( 1 * N)
You can refer here for simplification calculations: (I asked HERE )
[YOUR ANSWER]
= ( ((N) * (N+1) * (N+2)) / 6 )
And, I think its correct. I checked as follows:
N = 1, (1 * 2 * 3)/6 = 1
N = 2, (2 * 3 * 4)/6 = 4
N = 3, (3 * 4 * 5)/6 = 6
N = 4, (4 * 5 * 6)/6 = 10
N = 5, (5 * 6 * 7)/6 = 35
Also, The complexity of this algorithm is O(n3)
EDIT:
The following loop also has same numbers of count, that is = ( ((N) * (N+1) * (N+2)) / 6 )
for i in 1 … N loop
for j in i … N loop
for k in j … N loop
sum = sum + i ;
end loop;
end loop;
end loop;

Resources