뜨개질 도안의 한 단은 코 묶음을 빈칸 없이 이어 쓴 문자열이다.
코 묶음 하나는 코의 종류를 나타내는 글자 하나와, 그 바로 뒤에 붙는 개수로 되어 있다.
개수는 1 이상의 정수이고, 개수가 1이면 숫자를 쓰지 않을 수도 있고 1이라고 쓸 수도 있다.
예를 들어 k12p2<y는 k 12코, p 2코, < 1코, y 1코이다.
뜨던 것을 돌려 뒤쪽에서 보면 코 묶음의 차례가 맨 끝 묶음부터 맨 앞 묶음까지 거꾸로 된다.
또 뒤쪽에서는 k는 p로, p는 k로, <는 >로, >는 <로 보인다. 다른 종류는 그대로 보인다.
첫 줄에 단의 수 n이, 다음 n줄에 단이 하나씩 주어진다.
단마다 뒤쪽에서 본 단을 정리한 꼴로 한 줄에 출력하라.
정리한 꼴에서는 이웃한 묶음의 종류가 같으면 하나로 합쳐 개수를 더하고, 이웃한 묶음의 종류가 모두 다를 때까지 되풀이한다.
정리한 꼴에서는 개수가 1이면 숫자를 쓰지 않고, 2 이상이면 종류 글자 바로 뒤에 쉼표 없이 숫자만 쓴다.
k12p2<y를 뒤쪽에서 보면 y>k2p12이고, k2k3pk1을 뒤쪽에서 보면 pkp5이다.
입력
1 ≤ n ≤ 20. 단 하나는 1글자 이상 10,000글자 이하이고 빈칸이 없다. 종류 글자는 영어 소문자, <, > 가운데 하나다. 적힌 개수는 1 이상 999,999,999 이하이고 0으로 시작하지 않으며 쉼표 없이 숫자만 주어진다. 단은 반드시 종류 글자로 시작한다
출력
n줄, 줄마다 뒤쪽에서 본 단의 정리한 꼴
예시 1 · stdin
3
k12p2<y
k2k3pk1
p
stdout
y>k2p12
pkp5
k
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
문자열을 뒤집는 법은 언어마다 달라요. Python s[::-1], JS·TS [...s].reverse().join("")(문자열에는 reverse가 없어 배열로 바꿔요), Java new StringBuilder(s).reverse(), C# char[]로 바꿔 Array.Reverse 한 뒤 new string(a), C++ std::reverse(s.begin(), s.end()), 크레이콘 s.뒤집기()이고, C에는 그런 함수가 없어 양 끝 글자를 맞바꾸는 반복문을 써요. 함정 ① 글자를 통째로 뒤집기만 하면 묶음이 깨져요. k12p2<y가 y<2p21k가 되어 숫자가 글자 앞으로 가고 12가 21이 돼요. 뒤집은 문자열에서는 숫자가 먼저 나오고 종류 글자가 나중에 나오니, 숫자를 모았다가 종류 글자를 만났을 때 한 묶음으로 끊어요. ② 그렇게 모은 숫자는 거꾸로예요. 숫자만 한 번 더 뒤집어야 12로 돌아와요. 그대로 수로 바꾸면 21이 되고, 100은 001이라 1이 돼요. ③ 숫자가 없는 묶음은 1코예요. 빈 문자열을 수로 바꾸면 JS·TS Number("")는 오류 없이 0을 주고, Python int("")는 ValueError, Java Long.parseLong("")은 NumberFormatException, C# long.Parse("")는 FormatException, C++ std::stoll("")은 std::invalid_argument, 크레이콘 "".수로변환()은 '수로 바꿀 수 없어요'로 멈춰요. 그래서 빈 문자열인지 먼저 물어요. ④ k와 p를 replace("k", "p") 다음 replace("p", "k")처럼 차례로 바꾸면, 처음에 k에서 바뀐 p까지 다시 k가 되어 모두 k가 돼요. 한 글자씩 보며 한 번만 바꿔요. ⑤ 뒤집으면 이웃이 달라지지는 않지만, 입력이 k2k3처럼 정리되지 않은 꼴일 수 있어서 같은 종류가 이어지면 합쳐야 해요. 이때 1코와 1코가 합쳐지면 2를 써야 하고, 개수가 1일 때만 숫자를 빼요. ⑥ 합친 개수는 21억을 넘을 수 있어요(999,999,999코짜리 묶음 세 개면 넘어요). C·C++ long long, Java·C# long에 더해요. JS·TS·크레이콘의 수는 2^53까지 정확하고 Python int는 넘치지 않아요.
Pythonmain.py · 26 줄
import sysMIRROR = {"k": "p", "p": "k", "<": ">", ">": "<"}def from_back(row): kinds, counts = [], [] digits = "" for ch in row[::-1]: # 문자열을 통째로 뒤집어 맨 끝 글자부터 본다 if ch.isdigit(): digits += ch # 개수의 숫자도 거꾸로 모인다 continue count = int(digits[::-1]) if digits else 1 # 숫자만 다시 뒤집어 수로 바꾼다 digits = "" kind = MIRROR.get(ch, ch) # 한 글자씩 한 번만 바꾼다 if kinds and kinds[-1] == kind: counts[-1] += count # 이웃한 같은 코는 합친다 else: kinds.append(kind) counts.append(count) return "".join(k + (str(c) if c > 1 else "") for k, c in zip(kinds, counts))lines = sys.stdin.read().split("\n")n = int(lines[0])print("\n".join(from_back(lines[1 + i].strip()) for i in range(n)))
JavaScriptmain.js · 31 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const MIRROR = { k: "p", p: "k", "<": ">", ">": "<" };function fromBack(row) { const kinds = []; const counts = []; let digits = ""; // 문자열에는 reverse가 없어서 글자 배열로 바꿔 뒤집는다 for (const ch of [...row].reverse().join("")) { if (ch >= "0" && ch <= "9") { digits += ch; // 개수의 숫자도 거꾸로 모인다 continue; } // 숫자만 다시 뒤집어 수로 바꾼다. Number("")는 0이라 따로 1로 둔다 const count = digits === "" ? 1 : Number([...digits].reverse().join("")); digits = ""; const kind = MIRROR[ch] ?? ch; if (kinds.length > 0 && kinds[kinds.length - 1] === kind) { counts[counts.length - 1] += count; // 이웃한 같은 코는 합친다 } else { kinds.push(kind); counts.push(count); } } return kinds.map((k, i) => k + (counts[i] > 1 ? counts[i] : "")).join("");}const out = [];for (let i = 1; i <= n; i++) out.push(fromBack(lines[i].trim()));console.log(out.join("\n"));
TypeScriptmain.ts · 33 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const MIRROR: Record<string, string> = { k: "p", p: "k", "<": ">", ">": "<" };function fromBack(row: string): string { const kinds: string[] = []; const counts: number[] = []; let digits = ""; // 문자열에는 reverse가 없어서 글자 배열로 바꿔 뒤집는다 for (const ch of [...row].reverse().join("")) { if (ch >= "0" && ch <= "9") { digits += ch; // 개수의 숫자도 거꾸로 모인다 continue; } // 숫자만 다시 뒤집어 수로 바꾼다. Number("")는 0이라 따로 1로 둔다 const count: number = digits === "" ? 1 : Number([...digits].reverse().join("")); digits = ""; const kind: string = MIRROR[ch] ?? ch; if (kinds.length > 0 && kinds[kinds.length - 1] === kind) { counts[counts.length - 1] += count; // 이웃한 같은 코는 합친다 } else { kinds.push(kind); counts.push(count); } } return kinds.map((k, i) => k + (counts[i] > 1 ? String(counts[i]) : "")).join("");}const out: string[] = [];for (let i = 1; i <= n; i++) out.push(fromBack(lines[i].trim()));console.log(out.join("\n"));
JavaMain.java · 56 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;public class Main { static char mirror(char ch) { switch (ch) { case 'k': return 'p'; case 'p': return 'k'; case '<': return '>'; case '>': return '<'; default: return ch; } } static String fromBack(String row) { List<Character> kinds = new ArrayList<>(); List<Long> counts = new ArrayList<>(); // 합친 개수는 int를 넘을 수 있다 StringBuilder digits = new StringBuilder(); String back = new StringBuilder(row).reverse().toString(); // 문자열을 통째로 뒤집는다 for (int i = 0; i < back.length(); i++) { char ch = back.charAt(i); if (Character.isDigit(ch)) { digits.append(ch); // 개수의 숫자도 거꾸로 모인다 continue; } // 숫자만 다시 뒤집어 수로 바꾼다 long count = digits.length() == 0 ? 1 : Long.parseLong(digits.reverse().toString()); digits.setLength(0); char kind = mirror(ch); int last = kinds.size() - 1; if (last >= 0 && kinds.get(last) == kind) { counts.set(last, counts.get(last) + count); // 이웃한 같은 코는 합친다 } else { kinds.add(kind); counts.add(count); } } StringBuilder out = new StringBuilder(); for (int i = 0; i < kinds.size(); i++) { out.append(kinds.get(i)); if (counts.get(i) > 1) out.append(counts.get(i)); } return out.toString(); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int i = 0; i < n; i++) out.append(fromBack(in.readLine().trim())).append('\n'); System.out.print(out); }}
C#Main.cs · 66 줄
using System;using System.Collections.Generic;using System.Text;class Program{ static char Mirror(char ch) => ch switch { 'k' => 'p', 'p' => 'k', '<' => '>', '>' => '<', _ => ch, }; static string Reversed(string s) { char[] a = s.ToCharArray(); // 문자열에는 Reverse가 없어서 char[]로 바꿔 뒤집는다 Array.Reverse(a); return new string(a); } static string FromBack(string row) { var kinds = new List<char>(); var counts = new List<long>(); // 합친 개수는 int를 넘을 수 있다 string digits = ""; foreach (char ch in Reversed(row)) { if (char.IsDigit(ch)) { digits += ch; // 개수의 숫자도 거꾸로 모인다 continue; } // 숫자만 다시 뒤집어 수로 바꾼다 long count = digits == "" ? 1 : long.Parse(Reversed(digits)); digits = ""; char kind = Mirror(ch); int last = kinds.Count - 1; if (last >= 0 && kinds[last] == kind) { counts[last] += count; // 이웃한 같은 코는 합친다 } else { kinds.Add(kind); counts.Add(count); } } var sb = new StringBuilder(); for (int i = 0; i < kinds.Count; i++) { sb.Append(kinds[i]); if (counts[i] > 1) sb.Append(counts[i]); } return sb.ToString(); } static void Main() { int n = int.Parse(Console.ReadLine()); var sb = new StringBuilder(); for (int i = 0; i < n; i++) sb.Append(FromBack(Console.ReadLine().Trim())).Append('\n'); Console.Write(sb); }}
C++main.cpp · 57 줄
#include <algorithm>#include <iostream>#include <string>#include <utility>#include <vector>static char mirror(char ch) { switch (ch) { case 'k': return 'p'; case 'p': return 'k'; case '<': return '>'; case '>': return '<'; default: return ch; }}static std::string fromBack(std::string row) { std::vector<std::pair<char, long long>> runs; // 합친 개수는 int를 넘을 수 있다 std::string digits; std::reverse(row.begin(), row.end()); // 문자열을 통째로 뒤집는다 for (char ch : row) { if (ch >= '0' && ch <= '9') { digits += ch; // 개수의 숫자도 거꾸로 모인다 continue; } long long count = 1; if (!digits.empty()) { std::reverse(digits.begin(), digits.end()); // 숫자만 다시 뒤집는다 count = std::stoll(digits); digits.clear(); } char kind = mirror(ch); if (!runs.empty() && runs.back().first == kind) { runs.back().second += count; // 이웃한 같은 코는 합친다 } else { runs.emplace_back(kind, count); } } std::string out; for (const auto& [kind, count] : runs) { out += kind; if (count > 1) out += std::to_string(count); } return out;}int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n; std::cin >> n; std::string row; for (int i = 0; i < n; i++) { std::cin >> row; std::cout << fromBack(row) << '\n'; }}
Cmain.c · 63 줄
#include <stdio.h>#include <string.h>#define MAXLEN 10000static char row[MAXLEN + 2];static char kinds[MAXLEN];static long long counts[MAXLEN]; /* 합친 개수는 int를 넘을 수 있다 */static char mirror(char ch) { switch (ch) { case 'k': return 'p'; case 'p': return 'k'; case '<': return '>'; case '>': return '<'; default: return ch; }}/* C에는 문자열을 뒤집는 함수가 없다: 양 끝 글자를 맞바꾸며 가운데로 온다 */static void reverse(char *s, int len) { for (int l = 0, r = len - 1; l < r; l++, r--) { char t = s[l]; s[l] = s[r]; s[r] = t; }}int main(void) { int n; scanf("%d", &n); for (int line = 0; line < n; line++) { scanf("%10001s", row); int len = (int)strlen(row); reverse(row, len); int m = 0; /* 묶음 수 */ int start = 0; /* 거꾸로 모인 숫자가 시작하는 자리 */ for (int i = 0; i < len; i++) { if (row[i] >= '0' && row[i] <= '9') continue; long long count = 1; if (i > start) { reverse(row + start, i - start); /* 숫자만 다시 뒤집는다 */ count = 0; for (int j = start; j < i; j++) count = count * 10 + (row[j] - '0'); } start = i + 1; char kind = mirror(row[i]); if (m > 0 && kinds[m - 1] == kind) { counts[m - 1] += count; /* 이웃한 같은 코는 합친다 */ } else { kinds[m] = kind; counts[m] = count; m++; } } for (int i = 0; i < m; i++) { putchar(kinds[i]); if (counts[i] > 1) printf("%lld", counts[i]); } putchar('\n'); } return 0;}
Craykonmain.cray · 70 줄
거울(ch){ 선택 (ch) { 경우 "k": 돌려주기 "p"; 경우 "p": 돌려주기 "k"; 경우 "<": 돌려주기 ">"; 경우 ">": 돌려주기 "<"; } 돌려주기 ch;}뒤쪽에서(row){ kinds = []; counts = []; digits = ""; // 문자열을 통째로 뒤집어 맨 끝 글자부터 본다 각각 (ch 에서 row.뒤집기()) { 만약 (ch >= "0" && ch <= "9") { // 개수의 숫자도 거꾸로 모인다 digits = digits + ch; 건너뛰기; } count = 1; 만약 (digits != "") { // 숫자만 다시 뒤집어 수로 바꾼다 count = digits.뒤집기().수로변환(); digits = ""; } kind = 거울(ch); last = kinds.개수 - 1; 만약 (last >= 0 && kinds[last] == kind) { // 이웃한 같은 코는 합친다 counts[last] = counts[last] + count; } 아니면 { kinds.넣기(kind); counts.넣기(count); } } parts = []; 반복 (i = 0; i < kinds.개수; i++) { 만약 (counts[i] > 1) { parts.넣기(kinds[i] + counts[i]); } 아니면 { parts.넣기(kinds[i]); } } 돌려주기 parts.잇기("");}n = 콘솔.줄읽기().수로변환();반복 (i = 0; i < n; i++){ 콘솔.쓰기(뒤쪽에서(콘솔.줄읽기().공백제거()));}