Необходимо рассмотреть три отдельных случая.
(1) Веса не меняются.
Пример / решение:
val xs = List(1,2,3,4,5)
val ws = List(3,2,5,1,4)
// Desired:
// 1
// 1*3 + 2
// 1*3 + 2*2 + 3
// 1*3 + 2*2 + 3*5 + 4
// 1*3 + 2*2 + 3*5 + 4*1 + 5
val mul = (xs,ws).zipped.map(_ * _) // 1*3, 2*2, 3*5, etc.
val cuml = mul.scanLeft(0)(_ + _) // Cumulative sums of the above
val ans = (xs,cuml).zipped.map(_ + _) // Put it all together
(2) Веса меняются, но с помощью линейного масштабного коэффициента, как если бы они представляли знаковые расстояния вдоль линии.Тогда мы позволим (d1-a)*x1 + (d2-a)*x2 + ... + (dn-a)*xn = y
быть нашим предыдущим ответом, предполагая, что мы находимся в a
;затем, если мы перейдем к b
, мы можем изменить это как (d1-b)*x1...
= (d1-a+a-b)*x1+...
= (d1-a)*x1+(a-b)*x1+...
, что показывает, что нам просто нужны суммы значений x
и расстояние single , чтобы получитьновый ответ от наших старых.Итак:
val xs = List(1,2,3,4,5)
val ds = List(3,2,5,1,4) // Treat these as distances along a line
// Desired:
// 1
// (3-2)*1 + 2
// (3-5)*1 + (2-5)*2 + 3
// (3-1)*1 + (2-1)*2 + (5-1)*3 + 4
// (3-4)*1 + (2-4)*2 + (5-4)*3 + (1-4)*4 + 5
val ws = ds.map(_ - ds.head) // Distances from the first element
val mul = (xs,ws).zipped.map(_ * _)
val cuml = mul.scanLeft(0)(_ + _)
// If we used this alone we would get:
// 1
// (3-3)*1 + 2 <-- should be subtracting 2, not 3!
// (3-3)*1 + (2-3)*2 + 3 <-- should be subtracting 5, not 3!
// etc.
val cumlx = xs.scanLeft(0)(_ + _) // Need this to fix up our sums
val fix = (cumlx,ws).zipped.map(-1 * _ * _) // This will actually do it
val ans = (xs,cuml,fix).zipped.map(_ + _ + _)
Лучший способ понять, как это работает, - это разобрать утверждение на утверждение и выписать все вручную, чтобы убедиться, что оно действительно вычисляет то, что мы хотим вычислить.
(3) Вес меняется неравномерно по мере вашего продвижения.Расстояния до точек на плоскости, как правило, обладают этим свойством, поскольку нелинейность квадратного корня в основном означает, что вы должны вычислять каждое заново.Так что вам просто нужно каждый раз делать полный расчет.