Problem mit summen in tupeln

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.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Dienstag 12. Juni 2007, 13:43

Argh. Doch. Reduce ist unglaublich langsam, das lässt sich sogar mit einer Python only Implementierung schlagen Oo:

Code: Alles auswählen

def calculate_hand(cards):
    tmp = [0]
    for c in cards:
        tmp = [v + c for v in tmp] + (c == 1 and [v + 10 for v in tmp] or [])
    return sorted(set(tmp))
In etwa doppelt so schnell.
(Wenn man den and/or Trick vermeidet muss man eine Kopie von tmp anlegen, das macht die Sache dann langsamer)

//EDIT: wenn man die vielen set instanzierungen rausnimmt nähern sie sich an.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Dienstag 12. Juni 2007, 14:09

Darum wird es reduce auch bald nicht mehr geben :)
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Mittwoch 13. Juni 2007, 07:29

Moin,

dann war mein Ansatz
=((n-a)*x + a*y) # für jedes a der Menge 0..n
ja doch nicht so falsch. :-)

Was haltet ihr von dieser Variante:

Code: Alles auswählen

def calc_hand(l):
    n = l.count(1)
    return map(sum, zip([sum(l)-n]*(n+1), (9*a+n for a in range(n+1))))

l = [4, 1, 7, 10, 1]
calc_hand(l)
# [23, 32, 41]
Ich habe die normalen Zahlen aufsummiert, dann nach der obigen Vorschrift die Variationen aus den n (1, 10) Tupeln ermittelt und dann diese Tupel summiert.

Wie geht das eigentlich mit der Geschwindigkeitsmessung? Wo liegt die Lösung?

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Dienstag 19. Juni 2007, 06:24

Hi Jo!
jo_hb hat geschrieben:Also worum es dabei geht: tatsächlich um Blackjack! :)
Du hast es aber mit Glücksspielen. :lol:
jo_hb hat geschrieben:Das mit den tupeln für alle Karten, also auch zB (4,4) liegt daran dass ich mir dachte es wäre dann irgendwie einfacher, wenn ass und andere Karten sozusagen im selben format / typ vorliegen, aber vielleicht geht's dann anders doch einfacher?

Danke jedenfalls schonmal für eure Hilfe,
Ich habe noch einmal versucht, meinen Ansatz hinsichtlich der Berechnungsgeschwindigkeit für den mehrfachen Aufruf zu optimieren - d. h. möglichst viel aus der Funktion auszulagern, was nur einmal berechnet werden muss. Da die Kombinationsmöglichkeiten aufgrund der Austauschbarkeit der Asse in der Zählung doch arg begrenzt sind und es nur 8 Asse = 9 Möglichkeiten (0-8 auf der Hand) gibt, kann man alle Kombinationen schonmal vorher abspeichern. Sowas nennen die Hacker doch "Rainbow-Table", oder? :-)

Hier mal mein Ansatz:

Code: Alles auswählen

#   Mapping Dictionary berechnen, das fuer die Anzahl der Asse die
#   moeglichen Punktzahl-Kombinationen liefert
dMap = {}
for iAces in xrange(9):
    dMap[iAces] = [(9 * i + iAces) for i in xrange(iAces+1)]
print dMap
    
def calc_hand(lCards):
    "Berechnung der Punktzahl-Kombinationen aus Assen und zusammengezogenem Rest"
    iAces = lCards.count(1)
    iStaticValue = sum(lCards)-iAces
    return map(lambda iDynValue: iDynValue + iStaticValue, dMap[iAces])

l = [4, 1, 7, 10, 1]
print calc_hand(l)
Aber da habe ich auch eine Frage: was ist schneller, in calc_hand die Lambda-Funktion zu erzeugen oder doch alternativ mit zip eine Liste von Tupeln, die man per map(sum...) aufsummiert? Dann muss man aber aus iStaticValue auch erst eine Liste oder einen Generator machen...

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten