1

You are given an insect moves in a plane starting from the original point (0,0). The insect that can only move toward North-East, South-East, North-West, & South-West. Now the thing is insect can't move more than a specific number of steps at a time in one direction. For example, it can move only 3 steps in NE, 4 steps in SE, 5 steps in NW and 2 steps in SW.

If the insect moves 3 steps in direction NE at a stretch- it has to move NW, SE, or SW- before again going in direction NE.

How can I get the most efficient path to a given point in this situation? I am new to programming and came across this problem. Can anyone tell me a good approach to solve the kind of problems? Thank you.

My thoughts:

First, take a step in NE and SE to walk 2 steps in E. Similarly for N, S, and W. Now, find the shortest path. Basically, turn this problem into a simpler one instead of walking diagonally. (Not a good method. But can find a path.)

The second one is inspired by iterative methods used to find minima of 3-d curves. If I remove the limit on travelling in one direction at a time, we can do it by moving in the direction (one among the four) which takes us to the destination faster. This is similar to the gradient descent method but only four directions to move in.

Python code will be appreciated.

Joe Smith
  • 11
  • 2
  • Note: NE and SW are opposite to each other, similarly, NW and SE are, they will negate each other – Bhosale Shrikant Jan 05 '20 at 06:54
  • Yeah and thus with each back and forth movement , the insect can move one step. Well there's little progress now. – Joe Smith Jan 05 '20 at 07:11
  • @BhosaleShrikant but still I am not able to solve the whole problem. – Joe Smith Jan 05 '20 at 07:19
  • i will write code with: """Assumption say the insect moves in the plane from (-100,-100) to (100, 100) size plane North is Positive y-cord South is Negative y-cord East is Positive x-cord West is Negative x-cord """ – Bhosale Shrikant Jan 05 '20 at 07:29
  • Also, there will be coordinates where insects will never be able to go because it can only move in diagonals for examples inset can from (0,0) to (0,1) or to (1,0) – Bhosale Shrikant Jan 05 '20 at 07:32
  • i am not completely sure if this is a *pure optimization problem*, a *constrained optimization problem* (https://en.wikipedia.org/wiki/Constrained_optimization) or a *constraint-satisfaction problem* (https://en.wikipedia.org/wiki/Constraint_satisfaction_problem) because if you know this you possibly can adapt existing algorithms for movements i.e. on chessboards (Knight's tour, ...) – ralf htp Jan 05 '20 at 07:36
  • I.e. adapting this : https://www.geeksforgeeks.org/minimum-steps-reach-target-knight/ that uses Breadth-First search or see this https://leetcode.com/discuss/interview-question/322837/Google-or-Onsite-interview-or-Knight%27s-Shortest-Path-on-an-Infinite-Chessboard and this https://stackoverflow.com/questions/2339101/knights-shortest-path-on-chessboard/8778592#8778592 – ralf htp Jan 05 '20 at 07:44
  • The robot-moving-in-a-grid problem is also related https://stackoverflow.com/questions/17018312/robot-moving-in-a-grid and also path planning https://link.springer.com/content/pdf/10.1007%2F0-387-34403-9_35.pdf – ralf htp Jan 05 '20 at 07:53
  • @JoeSmith are still waiting for code on this? – Bhosale Shrikant Jan 05 '20 at 12:05
  • @BhosaleShrikant yeah dude still trying to crack it. – Joe Smith Jan 05 '20 at 12:07
  • Are you satisfied with my answer? – One Lyner Jan 13 '20 at 13:39

2 Answers2

0

TL;DR: shortest path => consider Dijkstra Algorithm.

Here you can think of a graph with nodes (Last Move, Position). Compute the shortest paths for the four possible Last Move and take the shortest one.

NB: if you just care about the number of moves, and not the distance traveled, then a breadth first search is more efficient.

Here is some code for the BFS case:

def neighbor(node):
    last, (x,y) = node
    r = []
    for d in ['NE', 'NW', 'SE', 'SW']:
        if d == last:
            continue
        if d == 'NE':
            p = (x+3, y+3)
        if d == 'NW':
            p = (x-5, y+5)
        if d == 'SE':
            p = (x+4, y-4)
        if d == 'SW':
            p = (x-2, y-2)
        r.append((d, p))
    return r

def find_shortest_path(x,y):
    """
    BFS to find the shortest path between (0,0) and (x,y)
    NB: we consider all moves have the same cost
    """
    predecessor = {(None, (0,0)): None}
    queue = [(None, (0,0))]
    while True:
        if not queue:
            return None
        next_queue = []
        for node in queue:
            for n in neighbor(node):
                if n not in predecessor:
                    predecessor[n] = node
                    last, (u,v) = n
                    if (u,v) == (x,y):
                        backtrack = []
                        while n in predecessor:
                            backtrack.append(n)
                            n = predecessor[n]
                        return list(reversed(backtrack))
                    next_queue.append(n)
        queue = next_queue

If the target is really far away, you can use the usual improvements: bidirectional search, A* algorithm with some heuristic, etc.

One Lyner
  • 1,804
  • 1
  • 2
  • 7
-2
    """You are given an insect moves in a plane starting from the original point (0,0).
The insect that can only move toward North-East, South-East, North-West, & South-West.
Now the thing is insect can't move more than a specific number of steps at a time in one direction.
For example, it can move only 3 steps in NE, 4 steps in SE, 5 steps in NW and 2 steps in SW.
If the insect moves 3 steps in direction NE at a stretch- it has to move NW, SE, or SW-
before again going in direction NE."""

"""Assumption say the insect moves in the plane from (-100,-100) to (100, 100) size plane
    North is Positive y-cord
    South is Negative y-cord
    East is Positive x-cord
    West is  Negative x-cord """


def walk_ne():
    max_ne = 3
    global x_curr
    global y_curr
    global x_home
    global y_home
    global walked_ne
    global walked_nw
    global walked_se
    global walked_sw
    walked_ne = walked_nw = walked_sw = walked_se = False
    walked_ne = True
    for i in range(max_ne):
        if x_curr < x_home and y_curr < y_home:
            x_curr += 1
            y_curr += 1
        elif x_curr == x_home and (y_curr + 1) < y_home:
            x_curr += 1
            y_curr += 1
            break
        elif y_curr == y_home and (x_curr + 1) < x_home:
            x_curr += 1
            y_curr += 1
            break
        # else:
        #     print("Cond did not meet")


def walk_nw():
    max_nw = 5
    global x_curr
    global y_curr
    global x_home
    global y_home
    global walked_ne
    global walked_nw
    global walked_se
    global walked_sw
    walked_ne = walked_nw = walked_sw = walked_se = False
    walked_nw = True
    for i in range(max_nw):
        if x_curr < x_home and y_curr > y_home:
            x_curr += 1
            y_curr -= 1
        elif x_curr == x_home and (y_curr - 1) > y_home:
            x_curr += 1
            y_curr -= 1
            break
        elif y_curr == y_home and (x_curr + 1) < x_home:
            x_curr += 1
            y_curr -= 1
            break
        # else:
        #     print("Cond did not meet")


def walk_se():
    max_se = 4
    global x_curr
    global y_curr
    global x_home
    global y_home
    global walked_ne
    global walked_nw
    global walked_se
    global walked_sw
    walked_ne = walked_nw = walked_sw = walked_se = False
    walked_se = True
    for i in range(max_se):
        if x_curr > x_home and y_curr < y_home:
            x_curr -= 1
            y_curr += 1
        elif x_curr == x_home and (y_curr + 1) < y_home:
            x_curr -= 1
            y_curr += 1
            break
        elif y_curr == y_home and (x_curr - 1) > x_home:
            x_curr -= 1
            y_curr -= 1
            break
        # else:
        #     print("Cond did not meet")


def walk_sw():
    max_sw = 2
    global x_curr
    global y_curr
    global x_home
    global y_home
    global walked_ne
    global walked_nw
    global walked_se
    global walked_sw
    walked_ne = walked_nw = walked_sw = walked_se = False
    walked_sw = True
    for i in range(max_sw):
        if x_curr > x_home and y_curr > y_home:
            x_curr -= 1
            y_curr -= 1
        elif x_curr == x_home and (y_curr - 1) > y_home:
            x_curr -= 1
            y_curr -= 1
            break
        elif y_curr == y_home and (x_curr - 1) > x_home:
            x_curr -= 1
            y_curr -= 1
            break
        # else:
        #         #     print("Cond did not meet")


x_curr = 0  # Current x location of insect
y_curr = 0  # Current y location of insect

x_home = int(input('home x cordinates (Integer between -100 to 100)'))
y_home = int(input('home y cordinates (Integer between -100 to 100)'))

walked_ne = walked_se = walked_nw = walked_sw = False

if (x_home + y_home) % 2 != 0:
    print('Nearest the insect can go to given coordinates is ({} {}) '
          'Because insect can only move in diagonal'.format(x_home-1, y_home))
    x_home -= 1

while x_home != x_curr and y_home != y_curr:
    if x_curr < x_home:
        if y_curr < y_home:
            if not walked_ne:
                walk_ne()
            else:
                x_curr += 1
                y_curr -= 1
                walked_ne = False
                walked_nw = True

        else:
            if not walked_nw:
                walk_nw()
            else:
                x_curr += 1
                y_curr += 1
                walked_nw = False
                walked_ne = True
    else:
        if y_curr < y_home:
            if not walked_se:
                walk_se()
            else:
                x_curr -= 1
                y_curr -= 1
                walked_se = False
                walked_sw = True
        else:
            if not walked_sw:
                walk_sw()
            else:
                x_curr -= 1
                y_curr += 1
                walked_sw = False
                walked_se = True
    if x_curr == x_home and y_curr != y_home:
        if y_curr < y_home:
            if not walked_ne:
                walk_ne()
            elif not walked_se:
                walk_se()
        else:
            if not walked_nw:
                walk_nw()
            elif not walked_sw:
                walk_sw()
    elif x_curr != x_home and y_curr == y_home:
        if x_curr < x_home:
            if not walked_ne:
                walk_ne()
            elif not walked_nw:
                walk_nw()
        else:
            if not walked_se:
                walk_se()
            elif not walked_sw:
                walk_sw()
    print(x_curr, y_curr)