週末農園に 1 番から n 番までの畑が n 個ある。 畑ごとに記録が一つずつあり、記録には作物の名前、水をやった回数、収穫した量が書かれる。 はじめはすべての畑が、作物の名前 -、水をやった回数 0、収穫した量 0 である。 命令は三種類ある。 plant k 名前 は k 番の畑の作物の名前をその名前に変え、水をやった回数を 0 に戻す(収穫した量はそのままにする)。 water k は k 番の畑の水をやった回数を 1 増やす。 pick k g は k 番の畑の収穫した量を g だけ増やす。 water と pick は、作物を一度でも植えた畑にだけ与えられる。 一行目に n と命令の数 q が空白一つで区切って与えられ、続く q 行に命令が一行に一つずつ与えられる。 命令を順にすべて処理したあと、1 番の畑から順に一行に一つずつ、作物の名前、水をやった回数、収穫した量を空白一つで区切って出力せよ。
入力
1 ≤ n ≤ 100、1 ≤ q ≤ 1,000、1 ≤ k ≤ n、1 ≤ g ≤ 1,000。 作物の名前は英小文字だけからなる 1 文字以上 10 文字以下の文字列である
出力
n 行:畑ごとに作物の名前、水をやった回数、収穫した量(カンマなしの数字だけ)
例 1 · stdin
4 9
plant 2 carrot
water 2
water 2
pick 2 300
plant 4 corn
water 4
plant 2 bean
water 2
pick 2 50
stdout
- 0 0
bean 1 350
- 0 0
corn 1 0
main.py
エラー一覧00F8 ↓ · ⇧F8 ↑
入力(stdin)
実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。
$ 準備完了
コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。
ほかの言語では?言語別の解答を見る · 8 言語の解答
いくつかの値をまとめた記録をリストに n 個入れる問題です。 記録は Python の辞書 {"crop": "-", "water": 0, "total": 0}、JS のオブジェクト、TS は interface Plot で形を書いたオブジェクト、Java・C# は class Plot、C・C++ は struct Plot、Craykon は 辞書() で作ります。 記録を要素ごとに別々に作る方法:Python [{...} for _ in range(n)]、JS・TS Array.from({ length: n }, () => ({...}))、Java・C# は new Plot[n] のあとループで要素ごとに new Plot()、C++ std::vector<Plot> plots(n)、C は struct Plot plots[100]、Craykon はループの中で plots.追加(新しい畑())。 C と C++ は配列・ベクターの中に記録そのものが入っていて、ほかの言語はリストの要素が記録を指しています。 落とし穴は三つ:① 記録を一つ作って n 個の要素に詰めると、すべての要素が同じ一つの記録を指すので、一つの畑を変えるとすべての畑が変わります(例は四行とも bean 1 350 に)。 Python [{...}] * n、JS Array(n).fill({...})、Java Arrays.fill(plots, new Plot())、Craykon 新リスト(n, 新しい畑()) はどれもそうです。 ② Java で new Plot[n] だけして記録を入れないと、要素がすべて null なので、最初の命令で NullPointerException で止まります。 ③ 逆に、C・C++ の構造体と C# の struct は取り出すとコピーされます。 C struct Plot p = plots[k - 1];、C++ Plot plot = plots[k - 1];、C# で Plot を struct にして Plot plot = plots[k - 1]; と書いてから変えると、コピーだけが変わり、リストの中の記録はそのままです(例は四行とも - 0 0 に)。 C はポインタ &plots[k - 1]、C++ は参照 Plot& plot で受け取り、C# は class にします。
Pythonmain.py · 18 行
n, q = map(int, input().split())# 밭마다 기록(사전)을 따로 하나씩 만든다. 반복할 때마다 새 사전이 생긴다plots = [{"crop": "-", "water": 0, "total": 0} for _ in range(n)]for _ in range(q): cmd = input().split() plot = plots[int(cmd[1]) - 1] # 복사가 아니라 목록 안의 그 기록을 가리킨다 if cmd[0] == "plant": plot["crop"] = cmd[2] plot["water"] = 0 elif cmd[0] == "water": plot["water"] += 1 else: plot["total"] += int(cmd[2])for plot in plots: print(plot["crop"], plot["water"], plot["total"])
JavaScriptmain.js · 20 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, q] = lines[0].trim().split(/\s+/).map(Number);// 밭마다 기록(객체)을 따로 하나씩 만든다. Array.from은 칸마다 함수를 불러 새 객체를 만든다const plots = Array.from({ length: n }, () => ({ crop: "-", water: 0, total: 0 }));for (let i = 1; i <= q; i++) { const cmd = lines[i].trim().split(/\s+/); const plot = plots[Number(cmd[1]) - 1]; // 복사가 아니라 목록 안의 그 기록을 가리킨다 if (cmd[0] === "plant") { plot.crop = cmd[2]; plot.water = 0; } else if (cmd[0] === "water") { plot.water += 1; } else { plot.total += Number(cmd[2]); }}console.log(plots.map((p) => `${p.crop} ${p.water} ${p.total}`).join("\n"));
TypeScriptmain.ts · 28 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, q]: number[] = lines[0].trim().split(/\s+/).map(Number);// 기록의 모양을 타입으로 적어 둔다interface Plot { crop: string; water: number; total: number;}// 밭마다 기록(객체)을 따로 하나씩 만든다. Array.from은 칸마다 함수를 불러 새 객체를 만든다const plots: Plot[] = Array.from({ length: n }, (): Plot => ({ crop: "-", water: 0, total: 0 }));for (let i = 1; i <= q; i++) { const cmd: string[] = lines[i].trim().split(/\s+/); const plot: Plot = plots[Number(cmd[1]) - 1]; // 복사가 아니라 목록 안의 그 기록을 가리킨다 if (cmd[0] === "plant") { plot.crop = cmd[2]; plot.water = 0; } else if (cmd[0] === "water") { plot.water += 1; } else { plot.total += Number(cmd[2]); }}console.log(plots.map((p: Plot) => `${p.crop} ${p.water} ${p.total}`).join("\n"));
JavaMain.java · 42 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer;public class Main { // 밭 하나의 기록 static class Plot { String crop = "-"; int water = 0; int total = 0; } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); int n = Integer.parseInt(st.nextToken()); int q = Integer.parseInt(st.nextToken()); // new Plot[n]은 칸만 만든다(모두 null). 칸마다 new Plot()으로 기록을 따로 만들어 넣는다 Plot[] plots = new Plot[n]; for (int i = 0; i < n; i++) plots[i] = new Plot(); for (int i = 0; i < q; i++) { st = new StringTokenizer(in.readLine()); String cmd = st.nextToken(); Plot plot = plots[Integer.parseInt(st.nextToken()) - 1]; // 복사가 아니라 그 기록을 가리킨다 if (cmd.equals("plant")) { plot.crop = st.nextToken(); plot.water = 0; } else if (cmd.equals("water")) { plot.water++; } else { plot.total += Integer.parseInt(st.nextToken()); } } StringBuilder out = new StringBuilder(); for (Plot p : plots) out.append(p.crop).append(' ').append(p.water).append(' ').append(p.total).append('\n'); System.out.print(out); }}
C#Main.cs · 40 行
using System;using System.Text;// 밭 하나의 기록. class이므로 변수에 담으면 복사되지 않고 같은 기록을 가리킨다class Plot{ public string Crop = "-"; public int Water = 0; public int Total = 0;}class Program{ static void Main() { string[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int n = int.Parse(first[0]), q = int.Parse(first[1]); // new Plot[n]은 칸만 만든다(모두 null). 칸마다 new Plot()으로 기록을 따로 만들어 넣는다 var plots = new Plot[n]; for (int i = 0; i < n; i++) plots[i] = new Plot(); for (int i = 0; i < q; i++) { string[] cmd = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); Plot plot = plots[int.Parse(cmd[1]) - 1]; if (cmd[0] == "plant") { plot.Crop = cmd[2]; plot.Water = 0; } else if (cmd[0] == "water") plot.Water++; else plot.Total += int.Parse(cmd[2]); } var sb = new StringBuilder(); foreach (Plot p in plots) sb.Append($"{p.Crop} {p.Water} {p.Total}\n"); Console.Write(sb); }}
C++main.cpp · 37 行
#include <iostream>#include <string>#include <vector>// 밭 하나의 기록struct Plot { std::string crop = "-"; int water = 0; int total = 0;};int main() { int n, q; std::cin >> n >> q; // vector<Plot>(n)은 기록 n개를 따로따로 만든다 std::vector<Plot> plots(n); for (int i = 0; i < q; i++) { std::string cmd; int k; std::cin >> cmd >> k; // &를 붙여 참조로 받아야 목록 안의 그 기록을 고친다. &가 없으면 복사본이다 Plot& plot = plots[k - 1]; if (cmd == "plant") { std::cin >> plot.crop; plot.water = 0; } else if (cmd == "water") { plot.water++; } else { int g; std::cin >> g; plot.total += g; } } for (const Plot& p : plots) std::cout << p.crop << ' ' << p.water << ' ' << p.total << '\n';}
Cmain.c · 42 行
#include <stdio.h>#include <string.h>/* 밭 하나의 기록 */struct Plot { char crop[11]; int water; int total;};int main(void) { int n, q; /* 구조체 배열은 기록 n개가 통째로 나란히 들어 있다 */ static struct Plot plots[100]; scanf("%d %d", &n, &q); for (int i = 0; i < n; i++) { strcpy(plots[i].crop, "-"); plots[i].water = 0; plots[i].total = 0; } for (int i = 0; i < q; i++) { char cmd[8]; int k; scanf("%7s %d", cmd, &k); /* 포인터로 배열 안의 그 기록을 가리킨다. struct Plot p = plots[k - 1]; 은 복사본이다 */ struct Plot *plot = &plots[k - 1]; if (strcmp(cmd, "plant") == 0) { scanf("%10s", plot->crop); plot->water = 0; } else if (strcmp(cmd, "water") == 0) { plot->water++; } else { int g; scanf("%d", &g); plot->total += g; } } for (int i = 0; i < n; i++) printf("%s %d %d\n", plots[i].crop, plots[i].water, plots[i].total); return 0;}
Craykonmain.cray · 44 行
// 밭 하나의 기록을 새로 만든다. 부를 때마다 새 사전이 생긴다새밭(){ p = 辞書(); p["crop"] = "-"; p["water"] = 0; p["total"] = 0; 返す p;}첫줄 = コンソール.数読み();n = 첫줄[0];q = 첫줄[1];// 칸마다 기록을 따로 만들어 넣는다plots = [];繰り返す (i = 0; i < n; i++){ plots.追加(새밭());}繰り返す (i = 0; i < q; i++){ cmd = コンソール.行読み().空白除去().分ける(); plot = plots[cmd[1].数に() - 1]; // 복사가 아니라 목록 안의 그 기록을 가리킨다 もし (cmd[0] == "plant") { plot["crop"] = cmd[2]; plot["water"] = 0; } でなければ もし (cmd[0] == "water") { plot["water"] += 1; } でなければ { plot["total"] += cmd[2].数に(); }}それぞれ (p の中 plots){ コンソール.書く(p["crop"] + " " + p["water"] + " " + p["total"]);}