Out of Memory Heap Space - java

I am working on a code that will output all the possible combinations of a certain amount of objects that will occur between three possibilities. My code is working for smaller numbers like 10,000 but I want it to be able to go up to 100,000. Anytime I go above 10,000 I get the following error code: java.lang.OutOfMemoryError: Java heap space.
Is there a more efficient way to store this information, or be able to circumvent the error code somehow? I have the code below to show what I am talking about
public static double Oxygen[][];
public static int OxygenPermutationRows;
public void OxygenCalculations(){
Scanner reader = new Scanner(System.in);
System.out.print("Oxygen Number: ");
int oxygenNumber = reader.nextInt();
System.out.println();
int oxygenIsotopes = 3;
OxygenPermutationRows = 0;
//Number of Feesable Permutations
if(oxygenNumber % 2 == 0)
{
OxygenPermutationRows = (1 + oxygenNumber) * ((oxygenNumber / 2) + 1);
}
else
{
OxygenPermutationRows = (1 + oxygenNumber) * (int)Math.floor(oxygenNumber / 2) + (int)Math.ceil(oxygenNumber / 2) + 2 + oxygenNumber;
}
int [][] Permutations = new int[OxygenPermutationRows][oxygenIsotopes];
int counterrow = 0;
int k;
for (int f = 0; f <= oxygenNumber; f++)
{
for (int j = 0; j <= oxygenNumber; j++)
{
k = oxygenNumber - j - f;
Permutations[counterrow][0] = f;
Permutations[counterrow][1] = j;
Permutations[counterrow][2] = k;
counterrow++;
if(f+j == oxygenNumber)
{
j = oxygenNumber + 10;
}
}
}
//TO CHECK PERMUTATION ARRAY VALUES
System.out.println("PERMUTATION ARRAY =======================================");
for (int i = 0; i < OxygenPermutationRows; i++) {
System.out.println();
for (int j = 0; j < 3; j++) {
System.out.print(Permutations[i][j] + " ");
}
}
public double[][] returnOxygen()
{
return Oxygen;
}
public double returnOxygenRows()
{
return OxygenPermutationRows;
}
}

Couldn't you split the 100000 iterations in chunks? Maybe chunks of 10000 iterations? And for every chunk, write the result in a file.This will get rid of the OOM error.

Raise max memory with the parameter -Xmx, you can do this in the run configuration for the java class

Related

UCF HSPT 2016 - Chomp Chomp

