Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1172to1176
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Mögliche Würfel-Würfe auflisten.

Mögliche Würfel-Würfe auflisten.
Klaus
Moin Forum,
ich hätte gerne die Möglichkeiten aller Würfe von n Würfeln aufgelistet. Für zwei Würfel kann man es leicht per Hand machen:
1-1 / 1-2 / 1-3 / 1-4 / 1-5 / 1-6
2-1 / 2-2 / 2-3 / 2-4 / 2-5 / 2-6
[...]
6-1 / 6-2 / 6-3 / 6-4 / 6-5 / 6-6
Bei drei Würfeln wird es schon anstrengend, es selbst aufzuschreiben.
Für vier Würfel habe ich mir eine Schleife in VBA geschrieben:
Sub WuerfelWuerfe()
startzeile = 2
For w1 = 1 To 6
For w2 = 1 To 6
For w3 = 1 To 6
For w4 = 1 To 6
Range("A" & startzeile) = w1
Range("B" & startzeile) = w2
Range("C" & startzeile) = w3
Range("D" & startzeile) = w4
startzeile = startzeile + 1
Next w4
Next w3
Next w2
Next w1
End Sub

Die Listet mir auch brav alle 1.296 Möglichkeiten auf.
Frage: wie erweitere ich das auf n Würfel? Klar, einfach mehr Schleifen ineinander schreiben. Aber es muss doch auch einfacher gehen, ohne 100 mal das gleiche zu tippen?
Es geht mir weniger um das Ergebniss, als eher um den Weg. Über Links und / oder Denkanstöße in die richtige Richtung wäre ich dankbar.
Grüße,
Klaus M.vdT.
AW: Mögliche Würfel-Würfe auflisten.
18.08.2010 11:47:52
Andi
Mit einem Makro ein Makro schreiben. Das was Sie von Hand schreiben, dazu könnte man ein Algorithmus schreiben.
Function GibDenWuerfelCode (AnzahlWürfel as long) as string
Dim strFor, strRange, StrNext, strCode as string
If isempty(n) then Exit Function
For n = 1 to AnzahWürfel
If n = 1 then
strFor = "For w" & cstr(n) & = 1 To 6"
strRange = "Thisworkbook.Activesheet.cells(startzeile," & cstr(n) & ") =W" & cstr(n)
strNext = "Next"
else
strFor = strFor & Chr(10) & "For w" & cstr(n) & = 1 To 6"
If n = AnzahlWuerfel then
strRange = strRange & Chr(10) & "Thisworkbook.Activesheet.cells(startzeile," & cstr(n) & ") =W"  _
& cstr(n) & chr(10) & "startzeile = startzeile + 1"
else
strRange = strRange & Chr(10) & "Thisworkbook.Activesheet.cells(startzeile," & cstr(n) & ") =W"  _
& cstr(n)
end if
strNext = strNext & chr(10) & "Next"
end if
next
GibDenWuerfelCode  = "

