1
votes

Inverser chaque élément pair de la liste Haskell

En Haskell, une liste est donnée, mais vous devez inverser chaque élément pair. Par exemple, la liste

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

doit être remplacée par

["Further", "Good" "Luck"]

Nous avons essayé cette fonction:

f ["rehtruF", "dooG", kcuL"]


4 commentaires

astuce: essayez carte inversée


@ assembly.jc qui n'aide pas du tout ici.


Si vous réduisez à la main, vous obtiendrez d'abord (reverse "rehtruF") :( f ["kcuL"]) , où l'absence de "Good" est un indice que vous avez oublié quelque chose du résultat.


Voir aussi stackoverflow .com / questions / 17383169 /… . Pour vos besoins, au lieu des fonctions * 2 et id , vous voudriez utiliser id et reverse .


5 Réponses :


1
votes

Le problème est que vous supprimez complètement l'élément ys . Ce que vous voulez en fait, c'est le garder tel quel , c'est-à-dire le mettre tel quel dans la liste de résultats.

f (xs:ys:xss) = reverse xs : ys : f xss

Notez que GHC vous aurait averti des inutilisés Liaison ys , si vous avez activé l'option -Wall (ce qui est généralement une bonne idée pour les débutants). Vous pouvez le faire en exécutant le compilateur / interpréteur avec ghc -Wall YOURFILE.hs , ou en tapant : set -Wall dans une session GHCi.

p>


1 commentaires

Le dernier élément est également supprimé, dans le cas du singleton.



0
votes

Pour inverser les éléments pairs de la liste, la première chose à faire est de trouver des éléments pairs, une des façons de le faire est d'indexer chaque élément de la liste d'abord comme:

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

et puis, on inverse les éléments a même index:

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

les mettre tous comme

zip [0..] xs


0 commentaires

3
votes

TL; DR - c'est la solution (basée sur cette réponse ) à laquelle Thomas M. DuBuisson a fait allusion dans son commentaire. Oups.


Vous n'avez même pas besoin d'itérer explicitement sur l'entrée. Imaginez que vous ayez une liste de fonctions fs = [f0, f1, f2, ...] et une liste de valeurs xs = [x0, x1, x2, ...] code>, et vous voulez obtenir [f0 x0, f1 x1, f2 x2, ...] . Vous faites cela avec zipWith ($) :

f :: [String] -> [String]
f = zipWith ($) (cycle [reverse, id])

Pour votre problème, votre fs serait une séquence alternée de reverse et id , que vous pouvez produire avec cycle [reverse, id] == [reverse, id, reverse, id, ...] code >

Assembler ceci,

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

ou simplement

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


2 commentaires

le cyclisme et la fermeture éclair sont également superflus , tout comme le mod prend. :)


C'est mon préféré jusqu'à présent.



0
votes

Il ne faut rien calculer qui ne nécessite pas de calcul. Pas de fermeture éclair, pas de cyclisme, pas de prise de mod , juste un appel de fonction pure :

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

Le premier élément est considéré comme étant à l'index 0, c'est-à-dire à la position paire, comme c'est le cas dans la question.

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

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

Avec une récursion simple, qu'est-ce que ci-dessus La définition basée sur foldr est la suivante:

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

, plus les cas évidents de gestion de [] . p >

Avec foldr , [] est vérifié par foldr lui-même; avec récursion mutuelle, elle doit être effectuée par chacune des deux fonctions coopérantes.


0 commentaires

0
votes

Si vous ajoutez une variable supplémentaire, vous pouvez suivre si vous êtes sur un élément pair ou un élément impair. Par exemple, nous utilisons ici 1 pour signifier impair et 0 pour signifier pair:

f = f' 1
  where
    f' _ []     = []
    f' 1 (x:xs) = reverse x: f' 0 xs
    f' 0 (x:xs) = x: f' 1 xs


0 commentaires