Frage zur Pokeraufgabe

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

yipyip hat geschrieben:Obwohl ich die Funktion 'pairwise' gestrichen und einfach nur

Code: Alles auswählen

def straight(hand):
  return all(a+1 == b for a, b in izip(hand, hand[1:]))
geschrieben haette.
Jo. Hab ich wiedermal zu kompliziert gedacht...
all(...) ist auch schöner, weil deklarativer.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

pillmuncher hat geschrieben:Meinst du algorithmisch oder die Verwendung von Tupeln statt einer Karten-Klasse? Falls ersteres, damit wollte ich ein bisserl pädagogisch werden, denn um es zu verstehen muss man set, len, itertools und generator expressions kennen (-lernen).
Ersteres. Ich seh da ein Problem mit der Lernbereitschaft des OP ;)
pillmuncher hat geschrieben:
ice2k3 hat geschrieben:Edit: Das funktioniert aber nur, wenn ``hand`` nach dem Wert aufsteigend sortiert ist, oder hab ich was übersehen?
Hast du nicht, aber da im Originalcode ja schon sortiert wurde, habe ich das vorausgesetzt..
Da aber noch gemischelt wird/werden sollte, ist es ja nicht mehr sortiert.
In *deinem* Orginalcode war es allerdings sortiert, da hast du Recht ;)
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

ice2k3 hat geschrieben:
pillmuncher hat geschrieben:... um es zu verstehen muss man set, len, itertools und generator expressions kennen (-lernen).
Ich seh da ein Problem mit der Lernbereitschaft des OP ;)
Ich denke, er wollte sich wohl nur vor Überforderung schützen. Es ist zudem auch schwierig zu verstehen, warum man etwas ändern soll, wenn es doch schon funktioniert. Dass das Funktionieren nicht das Problem ist, sondern die Eleganz / Kürze / "Pythonizität", lernt man erst mit der Zeit. Man sollte demgegenüber vielleicht etwas Langmut zeigen. Hängt bei mir aber von der Tageslaune ab.
ice2k3 hat geschrieben:
pillmuncher hat geschrieben: ...da im Originalcode ja schon sortiert wurde, habe ich das vorausgesetzt..
Da aber noch gemischelt wird/werden sollte, ist es ja nicht mehr sortiert.
In *deinem* Orginalcode war es allerdings sortiert, da hast du Recht ;)
Ich meinte dies hier:

Code: Alles auswählen

    for i in range(Anzahl):
        Karten=[]
        for f in range(5):
            e=e-1
            a=random.randint(0,e)
            Karten=Karten+[Liste[a]]
            del Liste[a]
        Karten.sort() # <--
Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Ich habe für unser Pokerprojekt eine Auswertung geschrieben:

http://paste.pocoo.org/show/147600/

Kritik (ausgenommen Kleinigkeiten) gerne erwünscht :)
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

me too. <-- [edit] neuer link, diesmal hoffentlich mit der richtigen Poker-Terminologie. [/edit]

Bemerkenswert, wie verschiedene Leute auch unterschiedlich an so ein Problem herangehen. Meine Variante ist völlig un-OO, fast schon Scheme-atisch.

Gruß,
Mick.
Zuletzt geändert von pillmuncher am Samstag 31. Oktober 2009, 12:19, insgesamt 1-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Falls ihr euch immer noch nicht ausgetobt habt mit der Poker-Geschichte, habt ihr vielleicht ja noch Lust darauf: https://www.spoj.pl/problems/POKER/
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Hm, das ganze ist schwieriger als ich dachte. Ich nutze Python 3.1, um die Unicode-Zeichen für Pik, Herz, usw. in repr-Strings benutzen zu können. Ich definiere auf den Karten eine Ordnung (`index`) die gemäß meiner 1-Minuten-Recherche der Poker-Rangfolge entspricht. Diese Ordnung nutze ich bei der Suche nach der richtigen Kombination. Um die Reihenfolge der Hände zu bestimmen und dann im nächsten Schritt die beste Hand zu bestimmen, muss ich jetzt für jede Hand eine Zahl und somit wieder eine Ordnung bestimmen. Gemäß der Aufgabenstellung ist das aber nicht eindeutig, denn was ist, wenn zwei Hände beide ein König-Paar haben? Kommt da Herz vor Karo? Oder zählt die höchste Beikarte? Und was ist, wenn diese Teil des Paars ist? Da ich das nicht recherchieren wollte, habe ich den Teil weggelassen und nur angedeutet, wie ich's berechnen würde.

