Coding Bubble Sort using Java - java

I don't know if I did this coding correctly, but can someone confirm if my doBubbleSort method and its implementation in the main method are programmed correctly? My coding requires me to create an array of size 20 and populate it with random integers between 1 and 1000 without hard coding them. The result should display the original, unsorted list of integers; and then display each pass of the bubble sorting algorithm on a separate line. I have to repeat the program until the user chooses to quit. **I have made edits to make sure that whatever variables I use, it is declared according to ArrayLists.
An example of how I want my output to come out as is shown below (although it only shows 5 integers when I'm trying to do 20):
Unsorted list: 68 3 298 290 1
Pass 1: 3 68 290 1 298
Pass 2: 3 68 1 290 298
Pass 3: 3 1 68 290 298
Pass 4: 1 3 68 290 298
// Used to capture keyboard input
import java.util.*;
// Our class called BubbleSort
public class BubbleSort {
// Create doBubbleSort method
public static void doBubbleSort(ArrayList<Integer> arr) {
boolean needNextPass = true;
while (needNextPass) {
// Array may be sorted and next pass not needed
needNextPass = false;
// Swap list
for (int i = 0; i < arr.size()-1; i++) {
if (arr.get(i) > arr.get(i+1)) {
int temp = arr.get(i);
arr.set(i, arr.get(i+1));
arr.set(i+1, temp);
printOut(i+1, arr); // using printOut method
needNextPass = true; // Next pass still needed
}
}
}
}
private static void printOut(int pass, ArrayList<Integer> list) {
System.out.print("PASS " + pass + ": ");
for (int i = 0; i < list.size()-1; i++) {
System.out.print(list.get(i) + ", ");
}
// Shows very last integer with a period
System.out.print(list.get(list.size()-1) + ".");
System.out.println();
}
// Main method
public static void main(String[] args) {
ArrayList<Integer> array = new ArrayList<Integer>(); // Declare and instantiate a new ArrayList object
Scanner userChoice = new Scanner(System.in); // User input for quitting program
String choice = ""; // Will hold user choice to quit program
boolean inputFlag = false; // True if input is valid, false otherwise
// Repeat program until user chooses to quit
while (inputFlag = true) {
System.out.print("\nWould you like to continue the program? (Y/N): ");
choice = userChoice.nextLine();
if (choice.equalsIgnoreCase("Y")) {
try {
/* Create an array of size 20 and populate it with random integers between 1 and 1000.
Do not ask user for the numbers and do not hard code them */
for (int i = 0; i < 20; i++) {
int integer = (int)(1000.0 * Math.random());
array.add(integer);
}
System.out.print("\nUNSORTED LIST: ");
//Display the 20 size of the unsorted ArrayList
for (int i = 0; i < array.size() - 1; i++) {
System.out.print(array.get(i) + ", ");
}
// Shows very last integer with a period
System.out.print(array.get(array.size() - 1) + ".");
System.out.println();
doBubbleSort(array);
}
catch (IndexOutOfBoundsException e) {
System.out.println("\nThere is an out of bounds error in the ArrayList.");
}
}
else if (choice.equalsIgnoreCase("N")) {
break;
}
// Error message when inputting anything other than Y/N
else {
System.out.println("\nERROR. Only Y, y, N, or n may be inputted.");
System.out.println("Please try again.");
}
}
}
}

Going with your implementation, since you seem to be newly learning this, there are a few things you should change. First of all, since you're using an int array for the doBubbleSort method, use an int array in the main method as well.
The implementation of bubblesort needs to be changed too. You should first look into its logic carefully. Going through the whole array every time is not necessary.
// Create doBubbleSort method
public static void doBubbleSort(int[] arr) {
boolean needNextPass = true;
// Array may be sorted and next pass not needed
// Swap list
for (int i = 0; i < arr.length - 1; i++) {
if (needNextPass) {
needNextPass = false;
for (int j = arr.length - 1; j > i; j--) {
int temp;
if (arr[j] < arr[j - 1]) {
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
needNextPass = true; // Next pass still needed
}
}
printOut(i + 1, arr); // using printOut method
}
}
}
And then, printing the array.
private static void printOut(int pass, int[] list) {
System.out.print("PASS " + pass + ": ");
for (int i = 0; i < list.length - 1; i++) {
System.out.print(list[i] + ", ");
}
// Shows very last integer with a period
System.out.print(list[list.length - 1] + ".");
System.out.println();
}
Now the main method. I've changed the input handling part for re-running the program, and used an int array as you had originally posted.
// Main method
public static void main(String[] args) {
int[] array = new int[20]; // Declare and instantiate a new ArrayList object
Scanner userChoice = new Scanner(System.in); // User input for quitting program
boolean inputFlag = true; // True if input is valid, false otherwise
String choice;
// Repeat program until user chooses to quit
while (inputFlag == true) {
try {
/* Create an array of size 20 and populate it with random integers between 1 and 1000.
Do not ask user for the numbers and do not hard code them */
for (int i = 0; i < 20; i++) {
int integer = (int) (1000.0 * Math.random());
array[i] = integer;
}
System.out.print("\nUNSORTED LIST: ");
//Display the 20 size of the unsorted ArrayList
for (int i = 0; i < array.length - 1; i++) {
System.out.print(array[i] + ", ");
}
// Shows very last integer with a period
System.out.print(array[array.length - 1] + ".");
System.out.println();
doBubbleSort(array);
} catch (IndexOutOfBoundsException e) {
System.out.println("\nThere is an out of bounds error in the ArrayList.");
}
System.out.print("\nWould you like to continue the program? (Y/N): ");
choice = userChoice.nextLine();
while (!(choice.equalsIgnoreCase("Y")) && !(choice.equalsIgnoreCase("N"))) {
// Error message when inputting anything other than Y/N
System.out.println("\nERROR. Only Y, y, N, or n may be inputted.");
System.out.println("Please try again.");
choice = userChoice.nextLine();
}
if (choice.equalsIgnoreCase("N")) {
inputFlag = false;
}
}
}
}

