Ich habe eine Liste und möchte jedes zweite Element in dieser Liste von rechts verdoppeln.
Es gibt eine andere verwandte Frage, die dieses Problem löst, aber es verdoppelt sich von links, nicht von rechts: Haskell: Verdopple jedes zweite Element in der Liste
Zum Beispiel würde [1,2,3,4] in meinem Szenario zu [2,2,6,4], und in dieser Frage würde [1,2,3,4] zu [1, 4,3,8].
Wie würde ich das umsetzen?
Ich denke, dass die erste Antwort die Frage falsch interpretiert hat. Der Titel besagt eindeutig, dass das OP die zweiten, vierten usw. Elemente von der rechten Seite der Liste verdoppeln möchte. Ørjan Johansens Antwort ist korrekt, aber langsam. Hier ist meine effizientere Lösung:
%Vor%Es faltet sich über die Liste von rechts. Der Anfangswert ist ein Tupel, das die leere Liste und einen booleschen Wert enthält. Der Boolesche Wert beginnt als falsch und wird jedes Mal umgekehrt. Der Wert wird nur dann mit 2 multipliziert, wenn der Boolesche Wert wahr ist.
OK, wie @TomEllis erwähnt, scheinen alle anderen Ihre Frage so interpretiert zu haben, als wären es Elemente mit ungeraden Zahlen von links und nicht mit geraden Zahlen von rechts, wie es Ihr Titel andeutet.
Da Sie beginnen, Positionen von rechts zu überprüfen, gibt es keine Möglichkeit zu wissen, was zu verdoppeln ist, bis das Ende der Liste gefunden wurde. Die Lösung kann also nicht träge sein, und muss die gesamte Liste vorübergehend speichern (selbst wenn sie nur auf dem Ausführungsstapel ist), bevor sie etwas zurückgibt.
Angesichts dieser Tatsache könnte die einfachste Lösung darin bestehen, vor und nach der von-links-Lösung die umgekehrte Richtung anzuwenden:
%Vor%Denken Sie darüber nach.
%Vor% BEARBEITEN Ich sollte beachten, das ist nicht wirklich meine Lösung, es ist die Lösung des verlinkten Posts mit dem (*2)
und id
umgedreht. Deshalb habe ich gesagt, darüber nachzudenken, weil es so eine triviale Lösung war.
Okay, also nicht elegant oder effizient wie die anderen Antworten, aber ich habe dies von einem Anfängerstandpunkt (ich bin eins) in Bezug auf Lesbarkeit und grundlegende Funktionalität geschrieben.
Dies verdoppelt jede zweite Zahl, beginnend mit rechts .
Verwendung dieses Skripts: doubleEveryOther [1,3,6,9,12,15,18]
erzeugt [1,6,6,18,12,30,18]
und doubleEveryOther [1,3,6,9,12,15]
erzeugt [2,3,12,9,24,15]
Mein erster Gedanke war:
%Vor%DiegoNolans Lösung ist eleganter, da die Funktion und die Sequenzlänge leichter verändert werden können, aber ich brauchte einen Moment, um zu grokern.
Versuche, das Problem etwas zu verallgemeinern: Da wir jedes zweite Element vom Ende verdoppeln wollen, können wir nicht im Voraus wissen, ob es von Anfang an ungerade oder gerade sein wird. Also ist der einfachste Weg, beides zu konstruieren, zu zählen, wenn die Gesamtgröße gerade oder ungerade ist, und dann zu entscheiden.
Definieren wir eine Applicative
Datenstruktur, die Folgendes erfasst:
wie folgt:
%Vor%Wenn Sie also eine Liste durchlaufen, erhalten Sie zwei Listen, die wie folgt aussehen:
%Vor%zwei Zick-Zack-Kopien. Jetzt können wir
berechnen %Vor% Ich lerne gerade Haskell , also finde bitte die folgende Anfängerlösung . Ich versuche limitierte cool Funktionen wie zipWith
, cycle
oder reverse
Das Wichtigste ist, dass Sie beim Verdoppeln jedes Elements von rechts die Verdoppelung in zwei Fälle einfügen können:
Ich habe dies als Teil der Hausaufgabe von CS194
Wenn ich einen Edx-Kurs in Haskell mache, ist das meine Noob-Lösung.
%Vor%Ich komme auch zu dieser Frage aus dem CIS 194 natürlich.
Ich habe das zwei Wege gemacht. Zuerst dachte ich, dass der Punkt der Frage nur auf Funktionen oder Arten des Programmierens beruhen sollte, die in einer der drei möglichen Quellen erwähnt sind. Die Vorlesung 1 , Reale Welt Haskell ch. 1,2 und Learn You a Haskell ch. 2 .
Also OK:
reverse
, Grundfunktionen wie max
, min
, odd
, even
head
, tail
, ... Nicht OK:
foldr
, foldl
, map
Erste Lösung, nur Rekursion mit einem Zähler:
%Vor%Diese Methode verwendet Rekursion, vermeidet jedoch die Berechnung der Länge auf jeder Rekursionsebene.
Zweite Methode, die meine erwähnten Regeln bricht:
%Vor%Diese zweite Methode funktioniert, indem Sie eine umgekehrte Menge von Indizes aufbauen und diese dann abbilden. Dies berechnet die Länge aber nur einmal.
z.B. [1,1,1,1] -> [(4,1),(3,1),(2,1),(1,1)]
Beide folgen der Forderung, jedes zweite Element von rechts zu verdoppeln.
%Vor%Wie wäre es mit dieser Einfachheit?
%Vor%Sie müssten eine umgekehrte Liste von Ziffern eingeben, falls Sie die Empfehlung dieses Kurses befolgt haben, da sie jedes andere Element verdoppeln wird, wenn es sich wieder umkehrt. Ich denke, dass dies anders ist, als zweimal die umgekehrte Funktion zu verwenden, mit einem anderen, um jede zweite Ziffer dazwischen zu verdoppeln, weil Sie das volle Ausmaß ihrer Liste nicht zum zweiten Mal wissen müssen. Mit anderen Worten, es löst das Problem dieses Kurses, aber jemand korrigiert mich, wenn ich falsch liege.
Tags und Links haskell