Python Liste mit integers auf "Kleine Straße" überprüfen?
Hey,
zurzeit programmiere ich das Spiel Kniffel. Ich bin so weit das mir nur die Abfragen kleine Straße und große Straße fehlen.
Zur Ausgangssituation:
ich habe eine Liste mit 5 integers (Zahlen 1-6) für die Würfel :
dice = [1,2,3,4,5]
Diese möchte ich jetzt überprüfen lassen ob eine kleine Straße da ist (Also 4 Zahlen in Folge). Mein Ansatz mit allen möglichen Antworten aufschreiben und dann jede Möglichkeit zu vergleichen gefällt mir nicht wirklich.
Habt ihr da bessere Ideen?
5 Antworten
Da es nur 6 verschiedene Werte gibt, wäre das Aufschreiben aller Kombinationen aber durchaus eine sinnvolle Implementierung. Auch beim Poker, wo es 13 Werte gibt (und das Ass an beiden Enden stehen kann), kann man das genauso machen.
Edit:
Es gibt 2 Kombinationen für eine große Straße und 3 Kombinationen für eine kleine Straße. Jedenfalls unter der Annahme, dass die Liste sortiert ist, was du aber hilfsweise machen kannst. Dann einfach prüfen:
(enthält 1 AND enthält 2 AND enthält 3 AND enthält 4 ) OR (dasselbe mit 2-5) OR (dasselbe mit 3-6)
Edit: Bug behoben?
In kniffel ist die reihenfolge der würfel egal, richtig?
dice = [1,2,3,4,5]
dice.sort()
i = 0
x = 0
j = 0
for d in dice:
if (d == x+1):
x = d
i = i + 1
if (i > j):
j = i
elif (d != x):
i = 1
x = d
print(j)
print(i)Das berechnet dir wie lang die längste straße ist.
Wenn du nun ausgeben willst ob es eine kleine oder große straße ist kannst du einfach anstatt print(i) sowas machen wie:
if (i == 5):
print("Große Straße")
elif (i == 4):
print("Kleine Straße")
else:
print("Keine Straße :(")
Aber, ganz ehrlich, vergleichen ist auch okay! Gibt ja nur 5 möglichkeiten(3 für die kleien straße, 2 für die große).
Wobei natürlich meine lösung für n würfel mit m seiten funktioniert. Also, funktioniert auch noch wenn du [16,15,17,18,300] da rein packst.
{1, 2, 3, 4}.issubset(dice)
oder ohne Sets:
1 in dice and 2 in dice and
3 in dice and 4 in dice
Und was ist dann mit [2,2,3,4,5]? und [6,3,4,5,6]?
Du müsstest bei so einer lösung alle möglichkeiten aufschreiben. Sind zwar nur 5, 3 für die kleine und 2 für die große, aber genau das will der fragesteller ja vermeiden.
Eine vollständige Lösung mit dem Ansatz würde so aussehen. Und das ist, wie ich die Frage verstehe, genau was der Fragesteller vermeiden will.
if({1, 2, 3, 4, 5}.issubset(dice) or {2, 3, 4, 5, 6}.issubset(dice)):
print("Große Straße")
elif({1, 2, 3, 4}.issubset(dice) or {2, 3, 4, 5}.issubset(dice) or {3, 4, 5, 6}.issubset(dice)):
print("Kleine Straße")
else:
print("Keine Straße :(")
Es ist keine schlechte Lösung, aber der Fragesteller hat explizit gesagt dass er eine andere sucht, wo er nicht alle möglichkeiten aufschreiben muss.
Ich habe ihn so verstanden, dass er nicht alle passenden Listen aufschreiben will. Das wären nämlich wirklich viele.
Mit meiner Antwort kann er sich das sparen. Die anderen 4 vier Fälle könnte man – wenn es unbedingt sein muss – auch in einer Schleife abbacken:
def strasse( dice ):
for size in (5, 4):
for start in range(1, 6-size+2):
test = frozenset(range(start, start+size))
if test.issubset(dice):
print( f"\aStraße mit Länge {size} ab {start}" )
return test
print( "keine Straße gefunden :-(" )
return None
Aber wenn es nur eine Übungsaufgabe ist, halte ich es für sinnvoller, die 5 Tests explizit hinzuschreiben.
Also, bei uns hätte der prof die aufgabe vermutlich so formuliert dass es für n würfel mit m seiten funktionieren muss...
Aber wenn es nur 5 würfel mit je 6 seiten sind, ist das natürlich eine gute lösung.
Die Anzahl der Würfel ist doch uninteressant. Und rate mal, warum ich "6-size+2" schrieb.
"size in (5, 4)" könnte man je nach Aufgabenstellung noch anpassen.
Ja stimmt, ich glaube dein code funktioniert für die aufgabenstellung.
Für die anzahl der seiten müsste man start+size ändern, weil so funktioniert es auch z.B. nicht für 5 zwanzigseitige würfel.
Wahrscheinlich müsste sowas gehen
Ist aber nicht wirklich getestet
dice = [2,1,2,3,4]
ok = False
dice.sort()
for i in range(len(dice)-3):
cur = dice[i]
checkCur = True
for j in range(i+1,i+4):
if dice[j] == cur + 1:
cur += 1
else:
checkCur = False
break
if checkCur:
ok = True
break
print(ok)
Ne, funktioniert nicht.
[3,1,2,4,5]
gibt false aus.
Verstehe aber tbh deinen code nicht, daher weiß ich nicht was damit nicht stimmt.
Sind doch auch nicht vier in Folge, oder habe ich was falsch verstanden...?
Noch nie kniffel gespielt?
Da tust du alle würfel in einen würfelbecher, die haben keine reihenfolge.
Achso....dann hast du recht, dann ist mein code eigentlich nicht zu gebrauchen :/
Naja, du könntest davor dice.sort() benutzen um sie zu sortieren, wenn es sortiert funktioniert.
Testet aber auch nur auf kleine straße, oder?
Ja, das könnte funktionieren und ja, dass testet nur auf kleine Straße. Habe das sort() mal ergänzt
Hier eine Python 3.10 Lösung:
from itertools import pairwise
dice = sorted(set(dice))
streets = [[dice[0]]]
for x, y in pairwise(dice):
if y-x == 1:
streets[-1].append(y)
else:
streets.append([y])
m = max(map(len, streets))
In streets sind alle Straßen, m ist die Länge der längsten Straße
Ja die Reihenfolge ist egal. Hab aber ein anderes Problem gefunden:
Sobald der Würfel wie folg aussieht dice = [1,2,1,4,5] sortiert er diese und es sieht so aus dice = [1, 1, 2, 4, 5]]. Nun gibt er mir aus das es sich um eine kleine Straße handelt welche nicht der Fall ist.
Trotzdem danke für den Versuch ich werde dann vermutlich alle möglichen Möglichkeiten aufschreiben und die dann vergleichen.