You are given t strings in which invisible characters are written with visible ones.
Read each string from the left and decode it by the rules below, then find the codes (ASCII numbers) of the decoded characters.
\n becomes one character with code 10, \t code 9, \s code 32, and \\ (two backslashes) code 92.
If the two characters right after \x are both hexadecimal characters, these four characters become one character whose code is that two-digit hexadecimal value (0 to 255). The hexadecimal characters are 0 to 9, a to f and A to F.
^ followed by an uppercase English letter becomes one character: ^A is code 1, ^B is code 2, …, ^Z is code 26.
^^ becomes one character with code 94 (^).
Any other character stays as it is, and its code is its ASCII number.
If any of the following is met while decoding, the whole string is invalid.
\ is followed by nothing, or by a character other than n, t, s, \ and x (an uppercase letter as in \N is also invalid).
\x has fewer than two characters left after it, or one of the two characters right after it is not a hexadecimal character.
^ is followed by nothing, or by a character that is neither an uppercase English letter nor ^ (a lowercase letter as in ^a is also invalid).
The first line gives t, and each of the next t lines gives one string.
For each string print one line with the codes of the decoded characters in decimal, in order, separated by single spaces.
For an invalid string print only error instead of the codes.
Input
1 ≤ t ≤ 100. Each string has length from 1 to 100. The strings consist only of characters with ASCII numbers 33 to 126 (no spaces)
Output
One line per string: the codes separated by single spaces, or error
Example 1 · stdin
5
Hi\n
^A^Z^^
\x41\xfF\\x
a\
\x4g
stdout
72 105 10
1 26 94
65 255 92 120
error
error
main.py
Error List00F8 ↓ · ⇧F8 ↑
Input (stdin)
When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).
$ Ready
Open this on a computer to write and run code. On mobile you can read the problem and the solutions.
In other languagesShow solutions by language · 8 languages
Languages differ in how they treat a character as a number. A C or C++ char is a small integer, and a Java or C# char also calculates like a number, so c - '0', c - 'a' + 10 and c - 'A' + 1 work directly and the result is an int. Python has no character type, only strings of length 1, so you must convert with ord(c) - ord('a') ('b' - 'a' is a TypeError). JS and TS also convert with c.charCodeAt(0); without it "b" - "a" silently becomes NaN. In Craykon it is Str.Code(c), and subtracting strings stops the program. Range checks are c >= 'a' && c <= 'f' in the C family and 'a' <= c <= 'f' in Python, while JS, TS and Craykon compare one-character strings with >=. A single backslash is written twice, as '\\' or "\\", in all eight languages. Trap 1: the hexadecimal letters a to f need 10 added to c - 'a', and both uppercase and lowercase must be accepted. Trap 2: ^A is 1, not 0 (c - 'A' + 1). Trap 3: always check that the character after ^ is in A to Z; otherwise ^a becomes 33. Trap 4: values go up to 255. A C/C++ signed char and a Java byte only reach 127, so \xff becomes -1. Whether C's plain char is signed depends on the machine. Store the value in an int. Trap 5: functions that convert two characters to a number are lenient: JS parseInt("4g", 16) is 4 and parseInt("+f", 16) is 15; Python int("+f", 16) is 15 and int("-1", 16) is -1. Check each character yourself. Trap 6: after a \ or ^ at the end of a line there is no character. Reading the next one without checking stops Java charAt, C# s[i], Python s[i] and Craykon with an error, gives undefined in JS and TS, and in C reads the '\0' that ends the string (never read further than that).
Pythonmain.py · 57 lines
import sysdef hex_value(c): """16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1""" if "0" <= c <= "9": return ord(c) - ord("0") if "a" <= c <= "f": return ord(c) - ord("a") + 10 if "A" <= c <= "F": return ord(c) - ord("A") + 10 return -1SIMPLE = {"n": 10, "t": 9, "s": 32, "\\": 92}def decode(s): """글자 코드 목록을 돌려준다. 잘못된 표기가 있으면 None""" codes = [] i = 0 while i < len(s): c = s[i] nxt = s[i + 1] if i + 1 < len(s) else "" # 뒤에 글자가 없으면 빈 문자열 if c == "\\": if nxt in SIMPLE: codes.append(SIMPLE[nxt]) i += 2 elif nxt == "x" and i + 3 < len(s): hi, lo = hex_value(s[i + 2]), hex_value(s[i + 3]) if hi < 0 or lo < 0: return None codes.append(hi * 16 + lo) i += 4 else: return None elif c == "^": if nxt == "^": codes.append(ord("^")) elif "A" <= nxt <= "Z": codes.append(ord(nxt) - ord("A") + 1) else: return None i += 2 else: codes.append(ord(c)) i += 1 return codeslines = sys.stdin.read().split("\n")t = int(lines[0])out = []for s in lines[1:1 + t]: codes = decode(s.strip()) out.append("error" if codes is None else " ".join(map(str, codes)))print("\n".join(out))
JavaScriptmain.js · 53 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const code = (c) => c.charCodeAt(0);// 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1function hexValue(c) { if (c >= "0" && c <= "9") return code(c) - code("0"); if (c >= "a" && c <= "f") return code(c) - code("a") + 10; if (c >= "A" && c <= "F") return code(c) - code("A") + 10; return -1;}const SIMPLE = { n: 10, t: 9, s: 32, "\\": 92 };// 글자 코드 배열을 돌려준다. 잘못된 표기가 있으면 nullfunction decode(s) { const codes = []; let i = 0; while (i < s.length) { const c = s[i]; const next = i + 1 < s.length ? s[i + 1] : ""; // 뒤에 글자가 없으면 빈 문자열 if (c === "\\") { if (Object.hasOwn(SIMPLE, next)) { codes.push(SIMPLE[next]); i += 2; } else if (next === "x" && i + 3 < s.length) { const hi = hexValue(s[i + 2]), lo = hexValue(s[i + 3]); if (hi < 0 || lo < 0) return null; codes.push(hi * 16 + lo); i += 4; } else { return null; } } else if (c === "^") { if (next === "^") codes.push(code("^")); else if (next >= "A" && next <= "Z") codes.push(code(next) - code("A") + 1); else return null; i += 2; } else { codes.push(code(c)); i += 1; } } return codes;}const t = Number(lines[0]);const out = [];for (let k = 1; k <= t; k++) { const codes = decode(lines[k].trim()); out.push(codes === null ? "error" : codes.join(" "));}console.log(out.join("\n"));
TypeScriptmain.ts · 56 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const code = (c: string): number => c.charCodeAt(0);// 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1function hexValue(c: string): number { if (c >= "0" && c <= "9") return code(c) - code("0"); if (c >= "a" && c <= "f") return code(c) - code("a") + 10; if (c >= "A" && c <= "F") return code(c) - code("A") + 10; return -1;}const SIMPLE = new Map<string, number>([["n", 10], ["t", 9], ["s", 32], ["\\", 92]]);// 글자 코드 배열을 돌려준다. 잘못된 표기가 있으면 nullfunction decode(s: string): number[] | null { const codes: number[] = []; let i = 0; while (i < s.length) { const c = s[i]; const next = i + 1 < s.length ? s[i + 1] : ""; // 뒤에 글자가 없으면 빈 문자열 if (c === "\\") { const simple = SIMPLE.get(next); if (simple !== undefined) { codes.push(simple); i += 2; } else if (next === "x" && i + 3 < s.length) { const hi = hexValue(s[i + 2]), lo = hexValue(s[i + 3]); if (hi < 0 || lo < 0) return null; codes.push(hi * 16 + lo); i += 4; } else { return null; } } else if (c === "^") { if (next === "^") codes.push(code("^")); else if (next >= "A" && next <= "Z") codes.push(code(next) - code("A") + 1); else return null; i += 2; } else { codes.push(code(c)); i += 1; } } return codes;}const t = Number(lines[0]);const out: string[] = [];for (let k = 1; k <= t; k++) { const codes = decode(lines[k].trim()); out.push(codes === null ? "error" : codes.join(" "));}console.log(out.join("\n"));
JavaMain.java · 60 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main { // 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1 static int hexValue(char c) { if (c >= '0' && c <= '9') return c - '0'; // char끼리 빼면 int가 된다 if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } // 글자 코드를 빈칸으로 이어 돌려준다. 잘못된 표기가 있으면 null static String decode(String s) { StringBuilder codes = new StringBuilder(); int n = s.length(), i = 0; while (i < n) { char c = s.charAt(i); char next = i + 1 < n ? s.charAt(i + 1) : '\0'; // 뒤에 글자가 없으면 코드 0인 글자 int value; if (c == '\\') { if (next == 'n') { value = '\n'; i += 2; } else if (next == 't') { value = '\t'; i += 2; } else if (next == 's') { value = ' '; i += 2; } else if (next == '\\') { value = '\\'; i += 2; } else if (next == 'x' && i + 3 < n) { int hi = hexValue(s.charAt(i + 2)), lo = hexValue(s.charAt(i + 3)); if (hi < 0 || lo < 0) return null; value = hi * 16 + lo; i += 4; } else { return null; } } else if (c == '^') { if (next == '^') value = '^'; else if (next >= 'A' && next <= 'Z') value = next - 'A' + 1; else return null; i += 2; } else { value = c; // char는 int로 저절로 넓어진다 i += 1; } if (codes.length() > 0) codes.append(' '); codes.append(value); } return codes.toString(); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int t = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int k = 0; k < t; k++) { String codes = decode(in.readLine().trim()); out.append(codes == null ? "error" : codes).append('\n'); } System.out.print(out); }}
C#Main.cs · 67 lines
using System;using System.Collections.Generic;using System.Text;class Program{ // 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1 static int HexValue(char c) { if (c >= '0' && c <= '9') return c - '0'; // char끼리 빼면 int가 된다 if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } // 글자 코드 목록을 돌려준다. 잘못된 표기가 있으면 null static List<int> Decode(string s) { var codes = new List<int>(); int n = s.Length, i = 0; while (i < n) { char c = s[i]; char next = i + 1 < n ? s[i + 1] : '\0'; // 뒤에 글자가 없으면 코드 0인 글자 if (c == '\\') { if (next == 'n') { codes.Add('\n'); i += 2; } else if (next == 't') { codes.Add('\t'); i += 2; } else if (next == 's') { codes.Add(' '); i += 2; } else if (next == '\\') { codes.Add('\\'); i += 2; } else if (next == 'x' && i + 3 < n) { int hi = HexValue(s[i + 2]), lo = HexValue(s[i + 3]); if (hi < 0 || lo < 0) return null; codes.Add(hi * 16 + lo); i += 4; } else return null; } else if (c == '^') { if (next == '^') codes.Add('^'); else if (next >= 'A' && next <= 'Z') codes.Add(next - 'A' + 1); else return null; i += 2; } else { codes.Add(c); // char는 int로 저절로 넓어진다 i += 1; } } return codes; } static void Main() { int t = int.Parse(Console.ReadLine().Trim()); var output = new StringBuilder(); for (int k = 0; k < t; k++) { List<int> codes = Decode(Console.ReadLine().Trim()); output.Append(codes == null ? "error" : string.Join(" ", codes)).Append('\n'); } Console.Write(output); }}
C++main.cpp · 62 lines
#include <iostream>#include <optional>#include <string>#include <vector>// 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1int hexValue(char c) { if (c >= '0' && c <= '9') return c - '0'; // char는 작은 정수라서 바로 뺄 수 있다 if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1;}// 글자 코드들을 돌려준다. 잘못된 표기가 있으면 값이 없다(std::nullopt)std::optional<std::vector<int>> decode(const std::string& s) { std::vector<int> codes; const std::size_t n = s.size(); std::size_t i = 0; while (i < n) { const char c = s[i]; const char next = i + 1 < n ? s[i + 1] : '\0'; // 뒤에 글자가 없으면 코드 0인 글자 if (c == '\\') { if (next == 'n') { codes.push_back('\n'); i += 2; } else if (next == 't') { codes.push_back('\t'); i += 2; } else if (next == 's') { codes.push_back(' '); i += 2; } else if (next == '\\') { codes.push_back('\\'); i += 2; } else if (next == 'x' && i + 3 < n) { const int hi = hexValue(s[i + 2]), lo = hexValue(s[i + 3]); if (hi < 0 || lo < 0) return std::nullopt; codes.push_back(hi * 16 + lo); // 255까지라 char가 아니라 int에 담는다 i += 4; } else { return std::nullopt; } } else if (c == '^') { if (next == '^') codes.push_back('^'); else if (next >= 'A' && next <= 'Z') codes.push_back(next - 'A' + 1); else return std::nullopt; i += 2; } else { codes.push_back(c); i += 1; } } return codes;}int main() { int t; std::cin >> t; while (t-- > 0) { std::string s; std::cin >> s; const auto codes = decode(s); if (!codes) { std::cout << "error\n"; continue; } for (std::size_t i = 0; i < codes->size(); i++) std::cout << (i ? " " : "") << (*codes)[i]; std::cout << '\n'; }}
Cmain.c · 60 lines
#include <stdio.h>#include <string.h>/* 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1 */static int hex_value(char c) { if (c >= '0' && c <= '9') return c - '0'; /* char는 작은 정수라서 바로 뺄 수 있다 */ if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1;}/* codes에 글자 코드를 채우고 개수를 돌려준다. 잘못된 표기가 있으면 -1 */static int decode(const char *s, int *codes) { int n = (int)strlen(s), count = 0, i = 0; while (i < n) { char c = s[i]; char next = s[i + 1]; /* 뒤에 글자가 없으면 문자열 끝의 '\0' */ if (c == '\\') { if (next == 'n') { codes[count++] = '\n'; i += 2; } else if (next == 't') { codes[count++] = '\t'; i += 2; } else if (next == 's') { codes[count++] = ' '; i += 2; } else if (next == '\\') { codes[count++] = '\\'; i += 2; } else if (next == 'x' && i + 3 < n) { int hi = hex_value(s[i + 2]), lo = hex_value(s[i + 3]); if (hi < 0 || lo < 0) return -1; codes[count++] = hi * 16 + lo; /* 255까지라 char가 아니라 int에 담는다 */ i += 4; } else { return -1; } } else if (c == '^') { if (next == '^') codes[count++] = '^'; else if (next >= 'A' && next <= 'Z') codes[count++] = next - 'A' + 1; else return -1; i += 2; } else { codes[count++] = c; i += 1; } } return count;}int main(void) { int t; scanf("%d", &t); while (t-- > 0) { char s[101]; int codes[100]; scanf("%100s", s); int count = decode(s, codes); if (count < 0) { printf("error\n"); continue; } for (int i = 0; i < count; i++) printf(i ? " %d" : "%d", codes[i]); printf("\n"); } return 0;}
Craykonmain.cray · 109 lines
// 16진수 글자 하나의 값(0 ~ 15). 16진수 글자가 아니면 -1십육진값(c){ if (c >= "0" && c <= "9") { return Str.Code(c) - Str.Code("0"); } if (c >= "a" && c <= "f") { return Str.Code(c) - Str.Code("a") + 10; } if (c >= "A" && c <= "F") { return Str.Code(c) - Str.Code("A") + 10; } return -1;}// 글자 코드 목록을 돌려준다. 잘못된 표기가 있으면 빈값풀기(s){ codes = []; n = s.Length; i = 0; while (i < n) { c = s[i]; // 뒤에 글자가 없으면 빈 문자열 next = ""; if (i + 1 < n) { next = s[i + 1]; } if (c == "\\") { if (next == "n") { codes.Add(10); i += 2; } else if (next == "t") { codes.Add(9); i += 2; } else if (next == "s") { codes.Add(32); i += 2; } else if (next == "\\") { codes.Add(92); i += 2; } else if (next == "x" && i + 3 < n) { hi = 십육진값(s[i + 2]); lo = 십육진값(s[i + 3]); if (hi < 0 || lo < 0) { return null; } codes.Add(hi * 16 + lo); i += 4; } else { return null; } } else if (c == "^") { if (next == "^") { codes.Add(Str.Code("^")); } else if (next >= "A" && next <= "Z") { codes.Add(Str.Code(next) - Str.Code("A") + 1); } else { return null; } i += 2; } else { codes.Add(Str.Code(c)); i += 1; } } return codes;}t = Console.ReadLine().ToNumber();for (k = 0; k < t; k++){ codes = 풀기(Console.ReadLine().Trim()); if (codes == null) { Console.WriteLine("error"); } else { Console.WriteLine(codes.Join(" ")); }}