Мне кажется, что реализация довольно хаотична. Например, partishner
, кажется, создает список списков списков a
, где, если я правильно понял, внешний список содержит списки с каждыми двумя элементами: список элементов «слева» и список элементов на «право». В результате для построения списков потребуется O (n 2 ) .
При использовании списков, состоящих из двух кортежей, это также довольно «небезопасно», поскольку список может - хотя и здесь, возможно, невозможный - не содержать элементов, одного элемента или более двух элементов. Если вы допустите ошибку в одной из функций, ее будет трудно обнаружить.
Мне кажется, что может быть проще реализовать «алгоритм развертки»: сначала мы вычисляем сумму всех элементов в списке. Это значение справа, если мы решили разделить в этой конкретной точке, затем мы начинаем двигаться слева направо, каждый раз вычитая элемент из суммы справа и добавляя его к сумме слева. , Мы можем каждый раз оценивать разницу в баллах, например:
import Data.List(unfoldr)
sweep :: Num a => [a] -> [(Int, a, [a])]
sweep lst = x0 : unfoldr f x0
where x0 = (0, sum lst, lst)
f (_, _, []) = Nothing
f (i, r, (x: xs)) = Just (l, l)
where l = (i+1, r-2*x, xs)
Например:
Prelude Data.List> sweep [1,4,2,5]
[(0,12,[1,4,2,5]),(1,10,[4,2,5]),(2,2,[2,5]),(3,-2,[5]),(4,-12,[])]
Таким образом, если мы выберем разделение в первой точке разделения (перед первым элементом), сумма справа будет на 12
больше, чем сумма слева, если мы разделим после первого элемента, сумма на справа (11
) на 10
больше суммы слева (1
).
Затем мы можем получить минимум этих разбиений с помощью minimumBy :: (a -> a -> Ordering) -> [a] -> a
:
import Data.List(minimumBy)
import Data.Ord(comparing)
findTheEquilizer :: (Ord a, Num a) => [a] -> ([a], [a])
findTheEquilizer lst = (take idx lst, tl)
where (idx, _, tl) = minimumBy (comparing (abs . \(_, x, _) -> x)) (sweep lst)
Затем получаем правильное значение для [1..10]
:
Prelude Data.List Data.Ord Data.List> findTheEquilizer [1..10]
([1,2,3,4,5,6,7],[8,9,10])
или за 70'000:
Prelude Data.List Data.Ord Data.List> head (snd (findTheEquilizer [1..70000]))
49498
Вышесказанное не является идеальным, его можно реализовать более элегантно, но я оставляю это как упражнение.