Seite 1 von 1

Datenstruktur für Lottozahl

Verfasst: Donnerstag 21. August 2014, 13:28
von lackschuh
Hallo,

Ich bräuchte mal einen Tipp für eine geeignete Datenstruktur um Lottozahlen inkl. Zusatzzahl zu speichern, damit diese mit den Gewinnzahlen verglichen werden können. Momentan benutze ich verschachtelte Listen:

Code: Alles auswählen

gewinn_zahlen = [14, 20, 28, 29, 31, 41, [5]]
meine_zahlen = [
                [22, 26, 29, 33, 35, 47, [2]],
                [12, 32, 2, 26, 3, 36, [6]],
                ]
Mir geht es darum, wie ich das mit der Zusatzzahl am besten handhaben könnte. Was wäre eine bessere Alternative?

mfg

Re: Datenstruktur für Lottozahl

Verfasst: Donnerstag 21. August 2014, 13:39
von BlackJack
@lackschuh: Ich würde das je eher anders herum machen, die 6 normalen in einer Liste zusammenfassen und die Zusatzzahl einzeln lassen: ``[[14, 20, 28, 29, 31, 41], 5]``. Dann lässt sich das deutlich einfacher vergleichen ohne Teillisten per slicing kopieren zu müssen. Ohne Zusatzzahl ``a[0] == b[0]`` und mit Zusatzzahl ``a == b``. Insbesondere eine Liste die immer nur ein Element enthält mach nicht so viel Sinn. Ansonsten könnte man auch ein Wörterbuch oder gar eine Klasse schreiben, oder zumindest ein `collections.namedtupel` erzeugen.

Re: Datenstruktur für Lottozahl

Verfasst: Donnerstag 21. August 2014, 14:54
von fail
Ich würde ein Set nehmen, da dort Objekte nur einmal vorkommen dürfen und man einfach sehen kann, ob die gespielten Zahlen ein Subset der gezogenen Zahlen ist

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 22. August 2014, 08:54
von lackschuh
Danke mal für die Tipps. Vergleichen tue ich momentan es so:

Code: Alles auswählen

for tip in meine_zahlen:
    print set(tip[0]) & set(gewinn_zahlen[0]), tip[1] == gewinn_zahlen[1]
Ist aber nicht sehr elegant und zudem gibt es erst ab 3 richtige Zahlen Kohle. Was müsste ich beachten, so dass nur ab 3 übereinstimmenden Zahlen eine 'print' Anweisung gemacht wird und kann man die 'print' Ausgabe der sets formatieren(?), denn so sieht es nicht übersichtlich aus:

Code: Alles auswählen

>> set([14]) False
>> set([41]) False
>> set([41]) True
>> set([14, 31]) True

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 22. August 2014, 10:07
von Sirius3
@lackschuh: hast Du schonmal was von len gehört?

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 22. August 2014, 10:26
von lackschuh
Ja, ist der Börsenkürzel von Lennar Corporation :wink:

Code: Alles auswählen

if len(set(tip[0]) & set(gewinn_zahlen[0])) >= 3:
Aber wie lasse ich 'set([])' verschwinden und stattdessen einfach die Zahlen anzeigen lassen?

Danke

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 22. August 2014, 12:01
von BlackJack
@lackschuh: Falls ich die Frage richtig verstanden habe: In dem Du Code schreibst der aus den Werten eine Zeichenkette erstellt die Deinen Vorstellungen entspricht, statt einfach Datenstrukturen auszugeben und deren Zeichenkettenrepräsentation zu verwenden. Das ist für Programmierer und die Fehlersuche gedacht, nicht um dem Endbenutzer etwas zu zeigen.

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 22. August 2014, 12:48
von lackschuh
Danke, anbei sieht es nun so aus:

Code: Alles auswählen

# coding: utf-8

import requests
from bs4 import BeautifulSoup

URL = "https://www.swisslos.ch/swisslotto/home.do"
lotto_zahl = []
lotto_zahlen = []
count = 0

html = requests.get(URL)
soup = BeautifulSoup(html.text)

for label in soup.select('li.numberLarge'):
     lotto_zahl.append(int(label.string))

zusatz_zahl = lotto_zahl[-1]
lotto_zahlen.append(lotto_zahl)
del lotto_zahl[-1]
lotto_zahlen.append(zusatz_zahl)

#gewinn_zahlen = [[14, 20, 28, 29, 31, 41], 5]

meine_zahlen = [
                [[9, 17, 20, 25, 26, 29], 2],
                [[1, 8, 16, 21, 32, 37], 6],
                [[15, 20, 34, 35, 36, 39], 5],
                [[14, 20, 29, 12, 14, 25], 5],
                ]


for tipp in meine_zahlen:
    if len(set(tipp[0]) & set(lotto_zahlen[0])) >= 3:
        count = count + 1
        richtige = set(tipp[0]) & set(lotto_zahlen[0])
        print '%d. Tipp:' % count, "%d richtige Zahlen %s," % (len(list(richtige)), list(richtige)), 'Zusatzzahl', tipp[1] == lotto_zahlen[1]
    else:
        count = count + 1
        print '%d. Tipp:' % count, 'Leider kein Gewinn'

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 22. August 2014, 13:06
von Hyperion
Also da sind einige Dinge noch unschön...