Code: Alles auswählen

#!/usr/bin/env python3.1

import random

class Card:
    def __init__(self, index):
        self.index = index
    
    @property
    def rank(self):
        return self.index // 4
    
    @property
    def suite(self):
        return self.index % 4

    def __repr__(self):
        rank = "234567890JQKA"[self.rank]
        if rank == "0": rank = "10"
        suite = "\u2660\u2663\u2666\u2665"[self.suite]
        return rank + suite


class Hand:
    def __init__(self, cards):
        self.cards = sorted(cards, key=lambda c: c.index)

    def __repr__(self):
        return repr(self.cards)

    def ranking(self):
        """
        highest card: index (0..51)
        1 pair:       rank * 100 + highest card (100..1251)
        2 pairs:      highest rank + 1300 (1300..1312)
        3 of a kind:  rank + 1400 (1400..1412)
        straight:     suite + 1500 (1500..1503)
        flush:        suite + 1600 (1600..1603)
        full house:   rank + 1700
        4 of a kind:  rank + 1800
        str. flush:   suite + 1900
        royal flush:  suite + 2000
        """
        if self.is_royal_flush(): return "royal flush"
        if self.is_straight_flush(): return "straight flush"
        if self.is_four_of_a_kind(): return "4 of a kind"
        if self.is_full_house(): return "full house"
        if self.is_flush(): return "flush"
        if self.is_straight(): return "straight"
        if self.is_three_of_a_kind(): return "3 of a kind"
        if self.is_two_pairs(): return "two pairs"
        if self.is_pair(): return "pair"
        return "highest card"
    
    def is_flush(self):
        return len(set(c.suite for c in self.cards)) == 1
    
    def is_straight(self):
        ranks = [c.rank for c in self.cards]
        return ranks == list(range(ranks[0], ranks[0] + 5))
    
    def is_straight_flush(self):
        return self.is_flush() and self.is_straight()
    
    def is_royal_flush(self):
        return self.is_straight_flush() and self.cards[4].rank == 12

    def kinds(self):
        ranks = {}
        for c in self.cards:
            ranks[c.rank] = ranks.get(c.rank, 0) + 1
        return ranks.values()

    def is_n_of_a_kind(self, n, but_not=13):
        if but_not is None:
            return None
        kinds = {}
        for c in self.cards:
            kinds[c.rank] = kinds.get(c.rank, 0) + 1
        for rank, occurences in kinds.items():
            if rank != but_not and occurences >= n:
                return rank
    
    def is_pair(self, but_not=13):
        return self.is_n_of_a_kind(2, but_not=but_not)
    
    def is_two_pairs(self):
        return self.is_pair(but_not=self.is_pair())

    def is_three_of_a_kind(self):
        return self.is_n_of_a_kind(3)

    def is_four_of_a_kind(self):
        return self.is_n_of_a_kind(4)
        
    def is_full_house(self):
        return self.is_pair(but_not=self.is_three_of_a_kind())

cards = [Card(i) for i in range(52)]
#print(cards)
random.shuffle(cards)
#print(cards)
hands = [Hand(cards[i:i+5]) for i in range(0, 50, 5)]
#print(hands)
print([repr(hand) + " " + hand.ranking() for hand in hands])
Stefan
Zuletzt geändert von sma am Sonntag 1. November 2009, 09:51, insgesamt 1-mal geändert.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Die Farbe ist egal. Es werden maximal 5 Karten ausgewertet. Das heißt bei einer Highcard entscheiden dann nach und nach die einzelnen Karten wer gewinnt.

Du musst beachten, dass bei der Straße das Ass als "1" und als "Ass" gelten kann.

Ich hab meine Lösung auf "Texas Holdem" ausgelegt, bei der man die besten 5 aus 7 Karten ermittelt. Weshalb auch manche Auswertungsschritte komplexer werden.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

