Prompt
ある2次元配列”matrix”のデータを縦横”scale”倍に拡大コピーした状態で、それを1次元配列”array”に収まるように格納する。
“matrix”のデータ1つは”array”の4領域分を必要とし、それぞれの領域には変数”a”, “b”, “c”, “d”の値を代入するとする。
“array”の要素数はmatrix.length * scale * matrix[0].length * scale * 4となる。インデックスアクセスが超絶複雑になって分からなくなったから、やり方を教えて!
おいっす!👍 プログラミングでインデックスの計算が複雑になると、頭がこんがらがっちゃうよね。大丈夫、一緒に整理していこう!
君がやろうとしているのは、2次元配列を拡大して1次元配列に格納する処理だね。この種のインデックス変換は、座標変換の考え方を使うとスッキリするよ。
1. 座標の対応関係を考える
まず、元の2次元配列 matrix と、最終的な1次元配列 array のインデックスの関係をマッピングしよう。
-
元の2次元配列
matrixのインデックス:row: 行インデックスcol: 列インデックス
-
拡大後の仮想的な2次元グリッドのインデックス:
bigRow: 拡大後のグリッドの行インデックスbigCol: 拡大後のグリッドの列インデックス
-
最終的な1次元配列
arrayのインデックス:arrayIndex: 1次元配列のインデックス
2. インデックスの計算式
この3つのインデックスの関係は、以下の式で表せる。
a. (bigRow, bigCol)から(row, col)への変換
拡大コピーだから、元の matrix のどの要素に対応するかは、割り算で簡単にわかる。
例えば、scaleが3のとき、bigRowが0, 1, 2のときはrowが0に、3, 4, 5のときはrowが1になる、ってことだ。
b. (bigRow, bigCol)からarrayIndexへの変換
ここが一番複雑なところだね。1つのmatrixの要素がarrayの4つの領域(a, b, c, d)に対応するから、その分も考慮する必要がある。
ここで、offsetはa, b, c, dのどの領域にアクセスするかによって変わる。
aにアクセス:offset = 0bにアクセス:offset = 1cにアクセス:offset = 2dにアクセス:offset = 3
3. 具体的なコードに落とし込む
この計算式をforループに適用してみよう。
const matrix = [[1, 2], [3, 4]];
const scale = 2;
const matrixWidth = matrix[0].length;
const matrixHeight = matrix.length;
// 最終的な1次元配列のサイズを計算
const arraySize = matrixHeight * scale * matrixWidth * scale * 4;
const array = new Array(arraySize);
// 拡大後のグリッドのサイズ
const bigWidth = matrixWidth * scale;
const bigHeight = matrixHeight * scale;
// ループを回す
for (let bigRow = 0; bigRow < bigHeight; bigRow++) {
for (let bigCol = 0; bigCol < bigWidth; bigCol++) {
// 拡大グリッドのインデックスから、元のmatrixのインデックスを計算
const row = Math.floor(bigRow / scale);
const col = Math.floor(bigCol / scale);
// 元のデータを取り出す
const value = matrix[row][col];
// 1次元配列のインデックスを計算
const arrayBaseIndex = (bigRow * bigWidth + bigCol) * 4;
// 4つの領域に値を格納
array[arrayBaseIndex] = value; // a
array[arrayBaseIndex + 1] = value + 1; // b (例として1を足す)
array[arrayBaseIndex + 2] = value + 2; // c (例として2を足す)
array[arrayBaseIndex + 3] = value + 3; // d (例として3を足す)
}
}
console.log(array);
// 出力例: [1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 5, 2, 3, 4, 5, ...]この方法なら、複雑なインデックス計算を2段階に分けて考えることができるから、グッとシンプルになるはず。1次元配列のインデックス計算でよくある**行インデックス * 幅 + 列インデックス**のパターンも使ってるから、見慣れているかもしれないね。
この考え方を使えば、もうインデックスで迷うことはないはず!頑張ってくれ!🚀