- Statt

Code: Alles auswählen

zusatz_zahl = lotto_zahl[-1]
del lotto_zahl[-1]
würde man ``list.pop`` nutzen:

Code: Alles auswählen

zusatz_zahl = lotto_zahlen.pop(-1)
- Wenn man einen zusätzlichen Zähler/Index in einer Schleife braucht, dann sollte man ``enumerate`` nutzen!

Code: Alles auswählen

for count, tipp in enumerate(meine_zahlen, 1):
- Wenn man Strings mit Platzhaltern nutzt, dann doch bitte "am Stück". Bisher sind die Platzhalter wenig sinnvoll und tragen nicht zur Lesbarkeit bei.

Code: Alles auswählen

'%d. Tipp: %d richtige Zahlen %s, Zusatzzahl %d' % ...
- Wieso die umständliche Umwandlung``(len(list(richtige))``? ``len`` kann man auch auf ``sets`` anwenden ;-)

- Der ``len`` Ausdruck in der ``if``-Bedingung wird darunter *exakt* noch einmal wiederholt. Zieh die Prüfung doch vor das ``if`` und schon hast Du ein wenig Redundanz weniger.

- Die Namensgebung ist imho inkonsistent: Wenn doch ``meine_zahlen`` eigentlich Tipps sind, wieso dann nicht ``meine_tipps``? Oder andersherum in der ``for``-Schleife eben ``for zahl in meine_zahlen``.

- Generell Code von Modulebene in Funktionen verlagern.

- Du vermischst hier noch zu viel Code miteinander. Ich würde mir für die Auswertung ggf. auch eine Struktur überlegen und die Ausgabe davon separieren. Dazu dann eine Funktion zum Holen und Parsen der richtigen Ergebnisse und schon bist Du viel flexibler bezüglich der Nutzung.

Re: Datenstruktur für Lottozahl

Verfasst: Sonntag 24. August 2014, 14:57
von BlackJack
@lackschuh: Zu den Namen wurde ja schon etwas gesagt. `lotto_zahl` (Einzahl) für eine Liste mit Zahlen (Mehrzahl) ist irreführend. Etwas präzisere Bezeichnungen wie Tipp und Ziehung statt allgemein Zahl(en) würden das Programm verständlicher machen.

Auch ungünstig ist das definieren von Namen lange bevor sie tatsächlich benötigt werden. Dann muss man dort nämlich erst wieder weiter oben suchen was die eigentlich für Startwerte haben. Es erschwert auch das spätere aufteilen in einzelne Funktionen wenn nicht der zusammengehörende Code beisammen steht und man sich erst alles über den Code verteilt zusammen suchen muss.

Die Tipps umgesetzt könnte das ungefähr so aussehen:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
import requests
from bs4 import BeautifulSoup
 
URL = 'https://www.swisslos.ch/swisslotto/home.do'


def hole_ziehung():
    soup = BeautifulSoup(requests.get(URL).text)
    lottozahlen = [
        int(n.string) for n in soup.select('div#actualNumbers li.numberLarge')
    ]
    result = [lottozahlen]
    result.append(lottozahlen.pop())
    return result


def vergleiche(tipp, ziehung):
    return (sorted(set(tipp[0]) & set(ziehung[0])), tipp[1] == ziehung[1])


def main():
    ziehung = hole_ziehung()
    tipps = [
        [[9, 17, 20, 25, 26, 29], 2],
        [[1, 8, 16, 21, 32, 37], 6],
        [[15, 20, 34, 35, 36, 39], 5],
        [[14, 20, 29, 12, 14, 25], 5],
    ]

    for tipp_nr, tipp in enumerate(tipps, 1):
        print('{0}. Tipp:'.format(tipp_nr), end=' ')
        richtige, ist_zusatzzahl_richtig = vergleiche(tipp, ziehung)
        if len(richtige) >= 3:
            print(
                '{0} richtige Zahlen {1}, Zusatzzahl: {2}.'.format(
                    len(richtige),
                    ', '.join(richtige),
                    'ja' if ist_zusatzzahl_richtig else 'nein'
                )
            )
        else:
            print('Leider kein Gewinn')


if __name__ == '__main__':
    main()

Re: Datenstruktur für Lottozahl

Verfasst: Montag 25. August 2014, 08:50
von lackschuh
Vielen Dank für die Tipps.

Ich benutze Python 2.7.
Was bedeutet ''from __future__ import print_function''?
Wenn ich dies auskommentiere, dann wird mir zB bei ''print('Leider kein Gewinn')'' ein Fehler angezeigt, wenn ich bei dieser print-Anweisung die Klammern entferne. Ist dies (__future__) vereinfacht gesagt das, was bei Python3 die print-Funktion neu ist?

Des Weiteren wurde noch gemeckert, dass bei ''''.join(richtige)'' ein String erwartet wird. ''''.join(str(richtige))''

Re: Datenstruktur für Lottozahl

