2017-10-19 3 views
2

Bitte beachten Sie, ein C-Programm, das, x gegeben, kehren y und z so dass y + z * 2 = x, für die kleinstmögliche y. Grob gesagt, ich könnte eine verschachtelte Schleife erstellen:Verschachtelte Schleife und funktionale Programmierung

for(y = 0; y < x; ++ y){ 
    for(z = 0; z < x; ++z){ 
     if(y + 2 * z == x){ 
      printf("%d + 2 * %d = %d", y, z, x); 
     } 
    } 
} 

Wie konnte ich diese Art von verschachtelter Schleife in übersetze die funktionelle Art und Weise? Ist es machbar? Ist es vernünftig oder verurteile ich nur den Ansatz? Mein bester Versuch so weit:

let foo x = 
    let rec aux (y, z, q) = 
     match (y + z * 2) with 
     r when r = q -> (y, z) 
     |_  -> aux(y + 1, z + 1, q) //How to check different values of z 
    aux(0, 0, x)       //for each value of y? 

Es wird nicht funktionieren, da es sowohl nur y und z erhöht wird. Wie kann ich verschiedene Werte von z für jeden Wert von y überprüfen?

+0

Prozedursprachen (wie C) und eine funktionale Sprache (wie F #) repräsentieren zwei verschiedene Paradigmen, wenn es um die Programmierung geht. Als solche können Sie nicht wirklich direkte Übersetzungen zwischen ihnen machen (naja, Sie * können * aber es werden keine guten Übersetzungen sein, sehr wahrscheinlich eher das Gegenteil), Sie müssen oft * anders * denken *. –

+2

Wie für die Frage im Kommentar Ihres funktionalen Ausschnitts -> verwenden Sie eine zweite rekursive Funktion. –

+0

unter der Annahme, dass es sich um vorzeichenlose Ganzzahlen handelt, warum berechnen Sie das Ergebnis nicht direkt? 'y = x% 2; z = x/2' würde tun .... (und kann in Funktionscode ausgedrückt werden) –

Antwort

4

Sie müssen diese Überprüfungen in das Spiel einfügen.

Sehen Sie hier, was Ihr Code fehlt:

let foo x = 
    let rec aux (y, z, q) = 
     match (y + z * 2) with 
     | r when r = q -> (y, z) 
     | _ when y = q -> failwith "not found !" 
     | _ when z = q -> aux (y + 1, 0, q) 
     | _   -> aux (y, z + 1, q) 
    aux (0, 0, x) 

Und hier ist ein anderer Ansatz, ebenso funktional, aber ohne Rekursion:

let foo2 x = 
    let s = 
     {0 .. x} |> Seq.collect (fun y -> 
      {0 .. x} |> Seq.collect (fun z -> 
       seq [y, z])) 
    Seq.find (fun (y, z) -> y + z * 2 = x) s 

, die in F # geschrieben werden können seq Ausdrücke:

let foo3 x = 
    let s = seq { 
     for y in {0 .. x} do 
      for z in {0 .. x} do 
       yield (y, z)} 
    Seq.find (fun (y, z) -> y + z * 2 = x) s 

und es ähnelt Ihrem ursprünglichen C-Programm.

+0

Sie brauchen die Klammern nicht. "Für y in 0 .. x do" funktioniert gleich gut. – Lars

+0

Danke Gustavo, deine Beispiele helfen mir, verschiedene Konzepte zu klären. Ich mache Übung auf ihnen! Ich habe nur eine Frage. In deinem ersten Snippet, was ist r? Ich bin kein Vater, ich habe es richtig verstanden. Hat es einen Wert? Ist es nur ein Name? – Worice

+0

@Worice Eigentlich kommt '' r'' aus deinem Code, nicht meins. Aber ja, es enthält das Ergebnis der Auswertung von '' (y + z * 2) ''. Wenn du mich fragst, würde ich das Match neu schreiben oder einen if then elif-Ausdruck verwenden, aber ich wollte nur so viel wie möglich an deinen Code kleben und dir zeigen, was du verpasst hast. – Gustavo

Verwandte Themen