AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Interessante (?) Frage Kombinatorik

Ein Thema von Möbius · begonnen am 25. Aug 2024 · letzter Beitrag vom 27. Aug 2024
Antwort Antwort
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.688 Beiträge
 
Delphi 12 Athens
 
#1

AW: Interessante (?) Frage Kombinatorik

  Alt 26. Aug 2024, 00:28
Ich hätte da einen iterativen Ansatz ohne Rekursion zu bieten:
Delphi-Quellcode:
procedure Kombinatorik(N: Integer; HandleArray: TProc<TArray<Integer>>);
var
  arr: TArray<Integer>;
begin
  SetLength(arr, N);
  { Triviale Startkombination }
  arr[0] := N;
  HandleArray(arr);
  var idx := 0;
  repeat
    if idx < High(arr) then begin
      { Schiebe einen Zähler um eine Stelle nach rechts }
      Dec(arr[idx]);
      Inc(idx);
      Inc(arr[idx]);
      HandleArray(arr);
    end
    else begin
      { Letzte Stelle: Merke und lösche den Übertrag }
      var K := arr[idx];
      arr[idx] := 0;
      { Suche den den größten Index mit einem Wert > 0.
        Gibt es keinen sind wir fertig.}

      repeat
        Dec(idx);
        if idx < 0 then
          Exit;
      until arr[idx] > 0;
      { Setze den Übertrag in die nächste Stelle (muss 0 enthalten) }
      arr[idx + 1] := k;
      { Im weiteren Verlauf wird wieder ein Zähler von idx auf den Übertragswert geschoben }
    end;
  until False;
end;
Das Ergebnis sieht dann so aus:
Code:
4 0 0 0
3 1 0 0
3 0 1 0
3 0 0 1
2 2 0 0
2 1 1 0
2 1 0 1
2 0 2 0
2 0 1 1
2 0 0 2
1 3 0 0
1 2 1 0
1 2 0 1
1 1 2 0
1 1 1 1
1 1 0 2
1 0 3 0
1 0 2 1
1 0 1 2
1 0 0 3
0 4 0 0
0 3 1 0
0 3 0 1
0 2 2 0
0 2 1 1
0 2 0 2
0 1 3 0
0 1 2 1
0 1 1 2
0 1 0 3
0 0 4 0
0 0 3 1
0 0 2 2
0 0 1 3
0 0 0 4
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Interessante (?) Frage Kombinatorik

  Alt 26. Aug 2024, 00:44
Ich bau solche Ziehungen auch fast nur iterativ auf, v.a. um Aufrufe zu verhindern.

Hier noch ein rekursiver direkter Ansatz (also ohne die "Ziehen ohne Zurücklegen" Überlegung).
[Damit man bei solchen Aufgaben das Rad nicht immer neu erfinden muss, lohnt es sich ein paar kombinatorische Aufgaben wie "Ziehen mit/ohne Zurücklegen", Permutationen etc. zu programmieren. Durch geschickte Parameterwahl kann man dank einer solchen Sammlung die meisten Probleme mit einer Zeile Code lösen.]

Delphi-Quellcode:
procedure af( rest : integer; var A: array of Integer; elnr : integer; var res : TStringList );
var i, j : integer;
    s : string;
begin
  if elnr = High(A) then // letzte Position in A erreicht
  begin
      s := '';
      A[elnr] := rest; // wir schreiben den Rest der Summe
      // und speichern A in res ab:
      for j := 0 to High(A) do s := s + A[j].ToString + ' ';
      res.Add(s);
  end else
  for i := 0 to rest do
  begin
    // an Postion elnr sind noch die Werte 0..rest möglich
    A[elnr] := i;
    // danach können wir noch rest-i auf die Elemente A[elnr+1] .. A[High(A)] verteilen:
    af(rest-i, A, elnr+1, res);
  end;
end;

....
 res := TStringList.Create;
 Setlength(A,v);
 af(s,A,0,res);
 ShowMessage( res.Text );
 res.free;
Michael Gasser

Geändert von Michael II (26. Aug 2024 um 01:07 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz