在一行上输入一个长度
,仅由可见字符构成的字符串
,代表输入的指令序列。
在一行上输出一个两个整数,代表小人最终位置的横纵坐标,使用逗号间隔。
A10;S20;W10;D30;X;A1A;B10A11;;A10;
10,-10
对于这个样例,我们模拟小人的移动过程:
第一个指令
是合法的,向左移动
个单位,到达
点;
第二个指令
是合法的,向下移动
个单位,到达
点;
第三个指令
是合法的,向上移动
个单位,到达
点;
第四个指令
是合法的,向右移动
个单位,到达
点;
第五个指令
不合法,跳过;
第六个指令
不合法,跳过;
第七个指令
不合法,跳过;
第八个指令
不合法,跳过;
第九个指令
是合法的,向左移动
个单位,到达
点。
ABC;AKL;DA1;
0,0
import re def jug (text): global ll if text == '': return 0 if text[-1].isdigit() and 1 < len(text) <= 3: pattern = re.compile(r'[asdwASDW]\d{1,2}') is_match = re.match(pattern, text) if is_match: ll.append(text.upper()) texts = input().split(';') ll = [] x, y = 0, 0 for i in texts: jug(i) for _ in ll: tmp = _[0] if tmp == 'A': x -= int(_[1:]) elif tmp == 'D': x += int(_[1:]) elif tmp == 'S': y -= int(_[1:]) else: y += int(_[1:]) print(f'{x},{y}')
#include<iostream> #include<string> #include<vector> using namespace std; bool check(string& s){ //检测子串是不是合法的 if(s.size()>3 || s.size() < 2) return false; bool flag1=false,flag2=false; if(s[0] == 'A' || s[0] == 'W' || s[0] == 'S' || s[0] == 'D'){ flag1=true; } //是一位数字还是两位数字 if((s.size() == 2 && s[1] >= '0' && s[1] <= '9') || (s.size() == 3 && s[1] >= '0' && s[1] <= '9' && s[2] >= '0' && s[2] <= '9')){ flag2=true; } return flag1 && flag2; } pair<int,int>addNum(string& s){ //获取子串中的坐标 int n=s.size(); char c=s[0]; int num=stoi(s.substr(1)); //截取子串1号位到结尾的数字大小 pair<int,int>ans={0,0}; switch (c) { case 'A':ans.first=-num;break; case 'D':ans.first=num;break; case 'W':ans.second=num;break; case 'S':ans.second=-num;break; } return ans; } void Solution(string &str,int& x,int& y){ int n=str.size(); int l=0,r=0; while(r<n){ while(str[r] != ';'){ r++; } string s=str.substr(l,r-l); //双指针截除去';'的子串 if(check(s)){ x+=addNum(s).first; y+=addNum(s).second; } l=r+1; //跳过';',取下一位位置; r=l; } } int main(){ string str; cin>>str; int x=0,y=0; Solution(str, x, y); cout<<x<<','<<y<<endl; return 0; }
import java.util.*; /** * @Title: Move * @auth: J * @date: 2022/5/24 13:17 * @Description: */ public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String all = sc.next(); String[] steps = all.split(";"); List<String> directions = new ArrayList<>(); directions.add("W"); directions.add("A"); directions.add("S"); directions.add("D"); Integer x = 0; Integer y = 0; // 过滤掉非法数据 for (String step : steps) { if (step.length() < 2 || step.length() > 3) { continue; } String direction = step.substring(0, 1); // 方向 try { Integer len = Integer.parseInt(step.substring(1)); // 步长 if (!directions.contains(direction) || len < 0) { continue; } switch (direction) { case "W": y += len; break; case "S": y -= len; break; case "D": x += len; break; case "A": x -= len; break; } } catch (NumberFormatException e) { // 如果步长非法,跳过 continue; } } System.out.println(x + "," + y); } }
import re lst = input().split(';') x,y = 0,0 for s in lst: if 2 <= len(s) <= 3: # 判断是否为有效的字符串 a,b = s[0],s[1:] if re.fullmatch(r'[A-Z]',a) and (re.fullmatch(r'\d{2}', b)&nbs***bsp;re.fullmatch(r'\d{1}', b)): b = int(b) if a == 'A': x -= b elif a == 'S': y -= b elif a == 'W': y += b elif a == 'D': x += b print('%d,%d'%(x,y))
#include <bits/stdc++.h> using namespace std; int main() { string n; while(cin>>n) {string t;pair<int,int> p (0,0); stringstream ss(n); while(getline(ss,t,';')) { if(regex_match(t,regex("^A[0-9]*"))) p.first-=stoi(t.substr(1)); else if(regex_match(t,regex("^D[0-9]*"))) p.first+=stoi(t.substr(1)); else if(regex_match(t,regex("^W[0-9]*"))) p.second+=stoi(t.substr(1)); else if(regex_match(t,regex("^S[0-9]*"))) p.second-=stoi(t.substr(1)); else continue; } cout<<p.first<<","<<p.second<<endl; } return 0; }
#include <iostream> #include <vector> int main() { int x = 0, y = 0; char tmp; //0 normal, -1 waste, 1 wait for num1, 2 wait for num2&nbs***bsp;end, 3 wait for end int state = 0; int direction = -1, bias = 0; std::vector<std::vector<int>> aim = { {0, 1}, {-1, 0}, {0, -1}, {1, 0} }; while (std::cin.get(tmp)) { if (tmp == '\n') { break; } switch (state) { case -1: switch (tmp) { case ';' : state = 0; break; default : break; } break; case 0 : bias = 0; switch (tmp) { case ';' : state = 0; break; case 'W' : direction = 0; state = 1; break; case 'A': direction = 1; state = 1; break; case 'S': direction = 2; state = 1; break; case 'D': direction = 3; state = 1; break; default : state = -1; break; } break; case 1: switch (tmp) { case ';': state = 0; break; default: if (tmp <= '9' && tmp >= '0') { bias = bias * 10 + tmp - '0'; state = 2; } else { state = -1; } break; } break; case 2: switch (tmp) { case ';': x += aim[direction][0] * bias; y += aim[direction][1] * bias; state = 0; break; default: if (tmp <= '9' && tmp >= '0') { bias = bias * 10 + tmp - '0'; state = 3; } else { state = -1; } break; } break; case 3: switch (tmp) { case ';': x += aim[direction][0] * bias; y += aim[direction][1] * bias; state = 0; break; default: state = -1; break; } break; } } std::cout << x << ',' << y; return 0; }状态机之状态转移大法。
#include<stdio.h> #include<string> #include<iostream> using namespace std; int main(){ string strs; int x = 0; int y = 0; getline(cin,strs); for(int i =0; i< strs.length();i++){ if(strs[i] == ';'){ //如果读取到;分隔符 int j =i-1; int len = 0; int step = 0; while(strs[j]!=';' && j>=0) {//计算这一段的位移是两位数还是三位数 j--; len++; } if(len==3) step =(strs[i-2]-48)*10+(strs[i-1]-48); //三位 else if(len==2) step =strs[i-1]-48; //两位 //判断输入是否合法 if((strs[i-1] >='0'&&strs[i-1] <='9')&&(strs[i-len] >='A'&&strs[i-len] <='Z')){ //判断方向 if(strs[i-len] == 'A') x = x-step; else if (strs[i-len] == 'D') x = x+step; else if (strs[i-len] == 'S') y = y-step; else if (strs[i-len] == 'W') y = y+step; } } } cout<<x<<','<<y<<endl; }
// 2021-12-16 // cpp 选手 #include <iostream> #include <string> #include <sstream> #include <set> using namespace std; set<char> gValidOP{'A', 'D', 'W', 'S'}; struct Point{ int x; int y; Point(int xx = 0, int yy = 0):x(xx), y(yy){} Point(const Point& other) { this->x = other.x; this->y = other.y; } Point& operator=(const Point& other) { this->x = other.x; this->y = other.y; return *this; } }; class CPosCalculator { public: CPosCalculator(Point po = Point(0, 0)) : m_pos(po), m_op(0) { } int ParseValidOp(const string& strOp) { // -1: 无效; 0: 无影响; 1: 有效,需要处理; int iRet = 0; bool bFirstValid = false; bool bSecondValid = true; if(!strOp.size()) return iRet; for(int i = 0; i < strOp.size(); ++i) { if(i==0) { // 第一个字符是否为有效操作 if(gValidOP.count(strOp[i])) { bFirstValid = true; if(strOp[i]=='A') { m_op = -1; } else if(strOp[i]=='D') { m_op = 1; } else if(strOp[i]=='W') { m_op = 2; } else { m_op = -2; } } else { iRet = -1; bSecondValid = false; break; } } else if(bFirstValid) { bSecondValid &= isdigit(strOp[i]); } } if(bSecondValid) { iRet = 1; m_offset = atoi(strOp.substr(1).c_str()); } else iRet = -1; return iRet; } void Move() { switch(m_op) { case -1: m_pos.x -= m_offset; break; case 1: m_pos.x += m_offset; break; case -2: m_pos.y -= m_offset; break; case 2: m_pos.y += m_offset; break; } } Point& GetPos() { return m_pos; } private: Point m_pos; int m_op; int m_offset; }; int main() { string strIn; while(getline(cin, strIn)) { string strEle; CPosCalculator calc; int idx_off = 0; int idx = -1; do { idx = strIn.find_first_of(';', idx_off); strEle = strIn.substr(idx_off, idx - idx_off); int op = 0; if((op = calc.ParseValidOp(strEle)) == 1) { calc.Move(); } idx_off += (idx-idx_off + 1); }while(idx != -1); Point& pp = calc.GetPos(); cout << pp.x << "," << pp.y << endl; } return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String str = sc.nextLine(); int[] point = new int[2]; move(point, str); System.out.println(point[0] + "," + point[1]); } } // 坐标移动 public static void move(int[] point, String str) { String[] arr = str.split(";"); for (String s : arr) { if (isOk(s)) { char direction = s.charAt(0); int size = Integer.parseInt(s.substring(1)); switch (direction) { case 'A': point[0] -= size; break; case 'S': point[1] -= size; break; case 'D': point[0] += size; break; case 'W': point[1] += size; } } } } // 判断是否合法 public static boolean isOk(String str) { if (str.length() < 2 || str.length() > 3) { return false; } char temp; for (int i=0; i<str.length(); i++) { temp = str.charAt(i); if (i == 0) { if (temp != 'A' && temp != 'S' && temp != 'D' && temp != 'W') { return false; } continue; } if (temp < '0' || temp > '9') { return false; } } return true; } }
while True: try: n = input().split(";") coords = [0, 0] dic = {"A": [-1, 0], "D": [1, 0], "W": [0, 1], "S": [0, -1]} for i in n: if len(i)>=2: if (i[0] in dic) and i[1:].isdigit(): temp = [j * int(i[1:]) for j in dic[i[0]]] coords = [x + y for x, y in zip(temp, coords)] print(str(coords[0]) + "," + str(coords[1])) except: break
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct{ int x; int y; }tCoord; void calculate(char *str, tCoord *coord) { int len = strlen(str); if(len<2) return; for(int i=1; i<len; i++) { if(str[i]<'0' || str[i]>'9') return; } switch(str[0]) { case 'A': coord->x -= atoi(&str[1]); break; case 'D': coord->x += atoi(&str[1]); break; case 'W': coord->y += atoi(&str[1]); break; case 'S': coord->y -= atoi(&str[1]); break; default: break; } } int main() { char str[10000]={0}; char *p; char *delim = ";"; tCoord coord; coord.x = 0; coord.y = 0; scanf("%s", str); p = strtok(str, delim); while (p) { calculate(p, &coord); p = strtok(NULL, delim); } printf("%d,%d\n", coord.x, coord.y); return 0; }
#include<stdio.h> #include<string.h> int main(){ char str[20000]={0}; int x=0,y=0,num; gets(str); int l=strlen(str); for(int i=0;i<l;i++){ if(str[i]==';'&&(str[i-4]==';'||str[i-4]==NULL)){ if(str[i-2]>='0'&&str[i-2]<='9'&&str[i-1]>='0'&&str[i-1]<='9'){ num = (str[i-2]-48)*10+str[i-1]-48; if(str[i-3]=='A') x-=num; else if(str[i-3]=='D') x+=num; else if(str[i-3]=='W') y+=num; else if(str[i-3]=='S') y-=num; } } if(str[i]==';'&&(str[i-3]==';'||str[i-3]==NULL)){ if(str[i-1]>='0'&&str[i-1]<='9'){ num = str[i-1]-48; if(str[i-2]=='A') x-=num; else if(str[i-2]=='D') x+=num; else if(str[i-2]=='W') y+=num; else if(str[i-2]=='S') y-=num; } } } printf("%d,%d",x,y); }
#include <bits/stdc++.h> using namespace std; int main(){ /* 下面是一个简单的例子 如:A10;S20;W10;D30;X;A1A;B10A11;;A10; 输入描述:一行字符串 输出描述:最终坐标,以逗号分隔 */ //分别定义横纵坐标,读取字符串,若读到分号,对临时字符串进行解析 //长度小于2或大于3的直接抛弃;第一个字母非...,直接抛弃;除第一个字母外,其余位置存在字母的,直接抛弃; //A:横坐标减操作;D:横坐标加操作;W:纵坐标加操作;S:纵坐标减操作 string inputStr; while(cin >> inputStr){ int m = 0 , n = 0; string tempStr; for(int i = 0; i < inputStr.size(); i++){ if(inputStr[i] == ';'){ int len = tempStr.size(); if(len < 2 || len > 3) tempStr = ""; if(tempStr[0] != 'A' && tempStr[0] != 'D' && tempStr[0] != 'W' && tempStr[0] != 'S') tempStr = ""; int sum = 0; for(int i = 1; i < tempStr.size(); i++){//临时字符串不为空,才会进来 if(tempStr[i] >= '0' && tempStr[i] <= '9') sum += (tempStr[i] - '0') * pow(10,(tempStr.size() - i - 1)); else{ tempStr = ""; break; } } if(tempStr[0] == 'A') m -= sum; if(tempStr[0] == 'D') m += sum; if(tempStr[0] == 'W') n += sum; if(tempStr[0] == 'S') n -= sum; tempStr = ""; } else{ tempStr += inputStr[i]; } } cout << m << "," << n << endl; } return 0; }
while True: try: s = input() s = list(s.split(";")) x,y = 0,0 for c in s: if not c: continue elif c[0]=='A' and c[1:].isdigit(): x-=int(c[1:]) elif c[0]=='S' and c[1:].isdigit(): y-=int(c[1:]) elif c[0]=='W' and c[1:].isdigit(): y+=int(c[1:]) elif c[0]=='D' and c[1:].isdigit(): x+=int(c[1:]) print(str(x)+','+str(y)) except: break
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int x = 0, y = 0; while (sc.hasNext()) { String[] strings = sc.nextLine().split(";"); for (String str : strings) { if (2 <= str.length() && 3 >= str.length()) { try { int dist = Integer.parseInt(str.substring(1)); switch (str.charAt(0)) { case 'A': x -= dist; break; case 'S': y -= dist; break; case 'W': y += dist; break; case 'D': x += dist; break; } } catch (NumberFormatException ignored) { } } } System.out.println(x + "," + y); } } }
x,y=0,0 a=input().split(';') for i in a: try: int(i[1:]) except: continue else: if i[0]=='A': x=x-int(i[1:]) if i[0]=='D': x=x+int(i[1:]) if i[0]=='W': y=y+int(i[1:]) if i[0]=='S': y=y-int(i[1:]) print(str(x)+','+str(y))
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { static int x, y; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; while((line = br.readLine()) != null){ String[] ops = line.split(";"); x = 0; y = 0; for(int i = 0; i < ops.length; i++) move(ops[i].toCharArray()); System.out.println(x + "," + y); } } private static void move(char[] op) { int rawX = x; int rawY = y; if(op.length <= 1) return; // 最后一个字符不是数字 if(op[op.length - 1] < '0' || op[op.length - 1] > '9') return; // 第一个字符不是方向字母 if(op[0] != 'A' && op[0] != 'S' && op[0] != 'D' && op[0] != 'W') return; int opPos = 0; int steps = 0; boolean flag = false; // 上一个单元是字母 int i = 0; while(i < op.length){ if(op[i] >= '0' && op[i] <= '9'){ steps = steps*10 + (op[i] - '0'); flag = false; }else{ // 上一次移动操作 if(flag) break; // 连续出现两个字母,无效 if(op[0] != 'A' && op[0] != 'S' && op[0] != 'D' && op[0] != 'W') break; if(op[opPos] == 'A'){ x -= steps; }else if(op[opPos] == 'D'){ x += steps; }else if(op[opPos] == 'S'){ y -= steps; }else if(op[opPos] == 'W'){ y += steps; } steps = 0; opPos = i; flag = true; } i ++; } if(i != op.length){ // 非正常退出,坐标还原 x = rawX; y = rawY; }else{ // 最后一次移动操作 if(op[opPos] == 'A'){ x -= steps; }else if(op[opPos] == 'D'){ x += steps; }else if(op[opPos] == 'S'){ y -= steps; }else if(op[opPos] == 'W'){ y += steps; } } } }
感觉题目没说清楚,就是那个空格出现的位置,好多玩家似乎都没考虑,比如 A 20;
这种,又或者是 A2 0 ;
空格可能出现的位置题目并没有明确说明,只是在例子中提到,但是好多玩家的解法里似乎都没考虑各种花式的空格插入的可能性,但似乎都过了(是我漏掉什么了吗)。
然后是非法字符,我最开始没看到数字长度最多为2,我以为是任意的整数,导致我的做法考虑得稍微多了点。
这个题 O(N) 的时间足矣,我的做法便是使用字符自动机从左开头扫描到结尾即可完成对这个字符串的分析,便类似一个在线算法,不用先分割,也不需要额外的数组去保存某个子串,向前指针走到到哪便分析到哪。
直接上C语言(含注释):
#include <stdio.h> #include <ctype.h> #include <stdbool.h> // 在C中使用bool类型 char buffer[2000]; // 全局缓冲区 int sign; // 决定方向的正负,取+1/-1 int* pxy; // 指向要修改的 x 或者 y (根据按键的方向修改) char* start; // 开始指针,指向单词的开头 char* forward; // 向前指针,指向单词的结尾 char* cur; // 当前游标位置 bool terminate; // 自动机是否终止 // 自动机启动 void startup() { // 指向 buffer 开头的前一个位置 start = forward = cur = buffer - 1; pxy = NULL; terminate = false; } // 负责获取下一个单词,以及决定自动机是否该停止 void next_word() { ++forward; while (*forward == ' ') ++forward; // 跳过下个单词开头的空格 start = forward; while (*forward != ';') { if (*forward == '\0') { terminate = true; return; } ++forward; } } // 字符自动机 void automaton(int* x, int* y) { startup(); // 每次循环处理一个单词 next_word(); while (!terminate) { // 如果开头字符不是方向,说明有误,故跳过这个单词 switch (*start) { case 'A': sign = -1; pxy = x; break; case 'D': sign = 1; pxy = x; break; case 'W': sign = 1; pxy = y; break; case 'S': sign = -1; pxy = y; break; default: next_word(); continue; } cur = start + 1; while (*cur == ' ') ++cur; // 跳过空格 if (!isdigit(*cur)) { // 如果方向后跟的不是数字则有误 next_word(); continue; } int number = *cur - '0'; while (isdigit(*++cur)) number = number * 10 + (*cur - '0'); while (*cur == ' ') ++cur; // 跳过空格 if (*cur != ';') { // 如果数字后跟的不是分号则有误 next_word(); continue; } *pxy += sign * number; next_word(); } } int main() { int x, y; while (scanf("%s", buffer) == 1) { x = y = 0; automaton(&x, &y); printf("%d,%d\n", x, y); } return 0; }