My try at code golfing.
The problem of finding the minimum value of ∑W_i*|X-X_i| reduces to finding the weighted median of a list of x[i]
with weights <
Haskell code, ungolfed: trying for a reasonable functional solution.
import Data.List (zip4)
import Data.Maybe (listToMaybe)
mid :: (Num a, Ord a) => [a] -> (Int, Bool)
mid w = (i, total == part && maybe False (l ==) r) where
(i, l, r, part):_ = dropWhile less . zip4 [0..] w v $ map (2*) sums
_:sums = scanl (+) 0 w; total = last sums; less (_,_,_,x) = x < total
v = map Just w ++ repeat Nothing
wmedian :: (Num a, Ord a) => [a] -> [a] -> (a, Maybe a)
wmedian w x = (left, if rem then listToMaybe rest else Nothing) where
(i, rem) = mid w; left:rest = drop i x
> wmedian [1,1,1,1] [1,2,3,4] (2,Just 3) > wmedian [1,1,2,1] [1,2,3,4] (3,Nothing) > wmedian [1,2,2,5] [1,2,3,4] (3,Just 4) > wmedian [1,2,2,6] [1,2,3,4] (4,Nothing)
> wmedian [1..10] [0..9] (6,Nothing) > wmedian ([1..6]++[6..8]) [1..9] (6,Just 7)
My original J solution was a straightforward translation of the above Haskell code.
Here's a Haskell translation of the current J code:
{-# LANGUAGE ParallelListComp #-}
import Data.List (find); import Data.Maybe (fromJust)
w&x=foldr((+).fst.fromJust.find((>=sum w).snd))0[f.g(+)0$map
(2*)w|f<-[zip x.tail,reverse.zip x]|g<-[scanl,scanr]]/2
Yeah… please don't write code like this.
> [1,1,1,1]&[1,2,3,4] 2.5 > [1,1,2,1]&[1,2,3,4] 3 > [1,2,2,5]&[1,2,3,4] 3.5 > [1,2,2,6]&[1,2,3,4] 4 > [1..10]&[0..9] 6 > ([1..6]++[6..8])&[1..9] 6.5