Verfasst: Montag 25. August 2014, 08:57
von BlackJack
@lackschuh: Der `__future__`-Import macht aus ``print`` eine Funktion.

Ich hätte es mit Treffern testen sollen. :-) Nein, natürlich darf man nicht die Datenstruktur `richtige` in *eine* Zeichenkette umwandeln, sondern muss die einzelnen Elemente umwandeln die man dann mit `join()` zusammenfügen möchte:

Code: Alles auswählen

                    ', '.join(map(str, richtige)),

Re: Datenstruktur für Lottozahl

Verfasst: Montag 25. August 2014, 11:38
von Malta
Ich habe mir auch schon mal Gedanken über ein Lottoprogramm gemacht, vielleicht kannst du daraus neue Erkenntnisse gewinnen:

https://github.com/MarkusHackspacher/pyLottoverwaltung

Re: Datenstruktur für Lottozahl

Verfasst: Montag 25. August 2014, 21:21
von darktrym
Ich würde das Projekt sicher nicht als Beispiel für guten Code sehen.
Besser er schaut nicht da rein, sonst schaut er sich wirklich noch was ab.

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 24. Oktober 2014, 15:30
von lackschuh
Hallo

Ich hab das Programm für ein anderes Lotto-System ein wenig umgeschrieben. Bei diesem System gibt es folgendes zu beachten für ein Gewinn:
Zahl (max 5) + Stern (max 2)
Gewinn ab 1 Zahl + 2 Sterne, zwei Zahlen + 0 Stern.

Nun habe ich zweimal die gleiche Print-Anweisung und eine 'if', 'elif' und 'else' Abfrage. Gäbe es eine Möglichkeit, dies alles zu verkürzen bzw zu vereinfachen?

mfg

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8

from __future__ import print_function
import requests
from bs4 import BeautifulSoup

URL = 'http://www.euro-millionen.org'


def hole_ziehung():
    soup = BeautifulSoup(requests.get(URL).text)
    lottozahlen = [
                   int(n.string) for n in soup.select('div#results-content li')
                   ]
    result = [lottozahlen]
    zusatz_zahlen = []
    zusatz_zahlen.append(lottozahlen.pop(-2,))
    zusatz_zahlen.append(lottozahlen.pop(-2,))
    result.append(zusatz_zahlen)
    return result


def vergleiche(tipp, ziehung):
    return sorted(set(tipp[0]) & set(ziehung[0])), sorted(set(tipp[1]) & set(ziehung[1]))


def main():
    #ziehung = hole_ziehung()
    ziehung = [[20, 21, 27, 33, 40], [2, 6]]
    print(ziehung)
    tipps = [
        [[1, 5, 21, 33, 48], [2, 6]],
        [[14, 20, 32, 33, 40], [3, 7]],
      ]

    for tipp_nr, tipp in enumerate(tipps, 1):
        print('{0:>1}. Tipp:'.format(tipp_nr), end=' ')
        richtige, sind_sterne_richtig = vergleiche(tipp, ziehung)

        if len(richtige) >= 1 and len(sind_sterne_richtig) == 2:
            print('{0} richtige Zahlen: "{1}": Sterne: "{2}"'.format(
                                                                     len(richtige),
                                                                     ', '.join(map(str, richtige)),
                                                                     '{0}'.format(', '.join(map(str, sind_sterne_richtig))) if sind_sterne_richtig else 'falsch'
                                                                     )
                  )

        elif len(richtige) >= 2:
            print('{0} richtige Zahlen: "{1}": Sterne: "{2}"'.format(
                                                                     len(richtige),
                                                                     ', '.join(map(str, richtige)),
                                                                     '{0}'.format(', '.join(map(str, sind_sterne_richtig))) if sind_sterne_richtig else 'falsch'
                                                                     )
                  )

        else:
            print('Leider kein Gewinn')


if __name__ == '__main__':
    main()

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 24. Oktober 2014, 17:58
von Sirius3
@lackschuh: in dem Du die beiden if per or in eines packst. Noch besser schreibst Du Dir eine Funktion, die ermittelt, ob gewonnen wurde oder nicht.

Re: Datenstruktur für Lottozahl

Verfasst: Freitag 8. Mai 2015, 09:23
von lackschuh
Hallo

Die Seite http://www.euro-millionen.org/ wurde umgebaut.
Die Sterne bekomme ich als Liste mit:

Code: Alles auswählen

[int(n.string) for n in soup.select('li.star')]
Da in der untergeordneterer Liste nochmals eine Liste ``<li class="star">`` drinsteht, habe ich gerade Mühe, alles auf einmal zu parsern. Ideal wäre als Resultat eine verschachtelte Liste [[1, 10, 17, 20, 42], [8, 9]]. Für einen Tipp wäre ich dankbar :wink:

Code: Alles auswählen

<ul class="numbers">
<li>
                        1                    </li>
<li>
                        10                    </li>
<li>
                        17                    </li>
<li>
                        20                    </li>
<li>
                        42                    </li>
<li class="star">
                        8                    </li>
<li class="star">
                        9                    </li>
</ul>