Euler Problems 54 to 60

# problem 54

def winner_calc(pointz1, pointz2, value_of_hand1, value_of_hand2, hi_card1, hi_card2):
        global winner

        if pointz1 < pointz2:
                return winner
        elif pointz1 > pointz2:
                ''' compare points '''
                winner += 1
                return winner
        elif pointz1 == pointz2 and value_of_hand1 > value_of_hand2:
                winner += 1
                return winner
        elif value_of_hand1 == value_of_hand2 and hi_card > hi_card2:
                winner += 1
                return winner
        elif value_of_hand1 == value_of_hand2 and hi_card == hi_card2:
                return winner
        else:
                return winner


def values(cards, rank):
        '''list of card rank
        ['A'} -> [14] '''
        lst =[]
        for item in cards:
                lst.append(rank[item])
        return lst


def card_values(hand):
        ''' list of values in hand
        ['TS'] -> ['T']'''
        values = []
        for item in hand:
                values.append(item[:-1])
        return values

def txt_feed():
        file = open('poker.txt', 'r')
        for line in file:
                line = line.strip('\n')
                line = line.split()
                if not line:
                        break
                yield line

def card_suits(hand):
        ''' list of suits in hand
         ['TS', 'TD'] -> ['S', 'D'] '''
        suits = []
        for item in hand:
                suits.append(item[-1])
        return suits


def card_count(hand, target):
        ''' card counter '''
        card_count = 0
        for card in hand:
                if card[-1] == target:
                        card_count += 1
        return card_count


def all_same( items ):
        return len(set(items)) == 1


def points_calc(hand, rank, flsh, royal):

        global hi_card
        global top_card
        global reserve
        item1 = None

        suits = card_suits(hand) # ['C', 'H',.....]
        val = card_values(hand)  # ['2', 'K', ..........]
        cardvalue = values(val, rank)  # ['2', '14', ......]
        suit = all_same(suits)          # check if one suit

        #-- Royal Flush --------------

        # perm to find if the hand equates to a Royal Flush

        chk = False
        for L in range(5, len(val)+1):
                for subset in itertools.permutations(val, L):
                        if set(subset) == set(royal):
                                chk = True

        if suit == True and chk == True:
                hi_card = 13
                top_card = 14
                points = 10
                return points


        #-- Straight Flush -------------------------

        # check all cards are of the same suit

        chk = False
        for L in range(5, len(val)+1):
                for subset in itertools.permutations(val, L):
                        subset = list(subset)
                        if ''.join(subset) in ''.join(flsh):
                                chk = True

        #  check if cards are consecutive.

        if suit and chk:
                cardvalue = sorted(cardvalue)
                cardvalue = cardvalue[::-1]
                hi_card = cardvalue[1]
                top_card = cardvalue[0]
                points = 9
                return points

        #-- Four of a kind ----------------------------

        # check for cards of the same value, a list of 4 and 1 required.


        #-- check for four of the same value
        for item in cardvalue:
                num = cardvalue.count(item)
                if num == 4:
                        item1 = item
                        top_card = item1
                        points = 8
                elif num == 1:
                        hi_card = item
                if num == 1 and top_card == item1:
                        return points

        #-- Three of a kind and a pair ----------------

        temp = set()

        # check for three and two of a kind
        for item in cardvalue:
                num = cardvalue.count(item)
                if num == 3 or num == 2:
                        temp.add(num)

                if num == 3:
                        item1 = item
                        top_card = item1

                for x in cardvalue:
                        if cardvalue.count(x) == 2:
                                hi_card = x

        if temp == {2, 3} or temp == {3, 2}:
                points = 7
                return points

        #-- Flush ----------------------------------

        suit_lst = []

        # check first item in suit equals the remainder
        for item in hand:
                suit_lst.append(item[-1])

        if suit_lst.count(suit_lst[0]) == 5:
                cardvalue = sorted(cardvalue)
                cardvalue = cardvalue[::-1]
                hi_card = cardvalue[1]
                top_card = max(cardvalue)
                points = 6

                return points

        #-- Straight ------------------------------

        chk = False

        # check all cards are consecutive values
        for L in range(5, len(val)+1):
                for subset in itertools.permutations(val, L):
                        if ''.join(subset) in ''.join(flsh):
                                chk = True
                                cardvalue = sorted(cardvalue)
                                cardvalue = cardvalue[::-1]
                                hi_card = cardvalue[1]
                                top_card = cardvalue[0]

        if chk:
                points = 5
                return points

        #-- Three of a kind -----------------------------

        temp = set()

        suits = card_values(hand)

        # count equal value cards
        for item in suits:
                num = suits.count(item)
                if num == 3:
                        points = 4

                        for x in cardvalue:
                                        if cardvalue.count(x) == 3:
                                                top_card = x

                        temp = set()
                        for x in cardvalue:
                                if cardvalue.count(x) == 1:
                                        temp.add(x)
                        hi_card = max(temp)

                        return points


        #-- Two pairs -------------------------------------

        temp = set()

        # check if there are two of each item
        for item in cardvalue:
                num = cardvalue.count(item)
                if num == 2:
                        temp.add(item)

                if len(temp) == 2:
                        points = 3
                        top_card = max(temp)
                        hi_card = min(temp)
                        return points

        #-- One pair -------------------------------------

        temp = set()

        for item in cardvalue:
                num = cardvalue.count(item)
                if num == 2:
                        temp.add(item)

                        top_card = max(temp)
                        points = 2
                        y = max(temp)
                        cardvalue_temp = cardvalue
                        cardvalue_temp = [x for x in cardvalue_temp if x != y]
                        hi_card = max(cardvalue_temp)
                        return points

        #-- High card ----------------------------------

        b = []
        for x in range(0, len(val)):
                b.append(card_rank[val[x]])

        b = sorted(b)
        b = b[::-1]
        hi_card = b[1]
        top_card = b[0]
        reserve = b[2]
        points = 1

        return points
