paizaラーニングレベルアップ問題集の「神経衰弱」をオブジェクト指向でやってみた

paiza×Qiita記事投稿キャンペーンということで、paizaラーニングレベルアップ問題集の[神経衰弱](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/concentration)をオブジェクト指向でやってみました。対象は[コードモンスター大図鑑](https://paiza.jp/code_monster)で対応している9言語です。

2024/08/25更新
Javascriptのコードを修正いたしました。
- - -
###### 方針
1. [並べられたトランプの縦方向の枚数`H`と横方向の枚数`W`、プレイヤーの数`N`を受け取ります。](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/concentration_01)
1. [トランプのデータ`t[i][j]`を受け取ります。](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/concentration_02)
1. 神経衰弱クラスを作成し、これらの入力値
	> $H$ $W$ $N$
	$t_{1,1}$ $t_{1,2}$ $\dots$ $t_{1,W}$
	$t_{2,1}$ $t_{2,2}$ $\dots$ $t_{2,W}$
	$\dots$
	$t_{H,1}$ $t_{H,2}$ $\dots$ $t_{H,W}$
	
	をコンストラクタに渡します。
1. 記録の長さ`L`を受け取ります。
1. 入力の後半部分
	> $a_1$ $b_1$ $A_1$ $B_1$
	$a_2$ $b_2$ $A_2$ $B_2$
	$\dots$
	$a_L$ $b_L$ $A_L$ $B_L$
	
	を一行ずつ受け取り、メソッドに渡します。
1. メソッドは、問題文の
	> - 並べられたトランプから2枚のトランプを選び、めくります。
	> - [めくった2枚のトランプに異なる数字が書かれていれば、](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/concentration_03)
	>	- [次のプレイヤーの手番となります。](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/concentration_04)
	> - [同じ数字であれば、](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/concentration_03)次の操作をおこないます。
	>	- まず、2枚のトランプはめくったプレーヤーのものとなり、
	
	を実装します。
- - -
###### PHP
```php
<?php
	// 神経衰弱クラス
	class Concentration
	{
		// プレイヤーの数
		private $nPlayers;
	
		// 配置されたトランプに書かれた数字
		private $cards;
	
		// 各プレイヤーが取り除いたトランプの枚数
		private $scores;
	
		// 手番のプレイヤー
		private $player;
	
		// プレイヤーが取り除いたトランプの枚数を返します。
		public function getScore($i)
		{
			return $this->scores[$i];
		}
	
		// コンストラクタ
		public function __construct($n, $t)
		{
			// プレイヤーの数
			$this->nPlayers = $n;
	
			// 配置されたトランプに書かれた数字
			$this->cards = $t;
	
			// プレイヤーが取り除いたトランプの枚数を初期化
			$this->scores = array_fill(0, $n, 0);
	
			// ゲームが始まると、0番の人からプレイしていきます。
			$this->player = 0;
		}
	
		// トランプを捲ります。
		public function play($a, $b, $c, $d)
		{
			//並べられたトランプから2枚のトランプを選び、めくります。
			$t0 = $this->cards[$a][$b];
			$t1 = $this->cards[$c][$d];
	
			// めくった2枚のトランプに
			if ($t0 == $t1) { // 同じ数字が書かれていれば
				// 2枚のトランプはめくったプレーヤーのものとなります。
				$this->scores[$this->player] += 2;
			} else { // 異なる数字が書かれていれば
				// 次のプレイヤーの手番となります。
				$this->player += 1;
	
				// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
				$this->player %= $this->nPlayers;
			}
		}
	}
	
	//1行目には3つの整数H, W, Nが入力されます。
	//HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
	//Nはプレイヤーの数を表します。
	[$h, $w, $n] = explode(" ", fgets(STDIN));
	
	//続くH行には、配置されたトランプに書かれた数字が入力されます。
	$t = [];
	for ($i = 0; $i < $h; $i++) {
		//t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
		$t[] = explode(" ", fgets(STDIN));
	}
	
	// 神経衰弱クラスをインスタンス化します。
	$concentration = new Concentration($n, $t);
	
	// 次の行には、記録の長さ L が与えられます。
	$L = fgets(STDIN);
	
	// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
	for ($i = 0; $i < $L; $i++) {
		// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
		[$a, $b, $A, $B] = array_map(fn($x) => $x - 1, explode(" ", fgets(STDIN)));
	
		// トランプを捲ります。
		$concentration->play($a, $b, $A, $B);
	}
	
	for ($i = 0; $i < $n; $i++) {
		// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
		echo $concentration->getScore($i) . "\n";
	}
?>
```
- - -
###### Ruby
```rb
# 神経衰弱クラス
class Concentration 
	# コンストラクタ
	def initialize(n, t) 
		# プレイヤーの数
		@nPlayers = n
		
		# 配置されたトランプに書かれた数字
		@cards = t
		
		# プレイヤーが取り除いたトランプの枚数を初期化
		@scores = Array.new(n, 0)
		
		# ゲームが始まると、0番の人からプレイしていきます。
		@player = 0
	end
	
	# トランプを捲ります。
	def play(a, b, c, d) 
		#並べられたトランプから2枚のトランプを選び、めくります。
		t0 = @cards[a][b]
		t1 = @cards[c][d]
		
		# めくった2枚のトランプに
		if t0 == t1  # 同じ数字が書かれていれば
			# 2枚のトランプはめくったプレーヤーのものとなります。
			@scores[@player] += 2
		else  # 異なる数字が書かれていれば
			# 次のプレイヤーの手番となります。
			@player += 1

			# N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			@player %= @nPlayers
		end
	end

	# プレイヤーが取り除いたトランプの枚数を返します。
	def score(i) 
		return @scores[i]
	end
end

#1行目には3つの整数H, W, Nが入力されます。
#HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
#Nはプレイヤーの数を表します。
h, w, n = gets.split.map(&:to_i)

#続くH行には、配置されたトランプに書かれた数字が入力されます。
t = []
h.times do 
	#t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
	t << gets.chomp.split
end

# 神経衰弱クラスをインスタンス化します。
concentration = Concentration.new(n, t)

# 次の行には、記録の長さ L が与えられます。
L = gets.to_i

# 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
L.times do
	# これは、a行b列のトランプとc行d列のトランプが捲られたことを表します。
	a, b, c, d = gets.split.map(&lambda{ |x| x.to_i - 1 })

	# トランプを捲ります。
	concentration.play(a, b, c, d)
end

n.times do |i|
	# i番目のプレイヤーが取り除いたトランプの枚数を出力します。
	p concentration.score(i)
end
```
- - -
###### Java	
```java
import java.util.*;

// 神経衰弱クラス
class Concentration {
	// プレイヤーの数
	private int nPlayers;

	// 配置されたトランプに書かれた数字
	private String[][] cards;

	// 各プレイヤーが取り除いたトランプの枚数
	private int[] scores;

	// 手番のプレイヤー
	private int player;

	// プレイヤーが取り除いたトランプの枚数を返します。
	public int getScore(int i) {
		return this.scores[i];
	}

	// コンストラクタ
	public Concentration(int n, String[][] t) {
		// プレイヤーの数
		this.nPlayers = n;

		// 配置されたトランプに書かれた数字
		this.cards = t;

		// プレイヤーが取り除いたトランプの枚数を初期化
		this.scores = new int[n];

		// ゲームが始まると、0番の人からプレイしていきます。
		this.player = 0;
	}

	// トランプを捲ります。
	public void play(int a, int b, int c, int d) {
		// 並べられたトランプから2枚のトランプを選び、めくります。
		String t0 = this.cards[a][b];
		String t1 = this.cards[c][d];

		// めくった2枚のトランプに
		if (t0.equals(t1)) { // 同じ数字が書かれていれば
			// 2枚のトランプはめくったプレーヤーのものとなります。
			this.scores[this.player] += 2;
		} else { // 異なる数字が書かれていれば
			// 次のプレイヤーの手番となります。
			this.player += 1;

			// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			this.player %= this.nPlayers;
		}
	}
}

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		// 1行目には3つの整数H, W, Nが入力されます。
		// HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
		// Nはプレイヤーの数を表します。
		int h = sc.nextInt();
		int w = sc.nextInt();
		int n = sc.nextInt();

		// 続くH行には、配置されたトランプに書かれた数字が入力されます。
		String[][] t = new String[h][];
		for (int i = 0; i < h; i++) {
			t[i] = new String[w];
			for (int j = 0; j < w; j++) {
				// t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
				t[i][j] = sc.next();
			}
		}

		// 神経衰弱クラスをインスタンス化します。
		Concentration concentration = new Concentration(n, t);

		// 次の行には、記録の長さ L が与えられます。
		int L = sc.nextInt();

		// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
		for (int i = 0; i < L; i++) {
			// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
			int a = sc.nextInt() - 1;
			int b = sc.nextInt() - 1;
			int A = sc.nextInt() - 1;
			int B = sc.nextInt() - 1;

			// トランプを捲ります。
			concentration.play(a, b, A, B);
		}
		sc.close();

		for (int i = 0; i < n; i++) {
			// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
			System.out.println(concentration.getScore(i));
		}
	}
}
```
- - -
###### Python
```py
# 神経衰弱クラス
class Concentration:
	# コンストラクタ
	def __init__(self, n, t):
		# プレイヤーの数
		self.nPlayers = n

		# 配置されたトランプに書かれた数字
		self.cards = t

		# プレイヤーが取り除いたトランプの枚数を初期化
		self.scores = [0 for _ in range(n)]

		# ゲームが始まると、0番の人からプレイしていきます。
		self.player = 0

	# トランプを捲ります。
	def play(self, a, b, c, d):
		# 並べられたトランプから2枚のトランプを選び、めくります。
		t0 = self.cards[a][b]
		t1 = self.cards[c][d]

		# めくった2枚のトランプに
		if t0 == t1:  # 同じ数字が書かれていれば
			# 2枚のトランプはめくったプレーヤーのものとなります。
			self.scores[self.player] += 2
		else:  # 異なる数字が書かれていれば
			# 次のプレイヤーの手番となります。
			self.player += 1

			# N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			self.player %= self.nPlayers

	# プレイヤーが取り除いたトランプの枚数を返します。
	def score(self, i):
		return self.scores[i]


# 1行目には3つの整数H, W, Nが入力されます。
# HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
# Nはプレイヤーの数を表します。
h, w, n = map(int, input().split())

# 続くH行には、配置されたトランプに書かれた数字が入力されます。
t = []
for _ in range(h):
	# t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
	t.append(input().split())

# 神経衰弱クラスをインスタンス化します。
concentration = Concentration(n, t)

# 次の行には、記録の長さ L が与えられます。
L = int(input())

# 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
for _ in range(L):
	# これは、a行b列のトランプとc行d列のトランプが捲られたことを表します。
	a, b, c, d = map(lambda x: int(x) - 1, input().split())

	# トランプを捲ります。
	concentration.play(a, b, c, d)

for i in range(n):
	# i番目のプレイヤーが取り除いたトランプの枚数を出力します。
	print(concentration.score(i))
```
- - -
###### C言語
```c
#include <stdio.h>
#include <string.h>

// 神経衰弱構造体
typedef struct Concentration {
	// プレイヤーの数
	int nPlayers;

	// 配置されたトランプに書かれた数字
	int **cards;

	// 各プレイヤーが取り除いたトランプの枚数
	int *scores;

	// 手番のプレイヤー
	int player;
} Concentration;

// トランプを捲ります。
void play(Concentration *concentration, int a, int b, int c, int d) {
	//並べられたトランプから2枚のトランプを選び、めくります。
	int t0 = concentration->cards[a][b];
	int t1 = concentration->cards[c][d];

	// めくった2枚のトランプに
	if (t0 == t1) { // 同じ数字が書かれていれば
		// 2枚のトランプはめくったプレーヤーのものとなります。
		concentration->scores[concentration->player] += 2;
	} else { // 異なる数字が書かれていれば
		// 次のプレイヤーの手番となります。
		concentration->player += 1;
		// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
		concentration->player %= concentration->nPlayers;
	}
}
/* プレイヤーが取り除いたトランプの枚数を返します。
int getScore(const Concentration *concentration, int i) {
	return concentration->scores[i];
}
 */
int main() {
	//1行目には3つの整数H, W, Nが入力されます。
	//HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
	//Nはプレイヤーの数を表します。
	int h, w, n;
	scanf("%d %d %d", &h, &w, &n);

	//続くH行には、配置されたトランプに書かれた数字が入力されます。
	int t[h][w];
	int *p[h];
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			//t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
			scanf("%d", &t[i][j]);
		}
		p[i] = t[i];
	}

	// 神経衰弱クラスをインスタンス化します。
	int scores[n];
	memset(scores, 0, sizeof(scores));
	Concentration concentration = { n, p, scores, 0 };

	// 次の行には、記録の長さ L が与えられます。
	int L;
	scanf("%d", &L);

	// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
	for (int i = 0; i < L; i++) {
		// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
		int a, b, A, B;
		scanf("%d %d %d %d", &a, &b, &A, &B);

		// トランプを捲ります。
		play(&concentration, a - 1, b - 1, A - 1, B - 1);
	}

	for (int i = 0; i < n; i++) {
		// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
		// printf("%d\n", getScore(&concentration, i));
		printf("%d\n", scores[i]);
	}
	return 0;
}
```
- - -
###### C#
```cs
using System;

// 神経衰弱クラス
class Concentration
{
	// プレイヤーの数
	private int nPlayers;

	// 配置されたトランプに書かれた数字
	private String[][] cards;

	// 各プレイヤーが取り除いたトランプの枚数
	private int[] scores;

	// 手番のプレイヤー
	private int player;

	// プレイヤーが取り除いたトランプの枚数を返します。
	public int GetScore(int i)
	{
		return scores[i];
	}

	// コンストラクタ
	public Concentration(int n, String[][] t)
	{
		// プレイヤーの数
		nPlayers = n;

		// 配置されたトランプに書かれた数字
		cards = t;

		// プレイヤーが取り除いたトランプの枚数を初期化
		scores = new int[n];

		// ゲームが始まると、0番の人からプレイしていきます。
		player = 0;
	}

	// トランプを捲ります。
	public void Play(int a, int b, int c, int d)
	{
		// 並べられたトランプから2枚のトランプを選び、めくります。
		string t0 = cards[a][b];
		string t1 = cards[c][d];

		// めくった2枚のトランプに
		if (t0.Equals(t1))
		{ // 同じ数字が書かれていれば
			// 2枚のトランプはめくったプレーヤーのものとなります。
			scores[player] += 2;
		}
		else
		{ // 異なる数字が書かれていれば
			// 次のプレイヤーの手番となります。
			player += 1;

			// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			player %= nPlayers;
		}
	}
}

class Program
{
	static void Main(string[] args)
	{
		// 1行目には3つの整数H, W, Nが入力されます。
		// HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
		// Nはプレイヤーの数を表します。
		int[] hwn = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
		int h = hwn[0];
		// int w = hwn[1];
		int n = hwn[2];

		// 続くH行には、配置されたトランプに書かれた数字が入力されます。
		string[][] t = new string[h][];
		for (int i = 0; i < h; i++)
		{
			// t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
			t[i] = Console.ReadLine().Split();
		}

		// 神経衰弱クラスをインスタンス化します。
		Concentration concentration = new Concentration(n, t);

		// 次の行には、記録の長さ L が与えられます。
		int L = int.Parse(Console.ReadLine());

		// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
		for (int i = 0; i < L; i++)
		{
			// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
			int[] abAB = Array.ConvertAll(Console.ReadLine().Split(), x => int.Parse(x) - 1);

			// トランプを捲ります。
			concentration.Play(abAB[0], abAB[1], abAB[2], abAB[3]);
		}

		for (int i = 0; i < n; i++)
		{
			// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
			Console.WriteLine(concentration.GetScore(i));
		}
	}
}
```
- - -
###### Javascript
2024/08/25 `parseInt`を`Number`に修正いたしました。
```js
// 神経衰弱クラス
class Concentration {
	// プレイヤーの数
	nPlayers = 0;

	// 配置されたトランプに書かれた数字
	cards = null;

	// 各プレイヤーが取り除いたトランプの枚数
	scores = null;

	// 手番のプレイヤー
	player = 0;

	// プレイヤーが取り除いたトランプの枚数を返します。
	getScore(i) {
		return this.scores[i];
	}

	// コンストラクタ
	constructor(n, t) {
		// プレイヤーの数
		this.nPlayers = n;

		// 配置されたトランプに書かれた数字
		this.cards = t;

		// プレイヤーが取り除いたトランプの枚数を初期化
		this.scores = new Array(n).fill(0);

		// ゲームが始まると、0番の人からプレイしていきます。
		this.player = 0;
	}

	// トランプを捲ります。
	play(a, b, c, d) {
		//並べられたトランプから2枚のトランプを選び、めくります。
		const t0 = this.cards[a][b];
		const t1 = this.cards[c][d];

		// めくった2枚のトランプに
		if (t0 === t1) { // 同じ数字が書かれていれば
			// 2枚のトランプはめくったプレーヤーのものとなります。
			this.scores[this.player] += 2;
		} else { // 異なる数字が書かれていれば
			// 次のプレイヤーの手番となります。
			this.player += 1;

			// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			this.player %= this.nPlayers;
		}
	}
}


const lines = require("fs").readFileSync("/dev/stdin", "utf8").split("\n");
let row = 0;
// 1行目には3つの整数H, W, Nが入力されます。
// HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
// Nはプレイヤーの数を表します。
// const [h, w, n] = lines[row++].split(" ").map(x => parseInt(x, 10));
const [h, w, n] = lines[row++].split(" ").map(Number);

//続くH行には、配置されたトランプに書かれた数字が入力されます。
const t = [];
for (var i = 0; i < h; i++) {
	//t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
	t.push(lines[row++].split(" "));
}

// 神経衰弱クラスをインスタンス化します。
const concentration = new Concentration(n, t);

// 次の行には、記録の長さ L が与えられます。
// const L = parseInt(lines[row++]);
const L = Number(lines[row++]);

// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
for (var i = 0; i < L; i++) {
	// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
	// let [a, b, A, B] = lines[row++].split(" ").map(x => parseInt(x, 10) - 1);
	let [a, b, A, B] = lines[row++].split(" ").map(x => Number(x) - 1);

	// トランプを捲ります。
	concentration.play(a, b, A, B);
}

for (var i = 0; i < n; i++) {
	// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
	console.log(concentration.getScore(i));
}
```
- - -
###### C++
```cpp
#include <iostream>
#include <vector>
using namespace std;

// 神経衰弱クラス
class Concentration {
	// プレイヤーの数
	int nPlayers;

	// 配置されたトランプに書かれた数字
	vector<vector<string>> &cards;

	// 各プレイヤーが取り除いたトランプの枚数
	vector<int> scores;

	// 手番のプレイヤー
	int player;

public:
	// プレイヤーが取り除いたトランプの枚数を返します。
	int getScore(int i) {
		return scores[i];
	}

	// コンストラクタ
	Concentration(int n, vector<vector<string>> &t) :
			nPlayers(n), cards(t) {
		// プレイヤーが取り除いたトランプの枚数を初期化
		scores.resize(n, 0);

		// ゲームが始まると、0番の人からプレイしていきます。
		player = 0;
	}

	// トランプを捲ります。
	void play(int a, int b, int c, int d) {
		//並べられたトランプから2枚のトランプを選び、めくります。
		string t0 = cards[a][b];
		string t1 = cards[c][d];

		// めくった2枚のトランプに
		if (t0 == t1) { // 同じ数字が書かれていれば
			// 2枚のトランプはめくったプレーヤーのものとなります。
			scores[player] += 2;
		} else { // 異なる数字が書かれていれば
			// 次のプレイヤーの手番となります。
			player += 1;

			// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			player %= nPlayers;
		}
	}
};

int main(void) {
	//1行目には3つの整数H, W, Nが入力されます。
	//HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
	//Nはプレイヤーの数を表します。
	int h, w, n;
	cin >> h >> w >> n;

	//続くH行には、配置されたトランプに書かれた数字が入力されます。
	vector<vector<string>> t(h, vector<string>(w));
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			//t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
			cin >> t[i][j];
		}
	}

	// 神経衰弱クラスをインスタンス化します。
	Concentration concentration(n, t);

	// 次の行には、記録の長さ L が与えられます。
	int L;
	cin >> L;

	// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
	for (int i = 0; i < L; i++) {
		// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
		int a, b, A, B;
		cin >> a >> b >> A >> B;

		// トランプを捲ります。
		concentration.play(a - 1, b - 1, A - 1, B - 1);
	}

	for (int i = 0; i < n; i++) {
		// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
		cout << concentration.getScore(i) << endl;
	}
}
```
- - -
###### Kotlin
```kotlin
import java.util.*

// 神経衰弱クラス
class Concentration {
	// プレイヤーの数
	var nPlayers: Int

	// 配置されたトランプに書かれた数字
	var cards: Array<Array<String>>

	// 各プレイヤーが取り除いたトランプの枚数
	var scores: Array<Int>

	// 手番のプレイヤー
	var player: Int

	// プレイヤーが取り除いたトランプの枚数を返します。
	fun getScore(i: Int): Int {
		return scores[i]
	}

	// コンストラクタ
	constructor(n: Int, t: Array<Array<String>>) {
		// プレイヤーの数
		this.nPlayers = n

		// 配置されたトランプに書かれた数字
		this.cards = t

		// プレイヤーが取り除いたトランプの枚数を初期化
		this.scores = Array(n) { 0 }

		// ゲームが始まると、0番の人からプレイしていきます。
		this.player = 0
	}

	// トランプを捲ります。
	fun play(a: Int, b: Int, c: Int, d: Int) {
		// 並べられたトランプから2枚のトランプを選び、めくります。
		val t0 = cards[a][b]
		val t1 = cards[c][d]

		// めくった2枚のトランプに
		if (t0.equals(t1)) { // 同じ数字が書かれていれば
			// 2枚のトランプはめくったプレーヤーのものとなります。
			this.scores[this.player] += 2
		} else { // 異なる数字が書かれていれば
			// 次のプレイヤーの手番となります。
			this.player += 1

			// N-1番のプレイヤーの次のプレイヤーは0番のプレイヤーであるとします。
			this.player %= this.nPlayers
		}
	}
}

fun main() {
	val sc = Scanner(System.`in`)

	// 1行目には3つの整数H, W, Nが入力されます。
	// HとWはそれぞれ並べられたトランプの縦方向の枚数と横方向の枚数で、
	// Nはプレイヤーの数を表します。
	val h = sc.nextInt()
	val w = sc.nextInt()
	val n = sc.nextInt()

	// 続くH行には、配置されたトランプに書かれた数字が入力されます。
	val t = Array(h){ Array(w) { "" }}
	for (i in 0 until h) {
		for (j in 0 until w) {
			// t[i][j]はi行j列に置かれたトランプに書かれた数字を表します。
			t[i][j] = sc.next()
		}
	}

	// 神経衰弱クラスをインスタンス化します。
	val concentration = Concentration(n, t)

	// 次の行には、記録の長さ L が与えられます。
	val L = sc.nextInt()

	// 続く L 行には、捲られたトランプの記録が時系列順で与えられます。
	for (i in 1..L) {
		// これは、a行b列のトランプとA行B列のトランプが捲られたことを表します。
		var a = sc.nextInt() - 1
		var b = sc.nextInt() - 1
		var A = sc.nextInt() - 1
		var B = sc.nextInt() - 1

		// トランプを捲ります。
		concentration.play(a, b, A, B)
	}
	sc.close()

	for (i in 0 until n) {
		// i番目のプレイヤーが取り除いたトランプの枚数を出力します。
		println(concentration.getScore(i))
	}
}
```