第19回【JavaScript】行列の転置、かけ算表

現在取り組んでいるのは、paiza ラーニング問題集「二重ループメニュー」になります。

はじめに

猫とキャンプと野球観戦と AWS が大好きな旦那、LeoSaki です。モフモフしたい。

JavaScript をゼロから勉強してみよう、のコーナー 19 回目です。

ルナちゃんとレオくんに挟まれて幸せな朝でした。暑かったけれど。最近、ルナちゃんの 1 つ下、2 つ下の子が続けざまに亡くなりました。猫の腎臓の問題はなかなかに困難です。ルナちゃんは年に 1 回の健康診断で健康のお墨付きを頂いています。長生きしてね。

それでは、今日も頑張ってみようと思います。

行列の転置 (paizaランク D 相当)

N 行 K 列の行列 A の i 行 j 列 の要素 A_ij を A_ji とした K 行 N 列の行列を元の配列 A の転置行列と言います。

例として、

1 2 3
4 5 6
7 8 9

の転置行列は

1 4 7
2 5 8
3 6 9

です。

行列 A についての情報が与えられるので、A の転置行列を出力してください。


入力される値

N K
A_11 A_12 ... A_1K
...
A_N1 A_N2 ... A_NK

・ 1 行目では行列の行数 N と列数 K が半角スペース区切りで与えられます。
・ 続く N 行では、A の各要素 A_ij (1 ≦ j ≦ Ki) が半角スペース区切りで与えられます。

入力値最終行の末尾に改行が1つ入ります。


期待する出力

A の転置行列の各要素を入力の A と同様の形式で出力してください。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ N , K ≦ 100
・ 0 ≦ A_ij ≦ 100 (1 ≦ i ≦ N , 1 ≦ j ≦ K)


入力例

5 5
23 54 0 37 0
1 4 5 6 3
48 49 13 49 20
20 49 58 38 48
4 5 7 3 100

出力例

23 1 48 20 4
54 4 49 49 5
0 5 13 58 7
37 6 49 38 3
0 3 20 48 100

行と列を入れ替えるパターン。結構、使われるやつです。

JavaScript
process.stdin.resume();
process.stdin.setEncoding('utf8');

var lines = [];
var reader = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
reader.on('line', (line) => {
  lines.push(line);
});
reader.on('close', () => {
  const [n,k] = lines[0].split(/\s/).map(Number);
  const a = [];
  for (let i = 1; i <= n; i++) {
      a.push(lines[i].split(/\s/).map(Number));
  }
  for (let i = 0; i < k; i++) {
      for (let j = 0; j < n; j++) {
          if (j == n - 1) {
              console.log(a[j][i]);
              break;
          }
          process.stdout.write(a[j][i] + ' ');
      }
  }
});
Python
N,K = map(int,input().split())
A = [input().split() for _ in range(N)]
for k in range(K):
    for n in range(N):
        if n == N-1:
            print(A[n][k])
        else:
            print(A[n][k],end=" ")

かけ算表 (paizaランク D 相当)

配列 A の要素数 N とその要素 A_i (1 ≦ i ≦ N) が与えられるので、A についてのかけ算表 B を出力してください。かけ算表は N * N の二次元配列の形式とし、B の i 行 j 列の要素 B_ij について、B_ij = Ai * Aj (1 ≦ i , j ≦ N) が成り立つものとします。

例として、A = [1,2,3] のとき B は

1 2 3
2 4 6
3 6 9

となります。


入力される値

N
A_1 ... A_N

・ 1 行目では配列 A の要素数 N が与えられます。
・ 2 行目では、A の各要素 A_i (1 ≦ i ≦ N) が半角スペース区切りで与えられます。

入力値最終行の末尾に改行が1つ入ります。


期待する出力

B_11 B_12 ... B_1N
...
B_N1 B_N2 ... B_NN

A のかけ算表 B を出力してください。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ N ≦ 100 (1 ≦ i ≦ N)
・ 0 ≦ A_i ≦ 100 (1 ≦ i ≦ N)


入力例

10
72 10 75 15 16 65 7 43 96 57

出力例

5184 720 5400 1080 1152 4680 504 3096 6912 4104
720 100 750 150 160 650 70 430 960 570
5400 750 5625 1125 1200 4875 525 3225 7200 4275
1080 150 1125 225 240 975 105 645 1440 855
1152 160 1200 240 256 1040 112 688 1536 912
4680 650 4875 975 1040 4225 455 2795 6240 3705
504 70 525 105 112 455 49 301 672 399
3096 430 3225 645 688 2795 301 1849 4128 2451
6912 960 7200 1440 1536 6240 672 4128 9216 5472
4104 570 4275 855 912 3705 399 2451 5472 3249

問題がよくわからん。問題を読み解くところから解答は始まっている。と、似たようなことを Python のときも書いていた。

JavaScript
process.stdin.resume();
process.stdin.setEncoding('utf8');

var lines = [];
var reader = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
reader.on('line', (line) => {
  lines.push(line);
});
reader.on('close', () => {
  const n = Number(lines[0]);
  const a = lines[1].split(/\s/).map(Number);
  for (let i = 0; i < n; i++) {
      for (let j = 0; j < n; j++) {
          if (j == n - 1) {
              console.log(a[i] * a[j]);
              break;
          }
          process.stdout.write(a[i] * a[j] + ' ');
      }
  }
});
Python
N = int(input())
A = [int(x) for x in input().split()]
for i in range(N):
    for j in range(N):
        if j == N-1:
            print(A[i]*A[j])
        else:
            print(A[i]*A[j],end=" ")

最後に

最近、横着をして、else 文を書いていないのだけれど、ちゃんと書いた方がいいんだろうか。if 文の条件が false なら if 文を抜けるんだからいいじゃん、じゃダメかなぁ。

学習を続けて、もっと大きな値の問題になったときに、実行時間に明らかな差が生じるかもしれない。うん、まぁ、それも勉強だと思って。

引き続き、よろしくお願いいたします!

Python の第19回はこちら