You wrote too much boiler plate code for bubble sort. For bubble sort, use recursive method. I wrote for you simple bubble method, do what you want with output
private int[] bubbleSort(int[] arr){
int c;
boolean isArranged = false;
for (int i = 0; i < arr.length; i++) {
if (i < (arr.length - 1) && arr[i] > arr[i+1]){
c = arr[i];
arr[i] = arr[i+1];
arr[i+1] = c;
isArranged = true;
}
}
if (isArranged){
return bubbleSort(arr);
}else{
return arr;
}
}
Call this like:
Scanner in = new Scanner(System.in);
int length = in.nextInt();
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = in.nextInt();
}
Main main = new Main();
int[] newArr = main.bubbleSort(arr);
for (int i = 0; i < newArr.length; i++) {
System.out.print(newArr[i] + " ");
}
You can write ArrayList instead int array.

Related

java fill 2D array with specific method

I have an 2D array(matrix) and a Integer n.n is full square
for example if n equals 16 fill matrix like this.
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
what can I do?
public static void main(String args[]) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter the dimension of the matrix : ");
int dimension = Integer.parseInt(br.readLine());
System.out.print("Enter the number of elements : ");
int n = Integer.parseInt(br.readLine()); // total number of elements to be filled
n = n/dimension; // Get the number of rows and columns
if(n % dimension != 0){
// Not a Square matrix
}
int circularArray[][] = new int[n][n];
int k = 1, c1 = 0, c2 = n - 1, r1 = 0, r2 = n - 1;
while (k <= n * n) {
for (int i = c1; i <= c2; i++) {
circularArray[r1][i] = k++;
}
for (int j = r1 + 1; j <= r2; j++) {
circularArray[j][c2] = k++;
}
for (int i = c2 - 1; i >= c1; i--) {
circularArray[r2][i] = k++;
}
for (int j = r2 - 1; j >= r1 + 1; j--) {
circularArray[j][c1] = k++;
}
c1++;
c2--;
r1++;
r2--;
}
/* Printing the Circular matrix */
System.out.println("The Circular Matrix is:");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(circularArray[i][j] + "\t");
}
System.out.println();
}
}
Here is a tiny example how this could look like.
What is actually happening is written as comments.
public class TestArray {
// A simple enum for each direction
public enum Mode {
right, down, left, up;
}
public static void main(String[] args) {
final int size = 4; // We set a fixed size for the square
int[][] arr = new int[size][size]; // create the array from the size
// Running vallues
// i and j to refer to the array.
// val holds the current value to be inserted
// circle holds how often we are going up. Each time we go up it´s increased by one
// In the end this should reduce the amount of steps we do to not override
// already assigned values.
int i = 0,j = 0, val = 1, circle = 0;
Mode runningMode = Mode.right; // We start by going to the right.
while(size*size >= val) { // loop until we reached the last value
arr[j][i] = val++; // Assign the value and increase the value by one afterwards.
// We go right.
if(runningMode == Mode.right) {
// we reached the last assignable item.
// subtract one to not get an index out of bound,
// subract the variable trips that is used to get the last item for the inner circle
if(i==arr.length-1-circle) {
// We are going down now and increase j
runningMode = Mode.down;
++j;
} else {
// go on going right.
++i;
}
} else if(runningMode == Mode.down){
// we reached the last assignable item.
// subtract one to not get an index out of bound,
// subract the variable trips that is used to get the last item for the inner circle
if(j==arr.length-1-circle) {
// We are going left now and decrease i
runningMode = Mode.left;
--i;
} else {
// go on going down.
++j;
}
} else if(runningMode == Mode.left){
// we reached the last assignable item.
// add the variable trips that is used to get the last item for the inner circle
if(i==0+circle) {
// We are going up now and decrease j
// Simultaniosly we are about to end our next circle, so we increase circle
runningMode = Mode.up;
++circle;
--j;
} else {
// go on going left.
--i;
}
} else if(runningMode == Mode.up){
// we reached the last assignable item.
// add the variable trips that is used to get the last item for the inner circle
if(j==0+circle) {
// We are going right now and increase i
runningMode = Mode.right;
++i;
} else {
// go on going up.
--j;
}
}
}
// Print the result
for(int[] a : arr) {
for(int b : a) {
System.out.print(b + "\t" );
}
System.out.println();
}
}
}

