You are given the log of output commands a program used to write on a terminal screen.
At first the screen has a single empty line, and the cursor is at column 1 of that line.
Columns of a line are counted from the left as 1, 2, 3, ….
There are six commands.
write s writes the characters of the string s one by one from the left, without changing lines.
For each character, if the cursor column already holds a character, it is overwritten by the new one; if the cursor is just after the last character of the line, the character is appended at the end of the line. Then the cursor moves one column right.
No command ever moves the cursor further right than just after the last character of the line, so writing a character is always one of these two cases.
print s does write s and then nl.
nl creates a new empty line below the current line and moves the cursor to column 1 of the new line.
cr moves the cursor to column 1 of the current line. It does not erase any characters.
back k moves the cursor k columns left. The cursor never goes left of column 1; it stops there. It does not erase any characters.
erase deletes the character at the cursor column and every character to its right on the current line. The cursor does not move.
The cursor is always on the bottom line.
The first line gives the number of commands q, and the next q lines give one command each. The command name and s or k are separated by one space.
After processing all commands, print the lines of the screen from top to bottom, one per line.
A line with no characters is printed as an empty line. However, if the bottom line is empty, do not print it.
Input
1 ≤ q ≤ 2,000. s is a string of 1 to 30 non-space ASCII characters (codes 33 to 126). 1 ≤ k ≤ 1,000. No line ever exceeds 1,000 characters. At least one character remains on the screen.
12
write abcdef
back 2
write XY
write Z
back 100
write 1
nl
nl
write hello
back 3
erase
write p!
stdout
1bcdXYZ
hep!
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
Writing without a newline: Python print(s, end="") or sys.stdout.write(s), JS/TS process.stdout.write(s) (console.log always ends the line), Java System.out.print (println ends the line), C# Console.Write (WriteLine ends the line), C fputs(s, stdout) or printf("%s", s), C++ std::cout << s (the line ends only when you add std::endl or '\n'), Craykon Console.Write(s) (Console.WriteLine ends the line). The cr here is a real terminal's \r. People rewrite a progress line with something like print(f"\r{p}%", end=""), and trap ① \r only moves the cursor; it does not clear the line. Overwriting with shorter text leaves the tail of the longer text, so writing done over loading... shows doneing.... Real programs pad with spaces or send \x1b[K, which is this problem's erase. ② back stops at column 1. If you keep the cursor as a 0-based number and just subtract, Python's cur[-1] is the last cell, so it silently overwrites the wrong character, and C/C++ write outside the array. In C++, a size_t cursor has no negatives and wraps to a huge number, so compare before subtracting. ③ erase only removes the cursor column and what is to its right: Python del cur[col:], JS/TS cur.length = col, Java setLength(col), C# Length = col, C++ resize(col), Craykon GetRange(0, col). ④ Overwriting is not inserting. C++ insert or Python insert pushes the rest to the right. ⑤ The names are confusing: this problem's print ends the line, but Java's print and C#'s Write do not. ⑥ In C, printing the collected line with printf(cur) reads % as a format, so 50%d… comes out broken. Use fputs or printf("%s", cur).
Pythonmain.py · 46 lines
import syslines = sys.stdin.read().split("\n")q = int(lines[0])screen = [] # 다 쓴 줄들cur = [] # 지금 줄의 글자들col = 0 # 커서 칸(0부터)def write(s): global col for ch in s: if col < len(cur): cur[col] = ch # 글자가 있으면 덮어쓴다 else: cur.append(ch) # 줄 끝 바로 뒤면 붙인다 col += 1def newline(): global cur, col screen.append("".join(cur)) cur = [] col = 0for line in lines[1:1 + q]: p = line.split() cmd = p[0] if cmd == "write": write(p[1]) elif cmd == "print": write(p[1]) newline() elif cmd == "nl": newline() elif cmd == "cr": col = 0 # 글자는 그대로 두고 커서만 맨 앞으로 elif cmd == "back": col = max(0, col - int(p[1])) # 음수 자리는 맨 끝 칸이 되니 0에서 멈춘다 else: # erase del cur[col:]if cur: screen.append("".join(cur))sys.stdout.write("".join(row + "\n" for row in screen))
JavaScriptmain.js · 33 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[0]);const screen = []; // 다 쓴 줄들let cur = []; // 지금 줄의 글자들let col = 0; // 커서 칸(0부터)function write(s) { for (const ch of s) { cur[col] = ch; // 글자가 있으면 덮어쓰고, 줄 끝 바로 뒤면 붙인다 col++; }}function newline() { screen.push(cur.join("")); cur = []; col = 0;}for (const line of lines.slice(1, 1 + q)) { const [cmd, arg] = line.trim().split(" "); if (cmd === "write") write(arg); else if (cmd === "print") { write(arg); newline(); } else if (cmd === "nl") newline(); else if (cmd === "cr") col = 0; // 글자는 그대로, 커서만 맨 앞으로 else if (cmd === "back") col = Math.max(0, col - Number(arg)); else cur.length = col; // erase: 커서 칸부터 뒤를 잘라 낸다}if (cur.length > 0) screen.push(cur.join(""));// console.log는 늘 줄을 바꾼다. 줄 바꿈 없이 쓰려면 process.stdout.writeprocess.stdout.write(screen.map((row) => row + "\n").join(""));
TypeScriptmain.ts · 35 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const q = Number(lines[0]);const screen: string[] = []; // 다 쓴 줄들let cur: string[] = []; // 지금 줄의 글자들let col = 0; // 커서 칸(0부터)function write(s: string): void { for (const ch of s) { cur[col] = ch; // 글자가 있으면 덮어쓰고, 줄 끝 바로 뒤면 붙인다 col++; }}function newline(): void { screen.push(cur.join("")); cur = []; col = 0;}for (const line of lines.slice(1, 1 + q)) { const [cmd, arg] = line.trim().split(" "); if (cmd === "write") write(arg); else if (cmd === "print") { write(arg); newline(); } else if (cmd === "nl") newline(); else if (cmd === "cr") col = 0; // 글자는 그대로, 커서만 맨 앞으로 else if (cmd === "back") col = Math.max(0, col - Number(arg)); else cur.length = col; // erase: 커서 칸부터 뒤를 잘라 낸다}if (cur.length > 0) screen.push(cur.join(""));// console.log는 늘 줄을 바꾼다. 줄 바꿈 없이 쓰려면 process.stdout.writeprocess.stdout.write(screen.map((row) => row + "\n").join(""));
JavaMain.java · 40 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;public class Main { static StringBuilder cur = new StringBuilder(); // 지금 줄 static int col = 0; // 커서 칸(0부터) static void write(String s) { for (char ch : s.toCharArray()) { if (col < cur.length()) cur.setCharAt(col, ch); // 덮어쓴다 else cur.append(ch); // 줄 끝 바로 뒤면 붙인다 col++; } } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(System.out); int q = Integer.parseInt(in.readLine().trim()); for (int t = 0; t < q; t++) { String[] p = in.readLine().trim().split(" "); switch (p[0]) { case "write" -> write(p[1]); case "print", "nl" -> { if (p[0].equals("print")) write(p[1]); out.println(cur); // 다 쓴 줄은 바로 내보낸다 cur.setLength(0); col = 0; } case "cr" -> col = 0; // 글자는 그대로, 커서만 맨 앞으로 case "back" -> col = Math.max(0, col - Integer.parseInt(p[1])); default -> cur.setLength(col); // erase } } if (cur.length() > 0) out.println(cur); out.flush(); }}
C#Main.cs · 58 lines
using System;using System.IO;using System.Text;class Program{ static StringBuilder cur = new StringBuilder(); // 지금 줄 static int col = 0; // 커서 칸(0부터) static void Write(string s) { foreach (char ch in s) { if (col < cur.Length) cur[col] = ch; // 덮어쓴다 else cur.Append(ch); // 줄 끝 바로 뒤면 붙인다 col++; } } static void Main() { var output = new StreamWriter(Console.OpenStandardOutput()); int q = int.Parse(Console.ReadLine().Trim()); for (int t = 0; t < q; t++) { string[] p = Console.ReadLine().Trim().Split(' '); switch (p[0]) { case "write": Write(p[1]); break; case "print": case "nl": if (p[0] == "print") Write(p[1]); output.Write(cur.ToString()); output.Write('\n'); cur.Clear(); col = 0; break; case "cr": col = 0; // 글자는 그대로, 커서만 맨 앞으로 break; case "back": col = Math.Max(0, col - int.Parse(p[1])); break; default: // erase cur.Length = col; break; } } if (cur.Length > 0) { output.Write(cur.ToString()); output.Write('\n'); } output.Flush(); }}
C++main.cpp · 41 lines
#include <algorithm>#include <iostream>#include <string>int main() { std::ios::sync_with_stdio(false); int q; std::cin >> q; std::string cur; // 지금 줄 std::size_t col = 0; // 커서 칸(0부터) std::string out; for (int t = 0; t < q; t++) { std::string cmd, arg; std::cin >> cmd; if (cmd == "write" || cmd == "print") { std::cin >> arg; for (char ch : arg) { if (col < cur.size()) cur[col] = ch; // 덮어쓴다 else cur += ch; // 줄 끝 바로 뒤면 붙인다 col++; } } if (cmd == "print" || cmd == "nl") { out += cur; out += '\n'; cur.clear(); col = 0; } else if (cmd == "cr") { col = 0; // 글자는 그대로, 커서만 맨 앞으로 } else if (cmd == "back") { std::size_t k; std::cin >> k; col = col > k ? col - k : 0; // size_t는 음수가 없어서 빼기 전에 비교한다 } else if (cmd == "erase") { cur.resize(col); } } if (!cur.empty()) out += cur + '\n'; std::cout << out; return 0;}
Cmain.c · 45 lines
#include <stdio.h>#include <string.h>static char cur[1001]; /* 지금 줄(한 줄은 1,000칸 이하) */static int len = 0, col = 0; /* 줄 길이, 커서 칸(0부터) */static void write_text(const char *s) { for (; *s; s++) { cur[col++] = *s; /* 덮어쓰거나, 줄 끝 바로 뒤면 붙인다 */ if (col > len) len = col; }}static void newline(void) { cur[len] = '\0'; fputs(cur, stdout); /* printf(cur)는 안 된다: %를 서식으로 읽는다 */ putchar('\n'); len = col = 0;}int main(void) { int q; char cmd[8], arg[32]; scanf("%d", &q); for (int t = 0; t < q; t++) { scanf("%7s", cmd); if (strcmp(cmd, "write") == 0 || strcmp(cmd, "print") == 0) { scanf("%31s", arg); write_text(arg); if (cmd[0] == 'p') newline(); } else if (strcmp(cmd, "nl") == 0) { newline(); } else if (strcmp(cmd, "cr") == 0) { col = 0; } else if (strcmp(cmd, "back") == 0) { int k; scanf("%d", &k); col = col > k ? col - k : 0; } else { /* erase */ len = col; } } if (len > 0) newline(); return 0;}
Craykonmain.cray · 57 lines
q = Console.ReadLine().ToNumber();cur = []; // 지금 줄의 글자들col = 0; // 커서 칸(0부터)쓰기(s){ foreach (ch in s) { if (col < cur.Count) { cur[col] = ch; // 글자가 있으면 덮어쓴다 } else { cur.Add(ch); // 줄 끝 바로 뒤면 붙인다 } col = col + 1; }}줄바꾸기(){ Console.WriteLine(cur.Join("")); cur = []; col = 0;}for (t = 0; t < q; t++){ p = Console.ReadLine().Trim().Split(" "); switch (p[0]) { case "write": 쓰기(p[1]); break; case "print": 쓰기(p[1]); 줄바꾸기(); break; case "nl": 줄바꾸기(); break; case "cr": col = 0; // 글자는 그대로, 커서만 맨 앞으로 break; case "back": col = Mathf.Max(0, col - p[1].ToNumber()); break; default: cur = cur.GetRange(0, col); // erase: 커서 칸부터 뒤를 버린다 break; }}if (cur.Count > 0){ Console.WriteLine(cur.Join(""));}