Java inner for-loop - java

I have to find all possibilities to distribute n things to k containers. The containers all should have a different size so I made k inner for-loops for counting every possibility. Sorry for the bad explanation, but my english is not that good.
Example code that works for 3 Containers:
for (int i = 0; i < container[0]; i++)
for (int j = 0; j < container[1]; j++)
for (int k = 0; k < container[2]; k++)
if ((i + j + k) == n)
Possibilities++;
Now i need to know how to make k for loops so that it works for 2 and for 10.
Thanks

I am assuming that containers holds the size of each container. Perhaps the simplest solution would be to just set the size of any containers you don't use to zero. Then you can have (say) 10 nested loops but if there are only 2 containers then set all the sizes above 2 to zero.
However nested loops are not really the best way to handle this. This is likely to be a good use for recursion.
private int combinationCount(int[] containerSizes, int from, int total) {
if (total == 0 || from == containerSizes.length - 1)
return 1;
int combinations = 0;
for (int i = 0; i <= Math.min(total, containerSizes[from]); i++)
combination += combinationCount(containerSizes, from + 1, total - i);
return combinations;
}
This would be called with combinationCount(containers, 0, n). You could remove the from argument altogether by either copying the array in each recursive call or passing a List and then a sublist in the recursive calls.
Here is my test code for your information:
System.out.println(combinationCount(IntStream.range(10, 30).toArray(), 0, 10));
Which returns 20030010
I'll explain how this works:
if (total == 0 || from == containerSizes.length - 1)
return 1;
If the total of the remaining containers is zero then there's only 1 combination because all the remaining containers must be empty. Similarly if there's only one container left there's only 1 combination because it must have all the remaining items.
int combinations = 0;
for (int i = 0; i <= Math.min(total, containerSizes[from]); i++)
combination += combinationCount(containerSizes, from + 1, total - i);
return combinations;
The current container might contain anything from zero to all the items. So iterate through those and total up all the combinations for the remaining containers that add up to the target minus the items in the current container.

Related

Intelligent method for particular traversing of a matrix

I have to traverse an n x n matrix in java (so indices are 0,...,n-1), to assign values to the single elements. I must start from the bottom right and arrive to the top left. The particularity is that I do not have to consider the matrix[n-1][n-1] element, that has been initialised before. The adjacent values depend on each other for initialazing and it must be initialized first.
One way could be inserting an if in the for cycle
for (i = n-1; i >= 0; i--)
for (j = n-1; j >= 0; j--)
if (i == n - 1 && j == n - 1)
//initialize particular value
else
//initialize others
but it seems to me a bit inefficient.
Another way could be to initialize the value matrix[n-1][n-1] outside the cycle, then doing 3 for cycles (one for the bottom line, one for the rightest column, one for the other elements). But it seems a bit inelegant.
So I'm searching, if exists, for a solution that involves only two annidate for, and without a control in every cycle (like first example).
Here is an approach that uses one loop through the matrix which makes it easy to avoid matrix[n-1][n-1]. Not sure how the calculations compares to an if though from a performance perspective
int[][] matrix = new int[n][n];
int current = n * n - 2;
int row = 0;
int col = 0;
while (current >= 0) {
col = current % n;
row = current / n;
matrix[row][col] = //init stuff
current--;
}
I think the solution of Joakim is good except the % and / operations... inspired to this, I've found an interesting variant that avoid them. I've called column index j1 to avoid problems with other "normal" cycles.
matrix[n-1][n-1] = //init code;
int j1 = n-2;
for (int i = n-1; i >= 0; i--) {
for (; j1 >= 0; j1--) {
matrix[i][j1] = //init code;
}
j1 = n-1;
}

I am stuck at implementing Radix sort recursively

