I am currently attempting to revise a Java Homework program for my Data Structures class that displays the output of the MaxSumTest program in a table.
I've created four arrays, and placed them inside one of the loops that calculates the timing info. I am trying to populate each array with only the timing info for one algorithm. So each array would have 4 elements. However, every time I run my revision of the program, I get an out of bounds error.
Here is the Original
The only method I revised is getTimingInfo. Here is my revision:
public static void getTimingInfo( int n, int alg )
{
int [] test = new int[ n ];
long startTime = System.currentTimeMillis( );;
long totalTime = 0;
//create an array for each Algorithm
long[] alg4;
long[] alg3;
long[] alg2;
long[] alg1;
//allocate memory for 5 long ints
alg4 = new long[5];
alg3 = new long[5];
alg2 = new long[5];
alg1 = new long[5];
int i;
int j;
int index = 0;
for( i = 0; totalTime < 4000; i++ )
{
for( j = 0; j < test.length; j++ )
test[ j ] = rand.nextInt( 100 ) - 50;
index = j;
switch( alg )
{
case 1:
maxSubSum1( test );
break;
case 2:
maxSubSum2( test );
break;
case 3:
maxSubSum3( test );
break;
case 4:
maxSubSum4( test );
break;
}
totalTime = System.currentTimeMillis( ) - startTime;
}
alg1[index] = totalTime * 1000 / i;
alg2[index] = totalTime * 1000 / i;
alg3[index] = totalTime * 1000 / i;
alg4[index] = totalTime * 1000 / i;
//Build first column of table
System.out.println("Size of N Algorithms\t" + "250\t" + "2500\t" + "25000\t" + "250000");
System.out.println("Alg #4\t" + alg4[0] + "\t" + alg4[1] + "\t" + alg4[2] + "\t" + alg4[3] + "\t" + alg4[4]);
System.out.println("Alg #3\t" + alg3[0] + "\t" + alg3[1] + "\t" + alg3[2] + "\t" + alg3[3] + "\t" + alg3[4]);
System.out.println("Alg #2\t" + alg2[0] + "\t" + alg2[1] + "\t" + alg2[2] + "\t" + alg2[3] + "\t" + alg2[4]);
System.out.println("Alg #1\t" + alg1[0] + "\t" + alg1[1] + "\t" + alg1[2] + "\t" + alg1[3] + "\t" + alg1[4]);
/*
System.out.println( "Algorithm #" + alg + "\t"
+ "N = " + test.length
+ "\ttime = " + ( totalTime * 1000 / i ) + " microsec" );
*/
}
Any advice or pointers in the right direction would be appreciated.
Shouldn't the lines that update the array elements be inside the inner loop?
alg1[index] = totalTime * 1000 / i;
alg2[index] = totalTime * 1000 / i;
alg3[index] = totalTime * 1000 / i;
alg4[index] = totalTime * 1000 / i;
You are assigning them outside the loop, where the value of index is 5, so it's out of bounds.
I'm not sure exactly what you are trying to do, but I think that what you really want to do is call getTimingInfo() a number of times and then assign the results to a table, not change the internal workings of getTimingInfo().
This requires that you define the arrays in which you will store the timing data OUTSIDE of getTimingInfo(), and then the only change inside of getTimingInfo() would be storing to that (already defined) array, rather than printing.
long[] alg1;
alg4 = new long[5];
Can be better expressed as
long[] alg1 = new long[5];
maxSubSum3( test );
Is written nicer as
maxSubSum3(test);
int j;
int index = 0;
Actually do the same thing.
Just to pick a few points.
You are setting the alg4, alg3, alg2, and alg1 to size 5, not size 4 as you said you needed.
Related
Im trying to solve EulerProblem8 https://projecteuler.net/problem=8 and i just don't get it , what am i doing wrong ? I tried before with a file and ArrayList but couldn't pull it off ... Whats wrong , the subtsrings , the loops , the *= ... i dont know what to do anymore?
package largestproductinaseries_ep8;
//The four adjacent digits in the 1000-digit number
//that have the greatest product are 9 × 9 × 8 × 9 = 5832.
//Find the thirteen adjacent digits in the 1000-digit number
//that have the greatest product. What is the value of this product?
public class LargestProductInASeries_EP8 {
public static void main(String[] args){
String bigNum = "73167176531330624919225119674426574742355349194934" +
"96983520312774506326239578318016984801869478851843" +
"85861560789112949495459501737958331952853208805511" +
"12540698747158523863050715693290963295227443043557" +
"66896648950445244523161731856403098711121722383113" +
"62229893423380308135336276614282806444486645238749" +
"30358907296290491560440772390713810515859307960866" +
"70172427121883998797908792274921901699720888093776" +
"65727333001053367881220235421809751254540594752243" +
"52584907711670556013604839586446706324415722155397" +
"53697817977846174064955149290862569321978468622482" +
"83972241375657056057490261407972968652414535100474" +
"82166370484403199890008895243450658541227588666881" +
"16427171479924442928230863465674813919123162824586" +
"17866458359124566529476545682848912883142607690042" +
"24219022671055626321111109370544217506941658960408" +
"07198403850962455444362981230987879927244284909188" +
"84580156166097919133875499200524063689912560717606" +
"05886116467109405077541002256983155200055935729725" +
"71636269561882670428252483600823257530420752963450";
int a = 0;
String peace = "";
String onePeace = "";
int onePeaceNum = 0;
int multi = 1;
int maxMulti = 0;
while(a<bigNum.length()-12){
peace = bigNum.substring(a, a+13);
if(!peace.contains("0")){
for(int i = 12; i>=0; i--){
onePeace = peace.substring(i, i+1);
onePeaceNum = Integer.parseInt(onePeace);
multi *= onePeaceNum;
if(multi>maxMulti){
maxMulti = multi;
}
}
multi = 1;
}
a++;
}
System.out.println(maxMulti);
}
}
//23514624000 this is Euler answer
// 2091059712 this is my output
You have a problem in your implementation, you never reset the mult value so you keep multiplying and you don't stop after 13 numbers.
Your code should be:
if (mult > maxMult) {
maxMult = mult;
mult = 1;
} else {
mult = 1;
}
I know my code can be simpler and more efficient... My code is supposed to grab the biggest set of 5 digits. It works, except it only is grabbing 3 digits, what would i need to modify to change that?
public class thousandDigits {
public static void main(String[] args) {
int greatest = 0;
String num = ("73167176531330624919225119674426574742355349194934"
+ "96983520312774506326239578318016984801869478851843"
+ "85861560789112949495459501737958331952853208805511"
+ "12540698747158523863050715693290963295227443043557"
+ "66896648950445244523161731856403098711121722383113"
+ "62229893423380308135336276614282806444486645238749"
+ "30358907296290491560440772390713810515859307960866"
+ "70172427121883998797908792274921901699720888093776"
+ "65727333001053367881220235421809751254540594752243"
+ "52584907711670556013604839586446706324415722155397"
+ "53697817977846174064955149290862569321978468622482"
+ "83972241375657056057490261407972968652414535100474"
+ "82166370484403199890008895243450658541227588666881"
+ "16427171479924442928230863465674813919123162824586"
+ "17866458359124566529476545682848912883142607690042"
+ "24219022671055626321111109370544217506941658960408"
+ "07198403850962455444362981230987879927244284909188"
+ "84580156166097919133875499200524063689912560717606"
+ "05886116467109405077541002256983155200055935729725"
+ "71636269561882670428252483600823257530420752963450");
for (int n = 0; n < num.length() - 5; n++) {
greatest = ((num.charAt(n)) + (num.charAt(n+1)) + (num.charAt(n+2)) + (num.charAt(n+3))
+ (num.charAt(n+4)));
if (greatest > n) {
n = greatest;
}
}
System.out.print(greatest);
}
}
OUTPUT:
357
I think you want to use String.substring(int, int) to iterate all possible 5 character substrings, and then you might use Math.max(int, int) to update greatest. Something like
int greatest = Integer.MIN_VALUE;
for (int i = 0; i < num.length() - 4; i++) {
// int value = Integer.parseInt(num.substring(i, i + 5));
int value = Integer.parseInt(String.valueOf(num.charAt(i))
+ num.charAt(1 + i) + num.charAt(2 + i) + num.charAt(3 + i)
+ num.charAt(4 + i));
greatest = Math.max(greatest, value);
}
System.out.println(greatest);
I get 99890.
I think you are trying to add 5 consecutive characters to get sum, and store starting index of highest sum.
But you should be using Character.getNumricValue(char) to convert (num.charAt(n)) to numeric value and then add.
greatest = Character.getNumericValue((num.charAt(n)) + Character.getNumericValue((num.charAt(n+1)) + Character.getNumericValue((num.charAt(n+2)) +
Character.getNumericValue((num.charAt(n+3)) +
Character.getNumericValue((num.charAt(n+4));
You need a valirable to store old value to compare and index
if(greatest > oldGreatest) {
index = n;
}
Then finally print using index out side loop:
System.out.print((num.charAt(index)) + (num.charAt(index+1) + (num.charAt(index +2)) + (num.charAt(index +3)) + (num.charAt(index +)));
Although #ElliottFrisch and #dave provides more elegant answer, I tried to modify from your original version and here is my code (I have tested it):
public class ThousandDigits {
public static void main(String[] args) {
int greatest = 0;
String num = ("73167176531330624919225119674426574742355349194934"
+ "96983520312774506326239578318016984801869478851843"
+ "85861560789112949495459501737958331952853208805511"
+ "12540698747158523863050715693290963295227443043557"
+ "66896648950445244523161731856403098711121722383113"
+ "62229893423380308135336276614282806444486645238749"
+ "30358907296290491560440772390713810515859307960866"
+ "70172427121883998797908792274921901699720888093776"
+ "65727333001053367881220235421809751254540594752243"
+ "52584907711670556013604839586446706324415722155397"
+ "53697817977846174064955149290862569321978468622482"
+ "83972241375657056057490261407972968652414535100474"
+ "82166370484403199890008895243450658541227588666881"
+ "16427171479924442928230863465674813919123162824586"
+ "17866458359124566529476545682848912883142607690042"
+ "24219022671055626321111109370544217506941658960408"
+ "07198403850962455444362981230987879927244284909188"
+ "84580156166097919133875499200524063689912560717606"
+ "05886116467109405077541002256983155200055935729725"
+ "71636269561882670428252483600823257530420752963450");
int max = -1;
for (int n = 0; n < num.length() - 4; n++) {
greatest = ((num.charAt(n) - '0') * 10000 + (num.charAt(n + 1) - '0') * 1000
+ (num.charAt(n + 2) - '0') * 100 + (num.charAt(n + 3) - '0') * 10 + (num.charAt(n + 4) - '0'));
if (max < greatest) {
max = greatest;
}
}
System.out.print(max);
}
}
I think you'll find it's not grabbing three digits, but rather the sum of the six characters you are pulling out is a 3-digit number.
If you're after the largest five digit number, you need to extract five digits (not six) as you do and assign them a weight. So the first digit must be multiplied by 10,000, the second by 1,000 and so on.
But there's more: you're are getting the character at an index within your string. This is not what you want as it is not the same as the numeric value of that character. For that you need:
num.charAt(n) - '0'
These changes should allow you to correct your algorithm as it stands.
A more efficient approach would be to extract 5-digit sub-strings and convert them to integers. The first one would be:
Integer.parseInt(num.subString(0, 5));
You can iterate to get each one to find the greatest.
public static void main(String[] args) {
//Numbers
int operand1 = 25;
int operand2 = 6;
//Arithmetic values
int sum = 0;
int difference = 0;
int product = 0;
int quotient = 0;
int remainder = 0;
//Operations
sum = operand1 + operand2;
difference = operand1 - operand2;
product = operand1*operand2;
quotient = operand1/operand2;
remainder = operand1%operand2;
//Output
System.out.println("Arithmetic");
System.out.println("============================");
System.out.println("25 + 6 = " + sum);
System.out.println("25 - 6 = " + difference);
System.out.println("25 * 6 = " + product);
System.out.println("25 / 6 = " + quotient);
System.out.println("25 % 6 = " + remainder);
I'm trying to find a way to replace "25 + 6", "25 - 6", etc... with variables like
(operand1 "+" operand2 "=" sum) so the values will change dynamically depending on what value I put on oeprand1 and operand2. Is there any way to do that? Thanks
You do it the same exact way you are inserting your result variables into the strings...
System.out.println(operand1 + " + " + operand2 + " = " + sum);
You could also use printf if you wanted to although you have to insert the line break explicitly:
System.out.printf("%d + %d = %d%n", operand1, operand2, sum);
Maybe it is just me but I find this to look much cleaner.
System.out.print(MessageFormat.format(
"Arithmetic\n" +
"============================\n"+
"{0} + {1} = {2}\n"+
"{0} - {1} = {3}\n"+
"{0} * {1} = {4}\n"+
"{0} / {1} = {5}\n"+
"{0} % {1} = {6}\n", operand1,operand2,sum,difference,product,quotient,remainder));
The MessageFormat.format provides a neat alternative way to accomplish what you are looking for.
Remember sometimes less is more! Why repeat the print command over and over again?
In an infinite loop, how would I print a random number that will increase every set number of times( example 10 times )? Here is my code at the moment.
`import hsa.*;
public class MidTermProject{
public static void main(String[] args){
Console con = new Console();
int intCount;
int intRand;
int intAnswer;
int intRand2;
int intTotal;
int intSubtractTotal;
int intAnswer2;
int intRand3;
int intRand4;
int intQuestionsAsked;
int intTotalQuestions;
int intTRand;
int intTRand1;
int intTRand2;
int intTRand3;
int intTRand4;
double dblTotalScore;
double dblScore;
dblScore = 0;
intQuestionsAsked = 0;
//5 - Math Training Game
con.println("This is the Math Training Game. The Questions will increase difficulty.");
con.println("There will be 30 Questions in Total");
con.println("");
con.println("One Digits:");
con.println("");
//Loop ---------------------------------------------------------------------
for(;;){
for(intCount=0; intCount<5;intCount++){
//----------------------------------------------------------------------------
//1 DIGITS
intRand=(int)(Math.random()*9+1);
intRand2=(int)(Math.random()*9+1);
intTotal = intRand + intRand2;
intRand3 =(int)(Math.random()*9+1);
intRand4 =(int)(Math.random()*9+1);
intSubtractTotal = intRand3 - intRand4;
con.println("What is " + intRand + " + " + intRand2);
intAnswer = con.readInt();
if(intAnswer == intTotal){
con.println("Correct");
con.println("");
//Add score
dblScore = dblScore + 1;
intQuestionsAsked = intQuestionsAsked + 1;
}else{
con.println("Wrong");
con.println("");
intQuestionsAsked = intQuestionsAsked + 1;
}
// SUBTRACTION ---------------------------------------------------------
con.println("What is " + intRand3 + " - " + intRand4);
intAnswer2 = con.readInt();
if(intAnswer2 == intSubtractTotal){
con.println("Correct");
con.println("");
//Add Score -------------------------------------------------------------
intQuestionsAsked = intQuestionsAsked + 1;
dblScore = dblScore + 1;
}else{
con.println("Wrong");
con.println("");
intQuestionsAsked = intQuestionsAsked + 1;
}
intTotalQuestions = intQuestionsAsked;
//----------------------------------------------------------
while(intTotalQuestions == 10){
intQuestionsAsked = 0;
intTRand = intRand * 10;
intTRand2 = intRand2 * 10;
intTRand3 = intRand3 * 10;
intTRand4 = intRand4 * 10;
con.println("What is " + intRand * intTRand + "+" + intTRand2 * intRand2);
intAnswer = con.readInt();
con.println("What is " + intRand2 * intTRand2 + "-" + intRand3 * intTRand3);
intAnswer2 = con.readInt();
}
//--------------------------------------------
}
}
}
}'
Could anyone tell me what I did wrong and how I could fix this code to make it work?
What I understand is that you want to generate random numbers that get increasingly higher. Store the previous random generated value. Generate your new random number from whatever range you want, and add the previous number to ensure it increases. Also, as it appears your code is way clunkier than it has to be, I would suggest using arrays to cut down on all of the excessive instance variables you have.
Having a program run forever is bad design.
That being said, if you want your random numbers to be of greater values every time you can set a range
(min + (int)(Math.random() * ((max - min) + 1)));
and increase min and max every iteration.
I have implemented (in Java) Insertion Sort, MergeSort, ModifiedMergeSort and Quick Sort:
ModifiedMergeSort has a variable for the "bound" of elements. When the elements to be sorted are less than or equal to "bound" then use Insertion Sort to sort them.
How come Version 1 is better than Versions 3, 4 and 5?
Are the results for Versions 2 and 6 realistic?
Here is my results (In Milliseconds):
Version 1 - Insertion Sort: Run-Times over 50 test runs
Input Size Best-Case Worst-Case Average-Case
N = 10000 14 19 14.96
N = 20000 59 60 59.3
N = 40000 234 277 243.1
Version 2 - Merge Sort: Run-Times over 50 test runs
Input Size Best-Case Worst-Case Average-Case
N = 10000 1 15 1.78
N = 20000 3 8 3.4
N = 40000 6 9 6.7
Version 3 - Merge Sort and Insertion Sort on 15 elements: Run-Times over 50 test runs
Input Size Best-Case Worst-Case Average-Case
N = 10000 41 52 45.42
N = 20000 170 176 170.56
N = 40000 712 823 728.08
Version 4 - Merge Sort and Insertion Sort on 30 elements: Run-Times over 50 test runs
Input Size Best-Case Worst-Case Average-Case
N = 10000 27 33 28.04
N = 20000 113 119 114.36
N = 40000 436 497 444.2
Version 5 - Merge Sort and Insertion Sort on 45 elements: Run-Times over 50 test runs
Input Size Best-Case Worst-Case Average-Case
N = 10000 20 21 20.68
N = 20000 79 82 79.7
N = 40000 321 383 325.64
Version 6 - Quick Sort: Run-Times over 50 test runs
Input Size Best-Case Worst-Case Average-Case
N = 10000 1 9 1.18
N = 20000 2 3 2.06
N = 40000 4 5 4.26
Here is my code:
package com.testing;
import com.sorting.InsertionSort;
import com.sorting.MergeSort;
import com.sorting.ModifiedMergeSort;
import com.sorting.RandomizedQuickSort;
/**
*
* #author mih1406
*/
public class Main {
private static final int R = 50; // # of tests
private static int N = 0; // Input size
private static int[] array; // Tests array
private static int[] temp; // Tests array
private static long InsertionSort_best = -1;
private static long InsertionSort_worst = -1;
private static double InsertionSort_average = -1.0;
private static long MergeSort_best = -1;
private static long MergeSort_worst = -1;
private static double MergeSort_average = -1.0;
private static long ModifiedMergeSort_V3_best = -1;
private static long ModifiedMergeSort_V3_worst = -1;
private static double ModifiedMergeSort_V3_average = -1.0;
private static long ModifiedMergeSort_V4_best = -1;
private static long ModifiedMergeSort_V4_worst = -1;
private static double ModifiedMergeSort_V4_average = -1.0;
private static long ModifiedMergeSort_V5_best = -1;
private static long ModifiedMergeSort_V5_worst = -1;
private static double ModifiedMergeSort_V5_average = -1.0;
private static long RandomizedQuickSort_best = -1;
private static long RandomizedQuickSort_worst = -1;
private static double RandomizedQuickSort_average = -1.0;
public static void main(String args[]) {
StringBuilder InsertionSort_text = new StringBuilder(
"Version 1 - Insertion Sort: Run-Times over 50 test runs\n");
StringBuilder MergeSort_text = new StringBuilder(
"Version 2 - Merge Sort: Run-Times over 50 test runs\n");
StringBuilder ModifiedMergeSort_V3_text = new StringBuilder(
"Version 3 - Merge Sort and Insertion Sort on 15 elements: Run-Times over 50 test runs\n");
StringBuilder ModifiedMergeSort_V4_text = new StringBuilder(
"Version 4 - Merge Sort and Insertion Sort on 30 elements: Run-Times over 50 test runs\n");
StringBuilder ModifiedMergeSort_V5_text = new StringBuilder(
"Version 5 - Merge Sort and Insertion Sort on 45 elements: Run-Times over 50 test runs\n");
StringBuilder RandomizedQuickSort_text = new StringBuilder(
"Version 6 - Quick Sort: Run-Times over 50 test runs\n");
InsertionSort_text.append("Input Size\t\t"
+ "Best-Case\t\tWorst-Case\t\tAverage-Case\n");
MergeSort_text.append("Input Size\t\t"
+ "Best-Case\t\tWorst-Case\t\tAverage-Case\n");
ModifiedMergeSort_V3_text.append("Input Size\t\t"
+ "Best-Case\t\tWorst-Case\t\tAverage-Case\n");
ModifiedMergeSort_V4_text.append("Input Size\t\t"
+ "Best-Case\t\tWorst-Case\t\tAverage-Case\n");
ModifiedMergeSort_V5_text.append("Input Size\t\t"
+ "Best-Case\t\tWorst-Case\t\tAverage-Case\n");
RandomizedQuickSort_text.append("Input Size\t\t"
+ "Best-Case\t\tWorst-Case\t\tAverage-Case\n");
// Case N = 10000
N = 10000;
fillArray();
testing_InsertionSort();
testing_MergeSort();
testing_ModifiedMergeSort(15);
testing_ModifiedMergeSort(30);
testing_ModifiedMergeSort(45);
testing_RandomizedQuickSort();
InsertionSort_text.append("N = " + N + "\t\t" + InsertionSort_best
+ "\t\t\t" + InsertionSort_worst + "\t\t\t"
+ InsertionSort_average + "\n");
MergeSort_text.append("N = " + N + "\t\t" + MergeSort_best
+ "\t\t\t" + MergeSort_worst + "\t\t\t"
+ MergeSort_average + "\n");
ModifiedMergeSort_V3_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V3_best
+ "\t\t\t" + ModifiedMergeSort_V3_worst + "\t\t\t"
+ ModifiedMergeSort_V3_average + "\n");
ModifiedMergeSort_V4_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V4_best
+ "\t\t\t" + ModifiedMergeSort_V4_worst + "\t\t\t"
+ ModifiedMergeSort_V4_average + "\n");
ModifiedMergeSort_V5_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V5_best
+ "\t\t\t" + ModifiedMergeSort_V5_worst + "\t\t\t"
+ ModifiedMergeSort_V5_average + "\n");
RandomizedQuickSort_text.append("N = " + N + "\t\t" + RandomizedQuickSort_best
+ "\t\t\t" + RandomizedQuickSort_worst + "\t\t\t"
+ RandomizedQuickSort_average + "\n");
// Case N = 20000
N = 20000;
fillArray();
testing_InsertionSort();
testing_MergeSort();
testing_ModifiedMergeSort(15);
testing_ModifiedMergeSort(30);
testing_ModifiedMergeSort(45);
testing_RandomizedQuickSort();
InsertionSort_text.append("N = " + N + "\t\t" + InsertionSort_best
+ "\t\t\t" + InsertionSort_worst + "\t\t\t"
+ InsertionSort_average + "\n");
MergeSort_text.append("N = " + N + "\t\t" + MergeSort_best
+ "\t\t\t" + MergeSort_worst + "\t\t\t"
+ MergeSort_average + "\n");
ModifiedMergeSort_V3_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V3_best
+ "\t\t\t" + ModifiedMergeSort_V3_worst + "\t\t\t"
+ ModifiedMergeSort_V3_average + "\n");
ModifiedMergeSort_V4_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V4_best
+ "\t\t\t" + ModifiedMergeSort_V4_worst + "\t\t\t"
+ ModifiedMergeSort_V4_average + "\n");
ModifiedMergeSort_V5_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V5_best
+ "\t\t\t" + ModifiedMergeSort_V5_worst + "\t\t\t"
+ ModifiedMergeSort_V5_average + "\n");
RandomizedQuickSort_text.append("N = " + N + "\t\t" + RandomizedQuickSort_best
+ "\t\t\t" + RandomizedQuickSort_worst + "\t\t\t"
+ RandomizedQuickSort_average + "\n");
// Case N = 40000
N = 40000;
fillArray();
testing_InsertionSort();
testing_MergeSort();
testing_ModifiedMergeSort(15);
testing_ModifiedMergeSort(30);
testing_ModifiedMergeSort(45);
testing_RandomizedQuickSort();
InsertionSort_text.append("N = " + N + "\t\t" + InsertionSort_best
+ "\t\t\t" + InsertionSort_worst + "\t\t\t"
+ InsertionSort_average + "\n");
MergeSort_text.append("N = " + N + "\t\t" + MergeSort_best
+ "\t\t\t" + MergeSort_worst + "\t\t\t"
+ MergeSort_average + "\n");
ModifiedMergeSort_V3_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V3_best
+ "\t\t\t" + ModifiedMergeSort_V3_worst + "\t\t\t"
+ ModifiedMergeSort_V3_average + "\n");
ModifiedMergeSort_V4_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V4_best
+ "\t\t\t" + ModifiedMergeSort_V4_worst + "\t\t\t"
+ ModifiedMergeSort_V4_average + "\n");
ModifiedMergeSort_V5_text.append("N = " + N + "\t\t" + ModifiedMergeSort_V5_best
+ "\t\t\t" + ModifiedMergeSort_V5_worst + "\t\t\t"
+ ModifiedMergeSort_V5_average + "\n");
RandomizedQuickSort_text.append("N = " + N + "\t\t" + RandomizedQuickSort_best
+ "\t\t\t" + RandomizedQuickSort_worst + "\t\t\t"
+ RandomizedQuickSort_average + "\n");
System.out.println(InsertionSort_text);
System.out.println(MergeSort_text);
System.out.println(ModifiedMergeSort_V3_text);
System.out.println(ModifiedMergeSort_V4_text);
System.out.println(ModifiedMergeSort_V5_text);
System.out.println(RandomizedQuickSort_text);
}
private static void fillArray() {
// (re)creating the array
array = new int[N];
// filling the array with random numbers
// using for-loop and the given random generator instruction
for(int i = 0; i < array.length; i++) {
array[i] = (int)(1 + Math.random() * (N-0+1));
}
}
private static void testing_InsertionSort() {
// run-times arrays
long [] run_times = new long[R];
// start/finish times
long start;
long finish;
for(int i = 0; i < R; i++) {
copyArray();
// recording start time
start = System.currentTimeMillis();
// testing the algorithm
InsertionSort.sort(temp);
// recording finish time
finish = System.currentTimeMillis();
run_times[i] = finish-start;
}
InsertionSort_best = findMin(run_times);
InsertionSort_worst = findMax(run_times);
InsertionSort_average = findAverage(run_times);
}
private static void testing_MergeSort() {
// run-times arrays
long [] run_times = new long[R];
// start/finish times
long start;
long finish;
for(int i = 0; i < R; i++) {
copyArray();
// recording start time
start = System.currentTimeMillis();
// testing the algorithm
MergeSort.sort(temp);
// recording finish time
finish = System.currentTimeMillis();
run_times[i] = finish-start;
}
MergeSort_best = findMin(run_times);
MergeSort_worst = findMax(run_times);
MergeSort_average = findAverage(run_times);
}
private static void testing_ModifiedMergeSort(int bound) {
// run-times arrays
long [] run_times = new long[R];
// setting the bound
ModifiedMergeSort.bound = bound;
// start/finish times
long start;
long finish;
for(int i = 0; i < R; i++) {
copyArray();
// recording start time
start = System.currentTimeMillis();
// testing the algorithm
ModifiedMergeSort.sort(temp);
// recording finish time
finish = System.currentTimeMillis();
run_times[i] = finish-start;
}
if(bound == 15) {
ModifiedMergeSort_V3_best = findMin(run_times);
ModifiedMergeSort_V3_worst = findMax(run_times);
ModifiedMergeSort_V3_average = findAverage(run_times);
}
if(bound == 30) {
ModifiedMergeSort_V4_best = findMin(run_times);
ModifiedMergeSort_V4_worst = findMax(run_times);
ModifiedMergeSort_V4_average = findAverage(run_times);
}
if(bound == 45) {
ModifiedMergeSort_V5_best = findMin(run_times);
ModifiedMergeSort_V5_worst = findMax(run_times);
ModifiedMergeSort_V5_average = findAverage(run_times);
}
}
private static void testing_RandomizedQuickSort() {
// run-times arrays
long [] run_times = new long[R];
// start/finish times
long start;
long finish;
for(int i = 0; i < R; i++) {
copyArray();
// recording start time
start = System.currentTimeMillis();
// testing the algorithm
RandomizedQuickSort.sort(temp);
// recording finish time
finish = System.currentTimeMillis();
run_times[i] = finish-start;
}
RandomizedQuickSort_best = findMin(run_times);
RandomizedQuickSort_worst = findMax(run_times);
RandomizedQuickSort_average = findAverage(run_times);
}
private static long findMax(long[] times) {
long max = times[0];
for(int i = 1; i < times.length; i++) {
if(max < times[i]) {
max = times[i];
}
}
return max;
}
private static long findMin(long[] times) {
long min = times[0];
for(int i = 1; i < times.length; i++) {
if(min > times[i]) {
min = times[i];
}
}
return min;
}
private static double findAverage(long[] times) {
long sum = 0;
double avg;
for(int i = 0; i < times.length; i++) {
sum += times[i];
}
avg = (double)sum/(double)times.length;
return avg;
}
private static void copyArray() {
temp = new int[N];
System.arraycopy(array, 0, temp, 0, array.length);
}
}
There seem to be some systematic errors on the approach you're currently undertaking. I'll state some of the most obvious experimental issues you're facing, even if they might not directly be the culprits of your experimental results.
JVM Compilation
As I've stated previously in a comment, the JVM will by default run your code in interpreted mode. That means each bytecode instruction found in your methods will be interpreted on-the-spot, and then ran.
The advantage of this approach is that it allows your application to have faster startup times than would a Java program that'd be compiled to native code on the startup of each of your runs.
The downside is that while there's no startup performance hit, you'll get a slower performing program than you'd get otherwise.
To ameliorate both concerns, a tradeoff was taken by the JVM team. Initially your program will be interpreted, but the JVM will gather information about which methods (or parts of methods) are being used intensively, and will compile down only those ones that seem to be used a lot. When compiling, you'll get a small performance hit, but then the code will be way faster than was before.
You'll have to take this fact into consideration when doing measurements.
The standard approach is to "warm up the JVM", that is, to run your algorithms for a bit to make sure the JVM does all the compilations it needs to do. It is important to have the code that warms the JVM be the same as the one you'll want to benchmark, otherwise there may be some compilation while you're benchmarking your code.
Measuring time
When measuring time, you should use System.nanoTime() instead of System.currentTimeMillis. I won't go over the details, those can be accessed here.
You should also be careful. The following blocks of code may seem equivalent at first, but will yield different results most of the times:
totalDuration = 0;
for (i = 0; i < 1000; ++i)
startMeasure = now();
algorithm();
endMeasure = now();
duration = endMeasure - startMeasure;
totalDuration += duration;
}
//...
TRIALS_COUNT = 1000;
startMeasure = now();
for (i = 0; i < TRIALS_COUNT; ++i)
algorithm();
}
endMeasure = now();
duration = endMeasure - startMeasure / TRIALS_COUNT;
Why? Because especially for faster algorithm() implementations, the faster they are, the harder it is to get accurate results.
Large input values
The asymptotic notation is useful to understand how different algorithms will escalate for big values of n. Applying them for small input values is often nonsensical, because at that magnitude generally what you'd want is to count the precise number of operations and their associated costs (something akin to what Jakub did). Big O notation only makes sense for big Os most of the time. Big O will tell you how the algorithm works for excruciating input value sizes, not how it will behave for small numbers. The canonical example is for instance QuickSort, which for big arrays will be king, but that will be generally slower for arrays of size 4 or 5 than Selection or Insertion Sort. Your input sizes seem to be big enough, though.
On a final note
and as previously stated by Chang, the mathematical exercise done by Jakub is completely wrong and should not be taken into consideration.
Do the computations of the complexity by yourself. I assume 10000 samples for the following calculations:
Insertion sort: O(n^2), 10 000*10 000 = 100 000 000.
Merge sort: O(nlogn), 10 000*log10 000 = 140 000.
Merge with insertion (15): 15 is between 9 (arrays of sizes 20) and 10 (arrays of sizes 10)
2^10 insertion sorts (of size 10), then 2^10 * 10 000 merges: 1 024 * 10*10 (insertions) + 1 024 * 10 000 (merges) = 10 342 400
Merge with insertion (30): 30 is between 8 (arrays of sizes 40) and 9 (arrays of sizes 20)
2^9 insertion sorts (of size 20), then 2^9 * 10 000 merges: 512 * 20*20 (insertions) + 512 * 10 000 (merges) = 5 324 800
Merge with insertion (45): 45 is between 7 (arrays of sizes 80) and 8 (arrays of sizes 40)
2^8 insertion sorts (of size 40), then 2^8 * 10 000 merges: 256 * 40*40 (insertions) + * 10 000 (merges) = 2 969 600
Quicksort: while worst-case quicksort takes O(n^2), the worst case must be specially crafted to hit that limit. Mostly, using radomly generated algorithm, on average it is O(nlogn): 10 000*log10 000 = 140 000.
Measuring sorting algorithm performace can became quite a pain because you need to measure efficiently, on as wide range of input data as possible.
The figures you see on insertion sort can be largerly biased by the input numbers. If you are using only 0s and 1s in the array, and the array is randomly generated, then you actually have much easier problem for the algorithm to solve. For the given case, on average half of the array is already sorted, and you don't need to compare 0s and 1s with each other. The problem is reduced to transporting all 0s to the left, which on average takes only (log(n/2))!+n time. For 10 000, the actual time is 5 000!+10 000 = 133 888.