Verdoppeln Sie jedes andere Element der Liste von rechts in Haskell

8

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?

    
Hossein Hadavi 08.11.2013, 19:55
quelle

13 Antworten

13

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.

    
gsingh2011 12.06.2014 07:17
quelle
10

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%     
Ørjan Johansen 09.11.2013 05:53
quelle
9

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.

    
DiegoNolan 08.11.2013 19:57
quelle
3

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]

%Vor%     
Isaac Curtis 18.07.2014 22:06
quelle
2

Eine direkte Implementierung wäre:

%Vor%     
Lee 08.11.2013 20:11
quelle
1

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.

    
Yann Vernier 08.11.2013 20:06
quelle
1

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:

  • Mit zwei Varianten von Werten,
  • behält die Parität der Länge (ungerade / gerade) und
  • bei
  • abwechselnd die beiden, wenn zwei solche Werte kombiniert werden,

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%     
Petr Pudlák 25.04.2015 20:35
quelle
1

Ich lerne gerade Haskell , also finde bitte die folgende Anfängerlösung . Ich versuche limitierte cool Funktionen wie zipWith , cycle oder reverse

zu verwenden %Vor%

Das Wichtigste ist, dass Sie beim Verdoppeln jedes Elements von rechts die Verdoppelung in zwei Fälle einfügen können:

  1. Wenn die Liste gerade ist, verdoppeln Sie letztendlich das erste Element der Liste.
  2. Wenn die Liste eine ungerade Länge hat, verdoppeln Sie nicht das erste Element der Liste.

Ich habe dies als Teil der Hausaufgabe von CS194     

Setheron 21.06.2016 18:19
quelle
0

Einige Antworten scheinen sich nicht mit der ungeraden / geraden Länge der Liste zu befassen.

%Vor%     
Sam Liao 01.03.2015 13:58
quelle
0

Wenn ich einen Edx-Kurs in Haskell mache, ist das meine Noob-Lösung.

%Vor%     
John Carpenter 09.11.2015 22:55
quelle
0

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:

  • Rekursion, Bedingungen
  • reverse , Grundfunktionen wie max , min , odd , even
  • liste Funktionen z.B. head , tail , ...

Nicht OK:

  • foldr , foldl , map
  • Funktionen höherer Ordnung
  • Alles darüber hinaus

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%     
icc97 17.12.2016 22:17
quelle
0

Hier sind meine zwei Lösungen, beachte, dass ich absoluter Anfänger in Haskell bin.

Zuerst verwendet man Listenfunktionen, Kopf , Schwanz und Länge :

%Vor%

Zweitens, ähnlich, aber mit einem anderen Ansatz verwendet nur length Funktion:

%Vor%     
toni rmc 30.05.2017 18:28
quelle
0

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.

    
user2535251 15.08.2017 23:33
quelle

Tags und Links