Algorithm to reach a number in a fixed amount of steps using addition, division and multiplication only

孤街醉人 提交于 2019-11-30 08:52:53

I would use dynamic programming. First, build a map of which numbers are reachable from each step, then backtrack to find out how you could've gotten there:

void CalculateRoute(int targetNumber, int numSteps)
{
    int maxValue = targetNumber * 16;
    bool[,] reachable = new bool[numSteps + 1, maxValue];

    // build up the map
    reachable[0, 0] = true;
    for (int step = 0; step < numSteps; step++)
    {
        for (int n = 0; n < maxValue; n++)
        {
            if (reachable[step, n])
            {
                foreach (int nextNum in ReachableNumbersFrom(n))
                {
                    if (nextNum < maxValue && nextNum >= 0)
                        reachable[step + 1, nextNum] = true;
                }
            }
        }
    }

    // figure out how we got there
    int current = targetNumber;
    for (int step = numSteps; step >= 0; step--)
    {
        Console.WriteLine(current);

        bool good = false;
        foreach (int prev in ReachableNumbersFromReverse(current))
        {
            if (reachable[step, prev])
            {
                current = prev;
                good = true;
                break;
            }
        }

        if (!good)
        {
            Console.WriteLine("Unable to proceed");
            break;
        }
    }
}

IEnumerable<int> ReachableNumbersFrom(int n)
{
    // additions
    for (int i = 1; i <= 15; i++)
        yield return n + i;

    // mults/divides
    yield return n / 2;
    yield return n / 4;
    yield return n * 2;
    yield return n * 4;
}

IEnumerable<int> ReachableNumbersFromReverse(int n)
{
    // additions
    for (int i = 1; i <= 15; i++)
        yield return n - i;

    // mults/divides
    if (n % 2 == 0)
        yield return n / 2;
    if (n % 4 == 0)
        yield return n / 4;
    yield return n * 2;
    yield return n * 4;
}

work backwards from your desired solution
with your division and multiplication only being by 2's and 4's, it makes it easy to know when you can or can't perform those operations
and then, for the last 4-5 steps you can just make it arbitrarily return to 0

To add to this; you can use random operations in the initial phase, checking that you aren't performing illegal operations, and you should also include a check for range. You don't want to end up with a number like 400 and then have to divide it by 4 a bunch of times as your last operations, to get back to 0.

Argote

You can brute force it with a search tree that is N levels deep where N is the number of steps. This would be O(m^n) where m is the number of operations allowed.

There is probably a better algorithm but this should work for smaller values of N.

For example, use {Breadth, Depth}-First Search or A*.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!