3
\$\begingroup\$

I'm trying to optimize my solution to Wiggle Walk for Kickstart's round 1C.

Problem

Banny has just bought a new programmable robot. Eager to test his coding skills, he has placed the robot in a grid of squares with R rows (numbered 1 to R from north to south) and C columns (numbered 1 to C from west to east). The square in row r and column c is denoted (r, c).

Initially the robot starts in the square (SR, SC). Banny will give the robot N instructions. Each instruction is one of N, S, E or W, instructing the robot to move one square north, south, east or west respectively.

If the robot moves into a square that it has been in before, the robot will continue moving in the same direction until it reaches a square that it has not been in before. Banny will never give the robot an instruction that will cause it to move out of the grid.

Can you help Banny determine which square the robot will finish in, after following the N instructions?

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line containing the five integers N, R, C, SR and SC, the number of instructions, the number of rows, the number of columns, the robot's starting row and starting column, respectively.

Then, another line follows containing a single string of N characters; the i-th of these characters is the i-th instruction Banny gives the robot (one of N, S, E or W, as described above).

Output

For each test case, output one line containing Case #x: r c, where x is the test case number (starting from 1), r is the row the robot finishes in and c is the column the robot finishes in.

Limits

Memory limit: 1GB. 1 ≤ T ≤ 100. 1 ≤ R ≤ 5 × 104. 1 ≤ C ≤ 5 × 104. 1 ≤ SR ≤ R. 1 ≤ SC ≤ C. The instructions will not cause the robot to move out of the grid. Test set 1 (Visible)

Time limit: 20 seconds. 1 ≤ N ≤ 100. Test set 2 (Hidden)

Time limit: 60 seconds. 1 ≤ N ≤ 5 × 104.

Here's my current solution:

def main():
    T = int(input())  # the number of test cases

    for case in range(1, T+1):
        N, R, C, r, c = map(int, input().split())
        instructions = input()  # string of N, S, E or W
        seen = {(r, c)}

        for i in instructions:
            if i == 'N':
                r -= 1
                while (r, c) in seen:
                    r -= 1
            elif i == 'S':
                r += 1
                while (r, c) in seen:
                    r += 1
            elif i == 'E':
                c += 1
                while (r, c) in seen:
                    c += 1
            else:  # 'W'
                c -= 1
                while (r, c) in seen:
                    c -= 1
            seen.add((r, c))

        print('Case #{}: {} {}'.format(case, r, c))


main()

How can I represent visited areas in the grid so that getting the destination cell for each instruction would be faster?

\$\endgroup\$
4
\$\begingroup\$

A simple dictionary will do once you get the idea ;)

def get_neighbor(r, c, i, neighbors):
    if (r, c, i) in neighbors:
        return neighbors[(r, c, i)]

    if i == 'N':
        return (r - 1, c)
    elif i == 'S':
        return (r + 1, c)
    elif i == 'E':
        return (r, c + 1)
    else:  # 'W'
        return (r, c - 1)


def link_neighbors(r, c, neighbors):
    north = get_neighbor(r, c, 'N', neighbors)
    south = get_neighbor(r, c, 'S', neighbors)
    east = get_neighbor(r, c, 'E', neighbors)
    west = get_neighbor(r, c, 'W', neighbors)

    neighbors[(*north, 'S')] = south
    neighbors[(*south, 'N')] = north
    neighbors[(*east, 'W')] = west
    neighbors[(*west, 'E')] = east


def main():
    T = int(input())  # the number of test cases

    for case in range(1, T+1):
        N, R, C, r, c = map(int, input().split())
        instructions = input()  # string of N, S, E or W
        neighbors = {}

        for i in instructions:
            link_neighbors(r, c, neighbors)
            r, c = get_neighbor(r, c, i, neighbors)  # new position

        print('Case #{}: {} {}'.format(case, r, c))


main()
\$\endgroup\$
0
\$\begingroup\$

I have participated in Google kickstart wiggle walk.