Generating 10 random numbers without duplicate with fundamental techniques

my intend is to use simplest java (array and loops) to generate random numbers without duplicate...but the output turns out to be 10 repeating numbers, and I cannot figure out why.
Here is my code:
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
do {
for (int i=0; i<number.length; i++) {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
}
} while (!repeat);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
How about you use a Set instead? If you also want to keep track of the order of insertion you can use a LinkedHashSet.
Random r = new Random();
Set<Integer> uniqueNumbers = new HashSet<>();
while (uniqueNumbers.size()<10){
uniqueNumbers.add(r.nextInt(21));
}
for (Integer i : uniqueNumbers){
System.out.print(i+" ");
}
A Set in java is like an Array or an ArrayList except it handles duplicates for you. It will only add the Integer to the set if it doesn't already exist in the set. The class Set has similar methods to the Array that you can utilize. For example Set.size() is equivalent to the Array.length and Set.add(Integer) is semi-equivalent to Array[index] = value. Sets do not keep track of insertion order so they do not have an index. It is a very powerful tool in Java once you learn about it. ;)
Hope this helps!
You need to break out of the for loop if either of the conditions are met.
int[] number = new int[10];
int count=0;
int num;
Random r = new Random();
while(count<number.length){
num = r.nextInt(21);
boolean repeat=false;
do{
for(int i=0; i<number.length; i++){
if(num==number[i]){
repeat=true;
break;
}
else if(i==count){
number[count]=num;
count++;
repeat=true;
break;
}
}
}while(!repeat);
}
for(int j=0;j<number.length;j++){
System.out.print(number[j]+" ");
}
This will make YOUR code work but #gonzo proposed a better solution.
Your code will break the while loop under the condition: num == number[i].
This means that if the pseudo-generated number is equal to that positions value (the default int in java is 0), then the code will end execution.
On the second conditional, the expression num != number[i] is always true (otherwise the code would have entered the previous if), but, on the first run, when i == count (or i=0, and count=0) the repeat=true breaks the loop, and nothing else would happen, rendering the output something such as
0 0 0 0 0 0...
Try this:
int[] number = new int[10];
java.util.Random r = new java.util.Random();
for(int i=0; i<number.length; i++){
boolean repeat=false;
do{
repeat=false;
int num = r.nextInt(21);
for(int j=0; j<number.length; j++){
if(number[j]==num){
repeat=true;
}
}
if(!repeat) number[i]=num;
}while(repeat);
}
for (int k = 0; k < number.length; k++) {
System.out.print(number[k] + " ");
}
System.out.println();
Test it here.
I believe the problem is much easier to solve. You could use a List to check if the number has been generated or not (uniqueness). Here is a working block of code.
int count=0;
int num;
Random r = new Random();
List<Integer> numbers = new ArrayList<Integer>();
while (count<10) {
num = r.nextInt(21);
if(!numbers.contains(num) ) {
numbers.add(num);
count++;
}
}
for(int j=0;j<10;j++){
System.out.print(numbers.get(j)+" ");
}
}
Let's start with the most simple approach, putting 10 random - potentially duplicated - numbers into an array:
public class NonUniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
number[count++] = ThreadLocalRandom.current().nextInt(21);
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
So that gets you most of the way there, the only thing you know have to do is pick a number and check your array:
public class UniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
int candidate = ThreadLocalRandom.current().nextInt(21);
// Is candidate in our array already?
boolean exists = false;
for (int i = 0; i < count; i++) {
if (number[i] == candidate) {
exists = true;
break;
}
}
// We didn't find it, so we're good to add it to the array
if (!exists) {
number[count++] = candidate;
}
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
The problem is with your inner 'for' loop. Once the program finds a unique integer, it adds the integer to the array and then increments the count. On the next loop iteration, the new integer will be added again because (num != number[i] && i == count), eventually filling up the array with the same integer. The for loop needs to exit after adding the unique integer the first time.
But if we look at the construction more deeply, we see that the inner for loop is entirely unnecessary.
See the code below.
import java.util.*;
public class RandomDemo {
public static void main( String args[] ){
// create random object
Random r = new Random();
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
int i=0;
do {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
i++;
} while (!repeat && i < number.length);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
}
}
This would be my approach.
import java.util.Random;
public class uniquerandom {
public static void main(String[] args) {
Random rnd = new Random();
int qask[]=new int[10];
int it,i,t=0,in,flag;
for(it=0;;it++)
{
i=rnd.nextInt(11);
flag=0;
for(in=0;in<qask.length;in++)
{
if(i==qask[in])
{
flag=1;
break;
}
}
if(flag!=1)
{
qask[t++]=i;
}
if(t==10)
break;
}
for(it=0;it<qask.length;it++)
System.out.println(qask[it]);
}}
public String pickStringElement(ArrayList list, int... howMany) {
int counter = howMany.length > 0 ? howMany[0] : 1;
String returnString = "";
ArrayList previousVal = new ArrayList()
for (int i = 1; i <= counter; i++) {
Random rand = new Random()
for(int j=1; j <=list.size(); j++){
int newRand = rand.nextInt(list.size())
if (!previousVal.contains(newRand)){
previousVal.add(newRand)
returnString = returnString + (i>1 ? ", " + list.get(newRand) :list.get(newRand))
break
}
}
}
return returnString;
}
Create simple method and call it where you require-
private List<Integer> q_list = new ArrayList<>(); //declare list integer type
private void checkList(int size)
{
position = getRandom(list.size()); //generating random value less than size
if(q_list.contains(position)) { // check if list contains position
checkList(size); /// if it contains call checkList method again
}
else
{
q_list.add(position); // else add the position in the list
playAnimation(tv_questions, 0, list.get(position).getQuestion()); // task you want to perform after getting value
}
}
for getting random value this method is being called-
public static int getRandom(int max){
return (int) (Math.random()*max);
}

Java not inclusive of 100 in 100 Lockers

MY desired output is locker 1,4,9,16,36,49,81 AND 100.
I'm iterating through trying to find which lockers after a student is sent, and opens every locker. (All are closed by default) and opens every locker. then student number 2 goes to every other locker, and if it is open, close it, and if it is closed, open it. Student three does the same but with every third locker. All the way up to student 100. I know the output should be all the square numbers but I can't get the 100 to show up. What am I missing? I put a <= on both of my iterations and it doesn't work. It throws an IndexOutOfRangeException. What should I do?
import java.util.Arrays;
public class runLocker {
final static int numberOfLockers = 100;
final static int numberOfStudents = 100;
public static void main(String[] args) {
// TODO Auto-generated method stub
int LockersToCloseBy = 1;
boolean[] totalLockersArray = new boolean[numberOfLockers];
for(int i = 0; i < totalLockersArray.length - 1; i++){
totalLockersArray[i] = false;
}
for(int n= 0; n < totalLockersArray.length ; ++n){
for(int j = 0; j < totalLockersArray.length; j+=LockersToCloseBy){
if(totalLockersArray[j] == true)
{
totalLockersArray[j] = false;
}
else
{
totalLockersArray[j] = true;
}
}
LockersToCloseBy++;
}
for(int i = 0; i < numberOfLockers; i++){
if(totalLockersArray[i] == true){
System.out.println("Locker " + i + " is open");
}
}
//Currently outputs 1, 4, 9, 16, 36, 49, and 81...
//Need it to output 1,4,9,16,36,49,81,100
}
}
Your array is defined for indices [0,...,99] (100 elements total, exclusive of 100).
In the following code:
for(int i = 0; i < numberOfLockers; i++){
if(totalLockersArray[i] == true){
System.out.println("Locker " + i + " is open");
}
}
100 is not even a candidate.
An easy fix could be to set the lockers array at 101 (numberOfLockers=101), so all the loops will be inclusive of 100.