Function WuerfelCode()" & Chr(10) & strFor & chr(10) & strRange & chr(10) & strNext & chr(10) & "End Function
"
End Function
Ereignis Button Click
- Abfrage Anzahl Wuerfel
- Modul add
- Makro add
- Makro ausführen
- Zuvor estelltes Modul incl. Makro löschen
Ende
Alles Dirty. Keine Gewährleistung.
Andi
Anzeige
AW: Mögliche Würfel-Würfe auflisten.
18.08.2010 12:17:44
Klaus
Hallo Andi,
ganz super! Es funktioniert! Vielen Dank für den Gedankenanstoß.
Der Vollständigkeit halber der überarbeitete Code
Sub test()
Call GibDenWuerfelCode(4)
End Sub
Function GibDenWuerfelCode(AnzahlWürfel As Long) As String
Dim strFor, strRange, StrNext, strCode As String
For n = 1 To AnzahlWürfel
If n = 1 Then
strFor = "StartZeile = 1" & Chr(10) & "For w" & CStr(n) & " = 1 To 6"
strRange = "Thisworkbook.Activesheet.cells(startzeile," & CStr(n) & ") =W" & CStr(n)
StrNext = "Next"
Else
strFor = strFor & Chr(10) & "For w" & CStr(n) & " = 1 To 6"
If n = AnzahlWürfel Then
strRange = strRange & Chr(10) & "Thisworkbook.Activesheet.cells(startzeile," & CStr( _
n) & ") =W" & CStr(n) & Chr(10) & "startzeile = startzeile + 1"
Else
strRange = strRange & Chr(10) & "Thisworkbook.Activesheet.cells(startzeile," & CStr( _
n) & ") =W" & CStr(n)
End If
StrNext = StrNext & Chr(10) & "Next"
End If
Next n
GibDenWuerfelCode = "Function WuerfelCode()" & Chr(10) & strFor & Chr(10) & strRange & Chr(10) & _
StrNext & Chr(10) & "End Function"
Sheets("Tabelle3").Range("A1").Value = GibDenWuerfelCode
End Function
Fürs Archiv:
Nebenbei habe ich eine Formel-Lösung gefunden ...
=REST(AUFRUNDEN(ZEILE()/(6^(SPALTE()-1));0);6)+1

im Bereich A1:F46657 ergibt alle Möglichen Kominatinen aus 6 Würfeln, danach wird die Excel-Grenze erreicht.
Grüße,
Klaus M.vdT.
Anzeige
1 1 1 1 1 6 <> 6 1 1 1 1 1 ?
18.08.2010 12:18:21
ransi
HAllo
Einen Vorschlag hab ich auch:
Option Explicit




Public Sub tst()
Dim objDic As Object
Dim L As Long
Dim n As Integer
Dim RegEx As Object
n = Application.InputBox("Wieviele Würfel ?", , , , , , , 1)
If n = False Or n > 6 Then Exit Sub
Set objDic = CreateObject("scripting.Dictionary")
Set RegEx = CreateObject("VbScript.Regexp")
With RegEx
    .Pattern = "[1-6]{" & n & "}"
    .Global = True
    For L = String(n, "1") To String(n, "6")
        If .test(L) Then objDic(L) = 0
    Next
End With
Range("A1").Resize(objDic.Count) = WorksheetFunction.Transpose(objDic.keys)
End Sub