#==============================================================================



if __name__ == '__main__':

        import itertools
        winner = 0
        valu = 0
        top_card = 0
        reserve = 0

        card_rank ={'A': 14, 'K': 13, 'Q': 12, 'J': 11, 'T': 10, '9': 9, '8': 8,
                                '7': 7, '6': 6, '5': 5, '4': 4, '3': 3, '2': 2}
        flush = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2']

        royal_flush = ['T', 'J', 'Q', 'K', 'A']

        test = txt_feed()
        while True:
                try:
                        while True:
                                pointz1 = 0  # points awarded for content of hand
                                pointz2 = 0

                                # -- evaluate hand1 -----------------------------------------------------------------

                                reserve1 = reserve
                                test2 = next(test)  # pulls out line of text
                                hand = test2[:5]   # splits test2 in half
                                ans = card_values(hand)  # list of values ['4', '7', '9', '3', 'j'] etc
                                pointz1 = points_calc(hand, card_rank, flush, royal_flush)  # initial value of hand(1 to 10)
                                hi_card1 = hi_card

                                valu = values(ans, card_rank)
                                value_of_hand1 = top_card


                                # -- evaluate hand2 -----------------------------------------------------------------------------------

                                reserve2 = reserve
                                hand2 = test2[5:]  # second half of list
                                ans = card_values(hand2)  # # list of values ['4', '7', '9',....
                                pointz2 = points_calc(hand2, card_rank, flush, royal_flush)  # analyse hand and award points

                                value_of_hand2 = top_card
                                hi_card2 = hi_card


                                # -- check for a winner! ----------

                                calc = winner_calc(pointz1, pointz2, value_of_hand1, value_of_hand2, hi_card1, hi_card2)


                except StopIteration:
                        break


        print('Wins for hand one = ', calc)
# problem 55
count_it = 0
lychrel = 0

for y in range(1, 10000):
        while True:
                y_reversed = int(str(y)[::-1])
                added_y = y + y_reversed
                count_it += 1
                # if the count goes up to 50 a lychrel number is declared
                if count_it == 50:
                        lychrel += 1
                        count_it = 0
                        break
                palindrome = added_y == int(str(added_y)[::-1])
                if palindrome:
                        count_it = 0
                        break

                y = added_y

print('Lychrel numbers under 10000 = ', lychrel)
# problem 56

temp = 0
for a in range(100, 1, -1):
    for b in range(100, 1, -1):
        natural_num = a ** b

        l = str(natural_num)
        digital_sum = 0
        for i in l:
            digital_sum += int(i)
        if digital_sum > temp:
            temp = digital_sum

print("Answer = ", temp)
#problem 57

'''
It is possible to show that the square root of two can be
 expressed as an infinite continued fraction.

v 2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213...

By expanding this for the first four iterations, we get:

1 + 1/2 = 3/2 = 1.5
1 + 1/(2 + 1/2) = 7/5 = 1.4
1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...
1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...

The next three expansions are 99/70, 239/169, and 577/408,
 but the eighth expansion, 1393/985, is the first example where
  the number of digits in the numerator exceeds the number of digits in the denominator.

In the first one-thousand expansions, how many fractions contain a
numerator with more digits than denominator?
'''

def root_two(num):
        ''' int -> int
        '''
        count = 0
        numerator = 3
        denominator = 2
        while num > 0:
                a = denominator * 2 + numerator
                b = numerator + denominator
                numerator = a
                denominator = b
                num -= 1
                if len(str(numerator)) > len(str(denominator)):
                        count += 1
        return count

