1..24 umcodieren in Kombination von 4 Ziffern

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2022
Beiträge
22.069
Reaktionspunkte
6.861
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich muß mit einer S7-xxxx einen Zahlenwert 1..24 umcodieren in die 24 Möglichkeiten, 4 unterschiedliche Ziffern in einer Reihe anzuordnen:

1 --> 1234
2 --> 1243
3 --> 1324
4 --> 1342
5 --> 1423
6 --> 1432
7 --> 2134
8 --> 2143
...
24 --> 4321

Es soll ausdrücklich keine Lookup-Tabelle verwendet werden. Ich habe das jetzt mit einer Fallunterscheidung der 24 Fälle (CASE, bzw. in AWL mit SPL) programmiert. Geht das vielleicht auch kürzer? Kennt jemand eine Formel oder einen Algorithmus, um aus 1..24 (oder 0..23 ;) ) die Kombination zu "berechnen" oder einen Bit Hack?

Ich habe das Gefühl, daß da was gehen müsste, komme aber nicht drauf. Im Internet finde ich keine Lösung, vielleicht verwende ich nicht die richtigen Suchworte?
Das Ergebnis darf als ein Dezimalwert oder BCD-Wert oder als 4 einzelne Werte herauskommen, es soll sowieso in 4 INT-Variablen zerlegt werden.

Harald
 
Kannst Du noch zwei, drei Worte zu den Ziel-Werten sagen? Gibt es Zusammenhänge zum Quell-Wert? Was spricht gegen ein Array mit Konstanten, und dem Quell-wert, als Index?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Zielwerte sind einfach die aufsteigend sortierte Liste der 24 Kombinationsmöglichkeiten.
Die 1..24 kommen aus einer Visu aus einer symbolischen Auswahlliste und sind der Index des ausgewählten Eintrags.
Ein Array mit Konstanten würde der Compiler auch nur in 24 Cases übersetzen, das Compilat würde nicht kürzer oder effizienter, ich hätte nur vielleicht etwas weniger Schreibarbeit (weniger Programmcode, dafür mehr Deklarationen).

Harald
 
Wenn es keinen mathematischen/logischen Zusammenhang zwischen Quell- und Ziel-Wert gibt, wirst Du auch keinen Berechnungsalgorithmus finden. Selbst wenn, tauschst Du CPU-Last gegen Schreibarbeit (Programmcode oder Deklaration). Ist dann eigentlich auch schon wurscht. Array fände ich persönlich bequemer, aber Case-Anweisung geht ebenso. Ob das für den Compiler, bzw. in der Abarbeitung das gleiche ist, würde ich aber bezweifeln. Was ist Dir wichtiger, Performance, Speichernutzung oder Programmieraufwand?
 
Wenn Du von "24 Kombinationsmöglichkeiten" sprichst, klingt das schon irgendwie nach Zusammenhang. Kannst Du das besser beschreiben? Hast Du 24 Checkboxen, die in Ihrer Kombination einen dezimalen Wert ergeben oder so etwas?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
quick and dirty
Code:
var
  i,j,k,l,m:Integer;
  Zahl:Array[1..4] of Integer;

begin
  for i := 1 to 4 do  begin
    Zahl[i] := 1;
    for j := 1 to 4 do begin
      if Zahl[j]=0 then   begin
        Zahl[j] := 2;
        for k := 1 to 4 do begin
          if Zahl[k]=0 then   begin
            Zahl[k] := 3;
            for l := 1 to 4 do begin
              if Zahl[l]=0 then   begin
                Zahl[l] := 4;
                Writeln(Zahl[1],Zahl[2],Zahl[3],Zahl[4]);
                Zahl[l] := 0;
              end;
            end;
            Zahl[k] := 0;
          end;
        end;
        Zahl[j] := 0;
      end;
    end;
    Zahl[i] := 0;
  end;
end;
Pascal ist ja gut lesbar

Gruß
Erich

p.s. : nochmal den Eingangstext gelesen und dann erst verstanden: Du suchst eine Funktion, die direkt die vierstellige Zahl liefert.
Vergiss meine Lösung
 
