bash - 在x和y轴上查找坐标对。

时间:2016-05-31 23:47:59

标签: bash

我接受了技术支持职位的面试测试。我认为我没有做好,因为他们没有回电话。我不关心这份工作,但其中一个问题困扰着我,因为我只能把它弄清楚。 我有一个机器人能够读取每行包含一条指令的指令。左转为“L”,右转为“R”,向前移动的数字为#n。 机器人朝北,坐标为(0,0) 这些是说明:

R
L
L
9
4
1
7
9
R
2

所以指示说 - 向右转90度(使其朝向东方),然后再次向左和向左转(使其朝向西)向前走30步,然后顺时针转90度(使其朝北)并向前迈出两步。 他们希望我写一个可以计算最大距离和坐标对(x和y值)的脚本 他们在上面的说明中给了我答案,机器人从开始走的最大距离是30.07,坐标对是(-30,2)

我理解机器人在视觉上的运动并写了一个bash数组,它为顺时针运动增加了10的x值,并从x的值中减去了10,用于逆时针方向运动。廉价的bash数组(bash 3.2没有数组支持)将x VALUE与一个360位置或四个箭头键之一匹配。脚本在向前移动n#步之前保存最后一条指令。我不知道如何在最大距离和坐标对中编写脚本。它是一个代数x和y轴函数 - 但无法弄清楚如何在bash中添加它。

#!/bin/bash 
#set -x 


dial_map=("up_1:10"    "right_1:20"    "down_1:30"    "left_1:40" 
      "up_2:50"    "right_2:60"    "down_2:70"    "left_2:80"
      "up_3:90"    "right_3:100"   "down_3:110"   "left_3:120")
x=50 # the robot starts at the up or north position
     # once clockwise click adds ten, one counter clockwise minus 10 from x value. 

IFS=$'\n' read -d"" -r -a directives < directions.txt

for i in "${directives[@]}" 
    do
    if   [ "$i" == "R" ] ; then
      #echo "R is clockwise"
      x=$(( $x + 10 ))
      #echo "x is $x" 
      for click in "${dial_map[@]}" ; do 
          KEY=${click%%:*}
          VALUE=${click#*:}
          if [ "$x" -eq "$VALUE" ] ; then 
              keytab=$KEY
              #echo "the keyboard command is $keytab" 
      fi 
      #sleep 1
      done  
    elif [ "$i" == "L" ] ; then 
      #echo "L is counterclock"
      x=$(( $x - 10 ))
      #echo "x is $x"
      for click in "${dial_map[@]}" ; do 
           KEY=${click%%:*}
           VALUE=${click#*:}
          if [ "$x" -eq "$VALUE" ] ; then 
              keytab=$KEY
              #echo "the keyboard command is $keytab" 
      fi 
      #sleep 1
      done  
    else 
      echo "Please move the cursor $i times $keytab" 
      sleep 1 
    fi  
done 

在bash中找到x和y坐标

3 个答案:

答案 0 :(得分:2)

这是一个没有关联数组的方法,如果我正确读取是一个要求 - 实际上我最初根本没有读取任何数组;这就是我使用这么多变量的原因。您可以使用关联数组而不是我使用的case语句。我对指令进行了硬编码,但是从文件中读取它们是微不足道的。在评论和回声陈述之间,它有希望自我解释。

#!/bin/bash - 

inst=(R L L 9 4 1 7 9 R 2)
# compass to cartesian translation
#              x = 1 : N
#                  ^
#                  |
# y = -1 : W  <--------->  y = 1 : E
#                  |
#                  v
#             x = -1 : S

startloc_x=0
startloc_y=0
newloc_x=0
newloc_y=0
dir_x=1
dir_y=0
a=0;
for i in ${inst[@]}; do
  ((a++))
  echo "[$a] Next Instruction: $i"
  slct="${i}${dir_x}${dir_y}"

#   lookup table for case statement
#
#   X  Y     turning Right     turning left
#   1  0         0  1               0  -1
#   0  1        -1  0               1   0
#  -1  0         0 -1               0   1
#   0 -1         1  0              -1   0
  case $slct in
    R10|L-10)
            dir_x=0
            dir_y=1
            ;;
    R01|L0-1)
            dir_x=-1
            dir_y=0
            ;;
    R-10|L10)
            dir_x=0
            dir_y=-1
            ;;
    R0-1|L01)
            dir_x=1
            dir_y=0
            ;;
           *)
             (( newloc_x += $i * dir_x )) 
             (( newloc_y += $i * dir_y )) 
             ;;
  esac
  echo "[$a] Current location (x,y) = ($newloc_x, $newloc_y)"
  echo "[$a] Current direction (x,y) = ($dir_x, $dir_y)"
  echo
done
echo;echo "---"
echo "Finished processing $a instructions"
echo "Starting Location: (x,y) ($startloc_x, $startloc_y)"
echo "Ending Location:   (x,y) ($newloc_x, $newloc_y)"
echo "Final Direction:   (x,y) ($dir_x, $dir_y)"            
delta_x=0
delta_y=0
((delta_x = $newloc_x - $startloc_x ))
((delta_y = $newloc_y - $startloc_y ))
distance=`echo "sqrt( (${delta_x}.000)^2 + (${delta_y}.000)^2 )" | bc`
echo "Distance traveled = $distance"
echo

最终输出:

Finished processing 10 instructions
Starting Location: (x,y) (0, 0)
Ending Location:   (x,y) (2, -30)
Final Direction:   (x,y) (1, 0)
Distance traveled = 30.066

答案 1 :(得分:2)

采用另一种方法(使用相同的坐标),基本上只需要case语句和bc

#!/bin/bash

dir=${1:-n}             ## (n) north (s) south (e) east (w) west
fn=${2:-/dev/stdin}     ## input file name (stdin default)

declare -i posx=0
declare -i posy=0

while read -r cmd || [ -n "$cmd" ]; do
    case "$cmd" in
        [0-9]* )
            case "$dir" in
                n ) ((posy += cmd)) ;;
                w ) ((posx -= cmd)) ;;
                s ) ((posy -= cmd)) ;;
                e ) ((posy += cmd)) ;;
            esac
            ;;
        R )
            case "$dir" in
                n ) dir='e' ;;
                w ) dir='n' ;;
                s ) dir='w' ;;
                e ) dir='s' ;;
            esac
            ;;
        L )
            case "$dir" in
                n ) dir='w' ;;
                w ) dir='s' ;;
                s ) dir='e' ;;
                e ) dir='n' ;;
            esac
            ;;
    esac
done <"$fn"

dist=$(printf "scale=2; sqrt($posx*$posx+$posy*$posy)\n" | bc)

printf "final coordinates (%d, %d)\n" "$posx" "$posy"
printf "distance traveled: %s units.\n" "$dist"

示例使用/输出

$ bash robotstat.sh <dat/robot.txt
final coordinates (-30, 2)
distance traveled: 30.06 units.

答案 2 :(得分:0)

用awk:

awk -f script.awk文件

<强> script.awk

#! /bin/awk -f
BEGIN{
    codX=0;
    codY=1;
    X=0;
    Y=0
}
$1~"R"{
    tmp = codX;
    codX = codY;
    codY = tmp*-1
}
$1~"L"{
    tmp=codX;
    codX=codY*-1;
    codY=tmp
}
$1 ~ /[[:digit:]]/{
    X += codX*$1;
    Y += codY*$1
}
END{
    print "Co-ordinate(X,Y) : ("X","Y")";
    print "Distance : " sqrt(X^2+Y^2)
}

<强> 输出

Co-ordinate(X,Y) : (-30,2)
Distance : 30.0666