I am having a lot of trouble finding an efficient solution to Problem #9 in the UCF HSPT programming competition. The whole pdf can we viewed here, and the problem is called "Chomp Chomp!".
Essentially the problem involves taking 2 "chomps" out of an array, where each chomp is a continuous chain of elements from the array and the 2 chomps have to have at least element between them that's not "chomped." Once the two "chomps" are determined, the sum of all the elements in both "chomps" has to be a multiple of the number given in the input. My solution essentially is a brute-force that goes through every possible "chomp" and I tried to improve the speed of it by storing previously calculated sums of chomps.
My code:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class chomp {
static long[] arr;
public static long sum(int start, int end) {
long ret = 0;
for(int i = start; i < end; i++) {
ret+=arr[i];
}
return ret;
}
public static int sumArray(int[] arr) {
int sum = 0;
for(int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
return sum;
}
public static long numChomps(long[] arr, long divide) {
HashMap<String, Long> map = new HashMap<>();
int k = 1;
long numchomps = 0;
while(true) {
if (k > arr.length-2) break;
for (int i = 0; i < arr.length -2; i++) {
if ((i+k)>arr.length-2) break;
String one = i + "";
String two = (i+k) + "";
String key1 = one + " " + two;
long first = 0;
if(map.containsKey(key1)) {
//System.out.println("Key 1 found!");
first = map.get(key1).longValue();
} else {
first = sum(i, i+k);
map.put(key1, new Long(first));
}
int kk = 1;
while(true){
if (kk > arr.length-2) break;
for (int j = i+k+1; j < arr.length; j++) {
if((j+kk) > arr.length) break;
String o = j + "";
String t = (j+kk) + "";
String key2 = o + " " + t;
long last = 0;
if(map.containsKey(key2)) {
//System.out.println("Key 2 found!");
last = map.get(key2).longValue();
} else {
last = sum(j, j+kk);
map.put(key2, new Long(last));
}
if (((first+last) % divide) == 0) {
numchomps++;
}
}
kk++;
}
}
k++;
}
return numchomps;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
for(int i = 1; i <= n; i++) {
int length = in.nextInt();
long divide = in.nextLong();
in.nextLine();
arr = new long[length];
for(int j = 0; j < length; j++) {
arr[j] = (in.nextLong());
}
//System.out.println(arr);
in.nextLine();
long blah = numChomps(arr, divide);
System.out.println("Plate #"+i + ": " + blah);
}
}
}
My code gets the right answer, but seems to take too long, especially for large inputs when the size of the array is 1000 or greater. I tried to improve the speed of my algorithm my storing previous sums calculated in a HashMap, but that didn't improve the speed of my program considerably. What can I do to improve the speed so it runs under 10 seconds?
The first source of inefficiency is constant recalculation of sums. You should make an auxiliary array of partial sums long [n] partial;, then instead of calling sum(i, i + k) you may simply do partial[i + k] - partial[i].
Now the problem reduces to finding indices i<j<k<m such that
(partial[j] - partial[i] + partial[m] - partial[k]) % divide == 0
or, rearranging terms,
(partial[j] + partial[m]) % divide == (partial[i] + partial[k]) % divide
To find them you may consider an array of triples (s, i, j) where s = (partial[j] - partial[i]) % divide, stable sort it by s, and inspect equal ranges for non-overlapping "chomps".
This approach improves performance from O(n4) to O(n2 log n). Now you shall be able to improve it to O(n log n).

Calculate factorial of 50 using array only in java

I'm a total beginner of java.
I have a homework to write a complete program that calculates the factorial of 50 using array.
I can't use any method like biginteger.
I can only use array because my professor wants us to understand the logic behind, I guess...
However, he didn't really teach us the detail of array, so I'm really confused here.
Basically, I'm trying to divide the big number and put it into array slot. So if the first array gets 235, I can divide it and extract the number and put it into one array slot. Then, put the remain next array slot. And repeat the process until I get the result (which is factorial of 50, and it's a huge number..)
I tried to understand what's the logic behind, but I really can't figure it out.. So far I have this on my mind.
import java.util.Scanner;
class Factorial
{
public static void main(String[] args)
{
int n;
Scanner kb = new Scanner(System.in);
System.out.println("Enter n");
n = kb.nextInt();
System.out.println(n +"! = " + fact(n));
}
public static int fact(int n)
{
int product = 1;
int[] a = new int[100];
a[0] = 1;
for (int j = 2; j < a.length; j++)
{
for(; n >= 1; n--)
{
product = product * n;
a[j-1] = n;
a[j] = a[j]/10;
a[j+1] = a[j]%10;
}
}
return product;
}
}
But it doesn't show me the factorial of 50.
it shows me 0 as the result, so apparently, it's not working.
I'm trying to use one method (fact()), but I'm not sure that's the right way to do.
My professor mentioned about using operator / and % to assign the number to the next slot of array repeatedly.
So I'm trying to use that for this homework.
Does anyone have an idea for this homework?
Please help me!
And sorry for the confusing instruction... I'm confused also, so please forgive me.
FYI: factorial of 50 is 30414093201713378043612608166064768844377641568960512000000000000
Try this.
static int[] fact(int n) {
int[] r = new int[100];
r[0] = 1;
for (int i = 1; i <= n; ++i) {
int carry = 0;
for (int j = 0; j < r.length; ++j) {
int x = r[j] * i + carry;
r[j] = x % 10;
carry = x / 10;
}
}
return r;
}
and
int[] result = fact(50);
int i = result.length - 1;
while (i > 0 && result[i] == 0)
--i;
while (i >= 0)
System.out.print(result[i--]);
System.out.println();
// -> 30414093201713378043612608166064768844377641568960512000000000000
Her's my result:
50 factorial - 30414093201713378043612608166064768844377641568960512000000000000
And here's the code. I hard coded an array of 100 digits. When printing, I skip the leading zeroes.
public class FactorialArray {
public static void main(String[] args) {
int n = 50;
System.out.print(n + " factorial - ");
int[] result = factorial(n);
boolean firstDigit = false;
for (int digit : result) {
if (digit > 0) {
firstDigit = true;
}
if (firstDigit) {
System.out.print(digit);
}
}
System.out.println();
}
private static int[] factorial(int n) {
int[] r = new int[100];
r[r.length - 1] = 1;
for (int i = 1; i <= n; i++) {
int carry = 0;
for (int j = r.length - 1; j >= 0; j--) {
int x = r[j] * i + carry;
r[j] = x % 10;
carry = x / 10;
}
}
return r;
}
}
How about:
public static BigInteger p(int numOfAllPerson) {
if (numOfAllPerson < 0) {
throw new IllegalArgumentException();
}
if (numOfAllPerson == 0) {
return BigInteger.ONE;
}
BigInteger retBigInt = BigInteger.ONE;
for (; numOfAllPerson > 0; numOfAllPerson--) {
retBigInt = retBigInt.multiply(BigInteger.valueOf(numOfAllPerson));
}
return retBigInt;
}
Please recall basic level of math how multiplication works?
2344
X 34
= (2344*4)*10^0 + (2344*3)*10^1 = ans
2344
X334
= (2344*4)*10^0 + (2344*3)*10^1 + (2344*3)*10^2= ans
So for m digits X n digits you need n list of string array.
Each time you multiply each digits with m. and store it.
After each step you will append 0,1,2,n-1 trailing zero(s) to that string.
Finally, sum all of n listed string. You know how to do that.
So up to this you know m*n
now it is very easy to compute 1*..........*49*50.
how about:
int[] arrayOfFifty = new int[50];
//populate the array with 1 to 50
for(int i = 1; i < 51; i++){
arrayOfFifty[i-1] = i;
}
//perform the factorial
long result = 1;
for(int i = 0; i < arrayOfFifty.length; i++){
result = arrayOfFifty[i] * result;
}
Did not test this. No idea how big the number is and if it would cause error due to the size of the number.
Updated. arrays use ".length" to measure the size.
I now updated result to long data type and it returns the following - which is obviously incorrect. This is a massive number and I'm not sure what your professor is trying to get at.
-3258495067890909184