Wobei sich jetzt die Frage stellt:
1 1 1 1 1 6 sind 5 Einsen und eine 6
6 1 1 1 1 1 sind auch 5 Einsen und eine 6
Soll das als 2 verschiedene Kombis gehandelt werden oder als eine ?
ransi
Anzeige
AW: 1 1 1 1 1 6 <> 6 1 1 1 1 1 ?
18.08.2010 12:31:14
Klaus
Hallo Ransi,
vielen Dank für deinen Vorschlag, den schaue ich mir gleich in Ruhe an.
ja, 1-1-1-1-1-6 ist ungleich 6-1-1-1-1-1. Ich möchte jeden Würfel einzeln betrachten. (Es gibt also 6 Kombis für den Wurf 1x6+5x1)
Grüße,
Klaus M.vdT.
Ich begreife den Code nicht :-(
18.08.2010 12:40:40
Klaus
Hallo Ransi,
vielen Dank, dein Code läuft 1a und ist super schnell. Bringt mich nur leider nicht weiter, weil ich nicht den Hauch einer Ahnung habe was er macht und wie ....
Regexp ist laut google eine Regular Expression. Hab ich schon mal gehört, dass es sowas gibt ;-) heut mittag wird der Wikipedia Eintrag dazu studiert.
Was eine scripting.Dictionary ist traue ich mich kaum zu fragen. Google schmeisst als zweiten Hit nach "Scripting.Dictionary VBA" einen Link auf Herber.de raus, in dem der User Ransi für die Benutzung eben dieser gelobt wird ;-)
Vielleicht hast du ja ein paar Hinweise oder lesenswerte Links für mich?
(wie gesagt - mit gehts nicht um das Ergebniss sondern um den Weg.)
Grüße,
Klaus M.vdT.
Anzeige
AW: Ich begreife den Code nicht :-(
18.08.2010 17:58:19
JogyB
Hallo Klaus,
der Code ist eigentlich ganz einfach.
Er erzeugt zunächst mal ein RegExp-Objekt und ein Dictionary-Objekt.
Ersteres ist für die Prüfung der Ausdrücke, letzteres zu deren Speicherung.
Dann erzeugt er ein Suchmuster, bei 6 Würfeln sieht das z.B. so aus [1-6]{6}
[1-6] bedeutet hier, dass nur die Zahlen 1-6 vorkommen sollen und zwar wegen {6} genau 6 Mal. 12345 wäre also ebenso wie 123457 nicht ok, 123456 dagegen schon. Warum er das Global setzt ist mir allerdings nicht klar, die Zahlenfolge kann ja nur ein Mal vorkommen.
Ich bleibe jetzt mal bei den 6 Würfeln: Er geht nun alle Zahlen von 111111 bis 666666 durch. Jede Zahl wird getestet, ob sie in das Suchmuster passt. Wenn sie passt, dann wird sie in das Dictionary-Objekt eingetragen, indem dem Element mit dem Schlüssel L der Wert 0 zugewiesen wird. Da es den Schlüssel noch nicht gibt, ist das äquivalent zu dem in der Hilfe beschriebenen
objDic.Add L, 0
Ist aber kürzer so.
Am Ende schreibt er dann einfach alle Keys des Dictionary-Objekts in die Tabelle. Und das sind eben dann genau die möglichen Würfe, weil nur diesen ein Wert zugewiesen wurde.
Anstelle des Dictionary-Objekts könnte man auch einfach ein Datenfeld nehmen, das wäre meines Erachtens sogar schneller. Der Vorteil des Dictionary-Objekts gegenüber einem Datenfeld ist meines Wissens, dass man keine Laufvariable mitschleppen und sich auch nicht um die korrekte Obergrenze sorgen muss. Wobei letzteres hier egal ist, da die von Beginn an feststeht.
Gruß, Jogy
Anzeige
AW: Ich begreife den Code nicht :-(
18.08.2010 18:12:17
ransi
HAllo Jogy
Ich wollt mich grad dran machen das zu erklären.
Aber so schön wie du das jetzt gemacht hast bekäme ich es sicher nicht hin !
Zitat:
Warum er das Global setzt ist mir allerdings nicht klar,
Jetzt wo du es ansprichst :
Mir eigentlich auch nicht ;-)
DAs RegEx ist eigentlich wie mit den Kanonen und den Spatzen.
Ich wollte das ursprünglich mit LIKE testen, aber das hier:
If Not l Like "*[7-9,0]*" ist mir nicht eingefallen.
Ich wäre auf sowas:
If L like "[1-6][1-6][1-6][1-6][1-6][1-6]" then
gekommen. Da schien mir das "[1-6]{6}" irgendwie eleganter ;-)
ransi
ransi
Anzeige
AW: 1 1 1 1 1 6 <> 6 1 1 1 1 1 ?
18.08.2010 12:34:24
Andi
@ransi respect
Set objDic = CreateObject("scripting.Dictionary")
Set RegEx = CreateObject("VbScript.Regexp")
werde ich mal erforschen müssen. Kenne ich noch nicht.
Andi
AW: Mögliche Würfel-Würfe auflisten.
18.08.2010 12:18:57
Andi

Function Test()
Debug.Print GibDenWuerfelCode(4, 3)
End Function

