Как можно выразить эту императивную функцию в функциональном языке на основе массива, таком как K (или Q)?
Как можно выразить эту императивную функцию в функциональном языке на основе массива, таком как K (или Q)?
В небрежном C++:
vector<int> x(10), y(10); // Assume these are initialized with some values.
// BTW, 4 is just a const -- it's part of the algorithm and is arbitrarily chosen.
vector<int> result1(x.size() - 4 + 1); // A place to hold a resulting array.
vector<int> result2(x.size() - 4 + 1); // A place to hold another resulting array.
// Here's the code I want to express functionally.
for (int i = 0; i <= x.size() - 4; i++) {
int best = x[i + 0] - y[i + 0];
int bad = best;
int worst = best;
for(int j = 0; j < 4; j++) {
int tmp = x[i + j] - y[i + 0];
bad = min(bad, tmp);
if(tmp > best) {
best = tmp;
worst = bad;
}
}
result1[i] = best
result2[i] = worst
}
Я бы очень хотел увидеть это в kdb и Q, но приветствуются и другие функциональные языки.
3 ответа
Решение
В Kona (диалект K с открытым исходным кодом):
Во-первых, установите несколько значений примера (используя то же самое, что и решение Clojure):
a:1+!8;b:8#0 / a is 1..8, b is eight 0s
Затем:
{(|/x;&/x)}@+{4#y _ x}[a+b;]'!#a
Где a и b - ваши переменные x и y выше. (K делает специальный случай для переменных x, y и z.)
Чтобы разбить это немного больше:
maxmin:{(|/x;&/x)} / (max;min) pairs of x
get4:{4#y _ x} / next 4 from x, starting at y
/ with <4 remaining, will repeat; doesn't matter for min or max
/ maxmin applied to flipped results of get4(a-b) at each index 0..(length a)-1
maxmin@+get4[a-b;]'!#a
/ result
(4 5 6 7 8 8 8 8
1 2 3 4 5 6 7 8)
Портирование @silentbicycle's k напрямую на q дает
q)a:1+til 8
q)b:8#0
q){(max x;min x)}flip{4#y _ x}[a+b;]each til count a
4 5 6 7 8 8 8 8
1 2 3 4 5 6 7 8
другой подход, немного более векторизованный (имао):
q){(max;min)@\:flip 4#'(til count x)_\:x+y}[a;b]
4 5 6 7 8 8 8 8
1 2 3 4 5 6 7 8
(defn minmax [x y](map #(vector (- (apply max %1) %2) (- (apply min %1) %2)))(partition-all 4 1 x) y)
(minmax [1 2 3 4 5 6 7 8] [0 0 0 0 0 0 0 0])
дам
[([4 1] [5 2] [6 3] [7 4] [8 5] [8 6] [8 7] [8 8])`(результат 1, результат 2) как вывод..
затем
(map #(first %1) result) is result1
(map #(last %1) result) is result2