How to remove element from a raw array

I have a program that will push pop and display, but I cannot pop the pushed numbers in my program probably I can't delete the element of that array. This is my code so far:
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
public class Class2 {
public static void main(String args[]) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out
.print("1.)Push\n2.)Pop\n3.)Display\n4.)Exit\n\nChoose Item :");
int x = Integer.parseInt(in.readLine());
int[] a = new int[10];
int b = 0;
int i = 0;
do
{
switch (x) {
case 1:
System.out.print("Enter Push number :");
int v = Integer.parseInt(in.readLine());
a[b] = v;
b += 1;
System.out.print("Item push :" + v + "\n");
System.out
.print("1.)Push\n2.)Pop\n3.)Display\n4.)Exit\n\nChoose Item :");
x = Integer.parseInt(in.readLine());
if (x == 3) {
for (i = 0; i < b; i++) {
System.out.print(a[i] + " ");
}
}
break;
case 2:
System.out.print("Enter Pop Number :");
int c = Integer.parseInt(in.readLine());
if (c == a[i]) {
}
System.out.print("Item Pop :" + c + "\n");
System.out
.print("1.)Push\n2.)Pop\n3.)Display\n4.)Exit\n\nChoose Item :");
x = Integer.parseInt(in.readLine());
if (x == 3) {
for (i = 0; i < b; i++) {
System.out.print(a[i] + " ");
}
}
break;
case 4:
break;
}
} while (x == 1 || x == 2);
}
}
First of all, if you want to change the elements of an array, then you should not use an array.
If you really don't want to use containers, then you could allocate dynamically a new array without the element you want to remove (not so a good idea probably because of bad performance and wasted memory).
This could be the method that returns the new array:
public static int[] removeElementAt(int [] array, int index){
if(index > 0 && index < array.length){
int [] newArray = new int[array.length - 1];
for(int i=0; i<index; i++)
newArray[i] = array[i]; // copying elements
for(int i=index+1; i<array.length; i++)
newArray[i-1] = array[i];
array = newArray;
}
return array;
}
This is just a simple example:
myArray = Class.removeElementAt(myArray, 5); // removes 6. element
You could also use the function removeElement from the API ArrayUtils, something like this:
array = ArrayUtils.removeElement(array, element)
Another alternative would be to convert your array to a list, remove the element, and then convert it back to an array: not so a good idea, because you could use directly an ArrayList.
So, the idea is to use dynamic containers when you want to modify the content, otherwise use a normal raw array.
you can use below code and it might solve your issue.
int brr[]= new int [a.length-1];
int j=0;
for(;j<a.length;j++)
{
if(c== a[j])
{
break;
}
else{
brr[j]=a[j];
}
}
for(j=j+1;j<a.length;j++)
{
brr[j-1] =a[j];
}
in display show brr array.
When you push 2, 5, and 6 you have a queue with 3 items in it:
a[0] == 2
a[1] == 5
a[2] == 6
When you pop 2, you want to remove it from the array. To do this, you need to copy everything after where 2 was popped from into the position above, so that you end up with:
a[0] == 5
a[1] == 6
The code for this would look something like:
int popPosition = findPopPosition();
for(int i = popPosition + 1; i < MAX; i++)
a[i - 1] = a[i];
b--; // Decrease effective queue size
Where findPopPosition() would need to find the index that 2 is at, so it would return 0 in this example.
Or, alternatively, the user could input the pop position directly (so pop element 0) instead of specifying what value they want to pop. That's probably more useful.
Not all test cases have been handled, but a sample working program as per your requirements.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ArrayDemo {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the Array Max Capacity");
int maxSize = Integer.parseInt(br.readLine().trim());
int[] array = new int[maxSize];
int arrayCount = 0;
int choice = 0;
do {
System.out.println("\n1.Insert\n2.Delete\n3.Display\n4.Exit");
choice = Integer.parseInt(br.readLine().trim());
switch (choice) {
case 1:
boolean insertTrue = insertElement(br, maxSize, array,
arrayCount);
if (insertTrue) {
arrayCount++;
}
break;
case 2:
System.out.println("Enter Element to delete");
int delElement = Integer.parseInt(br.readLine().trim());
int numOccurrence = getOccurrenceCount(array, arrayCount,
delElement);
int newArrayCount = arrayCount - numOccurrence;
if (numOccurrence == 0) {
System.out.println("No Such Element to delete");
} else {
array = deleteElement(array, arrayCount, delElement,
newArrayCount,maxSize);
}
arrayCount =newArrayCount;
break;
case 3:
displayArray(array, arrayCount);
break;
case 4:
System.out.println("Exiting");
break;
default:
System.out.println("Invalid Choice, Exiting");
choice = 4;
}
} while (choice >= 1 && choice <= 3);
}
private static int[] deleteElement(int[] array, int arrayCount,
int delElement, int newArrayCount,int maxSize) {
int newArray[] = new int[newArrayCount];
int index=0;
for (int i = 0; i < arrayCount; i++) {
if (array[i] != delElement) {
newArray[index] = array[i];
index++;
}
}
resetArray(array, maxSize);
for(int i=0;i<newArrayCount;i++){
array[i]=newArray[i];
}
return array;
}
private static int[] resetArray(int[] array,int maxSize){
for(int i=0;i<maxSize;i++){
array[i]=0;
}
return array;
}
private static int getOccurrenceCount(int[] array, int arrayCount,
int delElement) {
int numOccurrence = 0;
for (int i = 0; i < arrayCount; i++) {
if (array[i] == delElement) {
numOccurrence++;
}
}
return numOccurrence;
}
private static void displayArray(int[] array, int arrayCount) {
if (arrayCount == 0) {
System.out.println("No Elements to Display");
} else {
System.out.println("Array is");
for (int i = 0; i < arrayCount; i++) {
System.out.print(array[i] + " ");
}
System.out.println("\n");
}
}
private static boolean insertElement(BufferedReader br, int maxSize,
int[] array, int arrayCount) throws IOException {
if (arrayCount < maxSize) {
System.out.println("Enter Element for Insertion");
array[arrayCount] = Integer.parseInt(br.readLine().trim());
return true;
} else {
System.out.println("Max Limit Reached, Insertion not possible");
return false;
}
}
}

