BFS for arithmetic operations

后端 未结 3 1925
余生分开走
余生分开走 2021-01-24 08:35

Convert a number m to n with minimum operations. The operations allowed were subtraction by 1 and multiplication by 2.

For Eg : 4 and 6. Answer is 2. 1st operation : -1

3条回答
  •  独厮守ぢ
    2021-01-24 08:48

    BFS is not exactly an option here, due to the exponential growth (2 ^ (n - 1) to 2^n trys are performed, where n is the number of required steps). Instead try to find logic rules for generating the required number.

    Let a be the input-number and b the number that should be produced.

    There are three cases:

    • a == b, this case is trivial and just listed for completeness
    • a > b, the solution is a - b times substracting by -1
    • a < b: This is the more tricky part

    The smallest number of operations requires the minimum number of multiplications and substractions. Substractions can easily be minimized due to the following fact: (a - 1) * 2 = a * 2 - 2. Thus we can easily reduce the number of substractions by any number that is a power of 2 by simply substracting before multiplying.
    Since we can only substract and multiply, the minimum number of multiplications is min n => a * 2 ^ n >= b.
    Using this fact we can determine the amount to substract: s = b - 2 ^ n * a.

    The implementation would look like this in pseudocode (can't provide python code):

    //using the same variable-names as above in the description
    minOp(int a , int b)
        //find minimum number of multiplications
        int n
        for(n = 0 ; a << n < b ; n++)
            noop
    
        //find amount to substract
        int s = (a << n) - b
    
        for(int i = 0 ; i < n ; i++)
            print("(")
    
        print(a)
    
        //calculate operations
        while(n > 0)
            //calculate number of times we need to substract here (minimization of substractions)
            while(s >= 1 << n)
                print(" - 1")
                s -= 1 << n
    
            print(")")
    
            //divide by two
            print(" * 2")
            n -= 1
    
        while(s >= 1 << n)
            print(" - 1")
            s -= 1 << n
    
        print(" = ")
        print(b)
    

    This implementation aswell covers the cases a == b - with n = 0 and s = 0 - and a > b - with n = 0 and s = a - b.

    A test-run in a java-implementation of the above would produce this output:

    (((4) * 2 - 1) * 2 - 1) * 2 = 26

    The simplification of the above calculation shows the idea behind this algorithm:

    ((4 * 2 - 1) * 2 - 1) * 2 = 26
    (4 * 2 * 2 - 2 - 1) * 2 = 26
    4 * 2 * 2 * 2 - 3 * 2 = 26
    32 - 6 = 26
    

    Thanks to @user3386109 for this explanation:
    Assume that the start value is A, and the goal value is B. The first step is to create a list of target values starting at B, and proceeding by dividing by 2 (rounding up if necessary). For example, if B is 26, then the list of target values would be 26, 13, 7, 4, 2, 1. If the start value A is any of those target values, then you can easily climb to the goal B (by multiplying by 2 and subtracting 1 if necessary). If A is not one of those values, then you begin by subtracting 1 from A until you reach one of those target values. For example, if A is 6, then two subtractions are needed to reach 4, and then you climb from 4 to 26. If A is 12, five subtractions are needed to reach 7, and so on. Obviously, if A is larger than B, then all you do is subtract one until you reach B

提交回复
热议问题