{ }codelper
足し算P0222

足し算の宿題を採点する

弟が足し算の宿題をした。
式ごとに合っているか採点し、間違った答えは直してあげたい。
一行目に式の数 n が与えられる。
続く n 行に、弟が書いた式が "a + b = c" の形で一行に一つずつ与えられる。
a、b、c は整数で、数と記号のあいだには空白がちょうど一つずつある。
負の数は前に - を付けて書く(例:-8 + 3 = -5)。
数はコンマなしの数字だけで書き、前に 0 や + を付けない。
0 を -0 とは書かない。
式ごとに一行で採点結果を出力せよ。
c が a + b と等しければ "O a + b = c" を出力する。
c が a + b と違えば "X a + b = s" を出力する。
ここで s は a + b の正しい値である。
出力する数も入力と同じくコンマなしの数字だけで書く。
最後の行に、間違っていた式の数を出力せよ。

入力
1 ≤ n ≤ 1,000、-1,500,000,000 ≤ a, b ≤ 1,500,000,000、-3,000,000,000 ≤ c ≤ 3,000,000,000
出力
n 行の採点結果、最後の行に間違った式の数
例 1 · stdin
3
3 + 4 = 7
12 + 5 = 125
-8 + 3 = -11
stdout
O 3 + 4 = 7
X 12 + 5 = 17
X -8 + 3 = -5
2
例 2 · stdin
2
1500000000 + 1500000000 = 3000000000
1500000000 + 1500000000 = -1294967296
stdout
O 1500000000 + 1500000000 = 3000000000
X 1500000000 + 1500000000 = 3000000000
1
main.py
入力(stdin)

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

$ 準備完了

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

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

一つの + が足し算も文字列の連結もするのが一つ目の落とし穴です。
JS・TS で split(" ") で分けた断片は文字列なので、Number に変えないと "3" + "4" が "34" になり、弟が書いた間違いの答え 34 を正解と採点してしまいます(TS は number[] と書いておけば型チェックが教えてくれます)。
Craykon も 数に() なしで足すと同じようにつながります。
Python も "3" + "4" は "34" ですが、文字列と数を足すとエラーにしてくれます。
Java・C#・JS は文字列が出てくると、その後ろを左から順につなぐので、"= " + a + b は = 34 になります。
合計は s = a + b で先に求めるか、(a + b) のように括弧でくくります。
二つ目の落とし穴は大きさです。
a と b は 15 億までなので合計は 30 億まで行きますが、C・C++・Java・C# の int は約 21 億までなのであふれます。
C# と Java はあふれてもエラーなしに負の数になり(C# は checked で囲んだときだけ知らせます)、C・C++ の符号付き整数のあふれは未定義動作です。
そこで C は long long と scanf("%lld + %lld = %lld")、C++ は long long、Java・C# は long で受け取ります。
Python の整数には大きさの制限がなく、JS・TS・Craykon の数は 2^53 まで正確なので、30 億は問題ありません。

Pythonmain.py · 14 行
n = int(input())out = []wrong = 0for _ in range(n):    a, plus, b, eq, c = input().split()    a, b, c = int(a), int(b), int(c)   # 문자열끼리 +하면 이어 붙는다("3" + "4" → "34")    s = a + b    if s == c:        out.append(f"O {a} + {b} = {s}")    else:        out.append(f"X {a} + {b} = {s}")        wrong += 1out.append(str(wrong))print("\n".join(out))
JavaScriptmain.js · 17 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const out = [];let wrong = 0;for (let i = 1; i <= n; i++) {  // 빈칸으로 나눈 조각은 문자열이라 Number로 바꿔야 +가 덧셈이 된다  const [a, , b, , c] = lines[i].trim().split(" ").map(Number);  const s = a + b;  if (s === c) {    out.push(`O ${a} + ${b} = ${s}`);  } else {    out.push(`X ${a} + ${b} = ${s}`);    wrong++;  }}out.push(String(wrong));console.log(out.join("\n"));
TypeScriptmain.ts · 18 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const out: string[] = [];let wrong = 0;for (let i = 1; i <= n; i++) {  // 빈칸으로 나눈 조각은 문자열이라 Number로 바꿔야 +가 덧셈이 된다  const [a, , b, , c]: number[] = lines[i].trim().split(" ").map(Number);  const s: number = a + b;  if (s === c) {    out.push(`O ${a} + ${b} = ${s}`);  } else {    out.push(`X ${a} + ${b} = ${s}`);    wrong++;  }}out.push(String(wrong));console.log(out.join("\n"));
JavaMain.java · 29 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    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();        int wrong = 0;        for (int i = 0; i < n; i++) {            String[] p = in.readLine().trim().split(" ");            // 합이 30억까지 가니 int(약 21억)가 아니라 long으로 받는다            long a = Long.parseLong(p[0]);            long b = Long.parseLong(p[2]);            long c = Long.parseLong(p[4]);            long s = a + b;            char mark = 'O';            if (s != c) {                mark = 'X';                wrong++;            }            // 문자열 뒤에서 + a + b를 쓰면 이어 붙으니 합은 s로 따로 구해 둔다            out.append(mark).append(' ').append(a).append(" + ").append(b).append(" = ").append(s).append('\n');        }        out.append(wrong).append('\n');        System.out.print(out);    }}
C#Main.cs · 30 行
using System;using System.Text; class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        int wrong = 0;        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Trim().Split(' ');            // 합이 30억까지 가니 int가 아니라 long으로 받는다            long a = long.Parse(p[0]);            long b = long.Parse(p[2]);            long c = long.Parse(p[4]);            long s = a + b;            char mark = 'O';            if (s != c)            {                mark = 'X';                wrong++;            }            sb.Append($"{mark} {a} + {b} = {s}\n");        }        sb.Append(wrong).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 20 行
#include <iostream> int main() {    std::ios::sync_with_stdio(false);    int n, wrong = 0;    std::cin >> n;    for (int i = 0; i < n; i++) {        long long a, b, c;        char plus, eq;        std::cin >> a >> plus >> b >> eq >> c;        long long s = a + b;  // int로 더하면 30억에서 넘친다        char mark = 'O';        if (s != c) {            mark = 'X';            wrong++;        }        std::cout << mark << ' ' << a << " + " << b << " = " << s << "\n";    }    std::cout << wrong << "\n";}
Cmain.c · 20 行
#include <stdio.h> int main(void) {    int n, wrong = 0;    long long a, b, c;    scanf("%d", &n);    for (int i = 0; i < n; i++) {        /* 형식 문자열의 " + "와 " = "가 기호를 건너뛰어 준다 */        scanf("%lld + %lld = %lld", &a, &b, &c);        long long s = a + b; /* int로 더하면 30억에서 넘친다 */        char mark = 'O';        if (s != c) {            mark = 'X';            wrong++;        }        printf("%c %lld + %lld = %lld\n", mark, a, b, s);    }    printf("%d\n", wrong);    return 0;}
Craykonmain.cray · 19 行
n = コンソール.行読み().数に();wrong = 0;繰り返す (i = 0; i < n; i++){    p = コンソール.行読み().空白除去().分ける(" ");    // 나눈 조각은 문자열이라 수로변환해야 +가 덧셈이 된다    a = p[0].数に();    b = p[2].数に();    c = p[4].数に();    s = a + b;    mark = "O";    もし (s != c)    {        mark = "X";        wrong++;    }    コンソール.書く(mark + " " + a + " + " + b + " = " + s);}コンソール.書く(wrong);