Function GibDenWuerfelCode(AnzahlWuerfel As Long, Start As Long) As String
Dim strFor, strRange, StrNext, strCode As String
If IsEmpty(AnzahlWuerfel) Then Exit Function
For n = 1 To AnzahlWuerfel
If n = 1 Then
strFor = "For w" & CStr(n) & "= 1 To 6"
strRange = "Thisworkbook.Activesheet.cells(startzeile," & CStr(n) & ") =W" & CStr(n)
StrNext = "Next"
Else
strFor = strFor & Chr(10) & "For w" & CStr(n) & "= 1 To 6"
If n = AnzahlWuerfel Then
strRange = strRange & Chr(10) & "Thisworkbook.Activesheet.cells(startzeile," & CStr( _
n) & ") =W" _
& CStr(n) & Chr(10) & "startzeile = startzeile + 1"
Else
strRange = strRange & Chr(10) & "Thisworkbook.Activesheet.cells(startzeile," & CStr( _
n) & ") =W" _
& CStr(n)
End If
StrNext = StrNext & Chr(10) & "Next"
End If
Next
GibDenWuerfelCode = "

Function WuerfelCode()" & Chr(10) & "startzeile=" & CStr(Start) & Chr(10) & strFor & Chr(10) & strRange & Chr(10) & StrNext & Chr(10) & "End Function
"
End Function
Ergebnis Code
Function WuerfelCode()
startzeile = 3
For W1 = 1 To 6
For W2 = 1 To 6
For W3 = 1 To 6
For W4 = 1 To 6
ThisWorkbook.ActiveSheet.Cells(startzeile, 1) = W1
ThisWorkbook.ActiveSheet.Cells(startzeile, 2) = W2
ThisWorkbook.ActiveSheet.Cells(startzeile, 3) = W3
ThisWorkbook.ActiveSheet.Cells(startzeile, 4) = W4
startzeile = startzeile + 1
Next
Next
Next
Next
End Function

Funktioniert
Andi
Anzeige
AW: Mögliche Würfel-Würfe auflisten.
18.08.2010 13:13:10
MichaV
hier noch ne Möglichkeit mit rekursiver Programmierung.
Option Explicit
Option Base 1
Sub test()
Const anzal_wuerfel = 4
Dim wuerfe()
ReDim wuerfe(anzal_wuerfel)
werfen wuerfe, anzal_wuerfel
End Sub
Sub werfen(wuerfe, wuerfel As Integer)
Dim i As Integer
For i = 1 To 6
wuerfe(wuerfel) = i
If wuerfel > 1 Then
Call werfen(wuerfe, wuerfel - 1)
Else
Debug.Print Join(wuerfe, "-")
End If
Next i
End Sub
Gruss- Micha
mit Ausgabe und schön schnell...
18.08.2010 16:10:09
JogyB
Hallo Micha und Klaus.
Weil ich Michas Ansatz so schon finde, hier das Ganze noch mit Ausgabe der Daten.
Braucht auf meinem Rechner ca. eine halbe Sekunde für 6 Würfe. Die Zeit hängt aber stark vom im Join-Befehl verwendeten Trennzeichen ab, z.B. bei "+" braucht es mehr als 10 Mal so lange. Das von Micha ursprünglich verwendete "-" ist auch noch recht schnell, da dauert es ca. 1,5 s.
Sub test()
Dim erGebnis() As String
Dim wuRf()
Dim zeiLe As Long
Const anzahl_Wuerfel = 6
ReDim erGebnis(1 To 6 ^ anzahl_Wuerfel)
ReDim wuRf(1 To anzahl_Wuerfel)
zeiLe = 1
Call werfen(wuRf, erGebnis, zeiLe, anzahl_Wuerfel)
Application.ScreenUpdating = False
ActiveSheet.Cells(1, 1).Resize(UBound(erGebnis)) = Application.Transpose(erGebnis)
Application.ScreenUpdating = True
End Sub
Sub werfen(ByRef wuRf, ByRef erGebnis, ByRef zeiLe As Long, ByRef wuerfelNr As Integer)
Dim i As Integer
For i = 1 To 6
wuRf(wuerfelNr) = i
If wuerfelNr > 1 Then
Call werfen(wuRf, erGebnis, zeiLe, wuerfelNr - 1)
Else
' Geschwindigkeit hängt stark vom Trennzeichen ab!
erGebnis(zeiLe) = Join(wuRf, "")
zeiLe = zeiLe + 1
End If
Next i
End Sub
Oder fast gleich schnell mit einer Zelle je Würfel
Sub test()
Dim erGebnis()
Dim wuRf()
Dim zeiLe As Long
Const anzahl_Wuerfel = 6
ReDim erGebnis(1 To 6 ^ anzahl_Wuerfel, 1 To anzahl_Wuerfel)
ReDim wuRf(1 To anzahl_Wuerfel)
zeiLe = 1
Call werfen(wuRf, erGebnis, zeiLe, anzahl_Wuerfel, anzahl_Wuerfel)
Application.ScreenUpdating = False
ActiveSheet.Cells(1, 1).Resize(UBound(erGebnis), anzahl_Wuerfel) = erGebnis
Application.ScreenUpdating = True
End Sub
Sub werfen(ByRef wuRf, ByRef erGebnis, ByRef zeiLe As Long, _
ByRef wuerfelNr As Long, ByVal anzahl_Wuerfel As Long)
Dim i As Long
Dim k As Long
For i = 1 To 6
wuRf(wuerfelNr) = i
If wuerfelNr > 1 Then
Call werfen(wuRf, erGebnis, zeiLe, wuerfelNr - 1, anzahl_Wuerfel)
Else
' Geschwindigkeit hängt stark vom Trennzeichen ab!
For k = 1 To anzahl_Wuerfel
erGebnis(zeiLe, k) = wuRf(k)
Next
zeiLe = zeiLe + 1
End If
Next i