drawing Diamond of numbers with 2D array in java

So I need to make a diamond_look of numbers using 2D array in Java. I got my results but with null before the diamond. For drawNumDiamond(9) I have to get a diamond look that goes until 5 and back. I know I can make it without using array, but I want to learn more about 2D arrays :this is how it should look like and what are my results
public class Example1{
private static void drawNumDiamond(int h) {
if(h%2 != 0) {
int size = h/2 +1;
int count = 1;
int loop = 1;
String[][] dijamant = new String[h][];
for(int row = 0; row < dijamant.length; row++) {
dijamant[row] = new String[row+1];
for(int kolona=0; kolona<=row; kolona++) {
dijamant[0][0] = "1";
for(int i=0; i< loop;i++) {
dijamant[row][kolona]+= count;
}
}
count++;
loop+=2;
}
for (int k = 0; k < size; k++) {
System.out.printf("%" + h + "s", dijamant[k]);
h++;
System.out.println();
}
h--;
for (int q = size - 2; q>=0; q--) {
h--;
System.out.printf("%" + h + "s", dijamant[q]);
System.out.println();
}
}
}
public static void main(String[] args) {
drawNumDiamond(9);
}
}
The issue is in this line :
dijamant[row][kolona] += count;
if dijamant[row][kolona] is null and count is 2, the result of the string concatenation will be "null2". Try adding the following if statement before to initialize with an empty string :
if (dijamant[row][kolona] == null) {
dijamant[row][kolona] = "";
}
This will get your code working, but there are still things to think about. E.g. you keep setting dijamant[0][0] = "1"; in the loop.

Java - I have a 2D array. How can I add blocks of it together?

