{ }codelper
1行読み込み文字型P0161

棚ラベルの確認文字

倉庫の棚ラベルには英字と数字からなるコードが書かれている。
手で書き写したラベルなので小文字が混じり、空白と '-' がどこにでも入っていることがある。
一行目にラベルの数 n が与えられ、続く n 行に一行に一つずつラベルが与えられる。
ラベルごとに空白と '-' をすべて取り除き、小文字を大文字に変えてコードを作る。
コードの各文字に値を決める:'0'〜'9' は 0〜9、'A'〜'Z' は 10〜35 である。
コードの左から i 番目(1 から数える)の文字の値に i を掛けてすべて足し、その和を 36 で割った余りを r とする。
確認文字は r が 0〜9 なら数字 '0'〜'9'、r が 10〜35 なら 'A'〜'Z' である(10 は 'A'、35 は 'Z')。
ラベルごとにコード、'-'、確認文字をつなげて一行に出力せよ。

入力
一行目に n(1 ≤ n ≤ 1000)。
続く n 行のラベルは改行を除いて 1〜80 文字で、英字の大文字・小文字・数字・空白・'-' だけからなる。
行の前後に空白があることがあり、どのラベルにも英字か数字が一つ以上ある
出力
n 行。
各行に "コード-確認文字"
例 1 · stdin
3
sh-04 b
  q7-X  
9
stdout
SH04B-P
Q7X-V
9-9
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

二つのことを比べます。
① 空白を含む行を丸ごと読む:Python input()・sys.stdin.readline()、JS・TS は一度に読んで split("\n")、Java BufferedReader.readLine()、C# Console.ReadLine()、C fgets、C++ std::getline、Craykon コンソール.行読み()。
C++ cin >> s、Java Scanner.next()、C scanf("%s") は空白で切るので sh-04 b を二つに読みます。
数と行を混ぜて読むときの落とし穴もあります:C scanf("%d")、C++ cin >> n、Java Scanner.nextInt() は一行目の終わりの改行を残すので、すぐ次の fgets・getline・nextLine() が空の行を読みます。
一行目も行として読んで数に変えれば安全です。
② 文字と数を行き来する:C・C++・Java・C# の char は数なので、c - '0'、c - 'A' + 10 でそのまま値が得られます。
逆に数を文字に戻すとき 'A' + r - 10 は int なので、Java StringBuilder.append・C# StringBuilder.Append・C++ std::cout << にそのまま渡すと P ではなく 25 が付きます。
(char)(C++ は static_cast<char>)で変えます。
C printf("%c", ...) は int を受け取って文字として出します。
Python・JS・TS・Craykon には文字型がないのでコードを通ります:Python ord・chr(または int(c, 36) がそのまま 0〜35)、JS・TS charCodeAt・String.fromCharCode、Craykon 文字.コード・文字.コードから。
JS で "7" - "0" は 7 ですが英字には使えません:すべての文字に charCodeAt(0) - 48 を使うと 'B' が 11 ではなく 18 になります。
そして先に大文字にしないと 'b' - 'A' + 10 は 43 です。

