Обратный каждый четный элемент в списке Haskell - PullRequest
1 голос
/ 10 октября 2019

В Haskell указан список, но вы должны поменять местами каждый четный элемент. Например, список

f ["rehtruF", "Good", kcul "]

должен быть заменен на

[" Далее "," Хорошо "," Удача "]

Мы попробовали эту функцию

f [] = []
f [x] = []
f (xs:ys:xss) = (reverse xs):(f xss)

, но, к сожалению, она только перевернула первый элемент и распечатала его. У вас есть идеи, как мы могли бы изменить код, чтобы каждый четный элементЗарезервировано, и вывод соответствует желаемому.

Приветствую и благодарю.:)

Ответы [ 5 ]

3 голосов
/ 10 октября 2019

TL; DR - это решение (на основе этого ответа ), на которое ссылался Томас М. Дюбюссон в своем комментарии. Упс.


Вам даже не нужно явно перебирать ввод. Представьте, что у вас есть список функций fs = [f0, f1, f2, ...] и список значений xs = [x0, x1, x2, ...], и вы хотите получить [f0 x0, f1 x1, f2 x2, ...]. Вы делаете это с помощью zipWith ($):

zipWith ($) fs xs  -- == [f0 $ x0, f1 $ x1, f2 $ x2, ...]
                   -- == [f0 x0, f1 x1, f2 x2, ...]

Для вашей задачи ваша fs будет представлять собой чередующуюся последовательность reverse и id, которую вы можете создать с помощью cycle [reverse, id] == [reverse, id, reverse, id, ...]

Если сложить это вместе,

f :: [String] -> [String]
f strings = zipWith ($) (cycle [reverse, id]) strings
        -- == [reverse strings0, id strings0, reverse strings2, id strings3, ...]

или просто

f :: [String] -> [String]
f = zipWith ($) (cycle [reverse, id])
1 голос
/ 10 октября 2019

Проблема в том, что вы полностью отбрасываете элемент ys. На самом деле вы хотите сохранить его как есть , т.е. поместить его как есть в список результатов.

f (xs:ys:xss) = reverse xs : <b>ys :</b> f xss

Обратите внимание, что GHC предупредил бы вас о неиспользованном ysпривязка, если вы включили опцию -Wall (что, как правило, хорошая идея для начинающих). Вы можете сделать это, выполнив компилятор / интерпретатор с помощью ghc -Wall YOURFILE.hs или введя :set -Wall в сеансе GHCi.

0 голосов
/ 11 октября 2019

Если вы добавите дополнительную переменную, вы можете отслеживать, если вы находитесь на четном элементе или нечетном элементе. Например, здесь мы используем 1 для обозначения нечетного и 0 для обозначения четного:

f = f' 1
  where
    f' _ []     = []
    f' 1 (x:xs) = reverse x: f' 0 xs
    f' 0 (x:xs) = x: f' 1 xs
0 голосов
/ 10 октября 2019

Не следует рассчитывать что-либо, что не требует вычисления. Без зацикливания, без зацикливания, без mod взятия, только чистый вызов функции :

foo :: [[a]] -> [[a]]
foo xs = foldr (\ x r f g -> f x (r g f)) 
               (\ _ _ -> []) 
               xs 
               ((:) . reverse) 
               (:)

Первый элемент считается с индексом 0, то есть с четной позицией, как и ввопрос.

> foo ["Further","Good","Luck"]
["rehtruF","Good","kcuL"]

> foo $ foo ["Further","Good","Luck"]
["Further","Good","Luck"]

При простой рекурсии то, что делает приведенное выше определение foldr:

foo = f   where 
      f (x:xs)  =  reverse x : g xs
      g (x:xs)  =  x : f xs 

, плюс очевидные случаи []. 1015 *

С foldr, [] проверяется самим foldr;при взаимной рекурсии это должно выполняться каждой из двух взаимодействующих функций.

0 голосов
/ 10 октября 2019

Чтобы инвертировать четные элементы в списке, прежде всего нужно найти четные элементы, один из способов сделать это - сначала проиндексировать каждый элемент в списке, например:

zip [0..] xs

, а затеммы инвертируем элементы, имеющие четный индекс:

if index `mod` 2 == 0 then reverse x else x

ставим их все как

f xs = map reverseEven (zip [0..] xs)
    where reverseEven (index, x) = if index `mod` 2 == 0 
                                   then reverse x else x
...