一只乌龟站在 (0, 0),面朝北。 向北走一步 y 加 1,向东 x 加 1,向南 y 减 1,向西 x 减 1。 一行给出不含空格的命令字母。 F 向面朝的方向走一步,R 向右转 90 度,L 向左转 90 度,B 原地向后转(180 度)。 执行完所有命令后,输出乌龟的 x、y 和面朝方向的首字母(N、E、S、W 之一),用一个空格分隔。 试着把方向做成按顺时针顺序包含北、东、南、西四个值的枚举(enum)来解。
输入
命令长度在 1 到 100,000 之间,每个字母是 F、R、L、B 之一
输出
一行:x y 方向
样例 1 · stdin
FFRFFLFBFF
stdout
2 1 S
样例 2 · stdin
LF
stdout
-1 0 W
main.py
错误列表00F8 ↓ · ⇧F8 ↑
输入(stdin)
运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 6 种语言题解
这道题只接受能用枚举来解的 Python、TypeScript、Java、C#、C 和 C++。 Python 用标准模块 enum 的 class Dir(Enum) 来做。 JavaScript 没有枚举语法(只能用 Object.freeze({...}) 模仿),所以不在其中,Craykon 也没有枚举。 TypeScript 的 enum Dir { North, East, South, West } 是值为 0~3 的数字枚举,所以先像 (d + 1) % 4 这样用数计算,再用 as Dir 转回来,反向映射 Dir[d] 给出名字 "North"。 enum 不是只有类型的语法,它会生成运行时使用的对象。 各语言的枚举本质不同。 C 的 enum Dir { NORTH, EAST, SOUTH, WEST } 只是带名字的 int 常量 0~3,运行时不知道名字,要自己准备名字表,如 "NESW"[d]。 C++ 的 enum class 写作 Dir::North,不会自动变成 int,需要 static_cast<int>(d)。 Java 的 enum 是类,有 values()、ordinal()、name();C# 用 (Dir)(((int)d + 1) % 4) 来回转换,d.ToString() 给出名字。 Python 则有 Dir(值)、d.value、d.name。 三个陷阱:① 把左转写成 (d - 1) % 4,从北(0)出发时在 C、C++、Java、C#、TypeScript 中得到 -1(余数跟随被除数的符号);C# 甚至会毫无错误地造出 (Dir)(-1) 并输出 "-1",TypeScript 也不会阻止 -1 as Dir,于是 Dir[-1] 是 undefined。 要写 (d + 3) % 4(Python 中 -1 % 4 == 3,没问题)。 ② 在 C、C++(以及 Java 旧式的 case: switch)中漏写 break,会落到下一个 case,一步移动好几次。 C# 在编译时就禁止这样,Java 的箭头 switch case NORTH -> y++; 不会落下去。 ③ Python 的 Enum 成员不等于数字,所以 d == 0 永远是 False(用 IntEnum 才是 True);要用 d == Dir.NORTH 或 d.value 来比较。
Pythonmain.py · 23 行
from enum import Enumclass Dir(Enum): # 시계 방향 차례 NORTH = 0 EAST = 1 SOUTH = 2 WEST = 3STEP = {Dir.NORTH: (0, 1), Dir.EAST: (1, 0), Dir.SOUTH: (0, -1), Dir.WEST: (-1, 0)}TURN = {"R": 1, "B": 2, "L": 3} # 왼쪽 = 오른쪽으로 세 번x = y = 0d = Dir.NORTHfor c in input().strip(): if c == "F": dx, dy = STEP[d] x += dx y += dy else: d = Dir((d.value + TURN[c]) % 4) # 수로 바꿔 계산하고 다시 열거형으로print(x, y, d.name[0])
TypeScriptmain.ts · 34 行
import { readFileSync } from "node:fs";enum Dir { // 시계 방향 차례: North = 0, East = 1, South = 2, West = 3 North, East, South, West,}// 숫자 enum은 수로 계산할 수 있다. 결과를 다시 Dir로 돌려놓는다function turn(d: Dir, k: number): Dir { return ((d + k) % 4) as Dir; // 왼쪽은 -1 대신 +3}const s = readFileSync(0, "utf8").trim();let x = 0;let y = 0;let d = Dir.North;for (const c of s) { switch (c) { case "R": d = turn(d, 1); break; case "B": d = turn(d, 2); break; case "L": d = turn(d, 3); break; default: switch (d) { case Dir.North: y++; break; case Dir.East: x++; break; case Dir.South: y--; break; case Dir.West: x--; break; } }}// 역방향 표 Dir[d]가 이름("South")을 준다console.log(`${x} ${y} ${Dir[d].charAt(0)}`);
JavaMain.java · 33 行
import java.io.BufferedReader;import java.io.InputStreamReader;public class Main { enum Dir { NORTH, EAST, SOUTH, WEST } // 시계 방향 차례 static Dir turn(Dir d, int k) { Dir[] all = Dir.values(); return all[(d.ordinal() + k) % 4]; } public static void main(String[] args) throws Exception { String s = new BufferedReader(new InputStreamReader(System.in)).readLine().trim(); int x = 0, y = 0; Dir d = Dir.NORTH; for (char c : s.toCharArray()) { switch (c) { case 'R' -> d = turn(d, 1); case 'B' -> d = turn(d, 2); case 'L' -> d = turn(d, 3); default -> { switch (d) { // 화살표 switch는 아래로 흘러내리지 않는다 case NORTH -> y++; case EAST -> x++; case SOUTH -> y--; case WEST -> x--; } } } } System.out.println(x + " " + y + " " + d.name().charAt(0)); }}
C#Main.cs · 34 行
using System;enum Dir { North, East, South, West } // 시계 방향 차례class Program{ static Dir Turn(Dir d, int k) => (Dir)(((int)d + k) % 4); // 열거형 ↔ int는 명시적으로 바꾼다 static void Main() { string s = Console.ReadLine().Trim(); int x = 0, y = 0; Dir d = Dir.North; foreach (char c in s) { switch (c) { case 'R': d = Turn(d, 1); break; case 'B': d = Turn(d, 2); break; case 'L': d = Turn(d, 3); break; default: switch (d) { case Dir.North: y++; break; case Dir.East: x++; break; case Dir.South: y--; break; case Dir.West: x--; break; } break; } } Console.WriteLine($"{x} {y} {d.ToString()[0]}"); }}
C++main.cpp · 34 行
#include <iostream>#include <string>enum class Dir { North, East, South, West }; // 범위 있는 열거형: Dir::North로 쓰고 int로 저절로 바뀌지 않는다Dir turn(Dir d, int k) { return static_cast<Dir>((static_cast<int>(d) + k) % 4);}char name(Dir d) { return "NESW"[static_cast<int>(d)]; // C++도 열거형의 이름을 실행 중에 모른다}int main() { std::string s; std::cin >> s; int x = 0, y = 0; Dir d = Dir::North; for (char c : s) { switch (c) { case 'R': d = turn(d, 1); break; case 'B': d = turn(d, 2); break; case 'L': d = turn(d, 3); break; default: switch (d) { case Dir::North: y++; break; case Dir::East: x++; break; case Dir::South: y--; break; case Dir::West: x--; break; } } } std::cout << x << " " << y << " " << name(d) << "\n";}
Cmain.c · 32 行
#include <stdio.h>enum Dir { NORTH, EAST, SOUTH, WEST }; /* 이름 붙은 int 상수 0, 1, 2, 3 */static const char NAME[] = "NESW"; /* C 열거형은 실행 중에 이름을 모른다: 직접 둔다 */enum Dir turn(enum Dir d, int k) { return (enum Dir)((d + k) % 4);}int main(void) { static char s[100002]; scanf("%100001s", s); int x = 0, y = 0; enum Dir d = NORTH; for (int i = 0; s[i]; i++) { switch (s[i]) { case 'R': d = turn(d, 1); break; case 'B': d = turn(d, 2); break; case 'L': d = turn(d, 3); break; default: switch (d) { case NORTH: y++; break; /* break가 없으면 다음 case로 흘러내린다 */ case EAST: x++; break; case SOUTH: y--; break; case WEST: x--; break; } } } printf("%d %d %c\n", x, y, NAME[d]); return 0;}