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"]
5 Réponses :
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>
Le dernier élément est également supprimé, dans le cas du singleton.
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
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, ...]
le cyclisme et la fermeture éclair sont également superflus , tout comme le mod
prend. :)
C'est mon préféré jusqu'à présent.
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.
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
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
etid
, vous voudriez utiliserid
etreverse
.