Я пытался использовать функцию inits для создания функции, которая:

 [x1,x2,x3,x4,x5....] ==  [0,x1, x1+x2, x1+x2+x3, x1+x2+x3+x4, (x1+x2+x3+x4+x5) ....]

Это моя попытка:

sums:: [Int]->[Int]
sums (x:xs)  = [x] ++ map foldr 0 (+)  initial xs


inits1:: [int] -> [[int]]
inits1 []     = [[]]
inits1 (x:xs) = [[x]] ++ map (x:) (initial xs)
0
Ohad 23 Май 2014 в 19:04

3 ответа

Лучший ответ

Использование inits - плохой способ сделать это.

Подумай об этом. Если бы вы делали это на бумаге, вы бы не складывали первое число, затем первые два, затем первые три, затем первые четыре.

Это глупо, потому что, когда вы добавляете первые четыре, вам нужно повторно добавлять первые три, даже если вы уже добавляли их раньше.

Вместо этого вы просто начнете складывать их, сохраняя общую сумму, и эти суммы будут формировать ваши результаты.

Таким образом, вы должны использовать scanl1, который похож на foldl1, но дает вам результат в том виде, в каком он есть:

sums = scanl (+) 0

Отказ от библиотечных функций лучше показывает, как это должно быть сделано (и примерно как работает scanl:

sums2 ls = sums_worker 0 ls where
  sums_worker acc (l:ls) = acc:(sums_worker (acc + l) ls)
  sums_worker acc [] = [acc]
4
Clinton 23 Май 2014 в 19:42

Вы можете использовать стандартную библиотеку?

sums :: Num a => [a] -> [a]
sums = scanl (+) 0
4
Piotr Miś 23 Май 2014 в 19:15

inits предоставит все начальные сегменты списка, а sum даст сумму списка чисел, поэтому ваш sums может быть определен следующим образом:

sums = map sum . inits

Примере

> sums [1..10]
[0,1,3,6,10,15,21,28,36,45,55]
1
Lee Duhem 23 Май 2014 в 19:16