Zuletzt bearbeitet:
In einer Visu ist eine ausklappbare und dann scrollbare Liste (heißt wohl Kombinationsfeld?) mit 24 Einträgen/Zeilen, die mit den 24 Kombinationen 1234 bis 4321 aufsteigend sortiert beschriftet sind. Der Bediener wählt z.B. die 5. Zeile "1423", das liefert den Index 5 an die SPS, und die SPS muß nun die 5 umcodieren in 1423, und dann 1,4,2,3 in 4 Variablen schreiben.

PS: Ich bin jetzt unterwegs zum Bierchen trinken :D und melde mich wohl erst morgen wieder.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es ist bereits fertig. Aber aus Interesse und Spaß am Programmieren will ich wissen, ob es auch eine andere Lösung gibt. Vieeicht muß ich das mal wieder machen, dann vielleicht mit 5 Ziffern, da will ich evtl. nicht 120 Cases/Werte eintippen.

Harald
 
Die 1..24 kommen aus einer Visu aus einer symbolischen Auswahlliste und sind der Index des ausgewählten Eintrags.
Die Lösung ist, nicht 1-24 als sondern die gewünschte Zahlenwerte 1234, 1243, 1324, 1342 usw . als das Index konfigurieren.
Einfach in die Textliste:
Index / Text
1234 / "1234"
1243 / "1243"
1324 / "1324"
usw.

Kein SPS Code notwendig, ausser die Umwandlung von den Zahlenwert ins einselne Ziffern muss man programmieren mittels INT --> BCD und dann Abfrage von die Einzelne BCD Ziffern.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vieeicht muß ich das mal wieder machen, dann vielleicht mit 5 Ziffern, da will ich evtl. nicht 120 Cases/Werte eintippen.
Das Problem is wenn man kein normalen Eingabefeld hat, sondern ein Textliste weil man das Wahl den man eingeben kann begrenzen will.
Dann hat man ein Drop-Down der 120 Zeilen Tief ist, und es wird impraktikabel zu den unterste Wert zu scrollen.
In den Fall wäre es vielleicht besser mit ein virtuellen Codewheel (deutsche benennung ?).

Prost !
 
Die Visu ist WinCC 7.5, da kann man nicht festlegen welcher Index aus der Textauswahl-Liste zurückgegeben wird. (Schon das Eingeben der einzelnen Beschriftungen ist ziemlich mühselig...)

Prost!

Harald
 
Permutation oder Kombinatorik ist das Stichwort. Das ist aber nicht wirklich einfach zu lösen. Hier ein Beispiel in VB6: https://www.vbarchiv.net/tipps/tipp_68-rekursive-permutation.html
Da ist aber ein rekursiver Aufruf der Funktion drin, d.h. du würdest einen FC in sich selber aufrufen. Zudem ist die erhaltene Augabe nicht aufsteigend sortiert, da müsste noch ein Bubblesort dahinter geschaltet werden. Ausgabe von dem verlinkten Beispiel:
24 1234 1243 1324 1423 1342 1432 2134 2143 3124 4123 3142 4132 2314 2413 3214 4213 3412 4312 2341 2431 3241 4231 3421 4321
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn es da eine Abkürzung bei Permutationen für Ziffern gäbe, dann vermute ich würde das irgendwo stehen. Selbst wenn man nur die Ziffern 1 und 2 verwendet also 12 und 21, fiele mir dafür keine Abkürzung ein die man dann auf mehr Ziffern ausrollen könnte.
 
Zwar keine "Abkürzung", aber in VBA(Excel) zusammengewurschtelt:
Code:
Function Nummi4(X1) ' X1 : 1..24; Ergebnis 1234..4321 (4-stellige Zahlen mit je 1 Ziffer aus 1, 2, 3, 4)
xMi1& = Max(1, Min(24, X1)) - 1
xZi4& = Int(xMi1& / 6) Mod 6 + 1
xCh3$ = Replace("1234", xZi4&, "")
xZi3& = Mid$(xCh3$, Int(xMi1& / 2) Mod 3 + 1, 1)
xCh2$ = Replace(xCh3$, xZi3&, "")
If xMi1& Mod 2 = 0 Then
    xZi1& = Right$(xCh2$, 1)
    xZi2& = Left$(xCh2$, 1)
