Imperative Programmierung --> Funktionale

ComFreek

Mod | @comfreek
Moderator
Hallo Community,

ich bin gerade dabei, ein kleines F#-Programm zu schreiben, welches mir ein paar Daten aufbereiten soll.

Erstmal das eigentliche Problem:

Ich habe eine Reihe von Werten, zum Beispiel:
Code:
10
20
15
17
30
Nun möchte ich, dass alle Werte einen aufsteigenden Graphen ergeben. (Die Werte stammen von einer selbstgeschriebenen Objecttracking-Software, die manchmal aufgrund meines nur schlechten Videomaterials ungenau arbeitet.)

Lösung 1:
Code:
10
20
20 (15 --> 20)
20 (17 --> 20)
30
Man nimmt den zuletzt höchsten Wert und ersetzt die niedrigeren Werte einfach durch ihn.
Das ergibt allerdings im Graphen eine Zacke von 20 zu 30.

Deswegen möchte ich sozusagen "künstlich" Werte einschmuggeln, sodass die Lücke (=Bereich mit niedrigeren Werten) gleichmäßig befüllt wird:
Code:
10
20
23 1/3 (15 --> 23 1/3)
26 2/3 (17 --> 26 2/3)
30


Allerdings bin ich daran gescheitert, für folgenden imperativen Algorithmus einen funktionalen Code zu zaubern.

PHP-Version:
PHP:
$values = [1, 2, 3 /*, ...*/];
$out = [];

$prev = -1;
for ($i=0; $i<count($values); $i++) {
  if ($values[$i] > $prev) {
    $prev = $values[$i];
    $out[] = $values[$i];
  }
  else {
    $smallerValuesStop = -1;
    for ($j=$i; $j<count($values); $j++) {
      if ($values[$j] > $prev) {
        $smallerValuesStop = $prev;
      }
    }
    // Es ist garantiert, dass $smallerValuesStop != -1 (=Default-Wert) ist
    $splits = ($smallerValuesStop - $i);
    $splitValue = ($values[$smallerValuesStop] - $values[$i]) / ($splits+1);
    $sum = $values[$i];
    while ($splits--) {
      $sum += $splitValue;
      $out[] = $sum;
    }
    $i = $smallerValuesStop;
  }
}

Meine Fragen:

a) Gibt es einen besseren Lösungsweg bzw. Algorithmus als den, den ich oben in PHP geschrieben habe?

b) Wie würde man diesen in einer funktionalen Sprache (vornehmlich F#) ausdrücken? Ich scheitere schon beim Vorspulen des Array-Index-Zählers ($i = $smallerValuesStop im oberen Skript).


Vielen Dank schonmal im Voraus!
 

HonniCilest

Erfahrenes Mitglied
Was das Aufbessern der Werte angeht fällt mir spontan auch kein besserer Weg ein. Du hattest jedoch gesagt, du möchtest die Werte in einem Graphen darstellen. Wäre es ggf. möglich, einfach die unscharfen Werte zu entfernen und der Graph selbst ist dann gezwungen die Verbindung zum letzten verfügbaren Punkt herzustellen? Beispiel:

values[0] --> 1
values[1] --> 2
values[2] --> 1
values[3] --> 4

Du würdest dann den Punkt P(2,1) entfernen / als ungültig markieren und der Graph müsste dann eine Verbindung zwischen P(1/2) und P(3,4) zeichnen, welcher über P(2/3) laufen würde.
 
Zuletzt bearbeitet:

ComFreek

Mod | @comfreek
Moderator
Vielen Dank für den Denkanstoß!

Das ist in der Tat viel einfacher. Ich hatte vor, den Graphen in Excel zu plotten (nur zur Präsentation).
Hier habe ich ein Funktionskonstrukt zum Interpolieren gefunden. Allerdings muss ich natürlich alle Funktionsnamen zuerst ins Deutsche übersetzen.
Da gibt es zwar Tools für, aber die bringen selbst erstmal Syntaxfehler rein
Der Fehler war, dass das Tool die Kommata nicht zu Semikoli umgewandelt hat. Habe den Bug jetzt dem Entwickler gemeldet.
 
Hallo ComFreek,

hier mal mein Versuch mit F#:

Code:
let makeSteps min max steps = List.map (fun x -> min + float x * (max - min) / float steps) [1..steps]

let rec fixData' max steps values =
  match values with
  | value :: rest ->
      if value >= max
      then makeSteps max value (steps + 1) @ (fixData' value 0 rest)
      else fixData' max (steps + 1) rest
  | [] -> []

let fixData = fixData' 0.0 0

let values = [10.0; 20.0; 15.0; 17.0; 30.0; 32.0; 31.0; 40.0; 38.0]
printfn "%A" (fixData values)

Ergibt:
Code:
[10.0; 20.0; 23.33333333; 26.66666667; 30.0; 32.0; 36.0; 40.0]

Grüße
Matthias
 

ComFreek

Mod | @comfreek
Moderator
Vielen, vielen Dank Matthias!! Es funktioniert perfekt :)
Ich wusste gar nicht, dass du auch mit F# unterwegs bist, zumindest nicht hier im Forum.


Es scheint wohl, dass ich noch viel in F# lernen muss :-(

Danke nochmal & schönes Restwochenende!
ComFreek
 
Ich wusste gar nicht, dass du auch mit F# unterwegs bist, zumindest nicht hier im Forum.
Ich hatte bisher auch noch nichts mit F# zu tun. Ich musste nur die Syntax nachschlagen, den Rest kenne ich schon von ähnlichen (funktionalen) Programmiersprachen. Das heißt allerdings auch, dass mein Codeschnipsel nicht unbedingt idiomatisches F# ist.

Grüße
Matthias