# Title: Project 3 - Group validation # Author: Rory Healy # Date created - 23rd May 2019 # Date modified - 30th May 2019 def is_n_of_a_kind(cards): '''Takes a list of cards and returns a Boolean value based on if those cards are said to be "N-of-a-kind".''' # Analyse the numbers of the cards to determine validity. numbers_of_cards = [] for i in range(len(cards)): numbers_of_cards.append(cards[i][:-1]) if numbers_are_same(numbers_of_cards): return True return False def numbers_are_same(numbers): '''Takes a list of strings, "numbers", and returns True if all the numbers in the list of strings are the same, and False otherwise.''' original_number = numbers[0] for i in range(len(numbers)): if numbers[i] != original_number: return False return True def is_run(cards, aces): '''Takes two lists of cards (represented as strings), cards and aces, and returns a list of the lists of runs that are possible with all the given cards.''' return_list = [] possible_runs = [] original_cards_len = len(cards) for i in range(1, len(cards)): current_card = cards[0] current_run = [] if len(possible_runs) > 0: # This is to prevent any IndexErrors due to the use of a while # loop within a for loop. for run in possible_runs: if len(run) + len(cards) != original_cards_len: break else: continue break n = 1 while n < len(cards): if len(cards) == 1: break # This will check that the cards form a run. elif int(current_card[:-1]) == int(cards[i][:-1]) - n: current_run.append(cards[i]) cards.remove(cards[i]) n += 1 if len(current_run) > 0: current_run.append(current_card) possible_runs.append(current_run) cards.remove(current_card) # Numerically sorts the runs. for i in range(len(possible_runs)): current_run = order_a_list(possible_runs[i]) possible_runs.pop(i) possible_runs.insert(i, current_run) # Inserts any aces where necessary. for run in possible_runs: for i in range(len(run)): if i == len(run): break elif int(run[i][:-1]) != (int(run[i + 1][:-1]) - 1): if len(aces) > 0: run.insert(i + 1, aces[0]) aces.pop(0) break else: for card in run: cards.append(card) possible_runs.remove(run) break # Checks for alternating suits. for run in possible_runs: if not suits_are_alternating(run): for card in run: cards.append(card) run.remove(card) # Returns all the runs and leftover cards. return_list.append(possible_runs) return_list.append(cards) return_list.append(aces) return return_list def suits_are_alternating(suits): '''Takes a string "suits" and returns True if the suits of the string are alternating, and False otherwise.''' for i in range(1, len(suits)): if suits[i] == suits[i - 1]: return False return True def convert_0jqk(cards): '''Takes a list of cards and converts special numbers (0, J, Q, K) to their respective values (10, 11, 12, 13) respectively.''' # Replaces letters with numbers. for i in range(len(cards)): # Replaces Kings with their numerical value - 13. if cards[i][0] == 'K': suit = cards[i][1] cards[i] = '13' + suit # Replaces Queens with their numerical value - 12. elif cards[i][0] == 'Q': suit = cards[i][1] cards[i] = '12' + suit # Replaces Jacks with their numerical value - 11. elif cards[i][0] == 'J': suit = cards[i][1] cards[i] = '11' + suit # Replaces '0', representing 10, with its numerical value. elif cards[i][0] == '0': suit = cards[i][1] cards[i] = '10' + suit return cards def order_a_list(cards): '''Orders a list of cards based their numerical value with Aces last.''' ordered_list = [] numbers_of_cards = [] aces = [] for i in range(len(cards)): if cards[i][:-1] == 'A': aces.append('A') else: numbers_of_cards.append(cards[i][:-1]) numbers_of_cards.sort(key=int) numbers_of_cards += aces for number in numbers_of_cards: for card in cards: if number == card[:-1]: if card in ordered_list: continue ordered_list.append(number + card[-1]) return ordered_list def comp10001go_valid_groups(groups): '''Takes a list of lists of cards (stored as strings) and returns True or False depending on if it matches the conditions of valiidty as specified in the rules.''' # Handles empty lists. if not groups: return True for group in groups: # Converts all cards in the group to actual numbers (excluding aces) group = convert_0jqk(group) group = order_a_list(group) # Checks if the group is either an n-of-a-kind or a run if not is_n_of_a_kind(group): return False elif len(group) == 1: aces = [] for card in group: if card[0] == 'A': aces.append(card) group.remove(card) runs = is_run(group, aces) if len(runs[0]) == 0 and len(group) != 1: return False return True