I am trying to solve Project Euler problem 18. I have created an array for each row (starting from the bottom), and then an array of those arrays. I created a recursive method that starts from the bottom row, and looks ahead three rows to find the best path.
I created minimum and maximum methods to make sure that the index of my arrays could not go below zero, or above the length minus one.
/**
* A method that sets a minimum limit for an integer
* #param a The number
* #param b The lowest value it can go
* #return a
*/
public static int min(int a, int b) {
if (a<b) {
a=b;
}
return a;
}
/**
* Sets the maximum limit for an int
* #param a the number
* #param b The highest a number can go
* #return a
*/
public static int max(int a, int b) {
if(a>b) {
a=b;
}
return a;
}
Then I used these methods when calculating all possible paths in the next three rows.
I got the Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 11 error on this line of code:
eighthPoss = array[x+2][max(i, array[x].length-1)] + array[x+1][max(i, array[x].length-1)] + array[x][max(i, array[x].length-1)];
Where x is the current row, and i is the current position on the row.
I have if statements for when x+2 and x+1 are more than the amount of rows (When we are on the second to last, or last row of the triangle). I am genuinely confused how anything on this line of code is out of bounds as I have minimum and maximum values on each of them to make sure they don't go out of the range. I ran print statements and the last numbers the loops ran through before the error were x=1, i=10.
Below are my arrays. (I did not include the top row, since it is only one number.)
int[] row1 = {04, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 04, 23};
int[] row2 = {63, 66, 04, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31};
int[] row3 = {91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48};
int[] row4 = {70, 11, 33 ,28, 77, 73, 17, 78, 39, 68, 17, 57};
int[] row5 = {53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14};
int[] row6 = {41, 48, 72, 33, 47, 32, 37, 16, 94, 29};
int[] row7 = {41, 41, 26, 56, 83, 40, 80, 70, 33};
int[] row8 = {99, 65, 4, 28, 6, 16, 70, 92};
int[] row9 = {88, 2, 77, 73, 7, 63, 67};
int[] row10 = {19, 1, 23, 75, 3, 34};
int[] row11 = {20, 4, 82, 47, 65};
int[] row12 = {18, 35, 87, 10};
int[] row13 = {17, 47, 82};
int[] row14 = {95, 64};
int[][] rows = {row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12,
row13, row14};
Any help you could give me would be greatly appreciated.
Make sure that your x+2 isn't going out of bounds as it seems you're only checking to see if i is going out of bounds. (You may be checking for it somewhere else but you didn't provide that code).
Bonus clamp method that I personally use instead of individual max and min methods (since they're built into Java).
public static int clamp(int a, int min, int max) {
return Math.max(min, Math.min(max, a));
}
Related
As the title says, I am looking for a sorting algorithm that can sort the numbers between 1 and 100 using the least amount of statements in only one method which is the main.
Here's an example to give you an idea on how I can check it(using a counter)
class Solution{
public static void main(String[] args) {
//declaration
int count = 0,inner, outer, temp, h = 1; count++;
int [] array = {100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,}; count++;
System.out.println("Before: " + Arrays.toString(array)); count++;
//start of the sort
while (h <= array.length / 3) //start of while loop 1
{
h = h * 3 + 1; count++;
}count++; //end of while loop 1
while (h > 0) //start of while loop 2
{
for (outer = h; outer < array.length; outer++) //start of for loop
{
temp = array[outer]; count++;
inner = outer;count++;
while (inner > h - 1 && array[inner - h] >= temp) //start of while loop 3
{
array[inner] = array[inner - h]; count++;
inner -= h; count++;
}count++; //end of for loop 3
array[inner] = temp; count++;
}count++; //end of for loop
//equation to count for
count = count + array.length-h+1 + array.length - h +1 -1;
h = (h - 1) / 3; count++;
}count++; //end of while loop 2
System.out.println("After: " + Arrays.toString(array) + "\n" + "Counter = " + count);
}
}
The fastest algorithm with example would be quicksort, also as you are asking i believe this would also take the least amount of statments. Below you can find a link and also description of how it works.
https://www.geeksforgeeks.org/quick-sort/
The following is my implementation of Selection Sort:
package algorithm.selectionsort;
public class SelectionSort {
public static void main(String[] args) {
int[] myArray = selectionSort(new int[] { 9, 9, 9, 8, 7, 73, 32, 109, 1100, 432, 321, 0 });
for (int element : myArray) {
System.out.print("" + element + " ");
}
}
public static int[] selectionSort(int[] a) {
int min;
for (int i = 0; i < a.length - 1; i++) {
min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
return a;
}
}
I noticed that my instructor codes it slightly differently:
public static int[] selectionSort(int[] a) {
int min;
for (int i = 0; i < a.length - 1; i++) {
min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
}
}
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
return a;
}
Both implementations work. I'm curious as to what the difference here is. Is it efficiency?
The difference between your instructor's and yours is that he iterate through the array and for each element, search for the minimum, then perform a swap with the element after the wall index.
For yours, you iterate through the array and for each element, while searching for the minimum, if current value is < then the current tentative min, perform a swap with the element after the wall index.
So instead of swapping n times, you could possible swap n*n times for worst case:
Your swap for just one pass (worst case):
100, 90, 88, 70, 55, 43, 32, 28, 19, 10
90, 100, 88, 70, 55, 43, 32, 28, 19, 10
88, 100, 90, 70, 55, 43, 32, 28, 19, 10
70, 100, 90, 88, 55, 43, 32, 28, 19, 10
55, 100, 90, 88, 70, 43, 32, 28, 19, 10
43, 100, 90, 88, 70, 55, 32, 28, 19, 10
32, 100, 90, 88, 70, 55, 43, 28, 19, 10
28, 100, 90, 88, 70, 55, 43, 32, 19, 10
19, 100, 90, 88, 70, 55, 43, 32, 28, 10
10, 100, 90, 88, 70, 55, 43, 32, 28, 19
Your instructor's swap for just one pass (worst case):
100, 90, 88, 70, 55, 43, 32, 28, 19, 10
10, 90, 88, 70, 55, 43, 32, 28, 19, 100
In essence, you swap the values while in the midst of searching for the min. The "min" you swapped may not be the lowest value in the array.
ofcouse your instructor's code is more efficiency and more elegant.
What is Selection Sort?
The algorithm divides the input list into two parts: the sublist of items already sorted, which is built up from left to right at the front (left) of the list, and the sublist of items remaining to be sorted that occupy the rest of the list. Initially, the sorted sublist is empty and the unsorted sublist is the entire input list. The algorithm proceeds by finding the smallest (or largest, depending on sorting order) element in the unsorted sublist, exchanging (swapping) it with the leftmost unsorted element (putting it in sorted order), and moving the sublist boundaries one element to the right.
If the length of the list to be sorted is n, then just n times of exchange should be done, but in your code, it's n*(n-1)*(n-2)....
For a personal project I need to make a method, that compares two integer arrays and outputs how a percentage value of how alike they are. The arrays can be of different lengths from each other.
I.E. these could be examples of arrays I can get:
int[] array1 = {21, 154, 25, 180, 2, 159, 25, 25, 181, 25, 3, 181, 25, 180, 2, 160, 4, 179, 21, 2, 159, 17, 54, 21, 158, 25, 180, 21, 25, 180, 21, 4, 100, 46, 79, 25, 180, 21, 25, 180, 21, 4};
int[] array2 = {21, 154, 25, 180, 2, 159, 25, 25, 181, 25, 3, 181, 25, 180, 2, 160, 4, 179, 17, 54, 167, 25, 180, 21, 25, 180, 21, 4, 100, 46, 79, 25, 180, 21, 25, 180, 21, 4, 100, 50, 83, 25, 180, 21, 25, 180};
As you can see the first part is the same but the last part only has some comparison.
I assume that you have to count number of common elements, and then do something about it.
Your problem is strictly algorithmic one: the easiest solution is sort arrays (n*log(n)) then iterate through them in order get how many elements they have in common (it's possible to do it in one loop so you have n operations). It gives us O(n*log(n) + n) what is (n*log(n)).
But there is better approach - you can use associative arrays, your need then more memory (for this additional arrays), then check how many they have in common. It gives you n for putting in arrays and n for finding how many they have in common. So you have O(n+n) so it's O(n).
public class Compare {
public static Integer min(Integer a, Integer b) {
if (a != null && b != null) {
if (a.intValue() > b.intValue())
return b;
else
return a;
} else
// If any of them is null
return 0;
}
public static void how_many_common(int[] arr1, int[] arr2) {
System.out.println("First arr has " + arr1.length);
System.out.println("Second arr has " + arr2.length);
Map<Integer, Integer> arr1_map = new HashMap<>();
Map<Integer, Integer> arr2_map = new HashMap<>();
// Put first arr in Hash map
for (int i : arr1) {
Integer how_many = arr1_map.get(i);
if (how_many != null) {
arr1_map.put(i, how_many + 1);
} else {
arr1_map.put(i, 1);
}
}
// Put second arr in Hash map
for (int i : arr2) {
Integer how_many = arr2_map.get(i);
if (how_many != null) {
arr2_map.put(i, how_many + 1);
} else {
arr2_map.put(i, 1);
}
}
int sumOfCommon = 0;
for (int i : arr1_map.keySet()) {
sumOfCommon += min(arr1_map.get(i), arr2_map.get(i));
}
System.out.println("Arrays have " + sumOfCommon + " numbers in common");
//Rest of likeliness is for you
}
public static void main(String[] args) {
int[] array1 = {21, 154, 25, 180, 2, 159, 25, 25, 181, 25, 3, 181, 25, 180, 2, 160, 4, 179, 21, 2, 159, 17, 54, 21, 158, 25, 180, 21, 25, 180, 21, 4, 100, 46, 79, 25, 180, 21, 25, 180, 21, 4};
int[] array2 = {21, 154, 25, 180, 2, 159, 25, 25, 181, 25, 3, 181, 25, 180, 2, 160, 4, 179, 17, 54, 167, 25, 180, 21, 25, 180, 21, 4, 100, 46, 79, 25, 180, 21, 25, 180, 21, 4, 100, 50, 83, 25, 180, 21, 25, 180};
how_many_common(array1, array2);
int [] array3 = {1,2,3,4};
int [] array4 = {1,2,3,4};
how_many_common(array3, array4);
int [] array5 = {};
int [] array6 = {1,2,3,4};
how_many_common(array5, array6);
int [] array7 = {5};
int [] array8 = {1,2,3,4};
how_many_common(array7, array8);
}
}
It's completed working solution of second approach.
I'm supposed to take an array of the numbers: {51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96} and sort them from lowest to highest, and then highest to lowest.
When I try to print the highest to lowest it makes the first output the same. Does anyone see any errors in my code?
package l7c14sort;
import java.util.Arrays;
public class L7C14Sort {
public static void main(String a[]){
int[] arr1 = {51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96};
int[] arr2 = doInsertionSort(arr1);
int[] arr3 = doInsertionSortAgain(arr1);
System.out.println("Original input: "+Arrays.toString(arr1)+"\n");
System.out.println("Lowest to highest:\n");
for(int i:arr2)
{
System.out.print(i);
System.out.print(", ");
}
System.out.println("\n\n");
System.out.println("Highest to lowest:\n");
for(int k:arr3)
{
System.out.print(k);
System.out.print(", ");
}
System.out.println("\n");
}
public static int[] doInsertionSort(int[] input){
int temp;
for (int i = 1; i < input.length; i++) {
for(int j = i ; j > 0 ; j--){
if(input[j] < input[j-1]){
temp = input[j];
input[j] = input[j-1];
input[j-1] = temp;
}
}
}
return input;
}
public static int[] doInsertionSortAgain(int[] input2){
int temp2;
for (int k = 1; k < input2.length; k++) {
for(int j = k ; j > 0 ; j--){
if(input2[j] > input2[j-1]){
temp2 = input2[j];
input2[j] = input2[j-1];
input2[j-1] = temp2;
}
}
}
return input2;
}
}
Output:
Original input: [99, 98, 96, 92, 90, 89, 76, 75, 73, 64, 63, 63, 51,
48, 36, 36, 32, 32, 30, 4]
Highest to lowest:
99, 98, 96, 92, 90, 89, 76, 75, 73, 64, 63, 63, 51, 48, 36, 36, 32, 32, 30, 4,
Lowest to highest:
4,30,32,32,36,36,48,51,63,63,64,73,75,76,89,90,92,96,98,99
Good news: Your algorithm works fine.
In Java, arrays are passed by reference, not by value. What this means is that when you set int[] arr2 = doInsertionSort(arr1);, the array arr2 is being set to the result of your doInsertionSort method, which returns its input parameter after sorting it. Basically, arr1, arr2, arr3, input and input2 are all pointing to the very same array.
You have two easy options to fix the fact that you're printing:
Restructure main() so that you use one array: print its contents, sort it lowest to highest, print its contents again, sort it highest to lowest, then print its contents again. (This is probably what your instructor intends for you to do, if this is coursework.)
Make a copy of the input parameter to operate on. You can do this with System.arraycopy() like so:
int[] myArray;
System.arraycopy(input, 0, myArray, 0, input.length );
Then, for option 2, you would need to edit your method to use myArray instead of input for every other time you use input.
As a note, you don't need to call your variables input2, temp2, etc. Just like i, j and k go out of scope and are forgotten after the end of a for loop, your variables input and temp mean nothing outside of the block you declared them in.
Hope this helps!
You are ended up with same results, because arrays are mutable. Because of the following code, input array is mutated and its final value is printed.(Highest to lowest).
int[] arr2 = doInsertionSort(arr1);
int[] arr3 = doInsertionSortAgain(arr1);
If you organize your code like:
public static void main(String a[]) {
int[] arr1 = {51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96};
System.out.println("Original input: " + Arrays.toString(arr1) + "\n");
System.out.println("Lowest to highest:\n");
int[] arr2 = doInsertionSort(arr1);
for (int i : arr2) {
System.out.print(i);
System.out.print(", ");
}
System.out.println("\n\n");
System.out.println("Highest to lowest:\n");
int[] arr3 = doInsertionSortAgain(arr1);
for (int k : arr3) {
System.out.print(k);
System.out.print(", ");
}
System.out.println("\n");
}
You are going to get:
Original input: [51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96]
Lowest to highest:
4, 30, 32, 32, 36, 36, 48, 51, 63, 63, 64, 73, 75, 76, 89, 90, 92, 96, 98, 99,
Highest to lowest:
99, 98, 96, 92, 90, 89, 76, 75, 73, 64, 63, 63, 51, 48, 36, 36, 32, 32, 30, 4,
i got below mentioned error when run code:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.LinkedList.checkPositionIndex(Unknown Source)
at java.util.LinkedList.addAll(Unknown Source)
at Collection.Dynamycmaasiv.Collecktionaddlist.main(Collecktionaddlist.java:36)
code
public static void main(String[] args) {
LinkedList<Integer> num = new LinkedList<Integer>();
LinkedList<Integer> numodd = new LinkedList<Integer>();
LinkedList<Integer> numeven = new LinkedList<Integer>();
LinkedList<Integer> sumoffevenandodd = new LinkedList<Integer>();// help
// me
// to
// solve
for (double i = 0; i < 50; i++) {
num.add((int) i);
if (i % 2 == 0) {
numeven.add((int) i);
} else {
numodd.add((int) i);
}
}
System.out.println(num);
System.out.println("-----------------");
System.out.println(numodd);
System.out.println("-----------------");
System.out.println(numeven);
for (int i =0; i<numeven.size(); i++){
sumoffevenandodd.addAll(numeven.get(i)+ numodd.get(i), null);
}
System.out.println(sumoffevenandodd);
}
}
addAll() is not about adding up numbers. It is about adding all the elements of the method parameter to the collection itself.
So, you need to loop, like
int sum = 0;
for (Integer numberFromList : numeven) {
sum = sum + numberFromList;
Or, if you have Java8, you can use streams:
int sumEven = numeven.stream().sum();
Sum, done.
And for the record: the real lesson to be learned here: read the javadoc. Don't assume that method called addAll() does what you suppose it does. Turn to the javadoc and inform yourself what reality thinks about your assumptions.
But just to be clear; as I got carried away with your question, too.
In your code, if you change
sumoffevenandodd.addAll(numeven.get(i)+ numodd.get(i), null);
to
sumoffevenandodd.add(numeven.get(i)+ numodd.get(i));
it should work, too.
Long story short: if you intended to really have a list with 50 sums within, then my first paragraphs do not really help with your problem.
But it isn't exactly clear what you wanted to do; so I leave my answer as is - to address both possible explanations what is "wrong" in your logic.
if the intention of the question is
num odd
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
num even
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48]
sum of odd and even
[1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97]
then
for (int i =0; i< numeven.size(); i++){
sumoffevenandodd.add(numeven.get(i)+ numodd.get(i));
}