{ }codelper
二重ループ2次元リストP0234

二人とも空いている日の表

集まる日を決めるために、n 人にこれから m 日のうち都合のよい日を聞いた。
一行目に人数 n と日数 m が空白一つで区切って与えられる。
続く n 行には、1 番の人から順に一人の答えが長さ m の文字列で与えられる。
文字列の k 文字目は、その人が k 日目に都合がよければ大文字の O、だめなら大文字の X である。
二人 i と j がいっしょに空いている日の数は、二人とも O である日の数である。
一行目から n 行目まで、i 行目には j = 1 から n まで、i と j がいっしょに空いている日の数を空白一つずつで区切って出力せよ。
i と j が同じなら、その人ひとりが空いている日の数(O の個数)を書く。
最後の行には、異なる二人のうちいっしょに空いている日がいちばん多い組の番号 i と j を i < j として空白一つで区切って出力せよ。
そのような組が複数あれば i がいちばん小さいものを、それでも複数あれば j がいちばん小さいものを出力する。
すべての組でいっしょに空いている日が 0 なら 1 2 を出力する。

入力
2 ≤ n ≤ 100、1 ≤ m ≤ 100、答えは大文字の O と X だけでできた長さ m の文字列
出力
n 行:n × n の表 / 最後の行:いっしょに空いている日がいちばん多い二人の番号
例 1 · stdin
4 5
OOXOX
XOOOX
OOOOO
XXXXO
stdout
3 2 3 0
2 3 3 0
3 3 5 1
0 0 1 1
1 3
例 2 · stdin
2 3
OXO
XOX
stdout
2 0
0 1
1 2
main.py
入力(stdin)

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

$ 準備完了

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

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

三重ループです:人 i、人 j、日 k。
ループの書き出しは Python for i in range(n):、JS・TS・Java・C#・C・C++ for (int i = 0; i < n; i++)(JS・TS は let)、Craykon 繰り返す (i = 0; i < n; i++) です。
いちばん多い間違いは、数える変数 count = 0 を j のループの外に置くことです。
すると組が変わっても 0 に戻らず、前の組の数が積み重なります。
数えるものが変わるところ、つまり j のループのすぐ内側で 0 にします。
C でループ変数を関数の最初にまとめて宣言しておき、内側の for の初期化を空にすると(for (; j < n; j++))、j がやり直されず最初の人しか調べません。
for (int j = i + 1; ...) のように毎回新しく決めます。
表の作り方も言語ごとに違います。
Python [[0] * n] * n は同じ一行を n 回指すので、一つのマスを直すとすべての行の同じマスが変わります。
[[0] * n for _ in range(n)] で行ごとに新しく作ります。
JS・TS も new Array(n).fill(new Array(n).fill(0)) だと同じ問題が起きるので、Array.from({ length: n }, () => new Array(n).fill(0)) を使います。
Java new int[n][n]、C# new int[n, n]、C int common[100][100]、C++ std::vector<std::vector<int>>(n, std::vector<int>(n)) はマスごとに別々に作られます。
Craykon はループで行ごとに 新リスト(n, 0) を入れます。
文字の読み出しは Python・JS・TS・C#・C・C++・Craykon rows[i][k]、Java rows[i].charAt(k) です。
(i, j) と (j, i) は同じ値なので、j ≥ i だけ数えて二つのマスに入れれば仕事がおよそ半分になります。
いちばん多い組を探すときは、j を i + 1 から回せば自分自身とのマス(対角線)を選ばず、順に回って > のときだけ入れ替えれば、同じときに前の組が残ります。
出力する番号は配列の番号に 1 を足します。