I'm required to implement a programm that sorts numbers ranging from 0 to 99999 recursively (this is basically Radix sort). The process itself is kinda simpel: The user types in an array that contains those numbers in the main method. Then, the main method calls for the sort-method where I create a two-dimensional array named 'space' with 10 rows and 1 column. Then, I divide every number in the array by the digit, which would be 10.000 in the first run. So, for example, 23456 / 10000 = 2,3456 = 2 (in java), hence, the programm puts this number in space[2][0], so in the second row. Then, we take this entire row and extend it, which is done in the putInBucket-method. We do this in order to make sure that we can put another number into the same row.
We do this for every number that is inside the 'numbers'-array. Then, we want to work with these rows and sort them again by the same principle, but now we take a look at the second digit. We want to do this from left to right, not from right to left. So, if our second row would look like this
[23456, 24567],
we'd want to compare the 3 and the 4, which leads to 23456 < 24567.
We do this with the help of the recursive call at the end of the sort method. Now, this is where I am lost. I simply don't know how to manipulate the digit-variable in order to be able to work with the second, third, ... digit of each number. In the first run, as you see, this can be simply done by dividing through 10.000, but I didn't find a way to go further from here.
Please note: Yes, this is a homework question, hence, I'm only allowed to use primitives here. We didn't go through stuff like math.pow(...) yet. Thanks in advance!
public static int[] sort(int[] numbers, int digit) {
if (numbers.length == 0)
return numbers;
int[][]space = new int[10][1];
int i, j = 0;
for (j = 0; j < numbers.length; j++) {
i = numbers[j] / digit;
space[i][0] = numbers[j];
space[i] = putInBucket(space[i], numbers[j]);
}
for (i = 0; i < space[i].length; i++) {
sort(space[i], digit); //not sure how to work with digit here
}
return ... //not sure what to return here
}
private static int[] putInBucket(int[] bucket, int number) {
int[] bucket_new = new int[bucket.length+1];
for (int i = 1; i < bucket_new.length; i++) {
bucket_new[i] = bucket[i-1];
}
return bucket_new;
}
public static void main (String [] argv) {
int[] numbers = IO.readInts("Numbers: ");
int digit = 10000;
int[] bucket = sort(numbers, digit);
}
To extract the last digit, the remainder operator % is your friend:
123 % 10 == 3
if you haven't covered the % operator yet, you can use
123 % 10 == 123 - (123 / 10 * 10) == 3
To extract another digit, you can first move it to the end with /:
123 / 10 == 12
12 % 10 == 2
You can therefore extract an arbitrary digit using
(number / mask) % 10
where mask ∈ {..., 10000, 1000, 100, 10, 1}.
Extra credit
Radix sort is usually implemented in the binary number system instead because a binary digit (or a sequence thereof) can be extracted without performing a division, which is more efficient:
x % 16 == x & 15;
x \ 16 == x >> 4;
Also, if you are implementing this for real, you'd need a more efficient way to grow buckets (your implementation takes O(n) to add a single element to the bucket, adding n elements to the bucket therefore takes O(n^2), which makes your radix sort slower than insertion sort). Dynamic arrays are usually implemented with a more efficient geometric expansion.
This should work:
public static int[] sort(int[] numbers, int digit) {
if (numbers.length == 0 || digit <= 0)
return numbers;
int[][]space = new int[10][10];
int[] len = new int[10];
int i, j = 0;
for (j = 0; j < numbers.length; j++) {
i = (numbers[j] / digit) % 10;
len[i]++;
for (int k = len[i] - 1; k > 0; k--) {
space[i][k] = space[i][k - 1];
}
space[i][0] = numbers[j];
}
for (i = 0; i < 10; i++) {
int[] bucket = new int[len[i]];
for (int k = 0; k < len[i]; k++)
bucket[k] = space[i][k];
space[i] = sort(bucket, digit / 10);
}
int k = 0;
for (i = 0; i < 10; i++) {
for (j = 0; j < len[i]; j++) {
numbers[k] = space[i][j];
k++;
}
}
return numbers;
}
a) Firstly, space is allocated as having only one column. So, space[i] = bucket will not work.
Instead, you could declare it as int[10][10]. (Note: it will only support max of 10 values in one bucket). Or you may allocate new arrays programmatically. Or of course, a List might be better suited.
b) i = (numbers[j] / digit) % 10;
To get the required digit only. For eg: if the number is 12130, and digit = 1000, we want to set i to 2, not 12.
c) putInBucket replaced with an in-place loop.
d) For each bucket of space, we sort it by one digit lower by calling sort recursively.
e) Finally, the result to be returned (numbers), can be created by looping through space from digit 0 to 9.
Note:
This solution could probably be made better.

