检查是否存在圆圈

时间:2015-03-10 14:58:04

标签: algorithm geometry computational-geometry

在谷歌访谈期间我被问到这个问题。 我们给出一个由字母-F,L,R组成的字符串。 - 这是机器人遵循的指令

F-向前迈出一步。

左转。

右转。

字符串长度最多可达2500个字符。

字符串无限次地运行。我们需要判断是否存在一个带有半径的圆,r(r可以是任何实数),这样机器人就不会离开圆。 我被困在这一点。我想到使用凸包,但如何检查无限次。用代码进行解释将不胜感激。请帮忙。提前致谢

8 个答案:

答案 0 :(得分:24)

  1. 每次运行(一次运行执行给定字符串的所有命令一次)改变两件事:机器人看向的方向及其位置(即每次运行将其移动一些向量(此向量的方向取决于在运行之前的初始方向上)并旋转它)。
  2. 可能的方向数为4.因此,在运行模拟4次之后,它看起来与最初的方向相同(每次擦动以相同的角度旋转)。

  3. 这就是为什么连续4次运行只是将它移动一些矢量而没有任何旋转。

  4. 因此,我们可以连续4次运行模拟并查看它是否在原点停止。如果是这样,我们可以找到包含其路径的最小圆圈。否则,不存在这样的圈子。

答案 1 :(得分:2)

你会运行1次迭代来计算新的位置,比如newx,newy。 然后你会计算4次迭代,看看机器人是否回到了newx-newy。如果是这样,则圆圈存在,否则不存在。

半径是机器人在迭代中冒出的最大距离。

代码实施 -

//North, South, East, West directions
#define N 0 
#define S 1
#define E 2
#define W 3

// Function to compute the new pos (x, y, dir) after completing one iteration of the string.
// It will also update the max radius.
void findNewPos(char *str, int *origdir, int *origx, int *origy, double *maxrad) {
  int i, len, x, y, dir; 

  dir = *origdir;
  x = *origx;
  y = *origy;

  len = strlen(str);
  i=0;

  //Iterate through each character
  while(i < len) {
    char c = str[i];

    switch(c) {
    case 'L': // Turn left
      switch(dir) {
      case N:
         x--;
         dir = W;
         break;
      case S:
         x++;
         dir = E;
         break;
      case E:
         y++;
         dir = N;
         break;
      case W:
         y--;
         dir = S;
         break;
      }
      break;

    case 'R': // Turn right
      switch(dir) {
      case N:
         x++;
         dir = E;
         break;
      case S:
         x--;
         dir = W;
         break;
      case E:
         y--;
         dir = S;
         break;
      case W:
         y++;
         dir = N;
         break;
      }
      break;

    case 'F': // Go forward
      switch(dir) {
      case N:
         y++;
         dir = N;
         break;
      case S:
         y--;
         dir = S;
         break;
      case E:
         x++;
         dir = E;
         break;
      case W:
         x--;
         dir = W;
         break;
      }
      break;
    }

    // Update max radius till now
    double rad = x*x + y*y;
    if(rad > *maxrad)
      *maxrad = rad;
    i++;
  }

  *origx = x;
  *origy = y;
  *origdir = dir;
}

// Function to compute the max radius of movement, if bounded
double findCircle(char *str) {
  int x=0, y=0, dir=N;
  int refx, refy;
  double radius = 0, maxrad = 0;

  // Starting from origin(x=0, y=0), find new pos after single iteration
  findNewPos(str, &dir, &x, &y, &maxrad);

  refx = x;
  refy = y;

  // Find new positions after 4 more iterations
  findNewPos(str, &dir, &x, &y, &maxrad);
  findNewPos(str, &dir, &x, &y, &maxrad);
  findNewPos(str, &dir, &x, &y, &maxrad);
  findNewPos(str, &dir, &x, &y, &maxrad);

  // Are we back to position where we were after 1st iteration?
  if(x == refx && y == refy) {
    printf("Circle exists %f!\n", maxrad);
    radius = sqrt(maxrad);
  }
  else {
    printf("Circle does not exist!\n");
    radius = -1;
  }

  return radius;
}

答案 2 :(得分:0)

运行字符串,查看机器人在其末端的位置以及它看起来的方向。

如果它回到原点,请在执行过程中与原点保持最大距离,然后与r进行比较。

如果它没有回到原点,请检查其方向:

如果它具有与开头相同的方向,那么它将无限期地远离原点,因此不存在这样的r。

