简体   繁体   中英

Calculating all possible combinations of set numbers that have to result in another number

I'm not really sure if you understand the problem by reading the title, as I have no clue on how to well, explain it in the title.

I have to code the following: there is a method which has three parameters - the first number represents a distance, the second and third one represent jump lengths. The jump lengths have to be summed up in all possible combinations to eventually equal the distance, and then the amount of combinations has to be printed out.

As an example: 7, 3, 4. Distance = 7, jump length 1 = 3, jump length 2 = 4. There are two possible combinations to reach the 7 here: 3 + 4, and 4 + 3 => output = 2.

Or 8, 2, 4: distance = 8, jump length 1 = 2, jump length 2 = 4. Five possible combinations here: 4 + 4, 2+2+4, 2+4+2, 4+2+2, 2+2+2+2 => output = 5.

I have been trying to figure it out for the whole night basically, but I'm not really progressing. Anyone willing to help me out a bit? I'm just in the 1. semester and I'm almost completely clueless

The top level algorithm you will have to follow is:

  • Maintain one tree per input
  • Keep adding one of the inputs till you reach the distance
  • Add a node as a child node only if the distance matched (ie, sum = distance). This requires recursive looping.

However, when you implement it in code, it may look very different. Something like this:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Main{
    private int distance;
    private int a;
    private int b;
    
    public Main( int distance, int a, int b ){
        this.distance = distance;
        this.a = a;
        this.b = b;
    }
    
    /* Represents a node in the tree. Maintains the sum till now in the path, and the value for the current node. */
    private static class Node{
        int sumTillNow;
        int val;
        List<Node> children = new ArrayList<>();
        
        Node( int sumTillNow, int val ){
            super();
            this.sumTillNow = sumTillNow;
            this.val = val;
        }
        
        @Override
        public String toString(){
            String s = String.valueOf( this.val );
            if( !this.children.isEmpty() ) s = s + "," + this.children;
            return s;
        }
        
        /* This is the most difficult part - traversal in a way that each path is retrieved individually. */
        public List<List<Integer>> traverse( int distance, List<Integer> list ) {
            list.add( this.val );
            
            if( this.children.isEmpty() ) return Arrays.asList( list );
            if( this.children.size() == 1 ) return this.children.get( 0 ).traverse( distance, list );
            
            List<List<Integer>> listForReturning = new ArrayList<>();
            if( this.children.size() > 1 ) for( Node ch : this.children ) {
                List<Integer> copy = new ArrayList<>( list );
                List<List<Integer>> chList = ch.traverse( distance, copy );
                if( chList != null ) listForReturning.addAll( chList );
            }
            
            return listForReturning;
        }
    }
    
    public static void main( String[] args ) {
        List<List<Integer>> allCombs = new Main( 10, 4, 2 ).comp();
        for( List<Integer> comb : allCombs ) System.out.println( comb );
    }
    
    private List<List<Integer>> comp(){
        Node aNode = new Node( a, a );
        Node bNode = new Node( b, b );
        
        /* Handle the special cases of input here. */
        if( a > distance && b > distance ) return null;
        if( a == 0 && b == 0 ) return null;
        if( a == distance ) {
            aNode.sumTillNow = distance;
            aNode.val = a;
        }
        if( b == distance ) {
            aNode.sumTillNow = distance;
            aNode.val = b;
        }
        
        /* Run the computation once starting with the first input and then with the next input. */
        if( aNode.sumTillNow < distance ) loop( aNode );
        if( bNode.sumTillNow < distance ) loop( bNode );
        
        return traverse( aNode, bNode );
    }

    private boolean loop( Node node ){
        if( node.sumTillNow < distance ) {
            addIfRemaining( node, a );
            addIfRemaining( node, b );
            
            return true;
        }
        else if( node.sumTillNow == distance ) return true;
        else return false;
    }

    private void addIfRemaining( Node node, int addition ){
        if( node.sumTillNow + addition <= distance ) {
            Node n = new Node( node.sumTillNow + addition, addition );
            if( n.sumTillNow <= distance ) {
                boolean good = loop( n );
                if( good ) node.children.add( n );
            }
        }
    }

    private List<List<Integer>> traverse( Node aNode, Node bNode ){
        List<List<Integer>> allPaths = new ArrayList<>();
        allPaths.addAll( aNode.traverse( this.distance, new ArrayList<>() ) );
        allPaths.addAll( bNode.traverse( this.distance, new ArrayList<>() ) );
        
        return allPaths;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM