Find number x equal to sum of 1 number from n sets - java

I'm having the following problem:
I have n sorted collections of integers (2<n<10).
I have a number x.
I wanna know if there is a sum (there can be multiple), in which each set needs to contribute exactly 1 number, which is equal to x
Example 1:
Collection 1: {1, 2, 3, 5, 7, 8}
Collection 2: {2, 4, 4, 5, 6, 8, 9, 11 23}
x: 9
For this example, a possible sum is 5+4. Another possibility is 1+8.
Example2:
Collection 1: {1, 1, 5, 7, 8, 9}
Collection 2: {2, 4, 5, 6, 8, 9}
x: 8
In this example, there is no possible sum. The number 8 is in both collections but since all collections need to contribute in the summation, this doesn't matter.
I don't wanna brute force this so i'm thinking recursion could make this process a bit faster but i don't really know where to begin.
I'm looking for some kind of train of thought although pseudo code or working code (java) would be appreciated :)

Try this.
static boolean existSum(List<Collection<Integer>> collections, int x) {
int size = collections.size();
return new Object() {
boolean find(int index, int sum) {
if (index >= size)
return sum == x;
for (int i : collections.get(index)) {
int newSum = sum + i;
if (newSum > x)
break;
if (find(index + 1, newSum))
return true;
}
return false;
}
}.find(0, 0);
}
public static void main(String[] args) throws Exception {
System.out.println(existSum(List.of(
List.of(1, 2, 3, 5, 7, 8),
List.of(2, 4, 4, 5, 6, 8, 9, 11, 23)), 9));
System.out.println(existSum(List.of(
List.of(1, 1, 5, 7, 8, 9),
List.of(2, 4, 5, 6, 8, 9)), 8));
}
output:
true
false

Related

Quicksort went wrong (added some duplicates)

I'm new to sorting algorithms and can't seem to figure out what went wrong. With an unsorted array of int [] uArr = {5,2, 10, 7, 6, 0, 8, 1, 9}, i'm given 0,1,2,5,5,6,8,10 (the nine in the org. array was replaced with a duplicate 5 and the 7 was lost). If I add duplicates to the array, I get more duplicates after the array is sorted and a few more missing numbers.
public static void main(String args[]){
int [] uArr = {5,2, 10, 7, 6, 0, 8, 1, 9};
qSort(uArr, 0, 8);
}
public static void qSort(int [] A, int low, int high){
if (low < high){
int pivotL = partition(A, low, high);
qSort(A, low, pivotL);
qSort(A, pivotL+1, high);
}
}
public static int partition(int [] arr, int low, int high){
int pivot = arr[low];
int leftwall = low;
for (int i = low + 1; i < high; i++){
if (arr[i] < pivot){
int temp = arr[i];
arr[i] = arr[leftwall];
arr[leftwall] = temp;
leftwall += 1;
}
}
int temp2 = pivot;
pivot = arr[leftwall];
arr[leftwall] = temp2;
return leftwall;
}
}
So one thing you should seriously do is start writing documentation. Even though this is a small program, you seem to have forgotten what you were doing as you were writing the code.
For example, there are 9 elements in the array, and you pass in the offsets to sort, inclusive, as 0 through 8:
qSort( uArr, 0, 8 );
But then in the partition routine you only sort elements less than the high value:
for( int i = low + 1; i < high; i++ ) {
And unlike you the last value in the array, 9, is never touched for me and never sorted. So that's an issue. Figure out if you want your indexes to be inclusive or not. For me writing documentation as I go helps me keep these ideas straight.
I'm still looking for other problems like the duplication.
Update: I'm going to just post these as I figure them out, as a sort of stream-of-consciousness of how I look for problems. One thing I was taught early on is that adding print statements to your code can be faster than using a debugger. So (after re-formatting your code, because the formatting you posted was frankly crap) I added this:
public static void qSort( int[] A, int low, int high ) {
System.out.println( Arrays.toString( A ) + " low=" + low + " high=" + high );
And got this output:
run:
[5, 2, 10, 7, 6, 0, 8, 1, 9] low=0 high=8
[2, 0, 1, 5, 6, 5, 8, 10, 9] low=0 high=3
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=0 high=2
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=0 high=0
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=1 high=2
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=1 high=1
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=2 high=2
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=3 high=3
[0, 1, 2, 5, 6, 5, 8, 10, 9] low=4 high=8
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=4 high=5
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=4 high=4
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=5 high=5
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=6 high=8
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=6 high=6
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=7 high=8
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=7 high=7
[0, 1, 2, 5, 5, 6, 8, 10, 9] low=8 high=8
[0, 1, 2, 5, 5, 6, 8, 10, 9]
BUILD SUCCESSFUL (total time: 0 seconds)
I did have to stare at the output for a while, but what I noticed next was two things. The 5 is duplicated almost immediately, and the 5 is also the first element, which means it's going to be chosen by your partition code as the pivot. So it looks as though you have problems re-merging the pivot with the array.
Update 2: OK found another problem. This one I found by writing your array out by hand and walking through each value of i and leftwall as it makes the first partition. Problem here:
When the pivot, 5, encounters the element 0 in the array, the rest of the array has not been sorted. The 10, 7, 6, etc. are not less than the pivot and have not be touched. So when you make the swap, you sawp this:
[2, 5, 10, 7, 6, 0, 8, 1, 9]
for this:
[2, 5, 0, 7, 6, 5, 8, 1, 9]
This is because leftwall was 1 (it had been swapped with the 2 but not any other number, so it only had been incremented once) and there's the duplication and losing numbers too. I'm going to stop there because you have some pretty big problems.
What you need to do in this case is swap the 10, not the pivot, with the 0. This is going to require one additional pointer at least. Quicksort algorithms need to find the lowest and highest in the array and have two loops inside the outer for loop. What you have here is a kind of weird recursive insert sort. You'll need to think a bit more how to do this, but two more loops, nest inside the first, will be required.

What do square brackets before a number mean in Java? e.g. []89 or [1, 2, 3]89

I'm new to Java and haven't been able to find any explanations on what the syntax such as [1, 2, 3, 4]5 means.
import java.util.*;
class SumDigPower {
static List<Long> list = new ArrayList<Long>();
public static List<Long> sumDigPow(long a, long b) {
for(long i = a; i<=b; i++) {
if(isEureka(i)) {
list.add(i);
}
}
return list;
}
public static boolean isEureka(long num) {
//convert number to string to get length and then sum each digit to the nth power
//return true or false depending on whether the number qualifies for the list
String numString = Long.toString(num);
long sum = 0;
for(int i = 0; i < numString.length(); i++) {
sum += Math.pow(Character.getNumericValue(numString.charAt(i)), i+1);
}
if(sum == num) {return true;}
else {return false;}
}
}
expected:<..., 4, 5, 6, 7, 8, 9, []89]> but was:<..., 4, 5, 6, 7, 8, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9, ]89]>
JUnit uses that syntax to show why a test failed, and specifically when an expected String didn't match the actual value:
String expected = "[1, 2, 3, 4, 5, 6, 7, 8, 9, 89]";
List<Long> actualLongs = Arrays.asList(
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L,
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 89L);
String actualString = actualLongs.toString();
assertEquals(expected, actualString);
JUnit figures out the what's similar and different between the expected and actual, and uses the square brackets to highlight that. If you align the "expected" and "but was" bits, you get:
expected:<..., 4, 5, 6, 7, 8, 9, []89]>
but was:<..., 4, 5, 6, 7, 8, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9, ]89]>
... so it's telling you that in that [] space, it expected nothing extra, but found the characters 1, 2, 3, 4, 5, 6, 7, 8, 9,.
The difference becomes a bit more obvious if it's not just extra characters. For instance, let's say you didn't have the extra values, but the last 89 were instead a 66. Then it would look like:
expected:<..., 4, 5, 6, 7, 8, 9, [89]]>
but was:<..., 4, 5, 6, 7, 8, 9, [66]]>
"Where I expected an 89, I found a 66."
I'm not as familiar with TestNG, but it wouldn't surprise me if it does a similar thing.
If you run the test in IDEA IntelliJ, it will even pick up on that syntax and show you a nice diff view of the expected-but-was. Again, I'm not familiar with other IDEs (like Eclipse), but it wouldn't surprise me if they do that as well.

How can I remove excess values from an ArrayList but keep one of the original value? [duplicate]