如果它的方向与开头的方向不同,那么它将在字符串的4或2次迭代后返回原点,具体取决于它是否朝向其原始方向的左/右,或者反过来,分别。现在获取2次执行字符串后的最大距离。 (简单的案例区别将表明,无论期间是执行2次还是4次,它将在2次执行后访问其最大距离。)

答案 3 :(得分:0)

string doesCircleExists(string commands) {
    int dir=1; //1 is east; 2 north etc.
    pair<int,int> pos; 
    pos = make_pair(0,0);  //start at origin
    for(int i=0;i<4;i++) {
    for(int i=0;i<commands.size(); i++)
    {
       if(commands[i]=='F')
       {
        if(dir==1) pos.first++;  if(dir==2) pos.second++; 
        if(dir==3) pos.first--; if(dir==0) pos.second--; 
       }
       if(commands[i]=='L') {dir++; dir = dir%4;}
       if(commands[i]=='R') {dir--; dir = dir%4;}
    }
    }
    if(pos.first==0 && pos.second==0 && dir=1) return "YES"; else return "NO";

}

答案 4 :(得分:0)

这可能有效:

def encircular(string):

    ini_pos = [0,0]
    position = [0,0]
    direction = 'N'
    directions = {'NL':'W','NR':'E','EL':'N','ER':'S','SL':'E','SR':'W','WL':'S','WR':'N'}
    forward = {'N':[0,1],'E':[1,0],'S':[0,-1],'W':[-1,0]}
    for i in range(4):
        for i in string:
            if i == 'F':
                position = [x+y for x,y in zip(position,forward[direction])]
            else:
                #print(direction+i)
                direction = directions[direction+i]
                #print (direction)
    if ini_pos == position: return 'YES'
    else : return 'NO'

答案 5 :(得分:0)

def robot_bot(string):
    face = 0
    pos = [0, 0]
    string = string.upper()
    dirc = {
        0: [1, 0],
        90: [0, 1],
        180: [-1, 0],
        270: [0, -1],
        360: [1, 0],
        -90: [0, -1],
        -180: [-1, 0],
        -270: [0, 1]
    }
    for _ in range(4):
        for ch in string:
            if ch == "R": face -= 90
            elif ch == "L": face += 90
            if ch == "G":
                pos[0] += dirc[face][0]
                pos[1] += dirc[face][1]
            if abs(face) == 360:
                face = 0
    return True if pos == [0, 0] else False

答案 6 :(得分:0)

#include <bits/stdc++.h>
using namespace std;
struct point
{
    int x;
    int y;
    int dir;
};
int mod4(int a)
{
    if(a%4 < 0)
        return (a%4 + 4);
    else
        return a%4;
}
int main()
{
    struct point p;
    p.x = 0;
    p.y = 0;
    p.dir = 0;
    string s;cin>>s;
    int j;
    for(int i=0;i<4*s.size();i++)
    {
        j = i%s.size();
        if(s[j] == 'F')
        {
            if(p.dir == 0)//north
                p.y++;
            if(p.dir == 1)//east
                p.x++;
            if(p.dir == 2)//south
                p.y--;
            if(p.dir == 3)//west
                p.x--;
        }
        if(s[j] == 'L')
        {
            p.dir--;
            p.dir = mod4(p.dir);
        }
        if(s[j] == 'R')
        {
            p.dir++;
            p.dir = mod4(p.dir);
        }
        //cout<<p.x<<" "<<p.y<<" "<<p.dir<<endl;
    }
    if(p.x == 0 && p.y ==0 && p.dir == 0)
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;   
}

答案 7 :(得分:-1)

迭代给定的字符串一次并记下最终的位移和方向。如果位移非零并且单次迭代的机器人的起始和终止方向相同,则机器人不能包含在圆圈中,否则它可以是。

图:
在该图中,假设在给定字符串的单次迭代之后机器人从点A到达点B.现在,角度ABC是(90°-θ),这使角度ABD等于90度。所有边都相等,每个角度等于90度,四边形ABDE是一个正方形。对于θ(锐角或钝角)的任何值都是如此。如果留下单次迭代后的结束方向,则证明将是相似的。对于南方,机器人将在A点和B点之间振荡。

因此,作为问题的解决方案,您可以在机器人完成给定字符串的一次迭代后,检查开始和结束方向是否相同以及起始位置和结束位置是否相同。 / p>