Man könnte jetzt auch ein paar globale Variablen deklarieren, anstatt alles immer durchzuschleppen. Hat aber bei der Rechenzeit nichts ausgemacht und daher habe ich es jetzt mal so gelassen.
Gruß, Jogy
Anzeige
An alle Helfer!!
19.08.2010 09:48:21
Klaus
Hallo Jogy und Micha,
super - Stichwort "rekursive Programmierung", das war der Lösungsansatz den ich gesucht habe! Mit dieser Idee werde ich mich die nächsten Programme mal intensiver beschäftigen müssen.
An alle anderen: Danke für die guten Ideen! Ich werde jedes Programm ausprobieren!
Ich finde es ganz toll, wie die Community von Herber auf solche Aufgaben eingeht und sich gegenseitig mit schlankeren und schöneren Lösungen überbietet - es macht total Spaß!
Zum Schluss noch meine eigene Lösung: mit 0,8sek zwar nicht die schnellste, aber mit zwei Zeilen bestimmt die kürzeste :-)
Sub Makro1()
Const AnzahlWuerfel = 6
Range(Cells(1, 1), Cells(6 ^ AnzahlWuerfel, AnzahlWuerfel)).FormulaR1C1 = "=MOD(ROUNDUP(ROW()/( _
6^(COLUMN()-1)),0),6)+1"
End Sub
Grüße,
Klaus M.vdT.
Anzeige
noch ne Version
18.08.2010 13:14:27
Rudi
Hallo,
ähnlich ransi mit Dictionary aber ohne RegExp.
Sub test()
Dim l As Long, n As Integer, objDict As Object
Set objDict = CreateObject("scripting.Dictionary")
n = Application.InputBox("Wieviele Würfel ?", , , , , , , 1)
If n = False Or n > 6 Then Exit Sub
Set objDict = CreateObject("scripting.Dictionary")
For l = String(n, "1") To String(n, "6")
If Not l Like "*[7-9,0]*" Then objDict(l) = 0
Next
Range("A1").Resize(objDict.Count) = WorksheetFunction.Transpose(objDict.keys)
End Sub

Dictionary: ist sehr gut in der Hilfe beschrieben.
Gruß
Rudi
ohne dic und reg; JETZ NOCH BILLIGER
18.08.2010 14:21:46
EvilRik
GuckGuck zusammen,
Sub WuerfelmalmitRosenthal()
Dim AnzahlWürfel As Integer, Augen As Long, zae1 As Long
AnzahlWürfel = Application.InputBox("Würfelanzahl eingeben.", "Nicht Kombination :)", , , ,  _
, 1)
If AnzahlWürfel = False Or AnzahlWürfel > 6 Then Exit Sub
For Augen = String(AnzahlWürfel, "1") To String(AnzahlWürfel, "6")
If Not Augen Like "*[7-9,0]*" Then
zae1 = zae1 + 1
Cells(zae1, 2) = Augen
End If
Next Augen
End Sub