jbs hat geschrieben:Ich hab meine Lösung auf "Texas Holdem" ausgelegt, bei der man die besten 5 aus 7 Karten ermittelt. Weshalb auch manche Auswertungsschritte komplexer werden.
Das hab ich inzwischen auch gemacht. Hatte ich zuerst weggelassen, weil ich dachte, dass es kompliziert wird, aber dank itertools.combinations wars dann überraschend einfach. Einfach alle möglichen 5 aus 7 erzeugen und dann die Bewertungsfunktion darauf anwenden, mit der ich auch den Sieger ermittle. Muss mal überlegen, ob man vielleicht einen frühen Abbruch einbauen könnte.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Mal eine andere Frage: Sollte man unter Python 3.1 aus nostalgischen Gründen Klassen von ``object`` erben lassen? Der Code wäre dann immerhin besser rückwärts kompatibel.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

jbs hat geschrieben:Mal eine andere Frage: Sollte man unter Python 3.1 aus nostalgischen Gründen Klassen von ``object`` erben lassen?
Aus nostalgischen Gründen sicher nicht. Wenn du den Code gleichzeitig 2.x und 3.x kompatibel halten willst, ja (aber dann muss er wirklich kompatibel sein und nicht "besser kompatibel" aber nicht wirklich auf 2.x lauffähig). Ansonsten: nein.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Wenn Code zu 2 und 3 kompatibel sein soll, dann würde ich den umgekehrten Weg gehen: In 2.6 programmieren und das so, dass sie 3er Quellen automatisch per 2to3.py erstellt werden können.
Nickl
User
Beiträge: 8
Registriert: Dienstag 27. Oktober 2009, 10:12

numerix hat geschrieben:
Nickl hat geschrieben:und das mitm mischen is doch voll ok und kein problem so wie wir es gemacht haben!
Du bezeichnest dich als Laien, hast hier die Chance, kostenlos Expertenrat zu bekommen und bügelst das einfach weg, weil es "voll ok" ist, wie du es als Laie gemacht hast. :roll:

Der von dir gezeigte Code ist ganz überwiegend so, dass jemand, der kein Laie (mehr) ist, es so nicht machen würde.
nein ich bügel das nicht einfach weg, ich wollt damit sagen das ich das völlig ok finde so wie ich es gemacht hab weil wie mir das hier erklärt wird konnte ich es nicht nachvollziehen.
Sry ich arbeite halt noch nicht so lange mit python und orientier mich da nicht so schnell ich wär glücklich damit wenn ich die aufgabe iwann mal hinbekomme egal wie ellen lang sie ist.
Ich bin glücklich darüber das ich hier soeine profesionelle hilfe bekommen!

So und jetzt muss ich mir mal die restlichen forumbeiträge mal durchlesen :)
Nickl
User
Beiträge: 8
Registriert: Dienstag 27. Oktober 2009, 10:12

hey ich hab da noch ne frage zu deiner programmierung hab die durchgeguckt aber ich kenn nur tupel und nicht namedtupel was ist er unterschied?
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Nickl hat geschrieben:hey ich hab da noch ne frage zu deiner programmierung hab die durchgeguckt aber ich kenn nur tupel und nicht namedtupel was ist er unterschied?
Kleiner Tipp: Wenn du den Text quotest, auf den du dich beziehst, oder wenigstens ein @soundso: vor deine Frage stellst, muss man nicht erst lange überlegen, an wen du deine Frage wohl richtest.

Auf die Elemente eines Tupels kann man nur mittels Index zugreifen, also zB. so:

Code: Alles auswählen

mytup = (7,6,5)
x = mytup[1]
assert x == 6
Auf die Elemente eine namedtuples auch so:

Code: Alles auswählen

Tup = namedtuple("Tup", ["foo", "bar", "baz"])
yourtup = Tup(foo=7, bar=6, baz=5)
x = yourtup.bar
assert x == 6
# namedtuples sind auch tuples:
y = yourtup[1]
assert y == 6
Ich hab namedtuple verwendet, weil ich lediglich eine dumme Datenklasse ohne Methoden gebraucht habe. Und Buchstaben sparen wollte, so wie du Satzzeichen. :wink:

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Antworten