Why is this program running so slowly?

This is for project euler problem 14.
When a number is even, you're supposed to divide the number by two, but when it is odd you multiply it by three and add one. Eventually it should reach one.
My task is to find the number that takes the largest amount of steps to get to 1.
Here's my code:
int currentNum = 0;
int iterator = 0;
int[] largestChain = new int[]{0,0};
for(int i = 10;i<=1000000;i++)
{
currentNum = i;
iterator = 0;
while(currentNum!=1)
{
iterator++;
if(currentNum%2==0)
{
currentNum/=2;
}
else
{
currentNum = (currentNum*3)+1;
}
}
if(iterator>largestChain[1])
{
largestChain[0] = i;
largestChain[1] = iterator;
}
}
System.out.println("largest iterator:"+largestChain[1]+"for num:"+largestChain[0]);
Can you please help me out by telling me what's slowing it down? (It's taking >30 minutes right now and it still hasn't come up with the answer).
Use long variables instead of int. currentNum goes so high the values wrap around into the negatives!
Once you do that change, your algorithm works just fine. (I tested it)
The reason it take so long is that you are performing this while loop operation on 1 million numbers. The solution to this is to create an algorithm which saves the number of steps dynamically.
int[] steps = new int[1000000];
steps[0] = 0;
steps[1] = 1;
Iterate through the rest of your numbers, adding back to this base case. By the end, many of your paths will be computed, and you will not need a nested loop.
However, if you want to stick to your way:
I'd recommend putting some debug print statements in there to see where it is getting caught up. My guess is that the 1 Million looped while statements are the culprit, but the easiest way to find out is progress check.
try adding System.out.println(i+":"); before the while and System.out.println(" current number: "+currentnum); inside the while.
Should print out something like:
1:
1
2:
2
1
etc.
I modified the code to print the interesting info and how its looping. The loop is crazy.
I would suggest converting currentNum to 'long' and re-run it as that number goes negative (beyond int capacity).
public class TestLoop{
public static void main(String[] args){
int currentNum = 0;
int iterator = 0;
int[] largestChain = new int[]{0,0};
for(int i = 10;i<=1000000;i++)
{
currentNum = i;
iterator = 0;
System.out.println("\nCurrently Running :" + i);
while(currentNum!=1)
{
iterator++;
if(currentNum%2==0)
{
currentNum/=2;
}
else
{
currentNum = (currentNum*3)+1;
}
System.out.print(currentNum + " ");
}
if(iterator>largestChain[1])
{
largestChain[0] = i;
largestChain[1] = iterator;
}
}
System.out.println("\nLargest iterator: "+largestChain[1]+" for num:"+largestChain[0]);
}
}
I ran it on linux and got below answer in 10 mins after I changed the currentNum to 'long'.
Largest iterator: 524 for num:837799
Still there is a flaw in your logic: you are NOT checking if any other number taking the same iterations. E.g. below loop gives two such numbers :
import java.util.ArrayList;
public class TestLoop {
public static void main(String[] args) {
long currentNum;
int iterator;
int[] largestChain = new int[]{0, 0};
ArrayList Nums = new ArrayList();
for (int i = 10; i <= 300; i++) {
currentNum = i;
iterator = 0;
System.out.println("\nCurrently Running :" + i);
while (currentNum != 1) {
iterator++;
if (currentNum % 2 == 0) {
currentNum /= 2;
} else {
currentNum = (currentNum * 3) + 1;
}
System.out.print(currentNum + " ");
}
if (iterator > largestChain[1]) {
largestChain[0] = i;
largestChain[1] = iterator;
Nums.clear();
Nums.add(i);
} else if (iterator == largestChain[1]) {
Nums.add(i);
}
}
System.out.println("\nLargest iterator: " + largestChain[1]);
//+ " for num:" + largestChain[0]);
if (Nums.size() == 1) {
System.out.println("There is only one number with " + largestChain[1] + " iterations:" + largestChain[0]);
} else {
System.out.print("Below numbers took " + largestChain[1] + " iterations:");
for (int i = 0; i < Nums.size(); i++) {
System.out.print(" " + Nums.get(i));
}
}
}
}

Categories

Resources