Dynamic programming with Combination sum inner loop and outer loop interchangeable?

I am a little confuse about the dynamic programming solution for combination sum, that you are given a list of numbers and a target total, and you want to count how many ways you can sum up to this target sum. Numbers can be reused multiple times. I am confused about the inner loop and outer loop that whether they are interchangeable or not. Can some explain the difference between the following two, and in what case we would use one but not the other, or they are the same.
int [] counts = new int[total];
counts[0] = 1;
// (1)
for(int i = 0; i <= total; i++) {
for(int j = 0; j < nums.length; j++) {
if(i >= nums[j])
counts[i] += counts[i - nums[j]];
}
}
// (2)
for(int j = 0; j < nums.length; j++)
for(int i = nums[j]; i <= total; i++) {
counts[i] += counts[i - nums[j]];
}
}
The two versions are indeed different, yielding different results.
I'll use nums = {2, 3} for all examples below.
Version 1 finds the number of combinations with ordering of elements from nums whose sum is total. It does so by iterating through all "subtotals" and counting how many combinations have the right sum, but it doesn't keep track of the elements. For example, the count for 5 will be 2. This is the result of using the first element (with value 2) and finding 1 combination in nums[3] and another combination for the second element (value 3) with the 1 combination in nums[2]. You should pay attention that both combinations use a single 2 and a single 3, but they represent the 2 different ordered lists [2, 3] & [3, 2].
Version 2 on the other hand find the number of combinations without ordering of elements from nums whose sum is total. It does so by counting how many combinations have the right sum (fur each subtotal), but contrary to version 1, it "uses" each element completely before moving on to the next element thus avoiding different orderings of the same group. When counting subtotals with the first element (2), all counts will initially be 0 (except the 0 sum sentinel), and any even subtotal will get the new count of 1. When the next element used, it is as if it's coming after all 2's are already in the group, so, contrary to version 1, only [2, 3] is counted, and not [3, 2].
By the way, the order of elements in nums doesn't affect the results, as can be understood by the logic explained.
Dynamic programming works by filling out entries in a table assuming that previous entries in the table have been fully completed.
In this case, we have counts[i] is dependent on counts[i - nums[j]]; for every entry j in nums.
In this code snippet
// (1)
for(int i = 0; i < total; i++) {
for(int j = 0; j < nums.length; j++) {
if(i >= nums[j])
counts1[i] += counts1[i - nums[j]];
}
}
We fill the table in order from 0 to total in that order. This is the action of the outer loop. The inner loop goes through our different nums and updates the current entry in our table based on the previous values, which are all assumed to be completed.
Now look at this snippet
// (2)
for(int j = 0; j < nums.length; j++){
for(int i = nums[j]; i < total; i++) {
counts2[i] += counts2[i - nums[j]];
}
}
Here we are iterating through our list of different counts and updating our totals. This breaks the concept of dynamic programming. None of our entries can ever be assumed to be complete until we are completely finished with our table.
Are they the same? The answer is no they are not. The following code illustrates the fact:
public class dyn {
public static void main(String[] args) {
int total = 50;
int[] nums = new int[]{1, 5, 10};
int [] counts1 = new int[total];
int [] counts2 = new int[total];
counts1[0] = 1;
counts2[0] = 1;
// (1)
for(int i = 0; i < total; i++) {
for(int j = 0; j < nums.length; j++) {
if(i >= nums[j])
counts1[i] += counts1[i - nums[j]];
}
}
// (2)
for(int j = 0; j < nums.length; j++){
for(int i = nums[j]; i < total; i++) {
counts2[i] += counts2[i - nums[j]];
}
}
for(int k = 0; k < total; k++){
System.out.print(counts1[k] + ",");
}
System.out.println("");
for(int k = 0; k < total; k++){
System.out.print(counts2[k] + ",");
}
}
}
This will output 2 different lists.
They are different because we are updating our counts[i] with incomplete information from earlier in the table. counts[6] assumes you have the entry for counts[5] and counts[1], which in turn assume you have the entries for counts[4], counts[3], counts[2], and counts[0]. Thus, each entry is dependent on (in the worst case all of) the previous entries in the table.
Addendum:
Interesting (perhaps obvious) side-note:
The two methods produce the same list up until the smallest pairwise sum of entries in nums.
Why?
This is when the information from previous entries becomes incomplete (with respect to the first loop). That is, if we have int[] nums = new int[]{3, 6}, then counts[3+6] will not be computed correctly, because either
count[3] will not be right or count[6] will not align with the result obtained using the first loop, depending on which stage of the computation we have done yet.
In light of criticism of my previous answer, I thought I'd take a more mathematical approach.
As in #Amit 's answer, I will use nums = {2, 3} in examples.
Recurrence Relations
The first loop computes
S(n) = S(n-3) + S(n-2)
Or, more generally, for some set {x_1, x_2, x_3, ... ,x_k}:
S(n) = S(n- x_1) + S(n- x_2) + ... + S(n- x_k)
It should be clear that each S(n) is dependent on (possibly all) previous values, and so we must start on 0 and populate the table upwards to our desired total.
The second loop computes a recurrence S_2(n) with the following definitions:
S_1(n) = S_1(n-2)
S_2(n) = S_1(n) + S_2(n-3)
More generally, for some set {x_1, x_2, x_3, ... ,x_k}:
S_1(n) = S_1(n- x_1)
S_2(n) = S_1(n) + S_2(n- x_2)
...
S_k(n) = S_{k-1}(n) + S_k(n- x_k)
Each entry in this sequence is like those from the first loop; it is dependent on the previous entries. But unlike the first loop, it is also dependent on earlier sequences.
Put perhaps more concretely:
S_2 is dependent on not only (possibly all) previous entries of S_2, but also on previous entries of S_1.
Thus, when we want to compute the first recurrence, we begin at 0 and compute each entry, for each number in our nums.
When we want to compute the second recurrence, we compute each intermediate recurrence one at a time, each time storing the result in counts.
In Plain English
What do these two recurrences compute? As #Amit 's answer explains, they compute the number of combinations that sum to total, with and without preserving order. It's easy to see why, again using our example of nums = {2, 3}:
Note my use of the word list to denote something ordered, and the word set to denote something unordered.
I use append to mean adding to the former, and add to denote adding to the latter.
If you know
how many lists of numbers add to 2,
and how many add to 3,
and I ask you
how many add to 5?
You can append a 3 to every one of the former lists, and a 2 to every one of the latter lists.
Thus (how many add to 5) = (how many add to 3) + (how many add to 2)
Which is our first recurrence.
For the second recurrence,
If you know
how many sets of just 2's add to 5 (0)
how many sets of just 2's and 3's add to 2 (1)
You can just take all of the first number, and you can add a 3 to all the sets in the second number.
Note how "sets of just 2's" is a special case of "sets of just 2's and 3's". "sets of just 2's and 3's" depends on "sets of just 2's", just like in our recurrence!
Recursive functions written in java
The following recursive function computes the values for the first loop, with example values 3 and 2.
public static int r(int n){
if(n < 0)
return 0;
if(n == 0)
return 1;
return r(n-2) + r(n-3);
}
The following set of recursive functions computes the values for the second loop, with example values 3 and 2.
public static int r1(int n){
if(n < 0)
return 0;
if(n == 0)
return 1;
return r1(n-2);
}
public static int r2(int n){
if(n < 0){
return 0;
}
return r1(n) + r2(n-3);
}
I have checked them up to 10 and they appear to be correct.

