Die Haskell-Methode, Benutzereingaben zu akzeptieren, die ein Benutzer mehrmals eingegeben hat?

8

Ich fange gerade an, Haskell zu lernen, und es ist eine ganz andere Art zu denken als das, was ich gewohnt bin (die C-Stil-Sprachen).

Wie auch immer, für ein Problem, an dem ich gerade arbeite, brauche ich Benutzereingaben. Es wird in der Form

kommen %Vor%

zum Beispiel. Format ist die erste Zeile, die die Anzahl der Zeilen angibt, die folgen. Mein erster Gedanke war, dass ich die erste Zeile lesen würde und dann eine Schleife mehrmals ausführen würde. Das ist aber Haskell! Soweit ich weiß, sind Schleifen nicht möglich.

Mein nächster Gedanke war, dass ich die erste Zeile der Eingabe verwenden würde, um eine Liste mit den anderen n Zahlen zu füllen, die folgen. Ich habe keine Ahnung, wie ich das machen würde. Ich bin hier, weil ich nicht einmal sicher bin, nach was ich suchen würde, um es herauszufinden.

Vielen Dank im Voraus, dass Sie mir den Haskell-Weg gezeigt haben, dies zu tun. Es ist schwer, so weit zu gehen, aber ich höre begeisterte Kritiken von Leuten, die "erleuchtet" sind, also denke ich, dass es nicht schaden kann, die Sprache selbst zu lernen.

Hier ist der Code, der einmal gut ausgeführt wird, aber für jede der zweiten bis n Zeilen, die der ersten Zeile folgen, einmal ausgeführt werden muss.

%Vor%

(Ich würde auch gerne hören, ob es andere Verbesserungen gibt, die ich an meinem Code vornehmen könnte, aber in diesem speziellen Fall ist es für einen Wettbewerb, ein Problem mit möglichst wenigen Zeichen zu lösen. Ich will nicht um genauer zu werden, falls andere Leute nach einer Antwort auf das gleiche Problem suchen.)

EDIT: Danke für alle Antworten. Irgendwann bekam ich etwas, das sich so benahm, wie ich es wollte. Ich habe den Code für die Nachwelt unten angegeben. Obwohl die Testfälle mit Bravour bestanden, waren die tatsächlichen Daten, an denen sie getestet wurden, anders, und alles, was sie mir sagen, ist, dass ich die "falsche Antwort" bekommen habe. Dieser Code "funktioniert", bringt aber nicht die richtige Antwort.

%Vor%     
maccam912 03.02.2013, 00:36
quelle

4 Antworten

10

Als Erstes können Sie in haskell eine gute Schleife machen. Es passiert ständig. Sie haben einfach keine syntaktischen Konstrukte dafür, da es keine Notwendigkeit für sie gibt.

Die meisten allgemeinen Schleifen werden in Bibliotheken gespeichert. In diesem Fall befindet sich die benötigte Schleife in den Standardbibliotheken im Modul Control.Monad . Es heißt replicateM . Es hat die Typensignatur Monad m => Int -> m a -> m [a] . Um diese Signatur für Ihren Fall zu spezialisieren, hätte sie den Typ Int -> IO Int -> IO [Int] . Das erste Argument ist die Anzahl der Schleifen. Die zweite ist die IO-Aktion, die in jeder Schleife ausgeführt wird. Das Ergebnis der Funktion ist eine IO-Aktion, die die Liste der Eingaben erzeugt.

Wenn Sie beispielsweise inputs <- replicateM b readLn zu Ihrem do-Block hinzufügen, wird eine Liste mit dem Namen inputs in den Bereich eingefügt, die die Werte aus den b -Zeilen enthält, die der ersten folgen. Sie könnten dann Ihre Lösungsfunktion über diese Zeilen abbilden.

    
Carl 03.02.2013, 00:41
quelle
6

Carls Lösung wird funktionieren, aber es ist etwas undurchsichtig. Wenn du es schreiben willst, könntest du so etwas machen:

%Vor%

Was Sie hier mit readLines tun, ist, dass Sie im Wesentlichen den offensichtlichen Grundfall definieren (um 0 Dinge zu lesen, geben Sie einfach eine leere Liste) und den rekursiven Fall (um n Dinge zu lesen, lesen Sie dann eine Sache lies die anderen n-1 Dinge und kombiniere sie dann miteinander).

    
Venge 03.02.2013 00:52
quelle
2

Ich bin mir nicht sicher, was genau Sie tun möchten, aber um eine Ganzzahl n und dann die nächsten n Zeilen als Ganzzahlen zu lesen, könnten Sie etwas tun wie:

%Vor%

Das return $ sum xs am Ende des Kurses ist nicht wesentlich - wenn es nicht dort wäre, würden Sie eine explizite Typ-Signatur für test benötigen.

Wenn Sie keine dieser Funktionen verstehen, hoogle .

    
Cubic 03.02.2013 01:00
quelle
1

Sie könnten ein readInput n erstellen, wobei n die Anzahl der zu lesenden Zeilen ist. Der Aufruf dies rekursiv 1 von n jedes Mal subtrahieren. Ich bin auch ein Haskell-Noob, also ist das vielleicht nicht der beste Ansatz. Es sollte trotzdem funktionieren.

    
Code-Apprentice 03.02.2013 00:46
quelle

Tags und Links