This question already has answers here:
How do I remove repeated elements from ArrayList?
(40 answers)
Closed 6 years ago.
For example:
ArrayList<Integer> a = new ArrayList<Integer>();
while(a.size() < 50){
a.add(1);
a.add(2);
a.add(9);
}
System.out.println(a);
I would like to remove all the excess 1's, 2's, and 9's, but keep one of each.
Not cleared:
[1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9, 1, 2, 9]
Cleared:
[1, 2, 9]
Ideally I would like this to work for any x value that occurs any n number of times in the ArrayList.
My partial solution just returns whether or not a value occurs more than once (true if it occurs more than once, false if it doesn't)
public static boolean occ(ArrayList<Integer> l, int s) {
int n = 0;
boolean t = false;
for (int p : l) {
if (p == s) {
n++;
}
}
if (n > 1) {
t = true;
}
return t;
}
Method implementation:
occ(ArrayList, Selected Int Value to be Checked);
If I change to a HashSet or Set, would I be able to implement the ArrayList methods clear() and size()?
public static List<Integer> withoutDuplicates(List<Integer> withDuplicates) {
List<Integer> retVal = new ArrayList<>();
Set<Integer> alreadyParsed = new HashSet<>();
for (Integer val : withDuplicates) {
if (!alreadyParsed.contains(val)) {
retVal.add(val);
alreadyParsed.add(val);
}
}
return retVal;
}
or the Java 8 version
withDuplicates.stream().distinct().collect(Collectors.toList());
Set<Integer> set = new HashSet<Integer>(listWithDup);
From doc:
Set - a collection that contains no duplicate elements

Why does my insertion sort algorithm only work with single digit integers?

I've wrote a simple insertion sort algorithm for fun. It appears to be working just fine with one problem, it only works when all items in the array (the thing its trying to sort) are single digit integers. If an element is a multi-digit integer, it sorts everything up to that integer, then stops and throws an IndexOutOfBoundsException.
Note: Just so you understand the source code, the way my program works is like this: I pass the InsertionSort class a primative int array in construction. I then convert that to the ArrayList list. I know that the ArrayList list has the correct values copied over because I print it out and it matches up.
Example Runs:
Working:
{ 9, 2, 8, 5, 1, 6, 6, 7, 1}; //works perfectly ->
Unsorted List: [9, 2, 8, 5, 1, 6, 6, 7, 1]
Step 1: [9]
Step 2: [2, 9]
Step 3: [2, 8, 9]
Step 4: [2, 5, 8, 9]
Step 5: [1, 2, 5, 8, 9]
Step 6: [1, 2, 5, 6, 8, 9]
Step 7: [1, 2, 5, 6, 6, 8, 9]
Step 8: [1, 2, 5, 6, 6, 7, 8, 9]
Step 9: [1, 1, 2, 5, 6, 6, 7, 8, 9]
Sorted List: [1, 1, 2, 5, 6, 6, 7, 8, 9]
Not Working:
{ 9, 2, 8, 5, 1, 6, 6, 7, 1, 22, 823, 30, 244, 45, 5}; //doesn't work ->
Unsorted List: [9, 2, 8, 5, 1, 6, 6, 7, 1, 22, 823, 30, 244, 45, 5]
Step 1: [9]
Step 2: [2, 9]
Step 3: [2, 8, 9]
Step 4: [2, 5, 8, 9]
Step 5: [1, 2, 5, 8, 9]
Step 6: [1, 2, 5, 6, 8, 9]
Step 7: [1, 2, 5, 6, 6, 8, 9]
Step 8: [1, 2, 5, 6, 6, 7, 8, 9]
Step 9: [1, 1, 2, 5, 6, 6, 7, 8, 9]
java.lang.IndexOutOfBoundsException: Index: 9, Size: 9
Sorted List: [1, 1, 2, 5, 6, 6, 7, 8, 9]
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at InsertionSort.sort(InsertionSort.java:41)
at Executer.main(Executer.java:7)
Here is the relevant sorting code:
static ArrayList<Integer> list = new<Integer> ArrayList();
static ArrayList<Integer> list2 = new<Integer> ArrayList();
public static int[] sort() {
int s = 0;
System.out.println("Unsorted List: " + list.toString());
try {
for (int i = 0; i < list.size(); i++) {
s++;
if (i == 0) {
list2.add(list.get(i));
System.out.println("Step " + s + ": " + list2.toString());
continue;
} else {
int z = 0;
while (list2.get(z) < list.get(i)) {
z++;
}
list2.add(z, list.get(i));
}
System.out.println("Step " + s + ": " + list2.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Sorted List: " + list2.toString());
return toPrimative(list.toArray(new Integer[list.size()]));
}
It has nothing to do with single or multi digit numbers, in first example you were just lucky to have the biggest number as a first element in a list. There is an obvious mistake when you're choosing a position for the next element:
int z = 0;
while (list2.get(z) < list.get(i)) {
z++;
}
You increment index but don't do bounds check, so when it comes to number 22 you get an exception. The correct one would be
while (list2.get(z) < list.get(i) && z <= list2.size())
Mind debug. Problem is here:
while (list2.get(z) < list.get(i)) {
z++;
}
z exceeds list2 count if new value is the biggest.
First value 9 in small numbers example hid this problem.
I hope that solution is clear enough

How to Find Missing Number on Integer Array of 1 to 100?

Here is what i did. What can i do further? Can anybody suggest? I am looking for bitset solution.
public static void main(String args[]) {
// one missing number
printMissingNumber(new int[]{1, 2, 3, 4, 6}, 6);
// two missing number
printMissingNumber(new int[]{1, 2, 3, 4, 6, 7, 9, 8, 10}, 10);
// three missing number
printMissingNumber(new int[]{1, 2, 3, 4, 6, 9, 8}, 10);
// four missing number
printMissingNumber(new int[]{1, 2, 3, 4, 9, 8}, 10);
// Only one missing number in array
int[] iArray = new int[]{1, 2, 3, 5};
int missing = getMissingNumber(iArray, 5);
System.out.printf("Missing number in array %s is %d %n",
Arrays.toString(iArray), missing);
}
For n sequential numbers, the sum s = n(n+1)/2.
Sum up the numbers in the array and subtract it from s to find the missing number.
If n is the largest number, and there is only one missing, then the missing number is
n * (n + 1) / 2 - sum{elements in your array}
The first term is the sum of n consecutive integers from 1 to, and including, n.

Categories