The puzzle is to obtain the minimum number of steps it takes to make a number 1. Allowed operations are
1. You can subtract 1 from the number
2. You can divide the number by 2 if it is divisible by 2.
3. You can divide the number by 3 if it is divisible by 3.
At the end, you need to make the number 1 by performing the above operations. I am trying to obtain a solution that gives me the minimum number of the above operations required to make the number 1.
My code (in Java) is as follows.
public int minStepsBottomUp(int n) {
int[] memoArray = new int[n+1];
memoArray[0] = 0;
memoArray[1] = 0;
for(int i=2;i<=n;++i){
int r = 1 + memoArray[i-1];
if(n % 2 == 0) {
r = Math.min(r, 1+memoArray[n/2]);
}
if(n % 3 == 0) {
r = Math.min(r, 1+memoArray[n/3]);
}
memoArray[i] = r;
}
return memoArray[n];
}
But I get some ambiguous results.Example - if the number is 5, I get the minimun number of steps required as 4. Actually it should be 3. Can someone please explain where I have gone wrong?
I suggest reversing the problem: starting from 1 we should reach n by using three kinds of operations:
add 1
multiply by 2
multiply by 3
For instance for 5 we'll have 3 operations (multiply by 3, add 1, add 1):
1 -> 3 -> 4 -> 5
So far so good, now we have standard dynamic programming problem; C# implementation:
private static int Best(int value) {
if (value <= 0)
return -1; // or throw ArgumentOutOfRangeException
else if (value == 1)
return 0;
Dictionary<int, int> best = new Dictionary<int, int>() { {1, 0} };
List<int> agenda = new List<int>() { 1 };
for (int step = 1; ; ++step)
for (int i = agenda.Count - 1; i >= 0; --i) {
int item = agenda[i];
agenda.RemoveAt(i);
int[] next = new int[] { item + 1, item * 2, item * 3 };
foreach (int v in next) {
if (v == value)
return step;
if (!best.ContainsKey(v)) {
best.Add(v, step);
agenda.Add(v);
}
}
}
}
Tests:
// 3
Console.WriteLine(Best(5));
// 3
Console.WriteLine(Best(10));
// 7
Console.WriteLine(Best(100));
// 19
Console.WriteLine(Best(1000000));
Inside your loop, you are using n instead of i.
For instance, n % 2 == 0 should be i % 2 == 0
If the number is 5 you can get 1 by doing:
int x = 5 - 1;
x = x - 1;
x= x / 3;
Related
This is the question:
You are given Q queries. Each query consists of a single number N . You can perform any of the operations on in each move:
If we take 2 integers a and b where N=a*b (a ,b cannot be equal to 1), then we can change N=max(a,b)
Decrease the value of N by 1 .
Determine the minimum number of moves required to reduce the value of to .
Input Format
The first line contains the integer Q.
The next Q lines each contain an integer,N .
Output Format
Output Q lines. Each line containing the minimum number of moves required > to reduce the value of N to 0.
I have written the following code. This code is giving some wrong answers and also giving time limit exceed error . Can you tell what are the the mistakes present in my code ? where or what I am doing wrong here?
My code:
public static int downToZero(int n) {
// Write your code here
int count1=0;
int prev_i=0;
int prev_j=0;
int next1=0;
int next2=Integer.MAX_VALUE;
if (n==0){
return 0;
}
while(n!=0){
if(n==1){
count1++;
break;
}
next1=n-1;
outerloop:
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i*j==n){
if (prev_i ==j && prev_j==i){
break outerloop;
}
if (i !=j){
prev_i=i;
prev_j=j;
}
int max=Math.max(i,j);
if (max<next2){
next2=max;
}
}
}
}
n=Math.min(next1,next2);
count1++;
}
return count1;
}
This is part is coded for us:
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
int q = Integer.parseInt(bufferedReader.readLine().trim());
for (int qItr = 0; qItr < q; qItr++) {
int n = Integer.parseInt(bufferedReader.readLine().trim());
int result = Result.downToZero(n);
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
}
}
Ex: it is not working for number 7176 ....
To explore all solution tree and find globally optimal solution, we must choose the best result both from all possible divisor pairs and from solution(n-1)
My weird translation to Java (ideone) uses bottom-up dynamic programming to make execution faster.
We calculate solutions for values i from 1 to n, they are written into table[i].
At first we set result into 1 + best result for previous value (table[i-1]).
Then we factor N into all pairs of divisors and check whether using already calculated result for larger divisor table[d] gives better result.
Finally we write result into the table.
Note that we can calculate table once and use it for all Q queries.
class Ideone
{
public static int makezeroDP(int n){
int[] table = new int[n+1];
table[1] = 1; table[2] = 2; table[3] = 3;
int res;
for (int i = 4; i <= n; i++) {
res = 1 + table[i-1];
int a = 2;
while (a * a <= i) {
if (i % a == 0)
res = Math.min(res, 1 + table[i / a]);
a += 1;
}
table[i] = res;
}
return table[n];
}
public static void main (String[] args) throws java.lang.Exception
{
int n = 145;//999999;
System.out.println(makezeroDP(n));
}
}
Old part
Simple implementation (sorry, in Python) gives answer 7 for 7176
def makezero(n):
if n <= 3:
return n
result = 1 + makezero(n - 1)
t = 2
while t * t <= n:
if n % t == 0:
result = min(result, 1 + makezero(n // t))
t += 1
return result
In Python it's needed to set recursion limit or change algorithm. Now use memoization, as I wrote in comments).
t = [-i for i in range(1000001)]
def makezeroMemo(n):
if t[n] > 0:
return t[n]
if t[n-1] < 0:
res = 1 + makezeroMemo(n-1)
else:
res = 1 + t[n-1]
a = 2
while a * a <= n:
if n % a == 0:
res = min(res, 1 + makezeroMemo(n // a))
a += 1
t[n] = res
return res
Bottom-up table dynamic programming. No recursion.
def makezeroDP(n):
table = [0,1,2,3] + [0]*(n-3)
for i in range(4, n+1):
res = 1 + table[i-1]
a = 2
while a * a <= i:
if i % a == 0:
res = min(res, 1 + table[i // a])
a += 1
table[i] = res
return table[n]
We can construct the directed acyclic graph quickly with a sieve and
then compute shortest paths. No trial division needed.
Time and space usage is Θ(N log N).
n_max = 1000000
successors = [[n - 1] for n in range(n_max + 1)]
for a in range(2, n_max + 1):
for b in range(a, n_max // a + 1):
successors[a * b].append(b)
table = [0]
for n in range(1, n_max + 1):
table.append(min(table[s] for s in successors[n]) + 1)
print(table[7176])
Results:
7
EDIT:
The algorithm uses Greedy approach and doesn't return optimal results, it just simplifies OP's approach. For 7176 given as example, below algorithm returns 10, I can see a shorter chain of 7176 -> 104 -> 52 -> 13 -> 12 -> 4 -> 2 -> 1 -> 0 with 8 steps, and expected answer is 7.
Let's review your problem in simple terms.
If we take 2 integers a and b where N=a*b (a ,b cannot be equal to 1), then we can change N=max(a,b)
and
Determine the minimum number of moves required to reduce the value of to .
You're looking for 2 factors of N, a and b and, if you want the minimum number of moves, this means that your maximum at each step should be minimum. We know for a fact that this minimum is reached when factors are closest to N. Let me give you an example:
36 = 1 * 36 = 2 * 18 = 3 * 12 = 4 * 9 = 6 * 6
We know that sqrt(36) = 6 and you can see that the minimum of 2 factors you can get at this step is max(6, 6) = 6. Sure, 36 is 6 squared, let me take a number without special properties, 96, with its square root rounded down to nearest integer 9.
96 = 2 * 48 = 3 * 32 = 4 * 24 = 6 * 16 = 8 * 12
You can see that your minimum value for max(a, b) is max(8, 12) = 12, which is, again, attained when factors are closest to square root.
Now let's look at the code:
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i*j==n){
You can do this in one loop, knowing that n / i returns an integer, therefore you need to check if i * (n / i) == n. With the previous observation, we need to start at the square root, and go down, until we get to 1. If we got i and n / i as factors, we know that this pair is also the minimum you can get at this step. If no factors are found and you reach 1, which obviously is a factor of n, you have a prime number and you need to use the second instruction:
Decrease the value of N by 1 .
Note that if you go from sqrt(n) down to 1, looking for factors, if you find one, max(i, n / i) will be n / i.
Additionally, if n = 1, you take 1 step. If n = 2, you take 2 steps (2 -> 1). If n = 3, you take 3 steps (3 -> 2 -> 1). Therefore if n is 1, 2 or 3, you take n steps to go to 0. OK, less talking, more coding:
static int downToZero(int n) {
if (n == 1 || n == 2 || n == 3) return n;
int sqrt = (int) Math.sqrt(n);
for (int i = sqrt; i > 1; i--) {
if (n / i * i == n) {
return 1 + downToZero(n / i);
}
}
return 1 + downToZero(n - 1);
}
Notice that I'm stopping when i equals 2, I know that if I reach 1, it's a prime number and I need to go a step forward and look at n - 1.
However, I have tried to see the steps your algorithm and mine takes, so I've added a print statement each time n changes, and we both have the same succession: 7176, 92, 23, 22, 11, 10, 5, 4, 2, 1, which returns 10. Isn't that correct?
So, I found a solution which is working for all the test cases -
static final int LIMIT = 1_000_000;
static int[] solutions = buildSolutions();
public static int downToZero(int n) {
// Write your code here
return solutions[n];
}
static int[] buildSolutions() {
int[] solutions = new int[LIMIT + 1];
for (int i = 1; i < solutions.length; i++) {
solutions[i] = solutions[i - 1] + 1;
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
solutions[i] = Math.min(solutions[i], solutions[i / j] + 1);
}
}
}
return solutions;
}
}
There's a question I saw and I'm wondering if it's possible to solve it using recursion. It goes as follow:
Write an algorithm that, when given an array of input, finds the maximum product from those inputs. For example:
Input: [1, 2, 3]
Output: 6 (1*2*3)
Input: [-1, 1, 2, 3]
Output: 6 (1*2*3)
Input: [-2, -1, 1, 2, 3]
Output: 12 (-2*-1*1*2*3)
I'm trying to find a way of using recursion to solve it, but the algorithm I tried doesn't work. My algorithm, written in Java is as follow
Integer[] array;
public int maximumProduct(int[] nums) {
array=new Integer[nums.length];
return multiply(nums, 0);
}
public int multiply(int[] nums, int i){
if (array[i]!=null){
return array[i];
}
if (i==(nums.length-1)){
return nums[i];
}
int returnval=Math.max(nums[i]*multiply(nums, i+1), multiply(nums, i+1));
array[i]=returnval;
return returnval;
}
The problem with this algorithm is that it doesn't work well if there's an even number of negative numbers. For example, if nums[0]=-2, nums[1]=-1 and nums[2]=1, then multiply(nums, 1) will always return 1 instead of -1, and thus it will always see 1 as bigger than 1*-2 at multiply(nums, 0). I'm not sure how to solve this problem, however. Is there any way of solving this using recursion or dynamic programming?
If there is only one non-zero element in the array, and it happens to be a negative number, then then answer is either 0, if there is a 0 present in the input, or if the array contains only that single negative element, the answer is that element itself.
In all other cases, the final answer is going to be positive.
We first make a linear scan to find the number of negative integers. If this number is even, then the answer is the product of all the non-zero elements. If there are an odd number of negative elements, we need to leave out one negative element from the answer, so that the answer is positive. As we want the maximum possible answer, the number we want to leave out should have as small an absolute value as possible. So among all the negative numbers, find the one with the minimum absolute value, and find the product of the remaining non-zero elements, which should be the answer.
All this requires only two linear scans of the array, and hence runs in O(n) time.
What is the maximum product of integers?
To obtain the maximum sum, you will want to multiply all the positive integers with the product of the largest negative integers, with the number of negative integers included in the product being even to obtain a positive final result.
In an algorithm for a single traversal
I am going to treat the positive integers and the negative integers in the input separately. You will want to keep a running product of positive integers, a running product of negative integers and the largest negative integer (ie. the negative integer with the smallest absolute value) found so far.
Let us ignore the edge cases where the final answer is <= 0. That can be handled easily.
//Initialization
int [] nums // Input
int posProduct = 1;
int negProduct = 1;
int smallestNeg = 1;
//Input Traversal
for (int i : nums) {
if ( i == 0 ) {
// ignore
} else if ( i < 0 ) {
if (smallestNeg == 1) {
smallestNeg = i;
} else if ( i > smallestNeg ) {
negProduct *= smallestNeg; //Integrate the old smallest into the running product
smallestNeg = i; // i is the new smallest
} else {
negProduct *= i;
}
} else {
// i is strictly positive
posProduct *= i;
}
}
//Result Computation
int result = posProduct;
if ( negProduct < 0 ) {
// The running product of negative number numbers is negative
// We use the smallestNeg to turn it back up to a positive product
result *= smallestNeg;
result *= negProduct;
} else {
result *= negProduct
}
edit: In a recursive traversal
I personally find that writing the array traversal in a recursive manner to be clumsy but it can be done.
For the beauty of the exercise and to actually answer the question of the OP, here is how I would do it.
public class RecursiveSolver {
public static int findMaxProduct (int [] nums) {
return recursiveArrayTraversal(1, 1, 1, nums, 0);
}
private static int recursiveArrayTraversal(int posProduct, int negProduct,
int smallestNeg, int [] nums, int index) {
if (index == nums.length) {
// End of the recursion, we traversed the whole array
posProduct *= negProduct;
if (posProduct < 0) {
posProduct *= smallestNeg;
}
return posProduct;
}
// Processing the "index" element of the array
int i = nums[index];
if ( i == 0 ) {
// ignore
} else if ( i < 0 ) {
if (smallestNeg == 1) {
smallestNeg = i;
} else if ( i > smallestNeg ) {
negProduct *= smallestNeg;
smallestNeg = i;
} else {
negProduct *= i;
}
} else {
// i is strictly positive
posProduct *= i;
}
//Recursive call here!
//Notice the index+1 for the index parameter which carries the progress
//in the array traversal
return recursiveArrayTraversal(posProduct, negProduct,
smallestNeg, nums, index+1);
}
}
First, break the array in subproblems always you find a 0 in the list:
1 -2 4 -1 8 0 4 1 0 -3 -4 0 1 3 -5
|_____________| |____| |____| |_______|
p1 p2 p3 p4
Then, for each problem pi, count how many negative numbers are there.
If pi has an even number of negatives (or no negatives at all), the answer of pi is the product of all its elements.
If pi has only 1 negative number (say n), the answer will be the maximum between the product of all the elements in n's right and the product of all elements in n's left.
If pi has an odd number (bigger than only 1) of negative numbers, call the index of the leftmost negative number l and the index of the rightmost negative number r. Supposing pi has n elements, the answer will be:
max(
pi[ 0 ] * pi[ 1 ] * ... * pi[r - 1],
pi[l + 1] * pi[l + 2] * ... * pi[ n ]
)
Knowing that, it's easy to write a recursion for each step of the solution of this problem: a recursion to divide problems at zeros, another to count negatives and another to find answers, in O(n).
Linear version
List<Integer> vals = new ArrayList<>(List.of(5,1,-2,1,2,3,-4,-1));
int prod = 0;
int min = 1;
for (int v : vals) {
if (v == 0) {
// ignore zero values
continue;
}
if (prod == 0) {
prod = 1;
}
prod *= v;
// compute min to be the largest negative value in the list.
if (v < 0 && min < Math.abs(v)) {
min = v;
}
}
if (prod < 0) {
prod /= min;
}
System.out.println("Maximum product = " + prod);
}
Recursive version
int prod = prod(vals, new int[] {0} , vals.size());
System.out.println("Maximum product = " + prod);
public static int prod(List<Integer> vals, int[]min, int size) {
int prod = 0;
if(vals.size() > 0) {
int t = vals.get(0);
if (t < 0 && min[0] < Math.abs(t)) {
min[0] = t;
}
prod = prod(vals.subList(1,vals.size()), min, vals.size());
}
if (vals.isEmpty() || vals.get(0) == 0) {
return prod;
}
if (prod == 0) {
prod = 1;
}
prod *= t;
if (vals.size() == size && prod < 0) {
prod/=min[0];
}
return prod;
}
This is my solution - leaving it open for optimization and to figure out the runtime. This is a general purpose solution that finds the products of all the combinations of integers in a list. Of course, there is a O(n) solution but I present this solution as well.
import java.util.ArrayList;
import java.util.List;
public class MaxProd {
int[] input = {1, 2, 3};
// int[] input = {-2, -1, 1, 2, 3};
public static void main(String[] args) {
MaxProd m = new MaxProd();
List<Integer> ll = m.max(0);
for (int i : ll) {
System.out.println(i);
}
ll.sort((x,y) -> Integer.compare(x, y));
System.out.println("The max: " + ll.get(ll.size() -1 ));
}
private List<Integer> max(int index) {
if (index < input.length){
List<Integer> l = new ArrayList<>();
List<Integer> retList = max(index + 1);
for (int j : retList){
l.add(input[index] * j);
}
l.add(input[index]);
l.addAll(retList);
return l;
}
else return new ArrayList<>();
}
}
it prints:
6
2
3
1
6
2
3
The max: 6
If the requirements are constrained (as in this case) then one can get by without the need for generating all combinations resulting in a linear solution. Also, I'm sorting at the end. Note: you could easily get the result with a single pass on the returned list to find the maximum product as specified in other answers.
How to write a recursive method in Java which prints the combinations of 3 different numbers with variable count of the numbers used? (No repetitions should be included.) That is, the method should work for different combination lengths. For example, with the numbers 0, 1, 2 and two numbers used in the combinations you should have: 0 0 - 0 1 - 0 2 - 1 1 - 1 2 - 2 2.
With the same numbers, combinations of 3 numbers are:
0 0 0 - 0 0 1 - 0 0 2 - 0 1 1 - 0 1 2 - (...),
and so on.
I have checked several types of recursion methods in other similar topics, but I still cannot thoroughly understand this and write my own method.
Maybe try calculating all permutations first. Then move on to calculating combinations. The images on the wiki are very enlightening https://en.wikipedia.org/wiki/Combination
You could try pen and paper through this code as well: Combinations method return issue!
I have come up with a non-recursive solution based on counting the numbers of an n-based numeral system. E.g., for system with base 3, numbers are added which are powers of 3.
It should be noted that this prints all combinations, and the ones with repetitive elements should be later removed, as is needed in my case. For example, from the combinations 001, 010, 100, only the first one should be left, where the elements are in ascending order.
public static void main(String[] args) {
int t = 2;
int r = 2;
ArrayList<Integer> l = new ArrayList<Integer>();
int tmp;
for (int p = 0; p <= (int)(Math.pow((double)t, (double)r)) - 1; p++) {
tmp = p;
for (int q = r - 1; q >= 0; q--) {
for (int s = t - 1; s >= 0; s--) {
if (tmp >= s * (int) (Math.pow(t, q))) {
l.add(Integer.valueOf(s));
tmp = tmp - s * (int) (Math.pow(t, q));
break;
}
}
}
}
for (int i = 0; i <= l.size() - 1; i++) {
if (i % r != r - 1) {
System.out.print(l.get(i) + "-");
} else {
System.out.println(l.get(i));
}
}
}
Dear friends I have an assignment and I almost solved it. But I'm having a big problem recently which I couldn't figure a way out for 2 days. If you could help me I would very appreciate it!
So, let's say user entered 5 (N) I immediately create this sequence to get subsets out of it: {1,2,3,4,5}
If N = 4 than the sequence is like: {1, 2, 3, 4} etc.
Than this code below generates all kind of the variations of subsets:
public static int[] genarator(int N)
{
int[] generator = new int[(int) Math.pow(2, N)];
int[] binDigit = new int[(int) Math.pow(2, N)];
for (int i = 0; i < Math.pow(2, N); i++)
generator[i] = (i >> 1) ^ i; // Right Shifting
for (int i = 0; i < Math.pow(2, N); i++)
{
int one = 1;
binDigit[i] = 0;
while (generator[i] > 0)
{
binDigit[i] += (generator[i] % 2) * one;
generator[i] /= 2;
one = one * 10;
}
}
return binDigit;
}
And the way it returns the results like this (In case of: N = 4 {1, 2, 3, 4}) shown here :
1
1 2
2
2 3
1 2 3
1 3
3
3 4
1 3 4
1 2 3 4
2 3 4
2 4
1 2 4
1 4
4
But my lecturer wants from my program to return the result in this order:
1
2
3
4
1 2
1 3
1 4
2 3
2 4
3 4
1 2 3
1 2 4
1 3 4
2 3 4
1 2 3 4
I for now use TreeSet<Long> and parseLong so I can get true results till 1 <= N <= 9. But whenever user enters 10 or higher as N it goes crazy.
To recap, my question is how can I store those numbers which I get from int[] genarator(int N) and display them like my lecturer requires ?
How generator works and how do I get numbers in wrong order? Code is below:
int N = read.nextInt();
int[] sequence = new int[N];
for (int i = 0; i < N; i++)
sequence[i] = i + 1;
int[] tempArray = new int[(int) Math.pow(2, N)];
tempArray = genarator(N);
for (int i = 1; i < Math.pow(2, N); i++)
{
for (int j = 0; j < N; j++)
{
if (tempArray[i] % 10 == 1)
{
System.out.print(sequence[j] + " ");
}
tempArray[i] /= 10;
}
System.out.println();
}
Thank you for checking and I am really sorry for this too long question. But I couldn't make it clear with a short explanation.
What you can do is create a set abstraction that can be compared to other sets. See Java tutorials on Comparators.
//don't call this Set as there is already a Java Set
//interface that youdon't want to confuse yourself with
public class MySet implements Comparable<MySet>{
int[] backingArray;
public MySet(int n) {
//initialize the Set
this.backingArray = generator(n);
}
public static Int[] generator(int n) {
//..whatever you do to generate your results
}
#Override
public int compareTo(MySet otherSet) {
//define how sets are compared (e.g what your professor is asking.
//In your example, if one set is shorter than another,
//it is considered 'smaller')
}
}
Set<MySet> allSets = ....;
and simply invoke Collections.sort(allSets);
An algorithm which for any input positive integer, gives all possible distinct arrays of positive non-zero integers that can sum to it.
e.g Inputting 4 returns (1,1,1,1), (1,1,2), (1,2,1), (2,1,1), (1,3), (3,1), (2,2), (4)
Not homework, but "research". I just get lost trying.
Someone good at combinatorics would probably know this one.
Here is some idea.
If I'm not mistaken the number of the arrays is 2N-1 and the arrays map to bit patterns codding integers form 0 to 2N-1-1 as follows:
I'll show an example for N = 4
The first array is all ones. Imagine every bit in the bit pattern corresponds to the boundary between two array cells
1 1 1 1 <- array elements
| | | <- sections
0 0 0 <- bit pattern
Every 1 in the bit pattern means merging two neighbouring cells
1 (1+1) 1 <- array elements (1 2 1)
| | | <- sections
0 1 0 <- bit pattern
1 (1+1+1) <- array elements (1 3)
| | | <- sections
0 1 1 <- bit pattern
(1+1) (1+1)<- array elements (2 2)
| | | <- sections
1 0 1 <- bit pattern
(1+1+1+1) <- array elements (4)
| | | <- sections
1 1 1 <- bit pattern
To enumerate all arrays you can generate integers from 0 to 2N-1-1 and for every bit pattern you get, generate the corresponding array. It might be helpful to convert the integer to the string of zeros and ones of length N-1. You decode the pattern as follows:
First cell contains 1 initially. Going through the pattern from left to right, for every bit, if it's 1 add 1 to the current cell, if it's 0 create new cell containing 1.
The pattern 1 1 0 0 1 0 1 for N = 8 would be decoded to an array
(3 1 2 2)
Here is some C++ code without argument validation and processing the pattern from right to left. It just changes the order of arrays produced and is simpler to code.
std::vector<std::vector<int> > generateArrays(unsigned int N)
{
//validate the argument before processing
// N > 0 and N <= numeric_limits<unsigned int>::digits
unsigned int numOfArrays = (1U << (N-1));
std::vector<std::vector<int> > result(numOfArrays);
for(unsigned int i = 0; i < numOfArrays; ++i)
{
result[i].push_back(1);
unsigned int mask = 1U;
while(mask < numOfArrays)
{
if((i & mask) != 0)
{
result[i].back()++;
}
else
{
result[i].push_back(1);
}
mask <<= 1;
}
}
return result;
}
Recurse! The first entry (call it a[0]) could be any integer from 1 to N. Then you just need to find all the distinct arrays of positive nonzero integers that add up to N - a[0]...
Recursive approach
# Pseudo code, not any real language
function all_arrays_summing_to(int N) {
array_of_arrays All_solutions = ();
if (N == 1) return { [[1]] }; # This is array of one array containing 1 element with value 1
for each number x in (1 .. N-1) {
array_of_arrays AA = all_arrays_summing_to(N - x);
for each array A in (AA) {
push x onto array A;
Add A to All_solutions;
}
}
return All_solutions;
}
Maybe this isn't the most elegant solution since I'm using "Distinct" to filter out duplicate results but here is one way in C#.
The general idea is that you split the number into an array of 1's then you just combine each node side-by-side together like a tree and select distinct combinations. I pictured it like this:
[1,1,1]
/ \
[2,1] [1,2]
\ /
[3]
class Program
{
static void Main(string[] args)
{
Console.Write("Enter an integer value: ");
int num = int.Parse(Console.ReadLine());
var y = new int[num];
for (int x = 0; x < num; x++)
y[x] = 1;
var results = Combine(y, num)
.Distinct(new ArrayComparer())
.OrderByDescending(r => r.Length)
.ToArray();
foreach (var result in results)
{
Console.Write('[');
for (int x = 0; x < result.Length; x++)
{
if (x > 0)
Console.Write(", ");
Console.Write(result[x]);
}
Console.WriteLine(']');
}
Console.ReadKey(true);
}
public class ArrayComparer : IEqualityComparer<int[]>
{
bool IEqualityComparer<int[]>.Equals(int[] x, int[] y)
{
if (x.Length == y.Length)
{
for (int z = 0; z < x.Length; z++)
if (x[z] != y[z])
return false;
return true;
}
return false;
}
int IEqualityComparer<int[]>.GetHashCode(int[] obj)
{
return 0;
}
}
public static IEnumerable<int[]> Combine(int[] values, int num)
{
int val = 0;
for (int x = 0; x < values.Length; x++)
val += values[x];
if (val == num)
{
yield return values;
if (values.Length - 1 > 0)
{
for (int x = 0; x < values.Length; x++)
{
int[] combined = new int[values.Length - 1];
for (int y = 0; y < x; y++)
combined[y] = values[x];
if (values.Length > x + 1)
combined[x] = values[x] + values[x + 1];
for (int y = x + 2; y < values.Length; y++)
combined[y - 1] = values[y];
foreach (var result in Combine(combined, num))
yield return result;
}
}
}
}
}
Outputs:
Enter an integer value: 4
[1, 1, 1, 1]
[2, 1, 1]
[1, 2, 1]
[1, 1, 2]
[3, 1]
[2, 2]
[1, 3]
[4]