Gruß zum Schluß
Henrik
wirklich billig ;-)
18.08.2010 14:49:48
Rudi
Hallo,
44s für deinen vs. 0,8s für meinen und 2,7s für ransis Code.
Nebenerkenntnis: Like vergleicht schneller als RegExp.
Gruß
Rudi
GEPIMPT 0,4sec
18.08.2010 15:48:10
EvilRik

Sub WuerfelmalmitRosenthal()
Dim AnzahlWürfel As Integer, Augen As Long, zae1 As Long, Kombi As Long
Dim WürfelArray() As Variant
AnzahlWürfel = Application.InputBox("Würfelanzahl eingeben.", "Nicht Kombination :)", , , ,  _
, 1)
If AnzahlWürfel = False Or AnzahlWürfel > 6 Then Exit Sub
Kombi = 6 ^ AnzahlWürfel
ReDim WürfelArray(1 To Kombi, 1 To 1)
For Augen = String(AnzahlWürfel, "1") To String(AnzahlWürfel, "6")
If Not Augen Like "*[7-9,0]*" Then
zae1 = zae1 + 1
WürfelArray(zae1, 1) = Augen
End If
Next Augen
Range(Cells(1, 1), Cells(Kombi, 1)) = WürfelArray
End Sub

hast gewonnen owT
18.08.2010 16:14:31
Rudi
the winner is Micha
18.08.2010 17:07:00
ransi
HAllo
' **********************************************************************
' Modul: Tabelle1 Typ: Element der Mappe(Sheet, Workbook, ...)
' **********************************************************************

Option Explicit
Option Base 1

Dim L As Long
Dim arr As Variant

'Micha

Sub test()
Dim dblS As Double
Dim wuerfe()
Dim anzal_wuerfel As Integer
anzal_wuerfel = Application.InputBox("Würfelanzahl eingeben.", "Nicht Kombination :)", 6, , , , 1)
If anzal_wuerfel = False Or anzal_wuerfel > 6 Then Exit Sub
dblS = Timer
L = 0
Redim arr(1 To 6 ^ anzal_wuerfel, 1 To 1)
Redim wuerfe(anzal_wuerfel)
werfen wuerfe, anzal_wuerfel
Range("A1").Resize(UBound(arr), 1) = arr
Debug.Print Timer - dblS '0,3515625
End Sub


Sub werfen(wuerfe, wuerfel As Integer)
Dim i As Integer
For i = 1 To 6
    wuerfe(wuerfel) = i
    If wuerfel > 1 Then
        Call werfen(wuerfe, wuerfel - 1)
    Else
        L = L + 1
        arr(L, 1) = Join(wuerfe, "")
    End If
Next i
End Sub


'EvilRik
Sub WuerfelmalmitRosenthal()
Dim AnzahlWürfel As Integer, Augen As Long, zae1 As Long, Kombi As Long
Dim WürfelArray() As Variant
Dim dblS As Double
AnzahlWürfel = Application.InputBox("Würfelanzahl eingeben.", "Nicht Kombination :)", 6, , , , 1)
If AnzahlWürfel = False Or AnzahlWürfel > 6 Then Exit Sub
dblS = Timer
Kombi = 6 ^ AnzahlWürfel
Redim WürfelArray(1 To Kombi, 1 To 1)
For Augen = String(AnzahlWürfel, "1") To String(AnzahlWürfel, "6")
    If Not Augen Like "*[7-9,0]*" Then
        zae1 = zae1 + 1
        WürfelArray(zae1, 1) = Augen
    End If
Next Augen
Range(Cells(1, 1), Cells(Kombi, 1)) = WürfelArray
Debug.Print Timer - dblS ' 0,421875
End Sub


ransi

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige