Need explanation for one test case failed in Codility Peaks problem - java

A non-empty array A consisting of N integers is given.
A peak is an array element which is larger than its neighbors. More precisely, it is an index P such that 0 < P < N − 1, A[P − 1] < A[P] and A[P] > A[P + 1].
For example, the following array A:
A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
has exactly three peaks: 3, 5, 10.
We want to divide this array into blocks containing the same number of elements. More precisely, we want to choose a number K that will yield the following blocks:
A[0], A1, ..., A[K − 1],
A[K], A[K + 1], ..., A[2K − 1],
...
A[N − K], A[N − K + 1], ..., A[N − 1].
What's more, every block should contain at least one peak. Notice that extreme elements of the blocks (for example A[K − 1] or A[K]) can also be peaks, but only if they have both neighbors (including one in an adjacent blocks).
The goal is to find the maximum number of blocks into which the array A can be divided.
Array A can be divided into blocks as follows:
one block (1, 2, 3, 4, 3, 4, 1, 2, 3, 4, 6, 2). This block contains three peaks.
two blocks (1, 2, 3, 4, 3, 4) and (1, 2, 3, 4, 6, 2). Every block has a peak.
three blocks (1, 2, 3, 4), (3, 4, 1, 2), (3, 4, 6, 2). Every block has a peak. Notice in particular that the first block (1, 2, 3, 4) has a peak at A[3], because A[2] < A[3] > A[4], even though A[4] is in the adjacent block.
However, array A cannot be divided into four blocks, (1, 2, 3), (4, 3, 4), (1, 2, 3) and (4, 6, 2), because the (1, 2, 3) blocks do not contain a peak. Notice in particular that the (4, 3, 4) block contains two peaks: A[3] and A[5].
The maximum number of blocks that array A can be divided into is three.
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty array A consisting of N integers, returns the maximum number of blocks into which A can be divided.
If A cannot be divided into some number of blocks, the function should return 0.
For example, given:
A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
the function should return 3, as explained above.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [0..1,000,000,000].
My Understanding of the problem :
Each sub array should contain at least one peak
An element which forms a peak can be in an Adjacent sub array.
Return max possible sub arrays
My Question
Consider Main Array : [0,1,0,1,0]
Possible sub arrays as per understanding : [0,1] [0,1,0]
Each subarray has a peak.
Subarray 1 [0,1] has peak element shared with adjacent array [0,1,0].
Subarray 2 [0,1,0] contains peak 0<1>0.
So max possible sub arrays are 2 but a test case in Codility returns max possible sub arrays as 1.
Below is my code
// you can also use imports, for example:
import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
int count=0,size=A.length;
if(size<2)
return 0;
System.out.println(Arrays.toString(A));
for(int i=1;i<size-1;i++){
if(A[i-1]<A[i] && A[i]>A[i+1]){
count++;
i++;
}
}
return count;
}
}
Test case which failed in Codility click here
I believe there is a gap in my understanding. Any help would be helpful :)

https://app.codility.com/demo/results/training5KP2PK-P4M/
https://github.com/niall-oc/things/blob/master/codility/peaks.py
Breaking an array into even parts is another way of factorizing the length of the array.
Array of length 12
[0,1,0,1,0,0,0,1,0,0,1,0,]
Factors of 12.
The square root of 12 is 3.464... so start with 3 and irterate down to 1 and divide each number into 12. This gives you a set of numbers {1, 2, 3, 4, 6, 12}.
Process
Because of how a peak is defined you cannot have 12 peaks in this array so remove 12 from the set. Starting d as the largest number divide the array int d parts. And check each part has a peak, if so then d is the maximum number of equal parts to all contain at least one peak. If not so then iterate to the next largest divisor and try that until you find a solution.

First of all you need to be congratulated to write a concise program to calculate the number of peaks. But the question is not to count the peaks.
It is to find the number of equal sized array and each having at least one peak. And a peak cannot be the first or last element as stated in the problem 0 < P < N − 1
Now quoting your question:
Consider Main Array : [0,1,0,1,0]
Possible sub arrays as per understanding : [0,1] [0,1,0] Each subarray has a peak. Subarray 1 [0,1] has peak element shared with adjacent array [0,1,0]. Subarray 2 [0,1,0] contains peak 0<1>0.
So max possible sub arrays are 2 but a test case in Codility returns max possible sub arrays as 1.
I see below issues:
your sub array sizes are not equal
array [0,1] does not have a peak
So, the array cannot be divided in equal parts each having a peak and hence only one array remains [0,1,0,1,0].

Related

What is happening in this array? [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 3 years ago.
I'm reviewing arrays and for loops among other things in my computer science course. One of the examples used was the code below. After being run, the array displays 2, 3, 4, 2. How is this?
int[] numbers = {1, 2, 3, 4};
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[(i+1) % numbers.length];
}
System.out.println(numbers);
An important concept in understanding the code you are looking it, especially the block inside the for loop, is the modulus operator (%) also known as the remainder operator. When applied, the % operator returns the remainder of two numbers.
Hence, the computation:
(i+1) % numbers.length
will always return a remainder.
Walking through it with a debugger (or print statements as suggested) while evaluating the values (and operations) at each iteration is a great way of understanding it.
You can also read more about it: https://www.baeldung.com/modulo-java
As you are doing the operation on the same array in place.
original array [1, 2, 3, 4]
when i - 0 => number [2,2,3,4] // moving index 1 item to index 0
when i - 2 => number [2,3,3,4] // moving index 2 item to index 1 from the
immediate previous array
when i - 2 => number [2,3,4,4] // moving index 3 item to index 2 from the
immediate previous array
when i - 3 => number [2,3,4,2] // moving index 0 item to index 3 from the
previous array
Keep in mind that % is modular arithmetic - it's the remainder when you divide the left-hand side by the right-hand side. For example, 2 % 4 = 2, 4 % 4 = 0, 6 % 4 = 2, and 8 % 4 = 0.
Here are the steps:
i = 0. (i + 1) % 4 = 1 % 4 = 1. Value at index 1 is 2. Array now contains {2, 2, 3, 4}.
i = 1. (i + 1) % 4 = 2 % 4 = 2. Value at index 2 is 3. Array now contains {2, 3, 3, 4}.
i = 2. (i + 1) % 4 = 3 % 4 = 3. Value at index 3 is 4. Array now contains {2, 3, 4, 4}.
i = 3. (i + 1) % 4 = 4 % 4 = 0. Value at index 0 is 2. Array now contains {2, 3, 4, 2}.
I'd encourage you to step through this with a debugger and/or use print statements to convince yourself that this is true and to understand why this is the case (doing so will help with understanding; if you're not convinced by a statement, either it's not true or there's something you don't understand or know about yet).
Your loop reassignes each index in your array with the value currently stored in the next index by doing (i+1).
Therefor on index [0] you get the value 2 which was on index [1] before. Same for second and third index. For the last one it is a little bit special since there is no next index the % numbers.length computation basically wraps the index so that for index [3] you will get the value of index [0] since (3+1)%4 = 0.
Note on index [3] you are getting value 2 and not 1 since you already changed the value on index [0] before that.
1st iteration
numbers[i] = numbers[1 % 4]; // answer is 1 so numbers[1] = 2
2nd iteration
numbers[i] = numbers[2 % 4]; // answer is 2 so numbers[2] = 3
Like this it will go until I becomes 3

Calculate the values of counters after applying all alternating operations

I was trying to solve a problem from the Codility with a given solution. The problem is provided below:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max counter − all counters are set to the maximum value of any counter.
A non-empty array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
Write a function:
class Solution { public int[] solution(int N, int[] A); }
that, given an integer N and a non-empty array A consisting of M integers, returns a sequence of integers representing the values of the counters.
The sequence should be returned as:
a structure Results (in C), or
a vector of integers (in C++), or
a record Results (in Pascal), or
an array of integers (in any other programming language).
For example, given:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the function should return [3, 2, 2, 4, 2], as explained above.
Assume that:
N and M are integers within the range [1..100,000];
each element of array A is an integer within the range [1..N + 1].
Complexity:
expected worst-case time complexity is O(N+M);
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I have a solution provided,
public static int[] solution(int N, int[] A) {
int[] counters = new int[N];
int currMax = 0;
int currMin = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] <= N) {
counters[A[i] - 1] = Math.max(currMin, counters[A[i] - 1]);
counters[A[i] - 1]++;
currMax = Math.max(currMax, counters[A[i] - 1]);
} else if (A[i] == N + 1) {
currMin = currMax;
}
}
for (int i = 0; i < counters.length; i++) {
counters[i] = Math.max(counters[i], currMin);
}
return counters;
}
It seems they use 2 storage to hold and update the min/max values and use them inside the algorithm. Obviously, there is a more direct way to solve the problem ie. increase the value by 1 or set all the values to max as suggested and I can do that. The drawback will be to lower perfromance and increased time complexity.
However, I would like to understand what is going on here. I spend times debugging with the example array but the algorithm is still little confusing.
Anyone understand it and can explain to me briefly?
It is quite simple, they do lazy update. You keep track at all times of what is the value of the counter that has the highest value (currMax). Then, when you get a command to increase all counters to that maxValue, as that is too expensive, you just save that the last time you had to increase all counters to maxValue, that value was currMin.
So, when do you update a counter value to that value? You do it lazily, you just update it when you get a command to update that counter (increase it). So when you need to increase a counter, you update the counter to the max between its old value and currMin. If this was the first update on this counter since a N + 1 command, the correct value it should have is actually currMin, and that will be higher (or equal) to its old value. One you updated it, you add 1 to it. If now another increase happens, currMin doesn't actually matter, as the max will take its old value until another N + 1 command happens.
The second for is to account for counters that did not get an increase command after the last N + 1 command.
Note that there can be any number of N + 1 commands between 2 increase operations on a counter. It still follows that the value it should have is the maxValue at the time of the last N + 1 command, it doesn't really matter that we didn't update it before with the other maxValue from a previous N + 1, we only care about latest.

Java performance exercise: 0%