I'm not sure if this is the best way to ask my question.
Basically, I have a 2D array that is being built from a text file.
It takes the first two int's for the dimensions. Then fills the array with the remaining data. That part is working fine.
In my array, I need to add each value with each adjacent value. To determine which value, when added with all of its adjacent values, is the highest. I need to do the reverse also, to find the lowest.
What kind of loop or function could I use to accomplish this? I'l create a small example below.
2 4 3 7 8
1 5 7 9 2
2 9 2 5 7
So the 2 would become a 7, the 4 would become a 14, and so on. After the math is done I need to detect which coordinate in the array is the largest number.
For simplicity, lets use the example you provided. The array is 5 by 3. Lets call the array data Try this
int totals[5][3];
for(int x = 0;x<5;x++){
for(int y = 0;y<5;y++){
int total = data[x][y]
if(x>0){
total+= data[x-1][y];
}
if(x<4){
total+= data[x+1][y];
}
if(y>0){
total+= data[x][y-1];
}
if(y<2){
total+= data[x][y+1];
}
totals[x][y] = total;
}
}
Then loop through the arrays and compare the values.
My approach would be the following:
public int largeNeighbor(int[][] numbers) {
int max = 0;
for (int i = 0; i < numbers.length ; i++) {
for (int j = 0; j < numbers[0].length; j++) {
int temp = numbers[i][j];
if (i > 0) {
temp += numbers[i-1][j];
}
if (i < numbers.length - 1) {
temp += numbers[i+1][j];
}
if (j > 0) {
temp += numbers[i][j-1];
}
if (j < numbers[0].length - 1) {
temp += numbers[i][j+1];
}
if (temp > max) {
max = temp;
}
}
}
return max;
}
When given a 2D integer array, the method will compare every value with added neighbors to the current max value.
You explained your situation well but in future questions you should include what you already have in small blocks of code. :)
I did this for fun. Hope someone enjoys.
import java.lang.ArrayIndexOutOfBoundsException;
import java.util.Random;
public class HelloWorld{
int smallest = 10000;
int largest = -1;
int xCoords_small = -1;
int yCoords_small = -1;
int xCoords_large = -1;
int yCoords_large = -1;
//Make it as big as you want!!!!!
int iSize = 5;
int jSize = 3;
int[][] totals = new int[iSize][jSize];
int[][] yourNumbers = new int[iSize][jSize];
Random r = new Random();
//Initializes the array. With random numbers. Yours would read in the
//the file here and initialize the array.
public HelloWorld(){
for(int i = 0; i < iSize; i++){
for(int j = 0; j < jSize; j++){
yourNumbers[i][j] = r.nextInt(10);
}
}
}
//Calculates the total and whether or not it's the largest number and
//tracks position in array and the total number.
//It has crumby error catching but this way you can make your array
//as big as you want without needing to change anything but the two
//two size variables.
public void calculate(){
for(int i = 0; i < iSize; i++){
for(int j = 0; j < jSize; j++){
int total = 0;
try{
total += yourNumbers[i][j];
}catch(ArrayIndexOutOfBoundsException ex ){
//do nothing
}
try{
total += yourNumbers[i-1][j];
}catch(ArrayIndexOutOfBoundsException ex){
//do nothing
}
try{
total += yourNumbers[i][j-1];
}catch(ArrayIndexOutOfBoundsException ex){
//do nothing
}
try{
total += yourNumbers[i+1][j];
}catch(ArrayIndexOutOfBoundsException ex){
//do nothing
}
try{
total += yourNumbers[i][j+1];
}catch(ArrayIndexOutOfBoundsException ex){
//do nothing
}
totals[i][j] = total;
if(total > largest){
largest = total;
xCoords_large = i;
yCoords_large = j;
}
if(total < smallest){
smallest = total;
xCoords_small = i;
yCoords_small = j;
}
System.out.println(total);
}
}
System.out.println(largest + " = Largest Total and it's beginning number in your 2D array. " + xCoords_large+ "," + yCoords_large+ " Its value = " + yourNumbers[xCoords_large][yCoords_large]);
System.out.println(smallest + " = Smallest Total and it's beginning number in your 2D array. " + xCoords_small + "," + yCoords_small + " Its value = " + yourNumbers[xCoords_small][yCoords_small]);
}
public static void main(String []args){
HelloWorld hw = new HelloWorld();
hw.calculate();
}
}

How to display a result from a class?

