Как эффективно преобразовать переменные в массив в шаблоне
Извиняюсь за неуклюжую формулировку, я изо всех сил пытаюсь описать эту проблему.
Моя цель - написать функцию, которая принимает три переменные и выводит двумерный массив с этим шаблоном:
var foo = function(x, y, z) {
array = [
[x + 8, y + 16, z + 35],
[x + 6, y + 8, z + 30],
[x + 4, y + 4, z + 20],
[x + 2, y + 2, z + 10],
[x , y , z ],
[x - 2, y + 2, z - 10],
[x - 4, y + 4, z - 20],
[x - 6, y + 8, z - 30],
[x - 8, y + 16, z - 35]
]
return array;
}
Очевидно, такой способ написания функции кажется довольно неэффективным.
Один из способов, которыми я пытался решить это, с помощью цикла. Но мое решение представляет три массива и также довольно неэлегантно.
var x_mod = [8, 6, 4, 2, 0, -2, -4, -6, -8];
var y_mod = [16, 8, 4, 2, 0, 2, 4, 8, 16];
var z_mod = [35, 30, 20, 10, 0, -10, -20, -30, -35];
for(let i = 0; i < 9; i++) {
array[i] = [x + x_mod[i], y + y_mod[i], z + z_mod[i]);
}
Есть ли лучший способ написания этого алгоритма? Я также был бы признателен за любые подсказки относительно того, как называется эта проблема, или что я должен изучить, чтобы решить ее.
Спасибо!
РЕДАКТИРОВАТЬ
Это пример такой оптимизации, о которой я думал.
Следующая функция
var bar = function(x, y, z) {
array = [
[x + 1, y + 2, z + 3],
[x + 2, y + 4, z + 6],
[x + 3, y + 6, z + 9]
]
return array;
}
также может быть написано следующим образом:
var bar = function(x, y, z) {
array = [];
for(var i = 1; i < 4; i++)
array[i] = [x + i, x + i*2, x + i*3];
return array;
}
Это своего рода "оптимизация", которую я хотел применить к моей первоначальной проблеме. Опять же, я прошу прощения, что мне не хватает словарного запаса, чтобы адекватно описать эту проблему.
3 ответа
Это то, что вы ищете (в коде C#).
static class Program
{
static void Main(string[] args)
{
var m_2 = GenerateMatrix(2, 0.0, 0.0, 0.0);
// result:
// | 2.0 2.0 10.0 | + span = 2
// | 0.0 0.0 0.0 | +
// | -2.0 -2.0 -10.0 |
var m_3 = GenerateMatrix(3, 0.0, 0.0, 0.0);
// result:
// | 4.0 4.0 20.0 | +
// | 2.0 2.0 10.0 | | span = 3
// | 0.0 0.0 0.0 | +
// | -2.0 -2.0 -10.0 |
// | -4.0 -4.0 -20.0 |
var m_5 = GenerateMatrix(5, 0.0, 0.0, 0.0);
// result:
// | 8.0 16.0 40.0 | +
// | 6.0 8.0 30.0 | |
// | 4.0 4.0 20.0 | | span = 5
// | 2.0 2.0 10.0 | |
// | 0.0 0.0 0.0 | +
// | -2.0 -2.0 -10.0 |
// | -4.0 -4.0 -20.0 |
// | -6.0 -8.0 -30.0 |
// | -8.0 -16.0 -40.0 |
}
static double[][] GenerateMatrix(int span, double x, double y, double z)
{
var result = new double[2*(span-1)+1][];
result[span-1] = new double[] { x, y, z };
for (int i = 0; i < span-1; i++)
{
result[span-2-i] = new double[] { x+2*(i+1), y + (2<<i), z + 10*(i+1) };
result[span+i] = new double[] { x-2*(i+1), y - (2<<i), z - 10*(i+1) };
}
return result;
}
Я использую следующие правила (используйте counter=1..span-1
). Установите строки симметрично от середины, так как они следуют одному и тому же шаблону только с +
или же -
как разница:
x
значения кратны двум,x+2*counter
а такжеx-2*counter
y
значения - это сила двойок,pow(2,counter)=2<<counter
z
значения кратны десяткам,x+10*counter
а такжеx-10*counter
Хотя я думаю, что ваше первое определение является лучшим, формулы могут быть определены:
diff = (4 - i)
ad = abs(diff)
x + diff * 2
y + (1 << abs(ad)) - trunc((4 - ad) / 4)
//using bit shift to compose power of two if possible
z + 10 * diff - 5 * trunc(diff / 4)
//rounding towards zero!
Проверка Python:
import math
for i in range(0, 9):
diff = (4 - i)
ad = abs(diff)
print(i, diff * 2, (1 << abs(ad)) - (4 - ad) // 4, 10 * diff - 5 * math.trunc(diff / 4))
0 8 16 35
1 6 8 30
2 4 4 20
3 2 2 10
4 0 0 0
5 -2 2 -10
6 -4 4 -20
7 -6 8 -30
8 -8 16 -35
Вы можете использовать рекурсивный подход для вашего решения:
var your_array = []
function myFun(x, y, z, count){
//base case
if(count = 4)
return;
// head recursion
temp = [];
temp.push(x); temp.push(y); temp.push(z);
your_array.push(temp);
myFun(x-2, y/2, z-10, count+1)
//tail recursion
temp = []
temp.push(x); temp.push(y); temp.push(z);
your_array.push(temp);
}