Maximum Sum Subarray O(n) not Kadane's

I'm reading Cormen's "Introduction to Algorithms".
For the linear algorithm for Max Sum Subarray problem I came up with my own solution. Didn't check existing one (Kadena's) before implementing.
Now I'm testing it with different test scenarios and always have better results than Kadena's. I don't believe in such a luck, but can't find what have I missed. Could you take a look whether it is a working solution?
public void findMaxSubarray(Number[] numbers) {
int maxSum = Integer.MIN_VALUE;
int left = 0;
int right = numbers.length - 1;
int i = 0;
int j = i + 1;
int sum = numbers[i].intValue();
while (i < numbers.length) {
if (maxSum < sum) {
maxSum = sum;
left = i;
right = j - 1;
}
if (j >= numbers.length)
return;
sum = sum + numbers[j].intValue();
if (sum <= 0) {
// ignoring "first" negative numbers. shift i to first non-negative
while (numbers[j].intValue() <= 0) {
if (maxSum < numbers[j].intValue()) {
maxSum = numbers[j].intValue();
left = j;
right = j;
}
if (++j >= numbers.length)
return;
}
i = ++j;
sum = 0;
}
j++;
}
System.out.println(String.format("Max subarray is %d, [%d; %d]", maxSum, left, right));
}
Update
The idea of code is to keep in track only one subarray, and adding to its' tail numbers, when numbers are that low that sum becomes negative - set beginning of array after the tail.
Additionally negative items in the beginning are being ignored. head of subarray is just shifted forward.
Everytime sum appears to be maximum - maxSum and limits are updated.
shift i() --to first non negative number
from j = i+1 up to N.length
sum + N[j]
if sum <= 0
i = j+1
if N[i] < 0
shift i()
sum = 0
I think your algorithm is basically sound, but it has two bugs that I can see:
On the input 1 -2 10 3, it will skip over the 10 and output 3. I think you can fix this by changing i = ++j; to i = j;.
In 2 different places you return if j goes past the end, which will cause no output to be produced at all! (This will happen if, e.g., a long list of negative numbers appears at the end of the list.)
Also I don't expect it to be faster (or slower, for that matter) than Kadane's. Summing two numbers is a fast operation, as fast as copying one variable to another, which is what you are doing when you shift the start of the subarray.