Else
    xZi2& = Right$(xCh2$, 1)
    xZi1& = Left$(xCh2$, 1)
End If
Nummi4 = 1000 * xZi4& + 100 * xZi3& + 10 * xZi2& + xZi1&
End Function

' - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - +

Function Nummi5(X1) ' X1 : 1..120; Ergebnis 12345..54321 (5-stellige Zahlen mit je 1 Ziffer aus 1, 2, 3, 4, 5)
xMi1& = Max(1, Min(120, X1)) - 1
xZi5& = Int(xMi1& / 24) Mod 24 + 1
xCh4$ = Replace("12345", xZi5&, "")
xZi4& = Mid$(xCh4$, Int(xMi1& / 6) Mod 4 + 1, 1)
xCh3$ = Replace(xCh4$, xZi4&, "")
xZi3& = Mid$(xCh3$, Int(xMi1& / 2) Mod 3 + 1, 1)
xCh2$ = Replace(xCh3$, xZi3&, "")
If xMi1& Mod 2 = 0 Then
    xZi1& = Right$(xCh2$, 1)
    xZi2& = Left$(xCh2$, 1)
Else
    xZi2& = Right$(xCh2$, 1)
    xZi1& = Left$(xCh2$, 1)
End If
Nummi5 = 10000 * xZi5& + 1000 * xZi4& + 100 * xZi3& + 10 * xZi2& + xZi1&
End Function

' - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - +

Function Min(X1, X2)
If X1 < X2 Then Min = X1 Else Min = X2
End Function

Function Max(X1, X2)
If X1 > X2 Then Max = X1 Else Max = X2
End Function

PS:
Danke, Harald, für das verspätete WeihnachtsRätsel! ;)

PPS:
Glückwunsch, Harald, zum 17.777-ten Beitrag! (y)
 
Zuletzt bearbeitet:
Bei dem Weihnachtsrätsel wird allerdings erwartet, daß es da auch eine Lösung gibt. Hier wird es wohl eher so sein, daß es keine sinnvolle Lösung außer Fallunterscheidung und Lookup-Table gibt. 😢

Ich habe mir mal die Ergebniszahlen mit Excel angeschaut, ob da irgendeine berechenbare Regelmäßigkeit auffällt ... siehe Bild

Ich könnte mir nun noch vorstellen, daß der Code in einer Schleife die jeweils nächste Kombination berechnet/erzeugt bis zum gesuchten Index, vielleicht läßt sich das mit wenigen Regeln realisieren? Z.B. ausgehend von "1234" tauschen ja immer 2 Ziffern die Position (einmal Pos.3 mit Pos.4, dann Pos.4 mit Pos.2, dann wieder Pos.3 mit Pos.4, ...)

Harald
 