Pythonmain.py · 23 行
n, m = map(int, input().split())rows = [input() for _ in range(n)] # common[i][j]: i와 j가 둘 다 비는 날의 수. (i, j)와 (j, i)는 같으니 j >= i만 세고 거울처럼 채운다common = [[0] * n for _ in range(n)]for i in range(n):    for j in range(i, n):        count = 0  # 쌍마다 새로 센다        for k in range(m):            if rows[i][k] == "O" and rows[j][k] == "O":                count += 1        common[i][j] = common[j][i] = count for row in common:    print(" ".join(map(str, row))) # 서로 다른 두 사람만: j는 i + 1부터. 차례대로 돌며 >로 바꾸면 같을 때 앞의 쌍이 남는다best_i, best_j = 0, 1for i in range(n):    for j in range(i + 1, n):        if common[i][j] > common[best_i][best_j]:            best_i, best_j = i, jprint(best_i + 1, best_j + 1)
JavaScriptmain.js · 29 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const rows = lines.slice(1, 1 + n).map((s) => s.trim()); // common[i][j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다const common = Array.from({ length: n }, () => new Array(n).fill(0));for (let i = 0; i < n; i++) {  for (let j = i; j < n; j++) {    let count = 0; // 쌍마다 새로 센다    for (let k = 0; k < m; k++) {      if (rows[i][k] === "O" && rows[j][k] === "O") count++;    }    common[i][j] = common[j][i] = count;  }} const out = common.map((row) => row.join(" "));let bi = 0;let bj = 1;for (let i = 0; i < n; i++) {  for (let j = i + 1; j < n; j++) {    if (common[i][j] > common[bi][bj]) {      bi = i;      bj = j;    }  }}out.push(`${bi + 1} ${bj + 1}`);console.log(out.join("\n"));
TypeScriptmain.ts · 30 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const rows: string[] = lines.slice(1, 1 + n).map((s) => s.trim()); // common[i][j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다const common: number[][] = Array.from({ length: n }, () => new Array<number>(n).fill(0));for (let i = 0; i < n; i++) {  for (let j = i; j < n; j++) {    let count = 0; // 쌍마다 새로 센다    for (let k = 0; k < m; k++) {      if (rows[i][k] === "O" && rows[j][k] === "O") count++;    }    common[i][j] = common[j][i] = count;  }} const out: string[] = common.map((row) => row.join(" "));let bi = 0;let bj = 1;for (let i = 0; i < n; i++) {  for (let j = i + 1; j < n; j++) {    if (common[i][j] > common[bi][bj]) {      bi = i;      bj = j;    }  }}out.push(`${bi + 1} ${bj + 1}`);console.log(out.join("\n"));
JavaMain.java · 46 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    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()), m = Integer.parseInt(st.nextToken());        String[] rows = new String[n];        for (int i = 0; i < n; i++) rows[i] = in.readLine().trim();         // common[i][j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다        int[][] common = new int[n][n];        for (int i = 0; i < n; i++) {            for (int j = i; j < n; j++) {                int count = 0; // 쌍마다 새로 센다                for (int k = 0; k < m; k++) {                    if (rows[i].charAt(k) == 'O' && rows[j].charAt(k) == 'O') count++;                }                common[i][j] = common[j][i] = count;            }        }         StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            for (int j = 0; j < n; j++) {                if (j > 0) out.append(' ');                out.append(common[i][j]);            }            out.append('\n');        }        int bi = 0, bj = 1;        for (int i = 0; i < n; i++) {            for (int j = i + 1; j < n; j++) {                if (common[i][j] > common[bi][bj]) {                    bi = i;                    bj = j;                }            }        }        out.append(bi + 1).append(' ').append(bj + 1).append('\n');        System.out.print(out);    }}
C#Main.cs · 53 行
using System;using System.Text; class Program{    static void Main()    {        string[] nm = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        int n = int.Parse(nm[0]), m = int.Parse(nm[1]);        var rows = new string[n];        for (int i = 0; i < n; i++) rows[i] = Console.ReadLine().Trim();         // common[i, j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다        var common = new int[n, n];        for (int i = 0; i < n; i++)        {            for (int j = i; j < n; j++)            {                int count = 0; // 쌍마다 새로 센다                for (int k = 0; k < m; k++)                {                    if (rows[i][k] == 'O' && rows[j][k] == 'O') count++;                }                common[i, j] = common[j, i] = count;            }        }         var out_ = new StringBuilder();        for (int i = 0; i < n; i++)        {            for (int j = 0; j < n; j++)            {                if (j > 0) out_.Append(' ');                out_.Append(common[i, j]);            }            out_.Append('\n');        }        int bi = 0, bj = 1;        for (int i = 0; i < n; i++)        {            for (int j = i + 1; j < n; j++)            {                if (common[i, j] > common[bi, bj])                {                    bi = i;                    bj = j;                }            }        }        out_.Append(bi + 1).Append(' ').Append(bj + 1).Append('\n');        Console.Write(out_);    }}
C++main.cpp · 38 行
#include <iostream>#include <string>#include <vector> int main() {    std::ios::sync_with_stdio(false);    int n, m;    std::cin >> n >> m;    std::vector<std::string> rows(n);    for (auto& r : rows) std::cin >> r;     // common[i][j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다    std::vector<std::vector<int>> common(n, std::vector<int>(n, 0));    for (int i = 0; i < n; i++) {        for (int j = i; j < n; j++) {            int count = 0; // 쌍마다 새로 센다            for (int k = 0; k < m; k++) {                if (rows[i][k] == 'O' && rows[j][k] == 'O') count++;            }            common[i][j] = common[j][i] = count;        }    }     for (int i = 0; i < n; i++) {        for (int j = 0; j < n; j++) std::cout << (j ? " " : "") << common[i][j];        std::cout << '\n';    }    int bi = 0, bj = 1;    for (int i = 0; i < n; i++) {        for (int j = i + 1; j < n; j++) {            if (common[i][j] > common[bi][bj]) {                bi = i;                bj = j;            }        }    }    std::cout << bi + 1 << ' ' << bj + 1 << '\n';}
Cmain.c · 37 行
#include <stdio.h> static char rows[100][101];static int common[100][100]; int main(void) {    int n, m;    scanf("%d %d", &n, &m);    for (int i = 0; i < n; i++) scanf("%100s", rows[i]);     /* common[i][j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다 */    for (int i = 0; i < n; i++) {        for (int j = i; j < n; j++) {            int count = 0; /* 쌍마다 새로 센다 */            for (int k = 0; k < m; k++) {                if (rows[i][k] == 'O' && rows[j][k] == 'O') count++;            }            common[i][j] = common[j][i] = count;        }    }     for (int i = 0; i < n; i++) {        for (int j = 0; j < n; j++) printf(j ? " %d" : "%d", common[i][j]);        printf("\n");    }    int bi = 0, bj = 1;    for (int i = 0; i < n; i++) {        for (int j = i + 1; j < n; j++) {            if (common[i][j] > common[bi][bj]) {                bi = i;                bj = j;            }        }    }    printf("%d %d\n", bi + 1, bj + 1);    return 0;}
Craykonmain.cray · 50 行
nm = コンソール.数読み();n = nm[0];m = nm[1];rows = [];繰り返す (i = 0; i < n; i++){    rows.追加(コンソール.行読み().空白除去());} // common[i][j]: i와 j가 둘 다 비는 날의 수. j >= i만 세고 거울처럼 채운다common = [];繰り返す (i = 0; i < n; i++){    common.追加(新リスト(n, 0));}繰り返す (i = 0; i < n; i++){    繰り返す (j = i; j < n; j++)    {        count = 0; // 쌍마다 새로 센다        繰り返す (k = 0; k < m; k++)        {            もし (rows[i][k] == "O" && rows[j][k] == "O")            {                count++;            }        }        common[i][j] = count;        common[j][i] = count;    }} 繰り返す (i = 0; i < n; i++){    コンソール.書く(common[i].つなぐ(" "));}bi = 0;bj = 1;繰り返す (i = 0; i < n; i++){    繰り返す (j = i + 1; j < n; j++)    {        もし (common[i][j] > common[bi][bj])        {            bi = i;            bj = j;        }    }}コンソール.書く(bi + 1 + " " + (bj + 1));