문자열 s와 자르기 질문 q개가 주어진다. 질문마다 Python의 s[a:b:c]와 같은 규칙으로 자른 문자열을 출력하라.
s의 길이를 n이라 하고, 글자의 자리는 맨 앞을 0으로 하여 0부터 n − 1까지 센다.
질문은 a:b 또는 a:b:c 꼴이다. a, b, c는 각각 정수이거나 비어 있다. c가 없거나 비어 있으면 걸음 c는 1이다.
c가 양수일 때: a가 비어 있으면 시작은 0, b가 비어 있으면 끝은 n이다.
주어진 a는 음수이면 n을 더한다. 그 결과가 0보다 작으면 0으로, n보다 크면 n으로 바꾼 것이 시작이다. b도 같은 방법으로 끝을 정한다.
그다음 자리 시작, 시작 + c, 시작 + 2c, …의 글자를 자리가 끝보다 작은 동안 차례로 잇는다.
c가 음수일 때: a가 비어 있으면 시작은 n − 1, b가 비어 있으면 끝은 −1이다(0번 글자까지 넣는다는 뜻).
주어진 a는 음수이면 n을 더한다. 그 결과가 0보다 작으면 −1로, n − 1보다 크면 n − 1로 바꾼 것이 시작이다. b도 같은 방법으로 끝을 정한다.
그다음 자리 시작, 시작 + c, 시작 + 2c, …의 글자를 자리가 끝보다 큰 동안 차례로 잇는다.
첫 줄에 s가, 둘째 줄에 q가, 다음 q줄에 질문이 하나씩 주어진다.
질문마다 자른 문자열을 한 줄에 출력하라. 자른 문자열이 비어 있으면 -를 출력하라.
입력
s는 영어 소문자와 숫자로 된 1~200글자의 문자열이다. 1 ≤ q ≤ 400. 질문의 a, b, c는 비어 있지 않으면 -1,000 이상 1,000 이하의 정수이고, c는 0이 아니다. 질문에는 빈칸이 없다
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
Python만 s[a:b:c]로 걸음과 음수 자리를 모두 받아요. 빈 칸은 None이라 s[slice(None, None, -1)]처럼 넘기면 기본값을 Python이 걸음의 부호에 맞춰 정해요. 다른 언어는 직접 만들어야 해요: JS·TS slice(a, b)는 음수 자리를 받지만 걸음이 없고(substring은 음수를 0으로 봐요), Java substring(a, b)·C# Substring(시작, 길이)·크레이콘 부분문자열(시작, 개수)는 범위를 넘으면 오류를 내요. C++ substr(pos, len)은 길이가 넘치는 것만 봐주고 pos가 길이를 넘으면 out_of_range예요. 함정 ① 걸음이 음수일 때 빈 끝은 0이 아니라 −1이에요. 끝을 0으로 두면 ::-1에서 0번 글자가 빠져요. 그래서 Python에서도 s[a:b:c]의 빈 칸을 0이나 len(s)로 채우면 틀려요(s[0:8:-1]은 빈 문자열). ② 음수 자리는 먼저 n을 더하고, 그래도 밖이면 당겨요. 걸음이 음수이면 0 아래를 0이 아니라 −1로 당겨서 -100::-1은 빈 문자열이에요. ③ 걸음이 음수이면 시작의 위쪽 끝은 n이 아니라 n − 1이에요. n까지 두면 칸 밖을 읽어요(Java·C#·크레이콘은 오류, C는 정의되지 않은 동작). ④ 나누기에서 빈 칸이 사라지지 않게 해요: Java split(":")는 끝의 빈 칸을 버려서 split(":", -1)로 써요. C strtok도 이어진 ::를 하나로 보아요. C++ std::optional, TS string | undefined로 '비어 있음'을 0과 따로 나타낼 수 있어요.
Pythonmain.py · 11 줄
import syslines = sys.stdin.read().split("\n")s = lines[0].strip()q = int(lines[1])out = []for line in lines[2:2 + q]: # 빈 칸은 None: s[None:None:-1]처럼 기본값을 Python이 정한다(0을 넣으면 안 된다) parts = [int(p) if p else None for p in line.strip().split(":")] out.append(s[slice(*parts)] or "-")print("\n".join(out))
JavaScriptmain.js · 29 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const s = lines[0].trim();const n = s.length;const q = Number(lines[1]);// 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다function fit(x, lo, hi) { if (x < 0) x += n; return Math.min(Math.max(x, lo), hi);}function pySlice(text) { const [a, b, c] = text.trim().split(":"); // c가 없으면 undefined const step = c ? Number(c) : 1; let out = ""; if (step > 0) { const start = a ? fit(Number(a), 0, n) : 0; const stop = b ? fit(Number(b), 0, n) : n; for (let i = start; i < stop; i += step) out += s[i]; } else { // 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 const start = a ? fit(Number(a), -1, n - 1) : n - 1; const stop = b ? fit(Number(b), -1, n - 1) : -1; for (let i = start; i > stop; i += step) out += s[i]; } return out || "-";}console.log(lines.slice(2, 2 + q).map(pySlice).join("\n"));
TypeScriptmain.ts · 31 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const s = lines[0].trim();const n = s.length;const q = Number(lines[1]);// 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다function fit(x: number, lo: number, hi: number): number { if (x < 0) x += n; return Math.min(Math.max(x, lo), hi);}function pySlice(text: string): string { const [a, b, c]: (string | undefined)[] = text.trim().split(":"); // c가 없으면 undefined const step = c ? Number(c) : 1; let out = ""; if (step > 0) { const start = a ? fit(Number(a), 0, n) : 0; const stop = b ? fit(Number(b), 0, n) : n; for (let i = start; i < stop; i += step) out += s[i]; } else { // 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 const start = a ? fit(Number(a), -1, n - 1) : n - 1; const stop = b ? fit(Number(b), -1, n - 1) : -1; for (let i = start; i > stop; i += step) out += s[i]; } return out || "-";}console.log(lines.slice(2, 2 + q).map(pySlice).join("\n"));
JavaMain.java · 42 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main { static String s; static int n; // 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다 static int fit(int x, int lo, int hi) { if (x < 0) x += n; return Math.min(Math.max(x, lo), hi); } static String pySlice(String text) { String[] p = text.split(":", -1); // -1: 끝의 빈 칸도 버리지 않는다 boolean hasA = !p[0].isEmpty(), hasB = !p[1].isEmpty(); int step = p.length == 3 && !p[2].isEmpty() ? Integer.parseInt(p[2]) : 1; StringBuilder out = new StringBuilder(); if (step > 0) { int start = hasA ? fit(Integer.parseInt(p[0]), 0, n) : 0; int stop = hasB ? fit(Integer.parseInt(p[1]), 0, n) : n; for (int i = start; i < stop; i += step) out.append(s.charAt(i)); } else { // 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 int start = hasA ? fit(Integer.parseInt(p[0]), -1, n - 1) : n - 1; int stop = hasB ? fit(Integer.parseInt(p[1]), -1, n - 1) : -1; for (int i = start; i > stop; i += step) out.append(s.charAt(i)); } return out.length() > 0 ? out.toString() : "-"; } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); s = in.readLine().trim(); n = s.length(); int q = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int t = 0; t < q; t++) out.append(pySlice(in.readLine().trim())).append('\n'); System.out.print(out); }}
C#Main.cs · 47 줄
using System;using System.Text;class Program{ static string s = ""; static int n; // 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다 static int Fit(int x, int lo, int hi) { if (x < 0) x += n; return Math.Clamp(x, lo, hi); } static string PySlice(string text) { string[] p = text.Split(':'); // C#의 Split은 빈 칸도 남긴다 bool hasA = p[0] != "", hasB = p[1] != ""; int step = p.Length == 3 && p[2] != "" ? int.Parse(p[2]) : 1; var sb = new StringBuilder(); if (step > 0) { int start = hasA ? Fit(int.Parse(p[0]), 0, n) : 0; int stop = hasB ? Fit(int.Parse(p[1]), 0, n) : n; for (int i = start; i < stop; i += step) sb.Append(s[i]); } else { // 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 int start = hasA ? Fit(int.Parse(p[0]), -1, n - 1) : n - 1; int stop = hasB ? Fit(int.Parse(p[1]), -1, n - 1) : -1; for (int i = start; i > stop; i += step) sb.Append(s[i]); } return sb.Length > 0 ? sb.ToString() : "-"; } static void Main() { s = Console.ReadLine().Trim(); n = s.Length; int q = int.Parse(Console.ReadLine().Trim()); var output = new StringBuilder(); for (int t = 0; t < q; t++) output.Append(PySlice(Console.ReadLine().Trim())).Append('\n'); Console.Write(output); }}
C++main.cpp · 53 줄
#include <algorithm>#include <iostream>#include <optional>#include <string>#include <vector>std::string s;int n;// 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다int fit(int x, int lo, int hi) { if (x < 0) x += n; return std::clamp(x, lo, hi);}std::string pySlice(const std::string &text) { std::vector<std::optional<int>> p; // 빈 칸은 값이 없는 optional std::size_t from = 0; while (true) { std::size_t colon = text.find(':', from); std::string part = text.substr(from, colon == std::string::npos ? std::string::npos : colon - from); p.push_back(part.empty() ? std::nullopt : std::optional<int>(std::stoi(part))); if (colon == std::string::npos) break; from = colon + 1; } int step = p.size() == 3 && p[2] ? *p[2] : 1; std::string out; if (step > 0) { int start = p[0] ? fit(*p[0], 0, n) : 0; int stop = p[1] ? fit(*p[1], 0, n) : n; for (int i = start; i < stop; i += step) out += s[i]; } else { // 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 int start = p[0] ? fit(*p[0], -1, n - 1) : n - 1; int stop = p[1] ? fit(*p[1], -1, n - 1) : -1; for (int i = start; i > stop; i += step) out += s[i]; } return out.empty() ? "-" : out;}int main() { int q; std::cin >> s >> q; n = static_cast<int>(s.size()); std::string out; for (int t = 0; t < q; t++) { std::string line; std::cin >> line; out += pySlice(line) + '\n'; } std::cout << out; return 0;}
Cmain.c · 47 줄
#include <stdio.h>#include <stdlib.h>#include <string.h>static char s[256];static int n;/* 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다 */static int fit(int x, int lo, int hi) { if (x < 0) x += n; return x < lo ? lo : x > hi ? hi : x;}int main(void) { char line[64]; int q; scanf("%255s %d", s, &q); n = (int)strlen(s); for (int t = 0; t < q; t++) { scanf("%63s", line); /* ':'로 칸을 나눈다. strtok는 빈 칸을 건너뛰어서 직접 나눈다 */ char *part[3] = {line, NULL, NULL}; int k = 1; for (char *c = line; *c; c++) if (*c == ':') { *c = '\0'; part[k++] = c + 1; } int hasA = part[0][0] != '\0', hasB = part[1][0] != '\0'; int step = k == 3 && part[2][0] != '\0' ? atoi(part[2]) : 1; char out[256]; int len = 0; if (step > 0) { int start = hasA ? fit(atoi(part[0]), 0, n) : 0; int stop = hasB ? fit(atoi(part[1]), 0, n) : n; for (int i = start; i < stop; i += step) out[len++] = s[i]; } else { /* 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 */ int start = hasA ? fit(atoi(part[0]), -1, n - 1) : n - 1; int stop = hasB ? fit(atoi(part[1]), -1, n - 1) : -1; for (int i = start; i > stop; i += step) out[len++] = s[i]; } out[len] = '\0'; puts(len > 0 ? out : "-"); } return 0;}
Craykonmain.cray · 64 줄
s = 콘솔.줄읽기().공백제거();n = s.길이;q = 콘솔.줄읽기().수로변환();// 음수 자리는 n을 더하고, 그래도 밖이면 [lo, hi] 안으로 당긴다맞추기(x, lo, hi){ 만약 (x < 0) { x = x + n; } 돌려주기 수학.작은수(수학.큰수(x, lo), hi);}반복 (t = 0; t < q; t++){ p = 콘솔.줄읽기().공백제거().나누기(":"); 걸음 = 1; 만약 (p.개수 == 3 && p[2] != "") { 걸음 = p[2].수로변환(); } 답 = ""; 만약 (걸음 > 0) { 시작 = 0; 끝 = n; 만약 (p[0] != "") { 시작 = 맞추기(p[0].수로변환(), 0, n); } 만약 (p[1] != "") { 끝 = 맞추기(p[1].수로변환(), 0, n); } 반복 (k = 시작; k < 끝; k = k + 걸음) { 답 = 답 + s[k]; } } 아니면 { // 거꾸로 갈 때 빈 끝은 0번 글자까지 넣는다는 뜻이라 -1로 둔다 시작 = n - 1; 끝 = -1; 만약 (p[0] != "") { 시작 = 맞추기(p[0].수로변환(), -1, n - 1); } 만약 (p[1] != "") { 끝 = 맞추기(p[1].수로변환(), -1, n - 1); } 반복 (k = 시작; k > 끝; k = k + 걸음) { 답 = 답 + s[k]; } } 만약 (답 == "") { 답 = "-"; } 콘솔.쓰기(답);}