ans = root_two(1000)
print('answer = ', ans)
# problem 58
'''


Starting with 1 and spiralling anticlockwise in the following way,
 a square spiral with side length 7 is formed.

37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18  5  4  3 12 29
40 19  6  1  2 11 28
41 20  7  8  9 10 27
42 21 22 23 24 25 26
43 44 45 46 47 48 49

It is interesting to note that the odd squares lie along the bottom right diagonal,
 but what is more interesting is that 8 out of the 13 numbers lying along both
  diagonals are prime; that is, a ratio of 8/13 ≈ 62%.

If one complete new layer is wrapped around the spiral above, a square spiral
 with side length 9 will be formed. If this process is continued, what is the
 side length of the square spiral for which the ratio of primes along both diagonals
first falls below 10%?

'''



def isprime(n):

        # make sure n is a positive integer
        n = abs(int(n))

        # all other even numbers are not primes,
        #rejects other even numbers.
        if not n & 1:
                return False

        # range starts with 3 and only needs to go up the squareroot of n
        # for all odd numbers
        for x in range (3,int (n**0.5)+1, 2):

                        if n % x == 0:
                                n = n+ 1
                                return False

        return True

if __name__ == '__main__':

        import time
        tt = time.time()
        prime_count = 0
        ans = 1
        count = 0
        x = 2
        total = 0
        percent = 1

        while True:
                total += 1
                count += 1

                ans += x

                if isprime(ans):
                        prime_count += 1

                percent =  prime_count / total

                if percent <= 0.1:
                        print('Answer = ', x + 1)
                        print(time.time() - tt)
                        exit()

                if count == 4:
                        x += 2
                        count = 0

        print("done!", x + 1)
#problem 59
    from string import ascii_lowercase

    class Decoder:
            def __init__(self):
                    self.lst = [i for i in ascii_lowercase]
                    self.alphalist = self.lst
                    self.data = None
                    self.code_lst = None

            def text_read(self, text):
                    ''' text -> list
                    Read text and output as a list (data)
                    '''
                    with open(text) as file:
                            self.data = file.read()
                            self.data = self.data.strip('\n')
                            self.data = self.data.split(',')
                    return self.data

            def get_code(self):
                    ''' list -> list
                    Extract a three character code by
                    applying the alphabet to every third character and
                    checking for spaces (ascii 32)
                    '''
                    alpha = ''
                    dict1 = {}
                    key_list = []
                    temp_list = []
                    total_e = 0
                    for a in range(0, 3):
                            for x in range(0, len(self.alphalist)):
                                    for y in range(a, len(self.data), 3):
                                            if y > len(self.data):
                                                    y = len(self.data)
                                            data_y = int(self.data[y])
                                            alpha = self.lst[x]
                                            temp_list.append(int(ord(alpha)) ^ int(data_y))
                                    e_accum = temp_list.count(32)
                                    dict1[alpha] = e_accum
                                    if e_accum > total_e:
                                            total_e = e_accum
                                    temp_list = []
                            ans = max(dict1, key=dict1.get)
                            key_list.append(ans)
                            print(key_list)
                            total_e = 0
                    code_lst = [key_list[0], key_list[1], key_list[2]]
                    return code_lst

            def decrypt_text(self):
                    ''' list -> text
                    Decrypt the list and sum the ascii values
                    '''

                    text_out = ''  # decrypted text
                    y = 0
                    out_lst = []    # decrypted list
                    len_data = len(self.data)
                    index1 = 0
                    index2 = 3
                    slice = self.data[index1:index2]
                    while y != len(self.data):
                            for x in range(0, len(self.code_lst)):
                                    a = int(slice[x])
                                    b = ord(self.code_lst[x])
                                    ab_sum = a ^ b
                                    out_lst.append(ab_sum)
                                    #print(out)
                                    da = len(out_lst)
                                    if da == len_data:
                                            answer = sum(out_lst)
                                            print(answer)
                                            exit()
                                    y += 1
                            index1 += 3
                            index2 += 3
                            if index2 > len(self.data):
                                    index2 = len(self.data)
                            slice = self.data[index1:index2]

            def get_text(self, txt):
                    ''' number list -> text
                    convert list of numbers and convert to
                    characters
                    '''
                    for x in range(len(self.lst)):
                            txt += chr(self.lst[x])
                    return txt

    def main():
            my_code = Decoder()
            my_code.data = my_code.text_read('cipher1.txt')
            my_code.code_lst = my_code.get_code()
            my_code.decrypt_text()

    if __name__ =='__main__':
       main()

Comments | Gallery