I made this test to challenge myself while learning a bit of Java, and I got the worst possible result in the performance test, 0%.
This was the exercise:
You are given two non-empty zero-indexed arrays A and B consisting of
N integers. These arrays represent N planks. More precisely, A[K] is
the start and B[K] the end of the K−th plank.
Next, you are given a non-empty zero-indexed array C consisting of M
integers. This array represents M nails. More precisely, C[I] is the
position where you can hammer in the I−th nail.
We say that a plank (A[K], B[K]) is nailed if there exists a nail C[I]
such that A[K] ≤ C[I] ≤ B[K].
The goal is to find the minimum number of nails that must be used
until all the planks are nailed. In other words, you should find a
value J such that all planks will be nailed after using only the first
J nails. More precisely, for every plank (A[K], B[K]) such that 0 ≤ K
< N, there should exist a nail C[I] such that I < J and A[K] ≤ C[I] ≤
B[K].
For example, given arrays A, B such that:
A[0] = 1 B[0] = 4
A[1] = 4 B[1] = 5
A[2] = 5 B[2] = 9
A[3] = 8 B[3] = 10 four planks are represented: [1, 4], [4, 5], [5, 9] and [8, 10].
Given array C such that:
C[0] = 4
C[1] = 6
C[2] = 7
C[3] = 10
C[4] = 2 if we use the following nails:
0, then planks [1, 4] and [4, 5] will both be nailed. 0, 1, then
planks [1, 4], [4, 5] and [5, 9] will be nailed. 0, 1, 2, then planks
[1, 4], [4, 5] and [5, 9] will be nailed. 0, 1, 2, 3, then all the
planks will be nailed. Thus, four is the minimum number of nails that,
used sequentially, allow all the planks to be nailed.
Write a function:
class Solution { public int solution(int[] A, int[] B, int[] C); }
that, given two non-empty zero-indexed arrays A and B consisting of N
integers and a non-empty zero-indexed array C consisting of M
integers, returns the minimum number of nails that, used sequentially,
allow all the planks to be nailed.
If it is not possible to nail all the planks, the function should
return −1.
For example, given arrays A, B, C such that:
A[0] = 1 B[0] = 4
A[1] = 4 B[1] = 5
A[2] = 5 B[2] = 9
A[3] = 8 B[3] = 10
C[0] = 4
C[1] = 6
C[2] = 7
C[3] = 10
C[4] = 2 the function should return 4, as explained above.
Assume that:
N and M are integers within the range [1..30,000]; each element of
arrays A, B, C is an integer within the range [1..2*M]; A[K] ≤ B[K].
Complexity:
expected worst-case time complexity is O((N+M)*log(M)); expected
worst-case space complexity is O(M), beyond input storage (not
counting the storage required for input arguments). Elements of input
arrays can be modified.
Here is my solution:
class Solution {
public int solution(int[] A, int[] B, int[] C) {
int result = 0;
int empties = 0;
for(int i = 0; i < C.length; i ++){
for(int j = 0; j < A.length; j ++){
if(A[j] != 0){
if(C[i] >= A[j] && C[i] <= B[j]){
A[j] = B[j] = 0;
empties ++;
}
}
if(empties == A.length){
return i + 1;
}
}
}
return -1;
}
}
This is the link of the result: https://codility.com/demo/results/trainingXXEXMW-KVJ/
Questions:
First, I don't understand why my performance is measured O((N + M) * N) and not O(M * N), since I'm doing a for (M) and inside a for(N). Disclaimer, I only learned about Big O notation a couple of days ago.
Second, most likely the reason why the performance was bad was because I didn't use a binary search to find the nail-able elements, instead I looped through them.
However, I did that on purpose since in no part of the exercise is mentioned that the A and B arrays are sorted, in a way that 1 >= A[K] >= A[K+1]. And if I sorted those arrays, then the performance would be bad (I guess, no idea how much the sort hurts the performance honestly, just a guesstimate).
What is your opinion about it?.
I don't understand why my performance is measured O((N + M) * N) and not O(M * N)
They are probably doing curve fitting against a limited number of curves. (This is the problem with trying to determine complexity empirically.)
And if I sorted those arrays, then the performance would be bad (I guess, no idea how much the sort hurts the performance honestly, just a guesstimate).
Actually, sorting will be O(NlogN) if done with a good algorithm. So from a complexity perspective you could achieve the O(NlogN) overall worst-case by sorting and then doing a binary search. (I'm not saying it is the right solution though ....)

Grouping a squence is subsequences with a given sum with lexicographical priority

I am looking for a way to search for a subsequence in a given sequence that sums up to a given number (sum, here 4) with a lexicographical priority.
Take for instance the following example:
1,2,2,4,1,1
Different subsequences can sum up to 4. For instance 1,2,1, 2,2 2,1,1. In case multiple of such sequences exists, the lexicographical first of the corresponding index-array should be returned: so if it is possible to find such sequence with the first element, one has to returned that one, if not, aim for the second and so one (both iterative (take the next one), and recursively (after selecting the first, the next but first should be closest to the head of the sequence as well).
So for this example, we select 1,2,1. Now 2,4,1 is left. If we repeat this problem we cannot make a match with 2: 2,4 is greater than 4 and 2,1 is less than 4. Thus we select 4. Finally we have to select 2 and 1.
A practical application of this concept is a queue of a roller coaster. You need 4 people for a ride, but some people are in groups with their friends and would like to all get on the same ride together.
In this example 1 is a single person at the front of the line, 2 is a group of 2 friends behind him. Now we need a total of 4 people for this ride and we already have 3, so we cut the line (2 and 4) and take the first single person, which gives us 4 people total.
If I understand the problem correctly, what you basically try to do is grouping the numbers such that the sum is 4 and you give priority to adding numbers in the queue first.
You can do this using a dynamic programming approach. I'm here using a int[] and an int as sum, but the problem can be generalized to work with most datastructures.
First you must define a comparator that compares lists of indices for instance a lexicographical one:
public class LexComp<T extends Comparable<T>> implements Comparator<List<T>> {
#Override
public int compare (List<T> la, List<T> lb) {
Iterator<T> ita = la.iterator();
Iterator<T> itb = lb.iterator();
while(ita.hasNext() && itb.hasNext()) {
T ea = ita.next();
T eb = itb.next();
int cr = ea.compareTo(eb);
if(cr != 0x00) {
return cr;
}
}
if(itb.hasNext()) {
return 1;
} else if(ita.hasNext()) {
return -1;
}
return 0;
}
}
Next you can use the following method:
public ArrayList<Integer> groupSum (int[] values, int sum) {
ArrayList[] memory = new ArrayList[sum+1];
memory[0] = new ArrayList<Integer>();
LexComp<Integer> lc = new LexComp<Integer>();
int index = 0;
for(int val : values) {
for(int i = sum-val; i >= 0 ; i--) {
if(memory[i] != null) {
ArrayList<Integer> tmp = (ArrayList<Integer>) memory[i].clone();
tmp.add(index);
if(memory[i+val] == null || lc.compare(tmp,(ArrayList<Integer>) memory[i+val]) < 0) {
memory[i+val] = tmp;
}
}
}
index++;
}
return memory[sum];
}
This method returns an ArrayList<Integer> of indices whose corresponding elements will sum up to sum and null if no such group can be created. It will give priority to some groups according to the LexComp comparator.
For your given input:
groupSum(new int[] {1,2,2,4,1,1},4);
groupSum(new int[] {1,2,3,2,2,2},4);
groupSum(new int[] {1,2,2,3},4);
groupSum(new int[] {1,2,2,3,1},4);
It results in:
[0, 1, 4]
[0, 2]
[0, 3]
[0, 1, 4]
So you should pick the first, second and fifth element which indeed sum up to 4. You then will have to remove these items out of the array yourself and rerun the process. In case no such sum can be constructed, or there are not enough elements to sum up to 4 - as said before - the algorithm will return null. In that case you have to invent a fallback mechanism. Perhaps returning the group the differs the least from sum.
Background
This is a dynamic programming approach. You generate a memory which stores - for each sum - the thus far best found solution. Initially we haven't seen any values so all items contain null except memory[0] which contains an empty arraylist (because the sum of zero elements is 0). So the memory looks like:
Mem
4 -> null
3 -> null
2 -> null
1 -> null
0 -> []
Now the algorithm iterates over the values. The first value we encounter for the example case is a 1. Now we look for lists already defined and the only one is memory[0] we can upgrade that list into a list [0] (the arrays store indices) whose sum results in 1. Since at that moment the value for that list is null there is no alternative, thus we add this list to to memory[1]:
Mem
4 -> null
3 -> null
2 -> null
1 -> [0]
0 -> []
The next item is 2: we can upgrade two lists [] -> [1] and [0] -> [1] these will results in lists with sums 2 and 3 respectively, so we store them at these indices of the memory:
Mem
4 -> null
3 -> [0,1]
2 -> [1]
1 -> [0]
0 -> []
The next item is again a 2. Now we can upgrade 4 lists: [] -> [2], [0] -> [0,2], [1] -> [1,2] and [0,1] -> [0,1,2]. A first problem is that the sum of [0,1,2] is 5 which is higher than sum. That's not interesting, so we drop that one. The problem is however, that some of the places contain already lists:
Mem
4 -> null
3 -> [0,1] <> [0,2]
2 -> [1] <> [2]
1 -> [0]
0 -> []
For the conflicting lists, we need to look for a resolution. In that case the comparator - in this case the LexComp resolves the errors. Since we do this lexicographically, [0,1] wins from [0,2] and [1] from [2]. After resolution the lists looks like:
Mem
4 -> [3]
3 -> [0,1]
2 -> [1]
1 -> [0]
0 -> []
The next element is a 4. The only list we can upgrade such that the sum is still less than or equal to sum is [] -> [3]
Mem
4 -> [3]
3 -> [0,1]
2 -> [1]
1 -> [0]
0 -> []
The next element is 1. We can upgrade all lists except the one 4 -> [3] (otherwise the sum would be larger than 4). But again this results in a lot of conflicts:
Mem
4 -> [3] <> [0,1,4]
3 -> [0,1] <> [1,4]
2 -> [1] <> [0,4]
1 -> [0] <> [4]
0 -> []
Now if we run the lexicographically comparator, it will sometimes accept new lists and sometimes the old lists. After resolution, the memory looks like:
Mem
4 -> [0,1,4]
3 -> [0,1]
2 -> [0,4]
1 -> [0]
0 -> []
Now our current best solution to generate a group that sums up to four has changed from [3] to [0,1,4]. Finally the last element 1 won't change much to the game:
Mem
4 -> [0,1,4] <> [0,1,5]
3 -> [0,1] <> [0,4,5]
2 -> [0,4] <> [0,5]
1 -> [0] <> [5]
0 -> []
Which after resolution reads:
Mem
4 -> [0,1,4]
3 -> [0,1]
2 -> [0,4]
1 -> [0]
0 -> []
Now we have considered all elements and the best solution to generate 4 is memory[4] or [0,1,4].
Different order
This approach can be generalized in the sense that providing a different Comparator on List<T> (here the LexComp<T>) will give priority to another index array. The comparator should always fulfill at least the transitivity constraint: if x is less than y and y is less than z: x must be less than z. Furthermore the list of indices will always increase. An index array of [4,1,0] is thus impossible.
The correct answer to this question depends a lot on how you define your priorities.
Should we always pick the first group in the line if possible or is the optimal solution to have as many people from the front of the queue?
I.e. given
1, 2, 2, 3, 3, 4, 2, 2, 3, 1
is the optimal solution
1, 2, 1
or
1, 3
To get you started, here's a recursive solution that does the first:
private static List<Integer> getSumIndices(int sum, List<Integer> queue) {
return getSumIndices(sum, new ArrayList<>(queue), 0);
}
private static List<Integer> getSumIndices(int sum, List<Integer> queue, int offset) {
System.out.printf("Looking for sum %s in values of %s with offset %s%n", sum, queue, offset);
if(sum == 0) {
//Base case
return new ArrayList<>();
}
for(int i = 0; i < queue.size(); i++) {
int value = queue.get(i);
// Can we actually use this group
if(value <= sum) {
try {
// See if we can find the remainder if we use this group
ArrayList<Integer> list = new ArrayList<>();
list.add(i + offset);
list.addAll(getSumIndices(sum - value, queue.subList(i + 1, queue.size()), offset + i + 1));
return list;
} catch(IllegalArgumentException e) {
// We couldn 't, continue looking
}
}
}
// We could not construct the sum using the values in the queue
System.out.printf("Failed to construct sum %s from values in %s%n", sum, queue);
throw new IllegalArgumentException(String.format("Could not construct sum %s from values in %s%n", sum, queue));
}
Results:
q=[1, 2, 2, 3, 3, 4, 2, 2, 3, 1]
Looking for sum 4 in values of [1, 2, 2, 3, 3, 4, 2, 2, 3, 1] with offset 0
Looking for sum 3 in values of [2, 2, 3, 3, 4, 2, 2, 3, 1] with offset 1
Looking for sum 1 in values of [2, 3, 3, 4, 2, 2, 3, 1] with offset 2
Looking for sum 0 in values of [] with offset 10
Index: Group Size
0: 1
1: 2
9: 1
Remaining q=[2, 3, 3, 4, 2, 2, 3]
q=[1, 2, 3, 2, 3, 4, 2, 2, 3, 2]
Looking for sum 4 in values of [1, 2, 3, 2, 3, 4, 2, 2, 3, 2] with offset 0
Looking for sum 3 in values of [2, 3, 2, 3, 4, 2, 2, 3, 2] with offset 1
Looking for sum 1 in values of [3, 2, 3, 4, 2, 2, 3, 2] with offset 2
Failed to construct sum 1 from values in [3, 2, 3, 4, 2, 2, 3, 2]
Looking for sum 0 in values of [2, 3, 4, 2, 2, 3, 2] with offset 3
Index: Group Size
0: 1
2: 3
Remaining q=[2, 2, 3, 4, 2, 2, 3, 2]
q=[1, 2, 2]
Looking for sum 4 in values of [1, 2, 2] with offset 0
Looking for sum 3 in values of [2, 2] with offset 1
Looking for sum 1 in values of [2] with offset 2
Failed to construct sum 1 from values in [2]
Looking for sum 1 in values of [] with offset 3
Failed to construct sum 1 from values in []
Failed to construct sum 3 from values in [2, 2]
Looking for sum 2 in values of [2] with offset 2
Looking for sum 0 in values of [] with offset 3
Index: Group Size
1: 2
2: 2
Remaining q=[1]
q=[2, 3, 3]
Looking for sum 4 in values of [2, 3, 3] with offset 0
Looking for sum 2 in values of [3, 3] with offset 1
Failed to construct sum 2 from values in [3, 3]
Looking for sum 1 in values of [3] with offset 2
Failed to construct sum 1 from values in [3]
Looking for sum 1 in values of [] with offset 3
Failed to construct sum 1 from values in []
Failed to construct sum 4 from values in [2, 3, 3]
Could not construct sum 4 from values in [2, 3, 3]
You can loop through the list and add in order until it is larger than the value you are looking for.
Code:
public static int addListValues(int[] list, int num){//Returns number which can not be added by anything else in the list to be <= num.
boolean b[] = new boolean[list.length];//List of numbers already taken care of. True for not, false for cleared.
for(int i = 0; i < b.length; i++){
b[i] = true;
}
int count = 0;//Amount of numbers in int[] list which have been added to equal less than or equal to num.
int total = 0;
while(true){//loops until values left can not be added to equal or be less than num.
int check = 0;
for(int i = 0; i < list.length; i++){//Loops through list.
if(b[i]){//If the number has not been added already.
System.out.println("CHECKING: " + i);
if(total + list[i] > num){//Adds to check if the number is greater than num.
check++;
}
if(total + list[i] <= num){//Adds numbers together to equal num or less than num.
System.out.println("TEST: " + list[i] + " TOTAL: " + total);
if(total + list[i] != num){
boolean contains = false;
int index = 0;
for(int o = 0; o < list.length; o++){
if(list[o] == num - total && b[o] && o != i){
contains = true;
index = o;
break;
}
}
if(contains){
System.out.println("1: " + index + ", " + list[index]);
b[index] = false;
count++;
total = 0;
}else{
System.out.println("2");
b[i] = false;
count++;
total+= list[i];
}
}else{
System.out.println("3");
b[i] = false;
count++;
total = 0;
}
}else if(check == list.length - count){//Check if "check" is equal to the amount left over. In other words, if the numbers left are higher than the number you are looking for.
System.out.println("FINAL: 3");
int t = 0;
for(int j = 0; j < list.length; j++){
if(b[j]){
t += list[j];
}
}
return t;//More than one number is left and is higher than num. Returns numbers left added together
}else if(count == list.length-1){
System.out.println("FINAL: 2");
return list[i];//returns list[i] if it is the only number left over.
}
}else if(count >= list.length){
System.out.println("FINAL: 1");
return total;//Returns total if there is nothing left over. The total may be anything less than the "num".
}
}
}
}
I have tested this method with multiple sets of numbers and it works. I was unsure what to return if more than one value were left over and were higher than 4, so I added the left over values and returned this.
This code does not require any imports.

How to express 2n as sum of n variables (Java implementation?)

I wonder if there is an elegant way to derive all compositions of 2n as the sum of n non-negative integer variables.
For example, for n = 2 variables x and y, there are 5 compositions with two parts :
x = 0 y = 4; x = 1 y = 3; x = 2 y = 2; x = 3 y = 1; x = 4 y = 0
such that x + y = 4 = 2n.
More generally, the problem can be formulated to find all the compositions of s into n non-negative integer variables with their sum equals to s.
Any suggestion on how to compute this problem efficiently would be welcome, and some pseudo-code would be much appreciated. Thanks.
Edit: while solutions are presented below as in Perl and Prolog, a Java implementation may present a new problem as linear data structures such as arrays need to be passed around and manipulated during the recursive calls, and such practice can become quite expensive as n gets larger, I wonder if there is an alternative (and more efficient) Java implementation for this problem.
Here's some python:
def sumperms(n, total = None):
if total == None:
# total is the target sum, if not specified, set to 2n
total = 2 * n
if n == 1:
# if n is 1, then there is only a single permutation
# return as a tuple.
# python's syntax for single element tuple is (element,)
yield (total,)
return
# iterate i over 0 ... total
for i in range(total + 1):
# recursively call self to solve the subproblem
for perm in sumperms(n - 1, total - i):
# append the single element tuple to the "sub-permutation"
yield (i,) + perm
# run example for n = 3
for perm in sumperms(3):
print perm
Output:
(0, 0, 6)
(0, 1, 5)
(0, 2, 4)
(0, 3, 3)
(0, 4, 2)
(0, 5, 1)
(0, 6, 0)
(1, 0, 5)
(1, 1, 4)
(1, 2, 3)
(1, 3, 2)
(1, 4, 1)
(1, 5, 0)
(2, 0, 4)
(2, 1, 3)
(2, 2, 2)
(2, 3, 1)
(2, 4, 0)
(3, 0, 3)
(3, 1, 2)
(3, 2, 1)
(3, 3, 0)
(4, 0, 2)
(4, 1, 1)
(4, 2, 0)
(5, 0, 1)
(5, 1, 0)
(6, 0, 0)
The number of compositions (sums where ordering matters) of 2n into exactly n non-negative parts is the binomial coefficient C(3n-1,n-1). For example, with n = 2 as above, C(5,1) = 5.
To see this, consider lining up 3n-1 positions. Choose any subset of n-1 of these, and place "dividers" in those positions. You then have the remaining blank positions grouped into n groups between dividers (some possibly empty groups where dividers are adjacent). Thus you have constructed a correspondance of the required compositions with the arrangements of spaces and dividers, and the latter is manifestly counted as combinations of 3n-1 things taken n-1 at a time.
For the purpose of enumerating all the possible compositions we could write a program that actually selects n-1 strictly increasing items s[1],...,s[n-1] from a list [1,...,3n-1]. In accordance with the above, the "parts" would be x[i] = s[i] - s[i-1] - 1 for i = 1,...,n with the convention that s[0] = 0 and s[n] = 3n.
More elegant for the purpose of listing compositions would be to select n-1 weakly increasing items t[1],...,t[n-1] from a list [0,...,2n] and calculate the parts x[i] = t[i] - t[i-1] for i = 1,...,n with the convention t[0] = 0 and t[n] = 2n.
Here's a brief Prolog program that gives the more general listing of compositions of N using P non-negative parts:
/* generate all possible ordered sums to N with P nonnegative parts */
composition0(N,P,List) :-
length(P,List),
composition0(N,List).
composition0(N,[N]).
composition0(N,[H|T]) :-
for(H,0,N),
M is N - H,
composition0(M,T).
The predicate compostion0/3 expresses its first argument as the sum of a list of non-negative integers (third argument) having the second argument as its length.
The definition requires a couple of utility predicates that are often provided by an implementation, perhaps in slightly different form. For completeness a Prolog definition of the counting predicate for/3 and length of list predicate are as follows:
for(H,H,N) :- H =< N.
for(H,I,N) :-
I < N,
J is I+1,
for(H,J,N).
length(P,List) :- length(P,0,List).
length(P,P,[ ]) :- !.
length(P,Q,[_|T]) :-
R is Q+1,
length(P,R,T).

Categories

Resources