旋转编码的 3x3 matrix/list

Rotating an encoded 3x3 matrix/list

假设有一个编码的 3x3 平面:

1 2 3   
4 5 6  
7 8 9  

顺时针旋转后变为:

7 4 1
8 5 2
9 6 3

要将前者转换为后者,一个明显的方法是做这样的事情:

 switch (num) {
     case 1: return 7; break;
     case 2: return 4; break;
     ...
 }

例如,[1, 5, 6, 9] 给出 [7, 5, 2, 3]

有没有不用硬编码就可以做到这一点的方法?

将值转换为新值的函数,将到达相同的位置,您可以使用下面定义的函数(在 JavaScript 中):

function rotated(num) {
    num--; // convert to zero-based number
    return 1 + (2 - num % 3) * 3 + Math.floor(num / 3);
}

// demo: print original and new value next to each other:
for (let num = 1; num <= 9; num++) {
    console.log(num, rotated(num));
}

跟进

在评论中你问我是如何想出这个解决方案的。

有几种方法可以到达那里,但我认为这是这样的:

我想知道:如果我知道给定数字出现的行和列,那么从哪里获取新值的行和列是什么?

例如,3 出现在第 0 行和第 2 列(从零开始的索引编号)。我需要的值位于第 0 行和第 0 列。通过使用行和列,您会发现第 0 行中的所有条目都将从第 0 列获得它们的新值。同样,第 1 行中的那些将从第 1 列获得它们的新值。

与列号也有关系:第 0 列中的所有条目都从第 2 行获得它们的新值。那些第 1 列从第 1 行获得它们,而第 2 列中的那些从第 0 行获得它们。所以这里我们有相反的关系。

因此,给定一个数字,要采取的步骤是:

  1. 根据给定的数字得出它出现在哪一行和哪一列
  2. 从这些行和列索引派生出新值所在的其他行和列索引(遵循上述原则)
  3. 从其他行和列中得出哪个值位于那里 return 它。

到目前为止,我一直专注于步骤 2 的细节。第一步应该很容易。出现给定 num 的列索引是 (num-1) % 3(模运算符)。行索引为(num-1)/3(整数除法)。

第 3 步应该执行相反的操作:将行索引乘以 3,然后加上列索引。这给出了一个从零开始的值,因此应该向它添加 1。

所有这些导致以下代码:

function rotated(num) {
    num--; // convert to zero-based number
    // Step 1: derive row and column
    let col = num % 3;
    let row = Math.floor(num / 3);
    // Step 2: derive other row and column
    let valueCol = row;
    let valueRow = 2 - col; // opposite direction
    // Step 3: which value sits there?
    let value = valueRow * 3 + valueCol + 1;
    // Return that
    return value;
}

// demo: print original and new value next to each other:
for (let num = 1; num <= 9; num++) {
    console.log(num, rotated(num));
}

然后最后一步是减少该程序中使用的变量数量...这导致了上面的第一个代码段。