さらに先へ · 18
2次元リスト(グリッド)
行と列のグリッド:読み込み、行の合計・列の合計、範囲内だけで隣のマスを見る。
2次元リストはリストを入れたリストです。grid[i][j] は i 行目の j 列目のマスです。
下の例はグリッドを読み込み、行の合計と列の合計を求め、マスごとに隣のマスの合計を表示します。
r, c = map(int, input().split())grid = [list(map(int, input().split())) for _ in range(r)]print(*[sum(row) for row in grid])print(*[sum(grid[i][j] for i in range(r)) for j in range(c)])moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]near = [[0] * c for _ in range(r)]for i in range(r): for j in range(c): for di, dj in moves: ni, nj = i + di, j + dj if 0 <= ni < r and 0 <= nj < c: near[i][j] += grid[ni][nj]for row in near: print(*row)const [[r, c], ...grid] = require("fs").readFileSync(0, "utf8").trim().split("\n").map((l) => l.trim().split(/\s+/).map(Number));console.log(grid.map((row) => row.reduce((a, b) => a + b, 0)).join(" "));const colSums = Array.from({ length: c }, (_, j) => grid.reduce((s, row) => s + row[j], 0));console.log(colSums.join(" "));const moves = [[-1, 0], [1, 0], [0, -1], [0, 1]];const near = Array.from({ length: r }, () => new Array(c).fill(0));for (let i = 0; i < r; i++) { for (let j = 0; j < c; j++) { for (const [di, dj] of moves) { const ni = i + di, nj = j + dj; if (ni >= 0 && ni < r && nj >= 0 && nj < c) near[i][j] += grid[ni][nj]; } }}for (const row of near) console.log(row.join(" "));import { readFileSync } from "node:fs";const [[r, c], ...grid]: number[][] = readFileSync(0, "utf8").trim().split("\n").map((l) => l.trim().split(/\s+/).map(Number));console.log(grid.map((row) => row.reduce((a, b) => a + b, 0)).join(" "));const colSums: number[] = Array.from({ length: c }, (_, j) => grid.reduce((s, row) => s + row[j], 0));console.log(colSums.join(" "));const moves: [number, number][] = [[-1, 0], [1, 0], [0, -1], [0, 1]];const near: number[][] = Array.from({ length: r }, () => new Array<number>(c).fill(0));for (let i = 0; i < r; i++) { for (let j = 0; j < c; j++) { for (const [di, dj] of moves) { const ni = i + di, nj = j + dj; if (ni >= 0 && ni < r && nj >= 0 && nj < c) near[i][j] += grid[ni][nj]; } }}for (const row of near) console.log(row.join(" "));import java.util.Scanner; public class Main { static void print(int[] a) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < a.length; i++) sb.append(i > 0 ? " " : "").append(a[i]); System.out.println(sb); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int r = sc.nextInt(), c = sc.nextInt(); int[][] grid = new int[r][c]; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) grid[i][j] = sc.nextInt(); int[] rowSums = new int[r], colSums = new int[c]; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { rowSums[i] += grid[i][j]; colSums[j] += grid[i][j]; } print(rowSums); print(colSums); int[] di = {-1, 1, 0, 0}, dj = {0, 0, -1, 1}; for (int i = 0; i < r; i++) { int[] near = new int[c]; for (int j = 0; j < c; j++) for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni >= 0 && ni < r && nj >= 0 && nj < c) near[j] += grid[ni][nj]; } print(near); } }}using System;using System.Linq; class Program{ static void Main() { int[] rc = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); int r = rc[0], c = rc[1]; int[,] grid = new int[r, c]; for (int i = 0; i < r; i++) { int[] row = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); for (int j = 0; j < c; j++) grid[i, j] = row[j]; } Console.WriteLine(string.Join(" ", Enumerable.Range(0, r).Select(i => Enumerable.Range(0, c).Sum(j => grid[i, j])))); Console.WriteLine(string.Join(" ", Enumerable.Range(0, c).Select(j => Enumerable.Range(0, r).Sum(i => grid[i, j])))); int[] di = { -1, 1, 0, 0 }, dj = { 0, 0, -1, 1 }; for (int i = 0; i < r; i++) { int[] near = new int[c]; for (int j = 0; j < c; j++) for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni >= 0 && ni < r && nj >= 0 && nj < c) near[j] += grid[ni, nj]; } Console.WriteLine(string.Join(" ", near)); } }}#include <iostream>#include <vector> void print(const std::vector<int>& v) { for (size_t i = 0; i < v.size(); i++) std::cout << (i > 0 ? " " : "") << v[i]; std::cout << '\n';} int main() { int r, c; std::cin >> r >> c; std::vector<std::vector<int>> grid(r, std::vector<int>(c)); for (auto& row : grid) for (int& x : row) std::cin >> x; std::vector<int> rowSums(r, 0), colSums(c, 0); for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { rowSums[i] += grid[i][j]; colSums[j] += grid[i][j]; } print(rowSums); print(colSums); const int di[] = {-1, 1, 0, 0}, dj[] = {0, 0, -1, 1}; for (int i = 0; i < r; i++) { std::vector<int> near(c, 0); for (int j = 0; j < c; j++) for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni >= 0 && ni < r && nj >= 0 && nj < c) near[j] += grid[ni][nj]; } print(near); }}#include <stdio.h> #define MAX 100 int grid[MAX][MAX]; void print(const int *a, int n) { for (int i = 0; i < n; i++) printf(i > 0 ? " %d" : "%d", a[i]); printf("\n");} int main(void) { int r, c, rowSums[MAX] = {0}, colSums[MAX] = {0}; scanf("%d %d", &r, &c); for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { scanf("%d", &grid[i][j]); rowSums[i] += grid[i][j]; colSums[j] += grid[i][j]; } print(rowSums, r); print(colSums, c); const int di[] = {-1, 1, 0, 0}, dj[] = {0, 0, -1, 1}; for (int i = 0; i < r; i++) { int near[MAX] = {0}; for (int j = 0; j < c; j++) for (int k = 0; k < 4; k++) { int ni = i + di[k], nj = j + dj[k]; if (ni >= 0 && ni < r && nj >= 0 && nj < c) near[j] += grid[ni][nj]; } print(near, c); } return 0;}rc = コンソール.数読み();r = rc[0];c = rc[1];grid = [];繰り返す (i = 0; i < r; i++){ grid.追加(コンソール.数読み());}rowSums = 新リスト(r, 0);colSums = 新リスト(c, 0);繰り返す (i = 0; i < r; i++){ 繰り返す (j = 0; j < c; j++) { rowSums[i] += grid[i][j]; colSums[j] += grid[i][j]; }}コンソール.書く(rowSums);コンソール.書く(colSums);di = [-1, 1, 0, 0];dj = [0, 0, -1, 1];繰り返す (i = 0; i < r; i++){ near = 新リスト(c, 0); 繰り返す (j = 0; j < c; j++) { 繰り返す (k = 0; k < 4; k++) { ni = i + di[k]; nj = j + dj[k]; もし (ni >= 0 && ni < r && nj >= 0 && nj < c) { near[j] += grid[ni][nj]; } } } コンソール.書く(near);}3 4 1 2 3 4 5 6 7 8 9 10 11 12
10 26 42 15 18 21 24 7 10 13 11 16 24 28 23 15 26 29 19
ポイント
- すべてのマスを見るには、行を回るループの中に列を回るループを入れます(二重ループ)。
- 行の合計は行ごとにマスを足し、列の合計は列ごとに行をたどって足します。
一度回るあいだにrowSums[i]とcolSums[j]の両方に足してもかまいません。 - 隣のマス(上・下・左・右)は、
di = [-1, 1, 0, 0]、dj = [0, 0, -1, 1]のように方向をリストにして回ると短く書けます。 - 端のマスでは隣が外に出ます。
読む前に必ず0 <= ni < rかつ0 <= nj < cを確かめます。
負の側もです。 - 行は一つずつ新しく作る必要があります。
同じ行を何度も入れると、一マス変えただけですべての行が変わります。
言語ごとの書き方
| Python | [[0] * c for _ in range(r)]。grid[-1] はエラーではなく最後の行です |
|---|---|
| JavaScript | Array.from({ length: r }, () => new Array(c).fill(0))。外のマスは undefined、外の行のマスを読むと TypeError |
| TypeScript | JavaScript と同じです。 型は number[][] |
| Java | new int[r][c] — すべて 0 で埋まります。範囲外は ArrayIndexOutOfBoundsException |
| C# | 長方形配列 int[r, c](grid[i, j] で読みます)と配列の配列 int[r][] の二種類があります。範囲外は IndexOutOfRangeException |
| C++ | vector<vector<int>>(r, vector<int>(c))。[] は範囲を確かめません |
| C | int grid[100][100] のように大きさを先に決めておき、前のほうだけを使います。範囲外を読んでも何も言いません |
| Craykon | 行ごとに grid.追加(コンソール.数読み()) で積み上げ、新リスト(c, 0) で 0 が c 個の行を作ります。範囲外は「リストには 0〜3 番しかありません」エラー |
よくある間違い
いちばん上の行の「上の隣」を確認なしで読んだPython
grid = [[1, 2], [3, 4]]
i, j = 0, 0
print(grid[i - 1][j])→ 3 — grid[-1] は最後の行なので、エラーなしでいちばん下の行の値を読みます
0 <= ni < r のように負の側も必ず確かめます。
範囲の確認を忘れたJavaScript · TypeScript · C · C++
const grid = [[1, 2], [3, 4]];
console.log(1 + grid[0][2]);
console.log(grid[2][0]);→ NaN が出て、次の行は TypeError で止まります。C・C++ は何も言わずに隣の行や関係ないメモリを読みます
読む前に 0 <= ni && ni < r && 0 <= nj && nj < c を確かめます。
Java・C#・Craykon は範囲外エラーで止まってくれます。
言語ごとの違い
Python の
JavaScript の
Python の
[[0] * c] * r は同じ一行を r 回指すので、g = [[0] * 3] * 2; g[0][0] = 5 とすると [[5, 0, 0], [5, 0, 0]] になります。JavaScript の
new Array(r).fill(new Array(c).fill(0)) も同じなので、行は必ず一つずつ新しく作りましょう。