Euler: Problem 54

Euler: Problem 54

Avtor: Sanja Milasinovic

Euler: Problem 54

Sanja Milasinovic

Besedilo naloge

In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way: • High Card: Highest value card. • One Pair: Two cards of the same value. • Two Pairs: Two different pairs. • Three of a Kind: Three cards of the same value. • Straight: All cards are consecutive values. • Flush: All cards of the same suit. • Full House: Three of a kind and a pair. • Four of a Kind: Four cards of the same value. • Straight Flush: All cards are consecutive values of same suit. • Royal Flush: Ten, Jack, Queen, King, Ace, in same suit. The cards are valued in the order: 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace. If two players have the same ranked hands then the rank made up of the highest value wins; for example, a pair of eights beats a pair of fives (see example 1 below). But if two ranks tie, for example, both players have a pair of queens, then highest cards in each hand are compared (see example 4 below); if the highest cards tie then the next highest cards are compared, and so on. Consider the following five hands dealt to two players: Hand Player 1 Player 2 Winner 1 5H 5C 6S 7S KD Pair of Fives 2C 3S 8S 8D TD Pair of Eights Player 2 2 5D 8C 9S JS AC Highest card Ace 2C 5C 7D 8S QH Highest card Queen Player 1 3 2D 9C AS AH AC Three Aces 3D 6D 7D TD QD Flush with Diamonds Player 2 4 4D 6S 9H QH QC Pair of Queens Highest card Nine 3D 6D 7H QD QS Pair of Queens Highest card Seven Player 1 5 2H 2D 4C 4D 4S Full House With Three Fours 3C 3D 3S 9S 9D Full House with Three Threes Player 1 The file, poker.txt , contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order, and in each hand there is a clear winner.

Postopek reševanja v Python-u