Shell Sort: won't work with certain combos of intervals

I asked this question before, but my post was cluttered with a whole bunch of other code and wasn't clearly presented, so I'm going to try again. Sorry, I'm new here
Shell sort, how I wrote it, only works sometimes. Array a is an array of 100 integers unsorted, inc is an array of 4 integers whose values are the intervals that shell sort should use (they descend and the final value is always 1), count is an array which stores the counts for different runs of shell sort, cnt represents the count value which should be updated for this run of shell sort.
When I run shell sort multiple times, with different sets of 4 intervals, only sometimes does the sort fully work. Half the time the array is fully sorted, the other half of the time the array is partially sorted.
Can anyone help? Thanks in advance!
public static void shellSort(int[] a, int[] inc, int[] count, int cnt) {
for (int k = 0; k < inc.length; k++) {
for (int i = inc[k], j; i < a.length; i += inc[k]) {
int tmp = a[i];
count[cnt] += 1;
for (j = i - inc[k]; j >= 0; j -= inc[k]) {
if (a[j] <= tmp)
break;
a[j + inc[k]] = a[j];
count[cnt] += 1;
}
a[j + inc[k]] = tmp;
count[cnt] += 1;
}
}
}
One problem is that you're only sorting one inc[k]-step sequence for each k, while you should sort them all (you're only sorting {a[0], a[s], a[2*s], ... , a[m*s]}, leaving out {a[1], a[s+1], ... , a[m*s+1]} etc.). However, that should only influence performance (number of operations), not the outcome, since the last pass is a classical insertion sort (inc[inc.length-1] == 1), so that should sort the array no matter what happened before.
I don't see anything in the code that would cause failure. Maybe the inc array doesn't contain what it should? If you print out inc[k] in each iteration of the outer loop, do you get the expected output?
There is an error in your i loop control:
for (int i = inc[k], j; i < a.length; i += inc[k]) {
Should be:
for (int i = inc[k], j; i < a.length; i++) {
The inner j loop handles the comparison of elements that are inc[k] apart. The outer i loop should simply increment by 1, the same as the outer loop of a standard Insertion sort.
In fact, the final pass of Shellsort with an increment of 1 is identical to a standard Insertion sort.

Categories