{ }codelper
反转字符串P0316

各翻转一半的暗号纸条

朋友之间传纸条时用一种暗号。
设单词的长度为 L,L 除以 2 的商为 h。
把单词前面的 h 个字符倒过来写,后面的 h 个字符也单独倒过来写。
如果 L 是奇数,正中间会剩下一个字符,这个字符留在原位不动。
例如 notebook 把 note 和 book 各自翻转,变成 etonkoob。
pencils 把 pen 和 ils 各自翻转,中间的 c 不动,变成 nepcsli。
所以长度不超过 3 的单词变成暗号后不变。
第一行给出单词数 n,接下来 n 行每行给出一个单词。
对每个单词,在一行中输出变成暗号后的字符串。

输入
1 ≤ n ≤ 100。
单词长度为 1~1,000,只由英文大写字母、小写字母和数字组成
输出
n 行,每行是变成暗号后的单词
样例 1 · stdin
4
notebook
pencils
ab
x
stdout
etonkoob
nepcsli
ab
x
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

翻转字符串的一段,各语言写法不同。
Python 用 s[:h][::-1](倒着读出的新字符串),JS·TS 的字符串没有 reverse,所以用 [...t].reverse().join(""),Java 用 new StringBuilder(t).reverse().toString(),C# 先转成 char[] 再用 Array.Reverse(a, 起点, 个数),C 用从两端向中间走并交换两个字符的循环,C++ 用 std::reverse(s.begin(), s.begin() + h),Craykon 用 s.截取(0, h).反转()。
Python、JS、Java、Craykon 的解法生成翻转后的新字符串再拼接,C、C++、C#(char 数组)的解法在原地修改。
指明一段的两个数含义也不同。
Python s[a:b]、JS slice(a, b)、Java substring(a, b)、C++ std::reverse(开头, 结尾) 是(起点, 终点),终点位置不包含在内。
C# Array.Reverse(数组, 起点, 个数) 和 Craykon 截取(起点, 个数) 是(起点, 个数)。
六个陷阱:① 如果后一半从位置 h 开始取,长度为奇数时正中间的字符也会被翻转(示例中的 pencils 变成 nepslic)。
后一半应从位置(长度 − h)开始。
② Python s[-h:] 和 JS s.slice(-h) 表示“末尾的 h 个字符”,但 h 为 0 时 -0 就是 0,得到的是整个字符串(示例中的 x 变成 xx)。
③ Python reversed(t) 返回的不是字符串而是迭代器。
str(reversed(t)) 会变成 <reversed object at …> 这样的文字,要用 "".join(reversed(t)) 拼接。
④ JS 数组的 reverse() 不返回新数组,而是把这个数组本身翻转。
翻转一个数组之后再切片,切到的是已经翻转过的数组。
⑤ 在 C 中,交换的循环如果不在区间的中间停下而一直跑到末尾,就会交换两次,变回原样(notebook 原样输出)。
⑥ 在需要(起点, 个数)的地方传入终点位置:C# Array.Reverse(a, 长度 − h, 长度) 会超出数组,以 ArgumentException 停止;Craykon s.截取(h, 长度 − h) 不会报错,而是把中间的字符连同后一半一起截出来(notebook 变成 etonbookkoob)。

