- 题目大概是
有一个机器人,给一串指令,L左转 R右转,F前进一步,B后退一步,问最后机器人的坐标,最开始,机器人位于 0 0,方向为正Y。
可以输入重复指令n : 比如 R2(LF) 这个等于指令 RLFLF。
问最后机器人的坐标是多少?
第一种写法
/*
机器人行走
*/
package main
import (
"fmt"
"log"
"strconv"
)
func main() {
var s []string
s1 := "FRB"
s2 := "R2(B2(LF)BF2(BF))FBF"
s3 := "FRRB"
s4 := "FRRBLFRB"
s5 := "FRRRBLLFRBLF"
s6 := "R2(B2(LF))F"
s = append(s, s1, s2, s3, s4, s5, s6)
for _, v := range s {
cmds := getCmd(v)
fmt.Println(cmds)
x, y := getXY(cmds)
fmt.Println("x:", x, "y:", y)
}
}
func getXY(s string) (int, int) {
//aa[] {y,-x,-y,x}
var aa [4]int
var k, tem int
for _, v := range s {
a := string(v)
switch a {
case "F":
tem = (4 - (k % 4)) % 4
aa[tem]++
case "B":
tem = (4 - (k % 4)) % 4
aa[tem]--
case "R":
k++
case "L":
k--
}
}
return aa[3] - aa[1], aa[0] - aa[2]
}
func getCmd(s string) string {
var stack []string
var tem string
for _, v := range s {
a := string(v)
if a >= "0" && a < "9" {
stack = append(stack, tem)
stack = append(stack, a)
tem = ""
continue
}
if a == "(" {
if tem == "" {
continue
}
stack = append(stack, tem)
tem = ""
continue
}
tem += a
if a == ")" {
tem = tem[:len(tem)-1]
if stack[len(stack)-1] >= "0" && stack[len(stack)-1] <= "9" {
tem = getCopyStr(stack[len(stack)-1], tem)
tem = stack[len(stack)-2] + tem
} else {
stack[len(stack)-2] = stack[len(stack)-2] + stack[len(stack)-1]
}
stack = stack[:len(stack)-2]
}
}
return tem
}
func getCopyStr(n, str string) string {
nn, err := strconv.Atoi(n)
if err != nil {
log.Fatal(err)
}
for i := 1; i < nn; i++ {
str += str
}
return str
}
第二种写法
机器人的移动和转向可以用复数的计算来表示:
package main
import (
"fmt"
"log"
"strconv"
"strings"
)
const (
turnLeft complex128 = 1i
turnRight complex128 = -1i
)
type Robot struct {
loc complex128
dir complex128
}
func (r *Robot) L() { r.dir *= turnLeft }
func (r *Robot) R() { r.dir *= turnRight }
func (r *Robot) F() { r.loc += r.dir }
func (r *Robot) B() { r.loc -= r.dir }
func (r *Robot) Reset() { r.loc, r.dir = 0, 0+1i }
func (r *Robot) Report() (int, int) {
return int(real(r.loc)), int(imag(r.loc))
}
type initState struct{}
func (s *initState) Parse(cmd string) (string, string) {
if len(cmd) == 0 {
return "", ""
}
switch cmd[0] {
case 'L', 'R', 'F', 'B':
output, left := s.Parse(cmd[1:])
return cmd[:1] + output, left
}
if cmd[0] >= '1' && cmd[0] < '9' {
output, left := (&digitState{cmd[:1]}).Parse(cmd[1:])
if len(output) == 0 {
return "", cmd
}
a, b := s.Parse(left)
return output + a, b
}
return "", cmd
}
type digitState struct {
n string
}
func (s *digitState) Parse(cmd string) (string, string) {
if len(cmd) == 0 {
return "", ""
}
if c := cmd[0]; c >= '0' && c < '9' {
s.n += cmd[:1]
return s.Parse(cmd[1:])
} else if c == '(' {
n, err := strconv.Atoi(s.n)
if err != nil {
return "", s.n + cmd
}
output, left := (&initState{}).Parse(cmd[1:])
if len(left) == 0 || left[0] != ')' {
return "", s.n + cmd
}
return strings.Repeat(output, n), left[1:]
}
return "", s.n + cmd
}
func ParseCmd(cmd string) (string, error) {
a, b := (&initState{}).Parse(cmd)
if len(b) > 0 {
return "", fmt.Errorf("invalid input: %s", b)
}
log.Println(a)
return a, nil
}
func (r *Robot) RunCmd(cmd string) error {
instructions, err := ParseCmd(cmd)
if err != nil {
return err
}
for i := range instructions {
switch instructions[i] {
case 'L':
r.L()
case 'R':
r.R()
case 'F':
r.F()
case 'B':
r.B()
}
}
return nil
}
func main() {
robot := &Robot{}
var s []string
s1 := "FRB"
s2 := "R2(B2(LF)BF2(BF))FBF"
s3 := "FRRB"
s4 := "FRRBLFRB"
s5 := "FRRRBLLFRBLF"
s6 := "R2(B2(LF))F"
s = append(s, s1, s2, s3, s4, s5, s6)
for i := range s {
robot.Reset()
err := robot.RunCmd(s[i])
if err != nil {
log.Fatal(err)
}
x, y := robot.Report()
fmt.Println("location: ", x, y)
}
}