197 lines
9.3 KiB
Text
197 lines
9.3 KiB
Text
--------------------------------------------------------------------------------
|
|
Part 1 - Valid table
|
|
|
|
Write a function comp10001huxxy_valid_table() which takes a single argument:
|
|
|
|
- groups, a list of lists of cards (each a 2-element string, where the first
|
|
letter is the card value and the second letter is the card suit, e.g. '3H' for
|
|
the 3 of Hearts), where each list of cards represents a single group on the
|
|
table, and the combined list of lists represents the combined groups played to
|
|
the table.
|
|
|
|
Your function should return a bool, which evaluates whether the table state is
|
|
valid or not. Recall from the rules of the game that the table is valid if all
|
|
groups are valid, where a group can take one of the following two forms:
|
|
|
|
- an N-of-a-kind (i.e. three or more cards of the same value), noting that in
|
|
the case of a 3-of-a-kind, each card must have a unique suit (e.g. ['2S',
|
|
'2S', '2C'] is not a valid 3-of-a-kind, as the Two of Spades has been played
|
|
twice), and if there are 4 or more cards, all suits must be present.
|
|
- a run (i.e. a group of 3 or more cards, starting from the lowest-valued card,
|
|
and ending with the highest-valued card, forming a continuous sequence in
|
|
terms of value, and alternating in colour; note that the specific ordering of
|
|
cards in the list is not significant, i.e. ['2C', '3D', '4S'] and ['4S', '2C',
|
|
'3D'] both make up the same run.
|
|
|
|
Example function calls are as follows:
|
|
|
|
>>> comp10001huxxy_valid_table([])
|
|
True
|
|
>>> comp10001huxxy_valid_table([['AC']])
|
|
False
|
|
>>> # run too short
|
|
>>> comp10001huxxy_valid_table([['AC', '2S']])
|
|
False
|
|
>>> # run doesn't alternate in colour
|
|
>>> comp10001huxxy_valid_table([['AC', '2S', '3H']])
|
|
False
|
|
>>> # values not adjacent
|
|
>>> comp10001huxxy_valid_table([['AC', '2S', '4H']])
|
|
False
|
|
>>> comp10001huxxy_valid_table([['AC', '2H', '3S']])
|
|
True
|
|
>>> # test unsorted run
|
|
>>> comp10001huxxy_valid_table([['3C', 'AS', '2H']])
|
|
True
|
|
>>> comp10001huxxy_valid_table([['0C', 'JH', 'QS', 'KH', '9D']])
|
|
True
|
|
>>> # n-of-kind too short
|
|
>>> comp10001huxxy_valid_table([['2C', '2H']])
|
|
False
|
|
>>> # same suit twice for 3-of-kind
|
|
>>> comp10001huxxy_valid_table([['2C', '2H', '2C']])
|
|
False
|
|
>>> # same suit twice for 4-of-kind
|
|
>>> comp10001huxxy_valid_table([['2C', '2H', '2S', '2C']])
|
|
False
|
|
>>> comp10001huxxy_valid_table([['2C', '2H', '2S']])
|
|
True
|
|
>>> comp10001huxxy_valid_table([['2C', '2H', '2S', '2D']])
|
|
True
|
|
>>> comp10001huxxy_valid_table([['2C', '2H', '2S', '2D', '2S']])
|
|
True
|
|
>>> comp10001huxxy_valid_table([['2C', '2H', '2S', '2D', '2S'],
|
|
['0D', '9C', '8H']])
|
|
True
|
|
|
|
--------------------------------------------------------------------------------
|
|
Part 2 - Group validation
|
|
|
|
Write a function comp10001go_valid_groups() which takes a single argument:
|
|
|
|
- groups, a list of groups, each of which is a list of cards (following the same
|
|
definition as Part 1)
|
|
|
|
Your function should return a Boolean indicating whether all groups are valid or
|
|
not (i.e. a singleton card, a valid N-of-a-kind or a valid run). Note that the
|
|
function may be used to validate a grouping of partial discards or the full set
|
|
of discards, i.e. the total number of cards in groups will be between 0 and 10.
|
|
|
|
Example function calls are as follows:
|
|
|
|
>>> comp10001go_valid_groups([['KC', 'KH', 'KS', 'KD'], ['2C']])
|
|
True
|
|
>>> comp10001go_valid_groups([['KC', 'KH', 'KS', 'AD'], ['2C']])
|
|
False
|
|
>>> comp10001go_valid_groups([['KC', 'KH', 'KS', 'KD'], ['2C', '3H']])
|
|
False
|
|
>>> comp10001go_valid_groups([])
|
|
True
|
|
|
|
--------------------------------------------------------------------------------
|
|
Part 3 - Play and Group!
|
|
|
|
The third question requires that you implement the two functions that are called
|
|
in the tournament: (1) comp10001_play, which is used to select a discard over
|
|
the 10 turns of a game; and (2) comp10001_group, which is used to group the
|
|
discards into groups for scoring. We combine these together into a single
|
|
question in Grok as a means of validating that you have a complete player that
|
|
is qualified to enter the tournament. Note that in each case, we provide only a
|
|
single test case (and no hidden test cases) for two reasons: (1) there are very
|
|
few game states where there is a single possible option to either play a discard
|
|
or group the discards, and testing relies on there only being one possible
|
|
output; and (2) the real testing occurs in simulation mode in the actual
|
|
tournament, in the form of random games against other players. On validation of
|
|
implementations of each of the two functions, you will be given the option to
|
|
submit your player to the tournament.
|
|
|
|
First, write a function comp10001go_play() which takes three arguments:
|
|
|
|
- discard_history, a list of lists of four cards, each representing the discards
|
|
from each of the four players in preceding turns (up to 9 turns) in sequence
|
|
of player number (i.e. the first element in each list of four cards is for
|
|
Player 0, the second is for Player 1, etc.). Note that the list is sequenced
|
|
based on the turns, i.e. the first list of four cards corresponds to the first
|
|
turn, and the last list of four cards corresponds to the last turn.
|
|
- player_no, an integer between 0 and 3 inclusive, indicating which player is
|
|
being asked to play. player_no can also be used to determine the discards for
|
|
that player from discard_history by indexing within each list of four cards.
|
|
- hand, a list of cards held by the player.
|
|
|
|
Your function should return a single card to discard from hand.
|
|
|
|
An example function call is as follows:
|
|
|
|
>>> comp10001go_play([['0S', 'KH', 'AC', '3C'], ['JH', 'AD', 'QS', '5H'],
|
|
['9C', '8S', 'QH', '9S'], ['8C', '9D', '0D', 'JS'],
|
|
['5C', 'AH', '5S', '4C'], ['8H', '2D', '6C', '2C'],
|
|
['8D', '4D', 'JD', 'AS'], ['0H', '6S', '2H', 'KC'],
|
|
['KS', 'KD', '7S', '6H']], 3, ['QC'])
|
|
'QC'
|
|
|
|
Second, write a function comp10001go_group() which takes two arguments:
|
|
|
|
- discard_history, a list of lists of four cards, each representing the discards
|
|
from each of the four players in preceding turns in sequence of player number
|
|
(i.e., the first element in each list of four cards is for Player 0, the
|
|
second is for Player 1, etc.). Note that the list is sequenced based on the
|
|
turns, i.e. the first list of four cards corresponds to the first turn, and
|
|
the last list of four cards corresponds to the last turn. Additionally note
|
|
that the number of turns contained in discard_history will always be 10.
|
|
- player_no, an integer between 0 and 3 inclusive, indicating which player is
|
|
being asked to play. player_no can also be used to determine the discards for
|
|
that player from discard_history by indexing within each list of four cards.
|
|
|
|
Your function should return a list of lists of cards based on the discard
|
|
history of player_no, to use in scoring the player. Note that the grouping of
|
|
cards represented by the output must be valid (i.e. each list of cards must be a
|
|
singleton card, or a valid N-of-a-kind or run), but that the ordering of cards
|
|
within groups, and the ordering of groups is not significant.
|
|
|
|
An example function call is as follows:
|
|
|
|
>>> comp10001go_group([['0S', 'KH', 'AC', '3C'], ['JH', 'AD', 'QS', '5H'],
|
|
['9C', '8S', 'QH', '9S'], ['8C', '9D', '0D', 'JS'],
|
|
['5C', 'AH', '5S', '4C'], ['8H', '2D', '6C', '2C'],
|
|
['8D', '4D', 'JD', 'AS'], ['0H', '6S', '2H', 'KC'],
|
|
['KS', 'KD', '7S', '6H'], ['JC', 'QD', '4H', 'QC']], 3)
|
|
[['3C'], ['5H'], ['9S'], ['JS'], ['4C'],
|
|
['2C'], ['AS'], ['KC'], ['6H'], ['QC']]
|
|
|
|
--------------------------------------------------------------------------------
|
|
Part 4 - Optimal grouping
|
|
|
|
The final question is for bonus marks, and is deliberately quite a bit harder
|
|
than the four basic questions (and the number of marks on offer is, as always,
|
|
deliberately not commensurate with the amount of effort required). Only attempt
|
|
this is you have completed the earlier questions, and are up for a challenge!
|
|
|
|
Write a function comp10001go_best_partitions() which takes a single argument:
|
|
|
|
- cards, a list of up to 10 cards
|
|
|
|
Your function should return a list of list of lists of cards, representing the
|
|
groupings of cards that score the most points from cards. Note that the ordering
|
|
of the groupings is not significant, and neither is the ordering of the groups
|
|
within a grouping, nor the order of cards within a group.
|
|
|
|
One area of particular focus with this question is efficiency: there are strict
|
|
time limits associated with running your code over each example, that you must
|
|
work within, or you will fail the test. Good luck!
|
|
|
|
Example function calls are as follows:
|
|
|
|
>>> comp10001go_best_partitions(['0H', '8S', '6H', 'AC', '0S',
|
|
'JS', '8C', '7C', '6D', 'QS'])
|
|
[[['AC'], ['0H', '0S'], ['JS'], ['8S', '8C'], ['7C'], ['6H', '6D'], ['QS']]]
|
|
>>> comp10001go_best_partitions(['9D', '2S', '4D', '4H', '6D',
|
|
'AH', '2C', 'JH', '3C', '9H'])
|
|
[[['4D', '4H'], ['6D'], ['AH'], ['2S', '2C'],
|
|
['JH'], ['3C'], ['9D', '9H']]]
|
|
>>> comp10001go_best_partitions(['3C', '5H', '9S', 'JS', '4C',
|
|
'2C', 'AS', 'KC', '6H', 'QC'])
|
|
[[['3C'], ['5H'], ['9S'], ['JS'], ['4C'], ['2C'], ['AS'], ['KC'], ['6H'], ['QC']]]
|
|
>>> comp10001go_best_partitions(['0D', 'AS', '5C', '8H',
|
|
'KS', 'AH', 'QH', 'AC'])
|
|
[[['AS', '5C', '8H', 'AH'], ['0D', 'KS', 'QH', 'AC']],
|
|
[['0D', 'AS', 'KS', 'QH'], ['5C', '8H', 'AH', 'AC']]]
|