The North Carolina Lottery offers several draw games, two of which are Pick 3 and Pick 4. You pick 3 or 4 digits, respectively, between 0 and 9 (inclusive), and the numbers can repeat (e.g., 9-9-9 is a valid combination). I'll use Pick 3 for this example, because it's easier to work with, but I am trying to make this a generic solution to work with any number of numbers.
One of the features of Pick 3 and Pick 4 is "1-OFF," which means you win a prize if at least one of the numbers drawn are 1 up or 1 down from the numbers you have on your ticket.
For example, let's say you played Pick 3 and you picked 5-5-5 for your numbers. At least one number must be 1-off in order to win (so 5-5-5 does not win any prize, if you played the game this way). Winning combinations would be:
1 Number 2 Numbers 3 Numbers
-------- --------- ---------
4-5-5 4-4-5 4-4-4
5-4-5 5-4-4 6-6-6
5-5-4 4-5-4 4-4-6
6-5-5 6-6-5 4-6-6
5-6-5 5-6-6 4-6-4
5-5-6 6-5-6 6-4-4
4-5-6 6-6-4
6-5-4 6-4-6
6-4-5
5-6-4
5-4-6
4-6-5
(I think that's all the combinations, but you get the idea).
The most "efficient" solution I could come up with is to have arrays that define which numbers are altered, and how:
int[][] alterations = {
// 1 digit
{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
// 2 digits
{-1, -1, 0}, ...
};
And then modify the numbers according to each of the alteration arrays:
int[] numbers = {5, 5, 5};
for(int i = 0; i < alterations.length; i++) {
int[] copy = Arrays.copyOf(numbers, numbers.length);
for(int j = 0; j < alterations[i].length; j++) {
// note: this logic does not account for the numbers 0 and 9:
// 1 down from 0 translates to 9, and 1 up from 9 translates
// to 0, but you get the gist of how this is supposed to work
copy[j] += alterations[i][j];
}
printArray(copy);
}
...
private static void printArray(int[] a) {
String x = "";
for(int i : a)
x += i + " ";
System.out.println(x.trim());
}
But I'm wondering if there's a better way to do this. Has anyone come across something like this and has any better ideas?
Sounds like you're looking for backtracking since constructing the alterations array is quite tedious. In your backtracking algorithm you'd construct your candidates, apply the alteration, and check if the resulting combination is valid, if so then you'd print. I suggest you read Steven Skiena's Algorithms Design Manual Chapter 7 for some background information on backtracking and how it can be done with a combinatorial problem.
Related
I'm testing my neural network for XOR comparisons, and i've encountered an error i'd like to fix without altering the number of neurons in the first hidden layer. The code causing the error is:
public double dotProduct(int[][] a, double[][] ds)
{
int i;
double sum = 0;
for(i = 0; i < a.length; i++)
{
int j;
for(j = 0; j < a[i].length; j++)
{
sum += a[i][j] * ds[i][j];
}
}
return sum;
}
is giving me a null pointer exception. The dot product calculation itself is used to generate the dot product from an inputset my neural net has been provided with.
The input set is this:
int inputSets[][] =
{
{0, 0, 1},
{0, 1, 1},
{1, 0, 1},
{0, 1, 0},
{1, 0, 0},
{1, 1, 1},
{0, 0, 0}
};
It's a multidimensional array containing 7 arrays. It is then used in this:
public double think(int[][] input)
{
output_from_layer1 = sigmoid(dotProd.dotProduct(input, layer1.getWeights()));
return output_from_layer1;
}
The sigmoid part of the function isn't an issue, as it takes a double and
dotProduct is supposed to output a double. The issue as far as I'm aware is that the dotProduct function is taking a larger multidimensional array, and then attempting to cross it with a smaller one (The layer1.getWeights getter that calls the weights array for that layer).
The weights of a layer are defined as such:
layerWeights = new double[numNeurons][inpNum];
and the layer that's being used in the dot product is:
XORlayer layer1 = new XORlayer(4, 3);
So 4 neurons with 3 inputs each. The issue stems from the fact that there aren't enough neurons in this layer for the amount of inputs, as far as i'm aware, which is generating the null pointer exception when there isn't anything further to multiply against the input values.
We have 12 inputs in the neurons, and 21 input values.
My main question is, is there a way to solve this issue so the dot product operation is completed successfully without simply expanding the amount of neurons the layer contains to 7?
This discussion might help. As suggested there, since you're using a 2D array, matrix multiplication (instead of dot product) would likely be more appropriate.
Of course, similar to the dot product, the dimensions must be aligned for matrix multiplication.
inputSets is a 7x3 matrix and layerWeights is a 4x3 matrix. The transpose of layerWeights is a 3x4 matrix. Now the dimensions are aligned, and the matrix multiplication results in a 7x4 matrix.
Based on the posted code, I would suggest something like this:
output_from_layer1 = sigmoid(matrixMult.multiply(input, transpose(layer1.getWeights())));
I have arrays a1 to an each containing m number of elements. I have another symmetric n X n matrix b containing distance between the arrays. I want to select one element from each array x1 to xn limited to the following constraint. (a1 is an array and x1 a single value taken from a1)
For every xi (which was originally aiu) and xj (which was originally ajv), where i is not same as j, and u and v are the original array indices, we have |u - v| <= bij.
The total sum of x1 to xn is the maximum of all possible such sets.
An example
a1 = [1, 2, 3, 8, -1, -1, 0, -1]
a2 = [1, 2, 4, 0, -1, 1, 10, 11]
b = |0, 2|
|2, 0|
The selected values are x1 = 8 and x2 = 4. One can notice that we didn't select 10 or 11 from the second because the nearest possible value for any of them is just 0.
Now when I have only two arrays I can do the following in java in O(n2) time, I guess, and find the maximum sum, which is 12 in this case. How can I achieve better solution for more than 2 arrays?
int[][] a = new int[][]{{1, 2, 3, 8, -1, -1, 1, -1}, {1, 2, 4, 0, -1, 1, 10, 11}};
int[][] b = new int[][]{{0, 2}, {2, 0}};
int maxVal = Integer.MIN_VALUE;
for (int i = 0; i < a[0].length; i++) {
for (int j = Math.max(i - b[0][1], 0); j < Math.min(a[1].length, i + b[0][1]); j++) {
maxVal = Math.max(maxVal, a[0][i] + a[1][j]);
}
}
System.out.println("The max val: "+maxVal);
You can't use dynamic programming here, because there is no optimal substructure: the b_1n entry can ruin a highly valuable path from x_1 to x_{n-1}. So it's probably hard to avoid exponential time in general. However, for a set of b_ij that do reasonably restrict the choices, there is a straightforward backtracking approach that should have reasonable performance:
At each step, a value has been selected from some of the a_i, but no choice has yet been made from the others. (The arrays selected need not be a prefix of the list, or even contiguous.)
If a choice has been made for every array, return (from this recursive call) the score obtained.
Consider, for each pair of a chosen array and a remaining array, the interval of indices available for selection in the latter given the restriction on distance from the choice made in the former.
Intersect these intervals for each remaining array. If any intersection is empty, reject this proposed set of choices and backtrack.
Otherwise, select the remaining array with the smallest set of choices available. Add each choice to the set of proposed choices and recurse. Return the best score found and the choice made to obtain it, if any, or reject and backtrack.
The identification of the most-constrained array is critical to performance: it constitutes a form of fuzzy belief propagation, efficiently pruning future choices incompatible with present choices necessitated by prior choices. Depending on the sort of input you expect, there might be value in doing further prioritization/pruning based on achievable scores.
My 35-line Python implementation, given a 10x10 random matrix of small integers and b_ij a constant 2, ran in a few seconds. b_ij=3 (which allows up to 7 of the 10 values for each pair of arrays!) took about a minute.
For a school project i had to code the cracker barrel triangle peg game, http://www.joenord.com/puzzles/peggame/3_mid_game.jpg heres a link to what it is. I made a triangle symmetric matrix to represent the board
|\
|0\
|12\
|345\
|6789\....
public int get( int row, int col )
{
if (row >= col) // prevents array out of bounds
return matrix[row][col];
else
return matrix[col][row];
} //
and here is my get() function that's the form of the matrix. if i try to access get(Row, Column) and row>column i access get(column, row) its set that way in all my methods. This way its easier to prevent out of bounds stuff from happening. empty spots in the triangle are set to 0, all pegs are set to 1. There's unrelated reason why i didn't use a Boolean array. The project is a AI project and to develop a heuristic search algorithm i need access to the number of pegs adjacent to each other. I can easily prevent most duplicates by simply dividing by total/2 since it will count every adjacent in both directions. I don't know how to prevent duplicate checks when i cross that middle line. It only matters on the 0 2 5 and 9 positions. If i really wanted to i could write a separate set of rules for those positions, but that doesn't feel like good coding and is not functional for different sized triangles. any input is welcome and if you need more information feel free to ask.
0, 2, 5, 9 is not an arithmetic progression. The finite differences 2-0 = 2, 5-2 = 3, 9 - 5 = 4 are in arithmetic progression. So the sequence is 0, 0 + 2 = 2, 2 + 3 = 5, 5 + 4 = 9, 9 + 5 = 14, 14 + 6 = 20, etc. They are one less than the triangle numbers 1, 3, 6, 10, 15, 21, etc. The nth triangle number has a short-cut expression, n(n+1)/2 (where n starts at 1, not 0). So your numbers are n(n+1)/2 - 1 for n = 1, 2, 3, ...
Anyway, the situation you are experiencing should tell you that setting it up so get(row,col) == get(col,row) is a bad idea. What I would do instead is to set it up so that your puzzle starts at index 1,1 and increases from there; then put special values -1 in the matrix entries 0,y and x,0 and anything with col > row. You can check for out of bounds conditions just by checking for the value -1 in a cell. Then to count the number of pegs surrounding a position you always do the same thing: check all four adjacent cells for 1's.
This is the problem I have:
http://codingbat.com/prob/p185204
Try and split an array into two of equal sum. If possible, return true, else return false.
This is my logic:
given {1, 2, 3, 4, 5, 6, 7}
{1, 2, 3, 4, 5, 6, 7} {}
{1, 2, 3, 4, 5, 6} {7}
{2, 3, 4, 5, 6} {7, 1}
{3, 4, 5, 6} {7, 1, 2}
{4, 5, 6} {7, 1, 2, 3}
{5, 6} {7, 1, 2, 3, 4}
{5, 6, 1} {7, 2, 3, 4}
{5, 6, 1, 2} {7, 3, 4}
true
but if there is no possible way to split it to get 2 equal sums, it'll go into an infinite recursion. Recursion is a requirement for this. All I need is a way to check if it's going into an infinite recursion and have it return false.
EDIT: here's some psuedo-code to hopefully help get what I'm trying to do across.
2ndArray.add(largest from 1stArray)
public attemptSplit(using 1stArray and 2ndArray)
if (1st array and 2nd array aren't equal)
get the smallest value from the array with larger sum,
and move it to the other array
else
attempSplit(using the two new arrays) //<-this is where the recursive part comes in
So, I have the base case for when it's true, that's easy. I need a base case for when it's false.
The answer to the title of your question is you cannot.
The answer to the body of your question is - you've got it wrong - you won't hit infinite recursion, you will just finish all possibilities. At that point you can return false having tried each one and found none satisfying your criteria.
All you need to do is work out an algorithm that will iterate through all possibilities. This can be done with something like:
for each entry -
move it to the other set
check to see if you have found an answer and if so report it and finish
recurse on your new smaller set
move it back
It is not possible to decide, with a program, whether another program will end or not.
More information can be found on it here: http://en.wikipedia.org/wiki/Halting_problem
As for the actual question: You will need to think up another approach.
Perhaps you can (for this problem only) decide that it is going into infinite recursion if your method has done a certain number of moves.
The typical approach to curbing rampant recursion is to include a depth argument to the function call and increment it each time you recurse.
The first thing your function should do is check that the depth has not crossed a limit that you think would be unlikely to happen except in the case of an infinite recursion trap.
Then you throw an exception or at least stop the tailspin before the stack overflows.
EDIT: The other responders are correct, however, that your algorithm is flawed and a correct solution to this problem would require no such failsafe.
You can't just evenly divide the numbers and rely on only the lowest to split.. Actually it could be that one of the larger elements need to switch with several of the smaller numbers in solutions. You need to be able to iterate over all the possible permutations!
So every element can either be in the first bucket or the second so you could have a number representing if one element is in either bucket 0 or bucket 1. An integer has 32 bits, but we need to reserve two bits. Thus this will work for an array with 0-30 elements:
/** Find how to split an array of integers
into two even groups.
#param lst array of elements to be split
#return the bitmask or -1 if no solution exist
**/
public static int findSplit( int[] lst )
{
int lstLen = lst.length;
int maxMask = 1 << lstLen;
for(int mask=0; mask < maxMask; mask++) {
int[] c = {0,0};
for(int i=0, curMask=mask; i < lstLen; i++, curMask>>=1 ) {
c[curMask&1]+= lst[i];
}
if( c[0] == c[1] )
return mask;
}
return -1;
}
This will not solve you problem since you are required to use recursion, but both for loops can easily be replaced with one helper function.
public attemptSplit(using 1stArray and 2ndArray)
if (1st array and 2nd array aren't equal)
get the smallest value from the array with larger sum,
and move it to the other array
else
attempSplit(using the two new arrays) //<-this is where the recursive part comes in
OK, that's more information, but it's still somewhat confusing. The way this is written, if the 1st array and 2nd array are equal (I assume you mean the sums), which is the "else" part of your pseudo-code, I think this is when you want to return true since you've found a solution--you wouldn't want to recurse again.
Maybe you meant something like this?
if (1st array and 2nd array aren't equal)
get the smallest value from the array with larger sum,
and move it to the other array
attempSplit(using the two new arrays)
else
return true
There's an obvious problem here, that there's nothing in your algorithm that ever returns false. But the less obvious problem is that this approach just won't work, if I understand what you're trying to do; it could recurse infinitely even when the result should be true. Try with {1, 3, 6, 7, 10, 11}; it looks like your approach is to pull out the largest number into your first set:
{1, 3, 6, 7, 10} {11}
Then if the two sets have different sums, determine which set has the larger sum, and move the smallest number from that set to the other. This will give
{3, 6, 7, 10} {11, 1}
{6, 7, 10} {11, 1, 3}
{7, 10} {11, 1, 3, 6} -- now the right-hand set has a larger sum
{1, 7, 10} {11, 3, 6}
{1, 3, 7, 10} {11, 6} -- now the left-hand set is larger
{3, 7, 10} {11, 1, 6}
{7, 10} {11, 1, 3, 6}
and you're in an infinite loop now. You never get 11 and 7 together in the same set, which you need to do to solve the problem. Perhaps I don't understand exactly what you're trying to do, and maybe you left some steps out; but I think your approach is faulty.
Here's an outline of how I'd approach it: I'm assuming all the array elements are positive integers. First of all, if the sum of the entire array is N, and you can split it into two parts with equals sums, each part will add to N/2. If N is odd, just give up. Otherwise, try to find a subset whose sum is N/2. You can do this with recursion by writing a recursive routine findSubset(S,M) which finds a subset of S whose sum is M. To do this: Assume S1, S2, S3, ... are the elements of S in order. If one of the elements equals M, then you've found a one-element subset. If M<=0 or all the elements of S are larger than M, or if S is empty, then fail. Else: try findSubset({S2,S3, ...}, M-S1); if that doesn't work, findSubset({S3,S4,...}, M-S2); if that doesn't work, findSubset({S4,S5,...},M-S3), and so on.
Example:
Input: 3, 6, 3
Output: True (since 3 + 3 = 6)
Input: 3, 2, 6, 4
Output: False (since no combination will result in equality)
Input: 4, 7, 3, 6
Output: True (since 4 + 6 = 7 + 3)
can you guys give me an idea on how to code this?
i've started on how to code this but i'm confused on how I can add the numbers and compair them
I'll explain how a person could work on this without knowing magic words (like "partition problem", "dynamic programming", etc.) with which to consult some big book of answers (like Wikipedia).
If you take one instance of the largest not-yet-used number from the input and assign it to one of your two groups, then you have reduced the problem to a smaller instance of (a generalized version of) the same problem.
The generalized problem is, can you divide the input numbers into two groups such that the difference between the two groups' sums is a particular non-negative integer?
Let's say our input numbers are 4, 3, 2, 1 and we need to make two groups so that the difference between the groups' sums is 0.
We assign 4 to one of the groups, and in this particular case it doesn't matter which group.
Now our remaining input numbers are 3, 2, 1 and, ignoring the 4 that we already dealt with, we need to make these three numbers into two groups so that the difference between the groups' sums is 4. (That will balance out the difference between the two groups that we created by assigning the 4 to one of the groups.) As promised, this is a smaller instance of the original type of problem.
The difficulty is that sometimes, such as with 5, 5, 4, 3, 3 (example found in Wikipedia "Partition problem"), it's not obvious which group the next number needs to go into. If you keep track of what you've done, then when you find out your latest attempt didn't work, you can come back ("backtrack") and try the other way.
5, 5, 4, 3, 3 {} {}
5, 4, 3, 3 {5} {}
4, 3, 3 {5} {5}
3, 3 {5, 4} {5}
3 {5, 4} {5, 3}
{5, 4} {5, 3, 3} NO - backtrack
{5, 4, 3} {5, 3} NO - backtrack
3 {5, 4, 3} {5}
{5, 4, 3} {5, 3} NO - already tried - backtrack
{5, 4, 3, 3} {3} NO - backtrack
3, 3 {5} {5, 4} NO - symmetric to what we already tried - backtrack
4, 3, 3 {5, 5} {}
3, 3 {5, 5} {4}
3 {5, 5} {4, 3}
{5, 5} {4, 3, 3} YES
Will we be able to get the answer quickly? Well, this isn't the question that was asked, but in light of the complexity of backtracking, it's natural to ask. And the answer turns out to be, no, not even if we have the smartest person in the history of the world working for us. No one has ever found a method that is guaranteed to perform quickly no matter what instance of this kind of problem we give it. Maybe we can do pretty well for many instances of these problems, but in general and on average, a program to do this sort of thing is destined to be slow.
This is the partition problem, which is NP-complete. Despite that, there's a dynamic programming solution that you can use. See the Wikipedia article.
http://en.wikipedia.org/wiki/Partition_problem
public class Weirdie {
private boolean calculate(int[] array) {
boolean match = false;
List<Integer> list = new ArrayList<Integer>();
int length = array.length;
for(int i=0;i<length;i++) {
for(int j=i+1;j<length;j++) {
int sum = array[i] + array[j];
if(list.contains(sum)) {
match = true;
break;
} else {
list.add(sum);
}
}
if(match) {
break;
}
}
return match;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] array = { 3, 6, 3, 4, 8};
int[] array2 = { 3, 2, 6, 4};
int[] array3 = { 4, 7, 3, 6 };
Weirdie w = new Weirdie();
System.out.println(w.calculate(array));
System.out.println(w.calculate(array2));
System.out.println(w.calculate(array3));
}
}
Actually I still confusing with your requirement.As your description,number group 1 {3,6,3} will output true because of 3+3=6.And you said number group 2 {3,2,6,4} will output false,but appearently 2+4=6 is also match your condition.With your third number group,I think the reason why number group 1 output true is 3+6=6+3.
To determine is a array can be divided into two equal summed arrays, we can also find a subset which has half the sum of the whole array.
For e.g: Input: 4, 7, 3, 6
We should find a sub set whose sum == 10, which is a simple DP prob.
public static boolean isSubset(int[] a, int sum, int n) {
if(sum == 0)
return true;
if(n<0)
return false;
return isSubset(a, sum-a[n], n-1) || isSubset(a, sum, n-1);
}
OK! just use brute force calculation, my checking every possible option
int[] numbersArray = new int[10];
int sum = 0;
for(int j = 0; j < numbersArray.lenght;j++) // sum
sum += numbersArray[j];
for(int i = 0; i < numbersArray.lenght;i++)
{
int numChecking = numbersArray[i]; // right half ..
if((sum-numChecking) == numChecking)
return true;
}
return false;
// i haven't tested it but, this will check all possibility's for 1 value..