2016-10-10 13 views
0

Ich habe gerade angefangen zu lernen Haskell und ich verstehe nicht, wie man das Äquivalent eines solchen Programms in der Haskell schreiben, in dem es Schleifen und lokale Variablen gibt. Kann jemand vorschlagen, wie solch ein Programm auf Haskell aussehen würde? Wie ersetzt man den zweiten Zyklus, weil er die lokalen Variablen beinhaltet?Haskell Schleife und lokale Variable

#include <iostream> 
using namespace std; 

int main() { 

int n; 
int a [100]; 
cin >> n; 

for (int i = 0; i < n; i ++) { 
    cin >> a[i]; 
} 

int max = 0; 
int index = -1; 

for (int i = 0; i < n - 1; i ++) { 
    if (a[i+1] - a[i] > max) { 
     max = a[i+1] + a[i]; 
     index = i; 
    } 
} 

cout << index << endl; 

return 0; 

} 

Meine Versuche Code in Haskell zu schreiben:

module MyProgram where 

import Data.List 
import Data.Ord 

-- Getting a new modernized list 

f :: Int a => [a] -> [a] 
f x = zipWith (-) (tail x) (x) 

Jetzt muss ich durch die Liste nur laufen und das maximale Element zu finden und seinen Index zu speichern. Ich verstehe, wie man es in C und Java macht und gab das obige Beispiel, wie hätte ich es implementiert, aber in Haskell, weil es keine Zyklen gibt. Brauchen Rekursion?

Meine Hauptschwierigkeit liegt in der Tatsache, dass ich nicht verstehe, was Design in Haskell mich mit einer Zyklusvariablen innerhalb es ersetzen kann. Ich habe im Internet nach Informationen gesucht, konnte aber nichts für mich nachvollziehbar finden.

+0

Können Sie Ihren Haskell-Versuch zeigen? Die Menschen werden Ihnen besser helfen können, wenn sie verstehen, was Sie versucht haben. – Sibi

+0

Ja, natürlich bin ich jetzt Code hinzufügen – alex

+0

'Int a => [a] -> [a]' ist ungültig. Entweder du meintest 'Integral a => 'oder' Ord a => 'denke ich. – ThreeFx

Antwort

2

Zunächst möchten Sie eine Liste der Unterschiede zwischen den Elementen erhalten. Lassen Sie uns an Ihren Versuch aussehen:

findMax :: [Int] -> Int 
findMax list = helper 0 -1 minusInfinity $ zipWith (-) (tail list) list 
    where 
    helper _   maxIndex _   []   = maxIndex 
    helper currentIndex maxIndex currentMax (elem:list) 
     | elem > currentMax = helper (currentIndex + 1) currentIndex elem list 
     | otherwise = helper (currentIndex + 1) maxIndex currentMax list 
    minusInfinity = minBound :: Int -- the smallest element possible 

Aber irgendwie Rekursion ziemlich hässlich ist und ausführliche:

f x = zipWith (-) (tail x) x 

Wenn wir nun Rekursion verwendet, wir es so definieren könnte. Mal sehen, ob wir es besser machen können:

f erzeugt bereits die korrekte Subtraktionsliste.

Jetzt möchten Sie jedes Element mit seinem Index verknüpfen. In Haskell können Informationen kombiniert leicht mit einem Tupel (Int, Int) mit zip erfolgen:

zip [0..] list = [(0, 1st element), (1, 2nd element), ..] 

Das Element, das Sie der rechte Teil eines Tupels ist jetzt betrachten wollen, mit dem snd:

snd (index, elem) == elem 

Verwendung die Funktion maximumBy, erhalten wir jetzt:

g x = maximumBy (comparing snd) $ zip [0..] $ f x 

maximumBy (comparing snd) bedeutet „immer den m aximum Element von comparing der snd Teil jedes Tupel ". Dies gibt nun das Tupel (index, element) zurück, wobei element maximal ist. Um das erste Element eines Tupels zugreifen, können wir verwenden:

fst (index, element) == index 

So kann die gesamte Funktion geschrieben werden als:

f x = fst $ maximumBy (comparing snd) $ zip [0..] $ zipWith (-) (tail x) x 

Welche Art und Weise eleganter als die rekursive Formel oben ist.

0

Hier ist eine andere Art und Weise, es zu tun:

import Data.List 

calc :: (Integral a) => [a] -> a 
calc = snd . foldl (\(max,index) (x,y) -> if (y-x) > max then (y+x,index) else (max,index + 1)) (0,-1) . helper 

helper :: [a] -> [(a,a)] 
helper x = zip (tail x) (init x) 

helper erstellt eine Liste von aufeinanderfolgenden Paaren von Elementen auf. Dann führt calc den Vergleich und andere Manipulationen aus Ihrer Imperativ-Schleife aus.Der Akkumulator ist ein Tupel, bestehend aus Ihren lokalen Variablen max und index. Da Sie nur den Index am Ende benötigen, verwenden wir snd, um diesen Teil herauszuholen. Beachten Sie, dass wir die Eingabe auch als Tupel darstellen, um die Arbeit zu erleichtern.

Demo