Есть такая задачка: посчитать расстояние(просто модуль разности) между элементами списка.
Т.е. для [1,5,10] получить [4,9,5].
С явной рекурсией можно сделать так:
allDistances [] acc = acc
allDistances (x:xs) acc = allDistances xs (acc ++ distances x xs)
where distances x ys = map (\y -> abs (x-y)) ys
Можно ли переписать это без использования явной рекурсии?
Вариант через foldl не привел к нужным результатам:
allDistances xs = foldl step [] xs
where step ys x = ys ++ distances x xs
distances x ys = map (\y -> abs (x-y)) ys
т.к. здесь xs — весь список, а мне нужно хвост при каждом вызове получать.
Re: Haskell: переписать без явной рекурсии
От:
Аноним
Дата:
06.04.12 04:05
Оценка:
minus x = concat $ zipWith minus' (tails $ tail x) x
minus' ys x = zipWith (-) ys (repeat x)
Здравствуйте, Danila_a, Вы писали:
D_>Есть такая задачка: посчитать расстояние(просто модуль разности) между элементами списка. D_>Т.е. для [1,5,10] получить [4,9,5].
Можно изящно (хотя и менее эффективно) сделать на нотации do или list comprehensions
diffs xs =
do
let ixs = zip [1..] xs
i,x <- ixs
j,y <- ixs
when (i<j)
return abs(x-y)
diffs xs = [ abs(x-y) | (i,x) <- ixs, (j,y) <- ixs, (i<j) ] where ixs = zip [1..] xs
Здравствуйте, Danila_a, Вы писали:
D_>Есть такая задачка: посчитать расстояние(просто модуль разности) между элементами списка. D_>Т.е. для [1,5,10] получить [4,9,5].
Расстояние от 1-го до 3-го элемента есть сумма расстояний от 1-го до 2-го и от 2-го до 3-го. Поэтому задачу можно разбить.
Соответственно:
allDistances l = concat $ map (scanl1 (+)) $ tails $ zipWith subtract l (tail l)
zipWith subtract l (tail l)
Вернёт расстояния между соседними элементами, т.е. для [1,5,10,12,13] -> [4,5,2,1]
Применив к нему tails, получим списки расстояний, начиная с каждого элемента до последнего.
[4,5,2,1]
[5,2,1]
[2,1]
[1]
[]
Применив к каждому scanl1 (+) получим суммарные расстояния:
Здравствуйте, Danila_a, Вы писали:
D_>Есть такая задачка: посчитать расстояние(просто модуль разности) между элементами списка. D_>Т.е. для [1,5,10] получить [4,9,5].
D_>Можно ли переписать это без использования явной рекурсии?
Здравствуйте, Danila_a, Вы писали:
D_>Есть такая задачка: посчитать расстояние(просто модуль разности) между элементами списка. D_>Т.е. для [1,5,10] получить [4,9,5]. D_>С явной рекурсией можно сделать так: D_>
D_>allDistances [] acc = acc
D_>allDistances (x:xs) acc = allDistances xs (acc ++ distances x xs)
D_> where distances x ys = map (\y -> abs (x-y)) ys
D_>
D_>Можно ли переписать это без использования явной рекурсии?
[y — x | (x:xt) <- tails xs, y <- xt]
Re: Параморфизмы, наконец
От:
Аноним
Дата:
09.04.12 12:59
Оценка:
import Data.Functor.Foldable
allDistances :: Num a => [a] -> [a]
allDistances = para alg where
alg Nil = []
alg (Cons x (xs, tail)) = distances x xs tail
distances x xs tail = cata alg xs where
alg Nil = tail
alg (Cons y xs) = abs (x — y) : xs