Pythonmain.py · 8 行
n = int(input())for _ in range(n):    s = input().strip()    h = len(s) // 2    # 앞쪽 h글자, 한가운데(길이가 홀수일 때만 한 글자), 뒤쪽 h글자    front, middle, back = s[:h], s[h:len(s) - h], s[len(s) - h:]    # [::-1]은 거꾸로 읽은 새 문자열을 만든다    print(front[::-1] + middle + back[::-1])
JavaScriptmain.js · 15 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);// 문자열에는 reverse가 없어서 글자 배열로 바꿔 뒤집고 다시 잇는다const reversed = (t) => [...t].reverse().join("");const out = [];for (let i = 1; i <= n; i++) {  const s = lines[i].trim();  const h = Math.floor(s.length / 2);  // 앞쪽 h글자, 한가운데(길이가 홀수일 때만 한 글자), 뒤쪽 h글자  const front = s.slice(0, h);  const middle = s.slice(h, s.length - h);  const back = s.slice(s.length - h);  out.push(reversed(front) + middle + reversed(back));}console.log(out.join("\n"));
TypeScriptmain.ts · 16 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);// 문자열에는 reverse가 없어서 글자 배열로 바꿔 뒤집고 다시 잇는다const reversed = (t: string): string => [...t].reverse().join("");const out: string[] = [];for (let i = 1; i <= n; i++) {  const s: string = lines[i].trim();  const h: number = Math.floor(s.length / 2);  // 앞쪽 h글자, 한가운데(길이가 홀수일 때만 한 글자), 뒤쪽 h글자  const front: string = s.slice(0, h);  const middle: string = s.slice(h, s.length - h);  const back: string = s.slice(s.length - h);  out.push(reversed(front) + middle + reversed(back));}console.log(out.join("\n"));
JavaMain.java · 27 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    // String은 고칠 수 없어서 StringBuilder에 담아 뒤집는다    static String reversed(String t) {        return new StringBuilder(t).reverse().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++) {            String s = in.readLine().trim();            int len = s.length();            int h = len / 2;            // substring(시작, 끝): 끝 자리는 들어가지 않는다            String front = s.substring(0, h);            String middle = s.substring(h, len - h);            String back = s.substring(len - h);            out.append(reversed(front)).append(middle).append(reversed(back)).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 22 行
using System;using System.Text; class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine().Trim());        var sb = new StringBuilder();        for (int i = 0; i < n; i++)        {            // string은 고칠 수 없어서 char 배열로 바꿔 그 자리에서 뒤집는다            char[] a = Console.ReadLine().Trim().ToCharArray();            int h = a.Length / 2;            // Array.Reverse(배열, 시작, 개수): 셋째 값은 끝 자리가 아니라 개수다            Array.Reverse(a, 0, h);            Array.Reverse(a, a.Length - h, h);            sb.Append(new string(a)).Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 17 行
#include <algorithm>#include <iostream>#include <string> int main() {    int n;    std::cin >> n;    for (int i = 0; i < n; i++) {        std::string s;        std::cin >> s;        auto h = s.size() / 2;        // std::reverse(시작, 끝): 끝은 들어가지 않는다. 그 자리에서 뒤집는다        std::reverse(s.begin(), s.begin() + h);        std::reverse(s.end() - h, s.end());        std::cout << s << '\n';    }}
Cmain.c · 28 行
#include <stdio.h>#include <string.h> /* s[from] ~ s[to]를 그 자리에서 뒤집는다. 양 끝에서 가운데로 오며 맞바꾼다 */static void reverse_range(char *s, int from, int to) {    while (from < to) {        char tmp = s[from];        s[from] = s[to];        s[to] = tmp;        from++;        to--;    }} int main(void) {    int n;    static char s[1001];    scanf("%d", &n);    for (int i = 0; i < n; i++) {        scanf("%1000s", s);        int len = (int)strlen(s);        int h = len / 2;        reverse_range(s, 0, h - 1);         /* 앞쪽 h글자 */        reverse_range(s, len - h, len - 1); /* 뒤쪽 h글자 */        printf("%s\n", s);    }    return 0;}
Craykonmain.cray · 11 行
n = 控制台.读行().转数字();循环 (i = 0; i < n; i++){    s = 控制台.读行().去空白();    h = 数学.商(s.长度, 2);    // 부분문자열(시작, 개수): 둘째 값은 끝 자리가 아니라 글자 수다    앞쪽 = s.截取(0, h);    가운데 = s.截取(h, s.长度 - 2 * h);    뒤쪽 = s.截取(s.长度 - h, h);    控制台.输出(앞쪽.反转() + 가운데 + 뒤쪽.反转());}