comp10001-project03/old/part1.py
2024-06-08 21:41:57 +10:00

217 lines
7.5 KiB
Python

# Title: Project 3 - Group scoring
# Author: Rory Healy
# Date created - 17th 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):
'''Determines if a set of cards are said to be a "valid run" and returns a
corresponding Boolean value.'''
# Extracts the suits of all the cards in the list.
suits_of_cards = []
colour_of_cards = ''
red_cards = 'DH'
for i in range(len(cards)):
suits_of_cards.append(cards[i][-1])
for card in suits_of_cards:
if card in red_cards:
colour_of_cards += 'R'
else:
colour_of_cards += 'B'
# Extracts the numbers of the cards in the list.
numbers_of_cards = []
for i in range(len(cards)):
numbers_of_cards.append(cards[i][:-1])
# Return True/False based on the validity of the suits and numbers.
if suits_are_alternating(colour_of_cards) and \
numbers_are_monotonic(numbers_of_cards):
return True
return False
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 numbers_are_monotonic(numbers):
'''Takes a list of strings of numbers and returns True if the numbers in
the list are monotonic (i.e. strictly increasing or strictly decreasing),
where aces can represent any number.'''
# Replaces Aces with their numerical value, based on the values of the
# cards adjacent to the Ace.
for i in range(len(numbers)):
if numbers[i] == 'A':
if (i == 0) or (i == (len(numbers) - 1)):
return False
# The value the a is actually taking depends on whether the cards
# are increasing or decreasing in value, so this step is necessary
# for dealing with Aces.
if int(numbers[0]) < int(numbers[-1]):
a_actually_is = int(numbers[i - 1]) + 1
elif int(numbers[0]) > int(numbers[-1]):
a_actually_is = int(numbers[i + 1]) + 1
elif int(numbers[0]) == int(numbers[-1]):
return False
# Validating that the ace represents the correct number.
a_should_represent = (int(numbers[i + 1]) + int(numbers[i - 1])) \
/2
if a_should_represent != a_actually_is:
return False
else:
numbers.insert(i, str(a_actually_is))
numbers.remove('A')
# Checks if the numbers are consecutive.
for i in range(len(numbers)):
if int(numbers[0]) == int(numbers[-1]):
return False
# For runs that are ascending.
elif int(numbers[0]) < int(numbers[-1]):
if i == 0:
if int(numbers[0]) != (int(numbers[1]) - 1):
return False
elif i == (len(numbers) - 1):
if int(numbers[i]) != (int(numbers[i - 1]) + 1):
return False
elif int(numbers[i]) != (int(numbers[i - 1]) + 1):
return False
# For runs that are descending.
elif int(numbers[0]) > int(numbers[-1]):
if i == 0:
if int(numbers[0]) != (int(numbers[1]) + 1):
return False
elif i == (len(numbers) - 1):
if int(numbers[i]) != (int(numbers[i - 1]) - 1):
return False
elif int(numbers[i]) != (int(numbers[i - 1]) - 1):
return False
# If the run passes all of these cases, then it must be a valid run.
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 factorial(num):
'''Calculates the factorial of the number and returns it.'''
if num == 1:
return 1
else:
return num * factorial(num - 1)
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_score_group(cards):
'''Takes a list of cards (each a 2-element string, where the first letter
is the card value and the second letter is the card suit), and returns the
calculated score of that set of cards as an integer.'''
score = 0
cards = convert_0jqk(cards)
cards = order_a_list(cards)
# Given a list, identifies an n-of-a-kind case or a run.
if len(cards) > 1:
for i in range(2, len(cards) + 1):
# Handles the case where all of the cards are n-of-a-kind.
if is_n_of_a_kind(cards):
score += int(cards[0][:-1]) * factorial(len(cards))
return score
# Handles the case where only some of the cards are n-of-a-kind
# and the rest aren't.
elif not is_n_of_a_kind(cards[0:i]):
score += int(cards[0][:-1]) * factorial(i - 1)
value = int(cards[0][:-1])
for j in range(i):
if int(cards[0][:-1]) == value:
cards.pop(0)
# Any leftover cards have their values taken from the total score.
if len(cards) > 0:
for card in cards:
value = card[:-1]
if value == 'A':
value = 20
else:
value = int(value)
score -= value
return score