class Poker:
    def testni(self):
        f=open('poker.txt')
        self.lines=f.readlines()
        prviZmage=0
        drugiZmage=0
        for line in self.lines:
            #razdelimo karte
            karte=line.strip().split(' ')
            #za vsakega igralce izračunamo moč njegovih kart in zaporedje kart
            mocPrvi,kartePrvi=self.mocKart(karte[:5])
            mocDrugi,karteDrugi=self.mocKart(karte[5:])
            #pogledamo kateri je zmagal
            if mocPrvi>mocDrugi:
                prviZmage+=1
            elif mocDrugi>mocPrvi:
                drugiZmage+=1
            else:
                # izenačenje -> gledamo karte-od najvišje do najnižje
                for i in range(len(kartePrvi)-1,-1,-1):
                    #ko pride na vrsto prva karta v kateri se razlikujeta, se zanka konča
                    if kartePrvi[i]>karteDrugi[i]:
                        prviZmage+=1
                        break
                    elif karteDrugi[i]>kartePrvi[i]:
                        drugiZmage+=1
                        break

        print('Prvi je zmagal:',prviZmage)
        print('Drugi je zmagal:', drugiZmage)

    def mocKart(self,s):
        #s je seznam kart enega ali drugega igralca
        #numerično ocenimo moč enega ali drugega igralca
        #kako močna je posamezna kombinacija kart je navedeno spodaj
        """
        metoda vrne:
        High Card: 0
        One Pair: 1
        Two Pairs: 2
        Three of a Kind: 3
        Straight: 4
        Flush: 5
        Full House: 6
        Four of a Kind: 7
        Straight Flush: 8
        Royal Flush: 9
        poleg tega vrne tudi urejen seznam ostalih kart, v pomoč pri izenačenem izidu
        """
        #posebaj obravnavamo barve in številke
        #J, Q, K in A spremenimo v stevilke
        #s slovarjem si pomagamo spremeniti vse karte v številke
        pomozniSlovar={'2' : 2, '3': 3, '4' : 4, '5' : 5, '6' : 6, '7' : 7, '8' : 8, '9' : 9, 'T' : 10, 'J' : 11, 'Q' : 12, 'K' : 13, 'A' : 14}
        stevilke=[]
        barve=[]
        #razdelimo naše karte na s(številke) in b(barve)
        for s,b in s:
            stevilke.append(pomozniSlovar[s])
            barve.append(b)
            #številke sortiramo
        stevilke.sort()
        #preverimo če so številke zaporedne
        #začenmo z iskanjem 10 možnosti, ki so navedene zgoraj
        #pri vsaki razvejitvi problema (if zanki) imamo možnosti,
        #ki se lahko pojavijo pri tistem pogoju
        if self.zaporedne(stevilke):
            #možnosti, ki so lahko tukaj:4, 8, 9
            #preverimo ali so vse barve enake
            #ukaz set nam naredi množico števil in seznama števil
            #ce je torej dolžina set(barve) enaka 1. Pomeni da
            #imamo same enake barve v seznamu barve.
            if len(set(barve))==1:
                # možnosti: 8, 9
                if stevilke[-1]==14:
                    #če je najvišja karta as imamo možnost 9
                    return (9,stevilke)
                else:
                    #drugače je samo možnost 8
                    return (8,stevilke)
            else:
                #če pa vse barve niso enake, številke pa so vedno zaporedne
                #je možna samo možnost 4
                return (4,stevilke)
        elif len(set(barve))==1:
            #možnost:5
            #preverimo še možnost, ko številke niso zaporedne, vendar pa so vse iste barve
            return (5,stevilke)
        else:
            #če nič od zgoraj navedenega ne drži, začnemo iskati enake karte
            #možnosti:0, 1, 2, 3, 6, 7
            mnozice, pomembnost=self.zdruzi(stevilke)
            #v seznamu množice so torej shranjene samo tiste karte, ki se pojavijo 2 krat ali več
            if len(mnozice)==0:
                #če takih množic ni, potem štejejo samo karte
                return (0,pomembnost)
            elif len(mnozice)==1:
                #če je ena številka v množici, imamo lahko par,tris ali poker
                #možnosti:1, 3, 7
                if mnozice[0]==2:
                    return (1,pomembnost)
                elif mnozice[0]==3:
                    return (3,pomembnost)
                else:
                    return (7,pomembnost)
            else:
                #pri dveh številkah v množici nam ostanejo 2 možnosti
                # možnosti: 2, 6
                if 3 in mnozice:
                    #če je število 3 v množici potem imamo full house
                    return (6,pomembnost)
                else:
                    return (2,pomembnost)

    def zaporedne(self,s):
        # s je seznam številk
        #preverimo če so številke zaporedne
        #če slučajno razlika med 2 zaporednimi ni enaka 1, vrnemo False
        #če pa pridemo do konca for zanke pa vrnemo True(sej se številke med seboj razlikujejo za točno 1)
        for i in range(len(s)-1):
            if s[i + 1] - s[i] != 1:
                return False
        return True

    def zdruzi(self,s):
        # s je seznam številk
        l = [0]*15
        #v l shranimo število pojavitev vsake številke
        for i in s:
            l[i] += 1
        #vrnemo samo vrednosti tistih polj, kjer sta 2 ali več kart
        # poleg tega vrnemo tudi seznam vrednosti po katerih moramo preverjati karte,
        # ko sta moči enake (od najmanj pomembne do najbolj pomembne)
        vrni=[]
        for i in l:
            if i>=2:
                vrni.append(i)
        pomembne=[]
        #karte vračamo po pomebnosti, zato te karte razvrstimo po pomebnosti
        #začnemo s tisto ki se pojavi samo enkrat, nadaljujemo s tisto kis e pojavi dvakrat, ind.
        #druga for zanka nam naredi obhod po vseh kartah, začne pri 2 in konča pri as-u
        #tako doblejn seznam ima najvišjo karto na zadnjem mestu kar tudi preverjamo v __init__ metodi
        for i in range(1,5):
            for j in range(0, len(l)):
                if l[j]==i:
                    pomembne.append(j)

        return (vrni,pomembne)



Razlaga programa

Najprej naredimo program (mocKart(self,s)), ki nam pregleda moči kart. S je seznam kart enega ali drugega igralca. Številke in barve kart moramo posebej obravnavati, ter Jack, Queen, King, Ace pa spremenimo v številke. Se pravi imamo slovar. pomozniSlovar={'2' : 2, '3': 3, '4' : 4, '5' : 5, '6' : 6, '7' : 7, '8' : 8, '9' : 9, 'T' : 10, 'J' : 11, 'Q' : 12, 'K' : 13, 'A' : 14}

Razlaga(Kaj pomenijo posamezne številke, ko imamo možnosti v funkciji mocKart) High Card: 0 (Najvišja karta) One Pair: 1(En par-dve karti enake vrednosti) Two Pairs: 2(Dva para- dvakrat dve karti enake vrednosti) Three of a Kind: 3(tri karte enake vrednosti) Straight:4(pet zaporednih kart različne barve) Flush: 5(pet kart enake barve, kakršnihkoli vrednosti) Full House: 6(tri karte enake vrednosti in en par) Four of a Kind: 7(štirih kart enake vrednosti) Straight Flush: 8(pet zaporednih kart enake barve) Royal Flush: 9(deset, fant, kraljica, kralj, as enake barve)

Naredimo še funkcijo za združitev(združi(self,s)). Se pravi, da v seznam shranimo pojavitev vsake številke. Na koncu naredimo še testni program, ki nam bo izpisal končno vrednost posameznega igralca.

Ta testni program smo si izbrali, ker nam izračuna za vsakega igralca posebej moč kart. Pri tem pa nam program ustrezno preveri kakšne karte ima posamezni igralec. In glede na to nam vrne rezultat dveh igralcev.

0%
0%