נצרף גם את שלי 
PICTURES = ('T', 'J', 'Q', 'K', 'A')
SUIT_TYPES = ('C', 'D', 'H', 'S')
NUMBER = 0
SUIT = 1
NUMBER_OF_CARDS = 5
def parse_number(number):
    if number in PICTURES:
        parsed_number = PICTURES.index(number) + 10
    else:
        parsed_number = int(number)
    return parsed_number
def parse_card(card):
    parsed_number = parse_number(card[NUMBER])
    return parsed_number, card[SUIT]
def parse_hand(cards):
    i = 0
    new_cards = []
    while i < len(cards):
        parsed_card = parse_card(cards[i])
        new_cards.append(parsed_card)
        i += 1
    return new_cards
def count_card_numbers(hand):
    times_each_number_appeared = [0] * 15
    i = 0
    while i < len(hand):
        number = hand[i][NUMBER]
        times_each_number_appeared[number] += 1
        i += 1
    times_each_number_appeared[1] = times_each_number_appeared[14]  # Ace
    return times_each_number_appeared
def count_suits(hand):
    suits_counter = [0] * 4
    i = 0
    while i < len(hand):
        suit = hand[i][SUIT]
        suit_index = SUIT_TYPES.index(suit)
        suits_counter[suit_index] += 1
        i += 1
    return suits_counter
def get_only_numbers(hand):
    i = 0
    numbers = []
    while i < len(hand):
        numbers.append(hand[i][NUMBER])
        i += 1
    return numbers
def get_hand_as_kickers(hand):
    numbers = get_only_numbers(hand)
    numbers.sort()
    return numbers[::-1]
def get_highest_x_of_kind(hand, x):
    times_each_number_appears = count_card_numbers(hand)
    # The highest cards are in the end, so we flip the list
    if x in times_each_number_appears:
        descending_number_count = times_each_number_appears[::-1]
        highest_x_of_kind = descending_number_count.index(x)
        real_card_value = 15 - highest_x_of_kind - 1
        return real_card_value
    return False
def find_flush_color(hand, flush_length):
    suit = 0  # 0 = C, 1 = D, 2 = H, 3 = S
    suits_counter = count_suits(hand)
    while suit < len(suits_counter) and suits_counter[suit] < flush_length:
        suit += 1
    if suit >= len(suits_counter):  # We've gone through all the options
        return False
    return suit
def filter_by_suit(hand, suit):
    if str(suit).isdigit():
        suit = SUIT_TYPES[suit]
    i = 0
    filtered = []
    while i < len(hand):
        if hand[i][SUIT] == suit:
            filtered.append(hand[i])
        i += 1
    return filtered
def get_highest_of_suit(hand, suit, k):
    filtered = filter_by_suit(hand, suit)
    filtered.sort()
    return filtered[-k:]
def get_flush(hand, flush_length):
    flush_color = find_flush_color(hand, flush_length)
    if flush_color == False:
        return False
    flush = get_highest_of_suit(hand, flush_color, flush_length)
    if len(flush) != flush_length:
        return False
    return flush
def get_straight(hand, straight_length):
    card_numbers = count_card_numbers(hand)
    i = len(card_numbers) - 1
    length_so_far = 1
    while 0 < i:
        if length_so_far == straight_length:
            return i + length_so_far - 1
        if card_numbers[i] > 0 and card_numbers[i - 1] > 0:
            length_so_far += 1
        else:
            length_so_far = 1
        i -= 1
    return False
def get_two_pairs(hand):
    pair = get_highest_x_of_kind(hand, 2)
    if not pair:
        return False
    hand2 = filter_out_number(hand, pair)
    another_pair = get_highest_x_of_kind(hand2, 2)
    if not another_pair:
        return False
    
    kicker = filter_out_number(hand2, another_pair)
    return pair, another_pair, kicker
def get_kickers(hand, numbers_to_filter):
    i = 0
    hand2 = hand.copy()
    while i < len(numbers_to_filter):
        hand2 = filter_out_number(hand2, numbers_to_filter[i])
        i += 1
    hand_numbers = get_only_numbers(hand2)
    hand_numbers.sort()
    return hand_numbers[::-1]  # Highest first
def filter_out_number(hand, number):
    i = 0
    new_hand = []
    while i < len(hand):
        if hand[i][NUMBER] != number:
            new_hand.append(hand[i])
        i += 1
    return new_hand
def get_hand_strength(hand):
    flush = get_flush(hand, NUMBER_OF_CARDS)
    straight = get_straight(hand, NUMBER_OF_CARDS)
    if flush and straight:
        return 8, straight
    four_of_a_kind = get_highest_x_of_kind(hand, 4)
    if four_of_a_kind:
        kicker = get_kickers(hand, [four_of_a_kind])
        return 7, four_of_a_kind, kicker
    three_of_a_kind = get_highest_x_of_kind(hand, 3)
    pair = get_highest_x_of_kind(hand, 2)
    if three_of_a_kind and pair:
        return 6, three_of_a_kind, pair
    if flush:
        return 5, get_hand_as_kickers(hand)
    if straight:
        return 4, straight
    if three_of_a_kind:
        return 3, three_of_a_kind, get_kickers(hand, [three_of_a_kind])
    two_pairs = get_two_pairs(hand)
    if two_pairs:
        kicker = get_kickers(hand, two_pairs)
        return 2, two_pairs[0], two_pairs[1], kicker
    if pair:
        kicker = get_kickers(hand, [pair])
        return 1, pair
    return 0, get_hand_as_kickers(hand)
def get_winning_hand(hand1, hand2):
    strength1 = get_hand_strength(hand1)
    strength2 = get_hand_strength(hand2)
    if strength1 > strength2:
        return 0
    elif strength1 < strength2:
        return 1
    return 2
def add_all_uniques(l, items):
    i = 0
    while i < len(items):
        if items[i] not in l:
            l.append(items[i])
        i += 1
    return items
def create_all_hands_combinations(hand, length):
    if len(hand) == length:
        return [hand]
    combinations = []
    i = 0
    while i < len(hand):
        rest_of_hand = hand[:i] + hand[i+1:]
        created = create_all_hands_combinations(rest_of_hand, length)
        add_all_uniques(combinations, created)
        i += 1
    
    return combinations
def get_best_of_hands(hands):
    if not hands:
        return []
    best_hand = hands[0]
    max_i = 0
    i = 1
    while i < len(hands):
        current_hand = hands[i]
        winning_hand = get_winning_hand(best_hand, current_hand)
        if winning_hand % 2 == 1:
            best_hand = current_hand
            max_i = i
        i += 1
    
    return (best_hand, max_i)
    
def create_best_hand(larger_hand, wanted_size):
    combinations = create_all_hands_combinations(larger_hand, wanted_size)
    i = 0
    parsed_combinations = []
    while i < len(combinations):
        parsed_combinations.append(parse_hand(combinations[i]))
        i += 1
    return get_best_of_hands(parsed_combinations)[0]
def get_best_player(hands, public):
    i = 0
    new_hands = []
    while i < len(hands):
        actual_hand = create_best_hand(hands[i] + public, 5)
        print(actual_hand)
        new_hands.append(actual_hand)
        i += 1
    return get_best_of_hands(new_hands)[1]
def test_strength(hand, expected_strength):
    parsed_hand = parse_hand(hand)
    strength = get_hand_strength(parsed_hand)
    assert strength == expected_strength, f"{hand}:\t{strength} != {expected_strength}"
test_strength(['TH', 'AH', 'QH', 'KH', '3S'], (0, [14, 13, 12, 10, 3]))
test_strength(['TH', 'TH', 'QH', 'KH', '3S'], (1, 10))
test_strength(['2H', 'QH', '2H', 'KH', '3S'], (1, 2))
test_strength(['2H', 'QH', '2S', 'QS', '3S'], (2, 12, 2, [3]))
test_strength(['QH', 'QC', '2H', 'QS', '3S'], (3, 12, [3, 2]))
test_strength(['AH', 'KS', 'QH', 'JH', 'TS'], (4, 14))
test_strength(['9H', 'KS', 'QH', 'JH', 'TS'], (4, 13))
test_strength(['9H', '5H', '3H', 'JH', 'TH'], (5, [11, 10, 9, 5, 3]))
test_strength(['9H', '9S', '9C', 'JH', 'JS'], (6, 9, 11))
test_strength(['9H', '9S', 'JC', 'JH', 'JS'], (6, 11, 9))
test_strength(['9H', 'JD', 'JC', 'JH', 'JS'], (7, 11, [9]))
test_strength(['AH', 'KH', 'QH', 'JH', 'TH'], (8, 14))
test_strength(['9H', 'KH', 'QH', 'JH', 'TH'], (8, 13))
print(create_best_hand(['2S', '9H', 'KH', '5S', 'QH', 'JH', 'TH'], 5))
print(get_best_player([['2S, 9H'], ['9H', 'KH'], ['5H', '6H'], ['7H', '4H']], ['QH', 'JH', 'TH', '8H']))