I have optimized the solution to be \$\mathcal{O}(N\times logN)\$ but it's still getting "time limit exceeded".

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int t, n ,*arr, r , c, sr,sc,i=0;
    arr=(int*)malloc(5*sizeof(int));
    char temp;
    scanf("%d",&t);
    int z=1;
    while(z<=t)
    {
        int k=0;
        do {
            scanf("%d%c",arr+k,&temp);
            k++;
        } while(temp!='\n');
        n=*(arr);
        r=*(arr+1);
        c=*(arr+2);
        sr=*(arr+3);
        sc=*(arr+4);
        char *string;
        string =(char*)malloc(n*sizeof(char));
        int *grid = (int *)malloc(r * c * sizeof(int));
        int *northgrid =(int *)malloc(r * c * sizeof(int));
        int *southgrid = (int *)malloc(r * c * sizeof(int));
        int *eastgrid =(int *)malloc(r * c * sizeof(int));
        int *westgrid = (int *)malloc(r * c * sizeof(int));
        int current_sr,current_sc;
        *(grid + sr*c + sc)=1;
        for(int j=0; j<n; j++)
        {
            scanf("%c",string+j);
            current_sr = sr;
            current_sc = sc;

            if(*(string+j)=='N')
            {
                do
                {
                    if(*(northgrid + sr*c + sc)==0)
                    {

                        sr--;

                    }
                    else if(*(northgrid + sr*c + sc)!=0)
                    {
                        while(*(northgrid + sr*c + sc)!=0)
                        {
                            sr=*(northgrid + sr*c + sc);
                        }
                    }
                } while(*(grid + sr*c + sc)==1);
                *(grid + sr*c + sc)=1;
                *(southgrid+ sr*c + sc)=current_sr;
                *(northgrid+current_sr*c+current_sc)=sr;
            }
            else if(*(string+j)=='S')
            {
                do
                {
                    if(*(southgrid + sr*c + sc)==0)
                    {

                        sr++;

                    }
                    else if(*(southgrid + sr*c + sc)!=0)
                    {
                        while(*(southgrid + sr*c + sc)!=0)
                        {
                            sr=*(southgrid + sr*c + sc);
                        }
                    }
                } while(*(grid + sr*c + sc)==1);
                *(grid + sr*c + sc)=1;
                *(northgrid+ sr*c + sc)=current_sr;
                *(southgrid+current_sr*c+current_sc)=sr;
            }
            else if(*(string+j)=='E')
            {
                do
                {
                    if(*(eastgrid + sr*c + sc)==0)
                    {

                        sc++;

                    }
                    else if(*(eastgrid + sr*c + sc)!=0)
                    {
                        while(*(eastgrid + sr*c + sc)!=0)
                        {
                            sr=*(eastgrid + sr*c + sc);
                        }
                    }
                } while(*(grid + sr*c + sc)==1);
                *(grid + sr*c + sc)=1;
                *(westgrid+ sr*c + sc)=current_sc;
                *(eastgrid+current_sr*c+current_sc)=sc;
            }
            else if(*(string+j)=='W')
            {
                do
                {
                    if(*(westgrid + sr*c + sc)==0)
                    {

                        sc--;

                    }
                    else if(*(westgrid + sr*c + sc)!=0)
                    {
                        while(*(westgrid + sr*c + sc)!=0)
                        {
                            sc=*(westgrid + sr*c + sc);
                        }
                    }
                } while(*(grid + sr*c + sc)==1);
                *(grid + sr*c + sc)=1;
                *(eastgrid+ sr*c + sc)=current_sc;
                *(westgrid+current_sr*c+current_sc)=sc;
            }
            // printf("Values are: %d , %d",sr,sc);
        }
        printf("Case #%d: %d %d\n",z,sr,sc);

        z++  ;
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Please do something about the formatting. Your entire question is one big code block. That being said, is this an answer to the question? Check out the help center: codereview.stackexchange.com/help/how-to-answer \$\endgroup\$ – dfhwze Jul 10 at 19:49
  • 2
    \$\begingroup\$ You have presented an alternative solution to the problem in another language, but have not reviewed the code (see Why are alternative solutions not welcome?). And also have a look at How to Answer, which was already pointed out to you in the previous comment. To me it sounds more like you should ask this as a new question here on Code Review. \$\endgroup\$ – AlexV Jul 10 at 20:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.