Pythonmain.py · 22 行
import sys  def value(c):    # '0'~'9' → 0~9, 'A'~'Z' → 10~35 (글자 코드의 차이로 계산)    if c.isdigit():        return ord(c) - ord("0")    return ord(c) - ord("A") + 10  def check_char(r):    if r < 10:        return chr(ord("0") + r)    return chr(ord("A") + r - 10)  n = int(sys.stdin.readline())for _ in range(n):    line = sys.stdin.readline().rstrip("\n")  # 빈칸이 든 한 줄을 통째로    code = "".join(c.upper() for c in line if c not in " -")    total = sum(value(c) * i for i, c in enumerate(code, 1))    print(f"{code}-{check_char(total % 36)}")
JavaScriptmain.js · 20 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const ZERO = "0".charCodeAt(0);const A = "A".charCodeAt(0); // '0'~'9' → 0~9, 'A'~'Z' → 10~35const value = (c) => {  const k = c.charCodeAt(0);  return k <= "9".charCodeAt(0) ? k - ZERO : k - A + 10;};const checkChar = (r) => String.fromCharCode(r < 10 ? ZERO + r : A + r - 10); const out = [];for (let i = 1; i <= n; i++) {  const code = lines[i].replace(/[ -]/g, "").toUpperCase();  let total = 0;  for (let j = 0; j < code.length; j++) total += value(code[j]) * (j + 1);  out.push(`${code}-${checkChar(total % 36)}`);}console.log(out.join("\n"));
TypeScriptmain.ts · 23 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const ZERO: number = "0".charCodeAt(0);const A: number = "A".charCodeAt(0); // '0'~'9' → 0~9, 'A'~'Z' → 10~35function value(c: string): number {  const k: number = c.charCodeAt(0);  return k <= "9".charCodeAt(0) ? k - ZERO : k - A + 10;}function checkChar(r: number): string {  return String.fromCharCode(r < 10 ? ZERO + r : A + r - 10);} const out: string[] = [];for (let i = 1; i <= n; i++) {  const code: string = lines[i].replace(/[ -]/g, "").toUpperCase();  let total = 0;  for (let j = 0; j < code.length; j++) total += value(code[j]) * (j + 1);  out.push(`${code}-${checkChar(total % 36)}`);}console.log(out.join("\n"));
JavaMain.java · 30 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    // '0'~'9' → 0~9, 'A'~'Z' → 10~35 (char는 수처럼 뺄 수 있다)    static int value(char c) {        return Character.isDigit(c) ? c - '0' : c - 'A' + 10;    }     static char checkChar(int r) {        return r < 10 ? (char) ('0' + r) : (char) ('A' + r - 10); // int → char로 되돌린다    }     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 line = in.readLine(); // 빈칸이 든 한 줄을 통째로            StringBuilder code = new StringBuilder();            for (char c : line.toCharArray())                if (c != ' ' && c != '-') code.append(Character.toUpperCase(c));            int total = 0;            for (int j = 0; j < code.length(); j++) total += value(code.charAt(j)) * (j + 1);            out.append(code).append('-').append(checkChar(total % 36)).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 27 行
using System;using System.Text; class Program{    // '0'~'9' → 0~9, 'A'~'Z' → 10~35 (char끼리 빼면 int)    static int Value(char c) => char.IsDigit(c) ? c - '0' : c - 'A' + 10;     static char CheckChar(int r) => r < 10 ? (char)('0' + r) : (char)('A' + r - 10);     static void Main()    {        int n = int.Parse(Console.ReadLine());        var out_ = new StringBuilder();        for (int i = 0; i < n; i++)        {            string line = Console.ReadLine(); // 빈칸이 든 한 줄을 통째로            var code = new StringBuilder();            foreach (char c in line)                if (c != ' ' && c != '-') code.Append(char.ToUpperInvariant(c));            int total = 0;            for (int j = 0; j < code.Length; j++) total += Value(code[j]) * (j + 1);            out_.Append(code).Append('-').Append(CheckChar(total % 36)).Append('\n');        }        Console.Write(out_);    }}
C++main.cpp · 27 行
#include <cctype>#include <iostream>#include <string> // '0'~'9' → 0~9, 'A'~'Z' → 10~35int value(char c) {    return std::isdigit(static_cast<unsigned char>(c)) ? c - '0' : c - 'A' + 10;} int main() {    std::string line;    std::getline(std::cin, line);    int n = std::stoi(line); // cin >> n 뒤에 getline을 쓰면 남은 줄 끝을 빈 줄로 읽는다    std::string out;    for (int i = 0; i < n; i++) {        std::getline(std::cin, line); // 빈칸이 든 한 줄을 통째로        std::string code;        for (char c : line)            if (c != ' ' && c != '-') code += static_cast<char>(std::toupper(static_cast<unsigned char>(c)));        int total = 0;        for (std::size_t j = 0; j < code.size(); j++) total += value(code[j]) * static_cast<int>(j + 1);        int r = total % 36;        char check = static_cast<char>(r < 10 ? '0' + r : 'A' + r - 10); // int → char        out += code + '-' + check + '\n';    }    std::cout << out;}
Cmain.c · 26 行
#include <ctype.h>#include <stdio.h>#include <stdlib.h> /* '0'~'9' → 0~9, 'A'~'Z' → 10~35: C의 char는 작은 정수라 그대로 뺀다 */static int value(char c) {    return isdigit((unsigned char)c) ? c - '0' : c - 'A' + 10;} int main(void) {    char line[128], code[128];    fgets(line, sizeof line, stdin);    int n = atoi(line); /* scanf("%d")를 쓰면 줄 끝 '\n'이 남아 다음 fgets가 빈 줄을 읽는다 */    for (int i = 0; i < n; i++) {        fgets(line, sizeof line, stdin);        int len = 0;        for (char *p = line; *p && *p != '\n'; p++)            if (*p != ' ' && *p != '-') code[len++] = (char)toupper((unsigned char)*p);        code[len] = '\0';        int total = 0;        for (int j = 0; j < len; j++) total += value(code[j]) * (j + 1);        int r = total % 36;        printf("%s-%c\n", code, r < 10 ? '0' + r : 'A' + r - 10);    }    return 0;}
Craykonmain.cray · 39 行
// '0'~'9' → 0~9, 'A'~'Z' → 10~35값(c){    k = 文字.コード(c);    もし (k <= 文字.コード("9"))    {        返す k - 文字.コード("0");    }    返す k - 文字.コード("A") + 10;} 확인글자(r){    もし (r < 10)    {        返す 文字.コードから(文字.コード("0") + r);    }    返す 文字.コードから(文字.コード("A") + r - 10);} n = コンソール.行読み().数に();繰り返す (i = 0; i < n; i++){    줄 = コンソール.行読み().大文字();    코드 = "";    それぞれ (c の中 줄)    {        もし (c != " " && c != "-")        {            코드 = 코드 + c;        }    }    합 = 0;    繰り返す (j = 0; j < 코드.長さ; j++)    {        합 = 합 + 값(코드[j]) * (j + 1);    }    コンソール.書く(코드 + "-" + 확인글자(합 % 36));}