I've been working on a program which multiplies matrices using threads. I written the program in a non-threaded fashion and it was working like a charm. However when I was writing it w/ threading function, it appears that I am not getting a result from the Threading class (I will rename it later on). Also if I were to use 1 thread, I would get all 3 matrices followed by a empty results for the matC matrix. Anything more than 1 would get me a Array index out of bounds.
Still pretty inept using classes and whatnot, and i apologize in advance of being somewhat wordy. But any help would be appreciated.
Main class:
package matrixthread;
import java.io.*;
import java.util.*;
public class MatrixThread extends Thread{
public static void matrixPrint(int[][] A) {
int i, j;
for (i = 0; i < A.length; i++) {
for (j = 0; j < A.length; j++) {
System.out.print(A[i][j] + " ");
}
System.out.println("");
}
}
public static void matrixFill(int[][] A) {
int i, j;
Random r = new Random();
for (i = 0; i < A.length; i++) {
for (j = 0; j < A.length; j++) {
A[i][j] = r.nextInt(10);
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int threadCounter = 0;
System.out.print("Enter number of rows: ");
int M = in.nextInt();
System.out.print("Enter number of threads: ");
int N = in.nextInt();
Thread[] thrd = new Thread[N];
if (M < N)
{
System.out.println("Error! Numbers of rows are greater than number of threads!");
System.exit(0);
}
if(M % N != 0)
{
System.out.println("Error! Number of rows and threads aren't equal");
System.exit(0);
}
int[][] matA = new int[M][M];
int[][] matB = new int[M][M];
int[][] matC = new int[M][M];
try
{
for (int x = 0; x < N; x ++)
for (int y = 0; y < N; y++)
{
thrd[threadCounter] = new Thread(new Threading(matA, matB, matC));
thrd[threadCounter].start();
thrd[threadCounter].join();
threadCounter++;
}
}
catch(InterruptedException ie){}
long startTime = (int)System.currentTimeMillis();
matrixFill(matA);
matrixFill(matB);
//mulMatrix(matA, matB, matC);
long stopTime = (int)System.currentTimeMillis();
int execTimeMin = (int) ((((stopTime - startTime)/1000)/60)%60);
int execTimeSec = ((int) ((stopTime - startTime)/1000)%60);
System.out.println("\n" + "Matrix 1: ");
matrixPrint(matA);
System.out.println("\n" + "Matrix 2: ");
matrixPrint(matB);
System.out.println("\n" + "Results: ");
matrixPrint(matC);
System.out.println("\n" + "Finish: " + execTimeMin + "m " + execTimeSec + "s");
}
}
And here's my threading class:
package matrixthread;
public class Threading implements Runnable {
//private int N;
private int[][] matA;
private int[][] matB;
private int[][] matC;
public Threading(int matA[][], int matB[][], int matC[][]) {
this.matA = matA;
this.matB = matB;
this.matC = matC;
}
#Override
public void run() {
int i, j, k;
for (i = 0; i < matA.length; i++) {
for (j = 0; j < matA.length; j++) {
for (k = 0; k < matA.length; k++) {
matC[i][j] += matA[i][k] * matB[k][j];
}
}
}
}
}
Here are my results using 2 rows and 1 thread
Matrix 1:
7 8
4 5
Matrix 2:
3 0
1 5
Results:
0 0
0 0
You have a large number of problems here. First and foremost is this loop:
for (int x = 0; x < N; x ++)
for (int y = 0; y < N; y++) {
thrd[threadCounter] = new Thread(new Threading(matA, matB, matC));
thrd[threadCounter].start();
thrd[threadCounter].join();
threadCounter++;
}
You run this loop before calling matrixFill. matA and matB are both equal to the Zero matrix at this point.
You then, for each Thread, call join() which waits for completion. So all you do is 0 * 0 = 0 N2 times.
Creating threads in a loop and calling join() on them as they are created waits for each thread to finish. This means that you never have two tasks running in parallel. This isn't threading, this is doing something with a single thread in a very complicated manner.
You then fill matA and matB and print out all three. Unsurprisingly, matC is still equal to the Zero matrix.
Your next issue is with your threading:
public void run() {
int i, j, k;
for (i = 0; i < matA.length; i++) {
for (j = 0; j < matA.length; j++) {
for (k = 0; k < matA.length; k++) {
matC[i][j] += matA[i][k] * matB[k][j];
}
}
}
}
Each thread runs this code. This code multiplies two matrices. Running this code N2 times as you do just makes a single matrix multiplication N2 times slower.
If you fixed your threading (see above) so that all your threads ran concurrently then all you would have is the biggest race hazard since in creation of Java. I highly doubt you would ever get the correct result.
TL;DR The reason matC is zero is because, when multiplication happens, maA == matB == 0.
First of all I don't know why you run the thread with the same data N^2 times. Possible you wanted to fill matA and matB every time with different data?
If you want to compute many data parallel you should do it in this way:
//First start all Threads
for (int x = 0; x < N; x ++)
for (int y = 0; y < N; y++)
{
thrd[threadCounter] = new Thread(new Threading(matA, matB, matC));
thrd[threadCounter].start();
threadCounter++;
}
//then wait for all
for(int i = 0; i < threadCounter; i++){
thrd[threadCounter].join();
}
Otherwise there is nothing parallel because you wait until the first Thread is ready and then do the next.
That you get a result of 0 0 0 0 is because matA and matB are 0 0 0 0 at the moment you start the threads.

Categories