Anhänge

  • Kombinationen1234.png
    Kombinationen1234.png
    68,2 KB · Aufrufe: 35
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe mir mal die Ergebniszahlen mit Excel angeschaut, ob da irgendeine berechenbare Regelmäßigkeit auffällt ... siehe Bild
... vielleicht läßt sich das mit wenigen Regeln realisieren? Z.B. ausgehend von "1234" tauschen ja immer 2 Ziffern die Position (einmal Pos.3 mit Pos.4, dann Pos.4 mit Pos.2, dann wieder Pos.3 mit Pos.4, ...)
Ja, Harald, da fallen schon Regelmässigkeiten auf.
Die Differenzen zwischen zwei aufeinanderfolgenden Zahlen sind immer ein Vielfaches von 9.
Habe mir sogar schon die PrimFaktorenZerlegung der Differenzen angesehen und abgesehen von einigen Symmetrien ist mir noch nichts halbwegs Verwertbares auf gefallen.
Deine Behauptung, dass immer 2 Ziffern getauscht werden, stimmt so nicht, wenn die Zahlen in aufsteigend (oder absteigend) sortierter Reihenfolge betrachtet werden.
Anfangs hatte ich mir eine Rotation der Ziffern mit/mit ohne Tauschen von 2 Ziffern vorgestellt. Da habe ich noch nichts Einfaches gefunden, um die Sortierung zu gewährleisten (siehe auch den Beitrag #14 von Oberchefe).
Ich kann mich vage erinnern, dass ich mal eine solche Rotierei und Tauscherei auf einem hp25 (mit 4 Akkus) programmiert habe. Aber ich weiss nicht mehr mit welchem Ziel und mit welchen Eigenschaften ... ist viel zu lange her.

Hatte vor der Beschäftigung mit der Berechnung der n-stelligen Zahl aus dem Index versucht, zu einer gegebenen 4-stelligen Zahl die nächste bzw. vorherige in sortierter Reihenfolge zu berechnen. Hab's aber erstmal wieder eingestellt.

Bitte verzeih mir die übelsten impliziten DatenTypKonversionen in #16, die ich in VBA (gerne ;) ) nutze.
Das in SCL umzusetzen dürfte viel zusätzliche Tipperei erfordern. VBA finde ich sehr angenehm bei der Verarbeitung von Strings und davon mache ich auch hemmungslos Gebrauch an Stellen, an denen man diese als alles andere als naheliegend empfinden dürfte.

Z.Z. habe ich angefangen, den umgekehrten Weg einzuschlagen, nämlich aus der n-stelligen Zahl den zugehörigen Index zu berechnen.
Sieht nicht unlösbar aus, aber ganz schön abenteuerlich/aufwändig ...

Gruss, Heinileini
 
Zuletzt bearbeitet:
Deine Behauptung, dass immer 2 Ziffern getauscht, stimmt so nicht, wenn die Zahlen in aufsteigend (oder absteigend) sortierter Reihenfolge betrachtet werden.
Du hast recht, manchmal ändern auch mehr als 2 Ziffern die Position. Ich muß aber eine Liste in aufsteigend sortierter Reihenfolge verwenden.

Das Thema der Aufgabe ist durchaus recht interessant. Auch was dazu schon erforscht wurde, z.B.
https://de.wikipedia.org/wiki/Permutation
https://de.wikipedia.org/wiki/Fakultätsbasiertes_Zahlensystem
https://de.wikipedia.org/wiki/Fehlstand
Nur finde ich nicht, wie ich das für eine Formel oder einen Algorithmus nutzen könnte. :unsure:

Hatte vor der Beschäftigung mit der Berechnung der n-stelligen Zahl aus dem Index versucht, zu einer gegebenen 4-stelligen Zahl die nächste bzw. vorherige in sortierter Reihenfolge zu berechnen. Hab's aber erstmal wieder eingestellt.
Das wäre ein Ansatz für eine Schleifenlösung, die ich mir auch vorstellen könnte.

Harald
 
Also, es ist eine realen Augabe, kein Weihnachtsrätzel ?
Ich habe nichts geniales zu dem Thema.
Aber ich denke dass die Drop-Down liste kein gute Lösung für die Bediener ist. Schon bei 24 Kombination ist die Dropdown etwas (zu) tief.
Mit 5 Zifferen und 120 Kombinationen macht es kein Sinn mehr.
Besser die Aufgabe in ein anderen Weise lösen.

Erinnert Ihr die Thumbwheel (Daumenrad ?). Habe ich ungf. 1990 verwendet um ein Zahl in die SPS einzugeben, ohne Operatorpanel o.Ä.
So ein virtuellen Thumbwheel konnte man schnell programmieren, und die einzelne Ziffern sind dann in einzelne Variabeln.
Und man hat kein 120 stelligen Drop-down Liste. Kann 4, 5 oder 10 Zifferen haben ohne dass es komplizierter wird.
thumbwheel.png
 
Zurück
Oben