7 KiB
7 KiB
Exercise: Match the tarot cards!¶
Given 2 decks of tarot cards, deck1
and deck2
, find all the matching pairs. The output should be a set of tuples (idx1, idx2)
for every matching pair in deck1
, deck2
.
For example:
deck1 = ['C', 'B', 'A']
deck2 = ['A', 'C', 'B']
should return (in no particular order):
{(0, 1), (1, 2), (2, 0)}
- Write an algorithm to match the tarot cards
- Compute the Big-O complexity of your algorithm
In [1]:
import random
# List of tarot card names (Major Arcana)
tarot_cards = [
"The Fool", "The Magician", "The High Priestess", "The Empress", "The Emperor",
"The Hierophant", "The Lovers", "The Chariot", "Strength", "The Hermit",
"Wheel of Fortune", "Justice", "The Hanged Man", "Death", "Temperance",
"The Devil", "The Tower", "The Star", "The Moon", "The Sun", "Judgement",
"The World"
]
# Copy the list to create two separate decks
deck1 = tarot_cards.copy()
deck2 = tarot_cards.copy()
# Shuffle both decks
random.shuffle(deck1)
random.shuffle(deck2)
# Print the shuffled decks
print("-- Deck 1: --\n", deck1)
print("-- Deck 2: --\n", deck2)
Simplest implementation: O(N^2)¶
In [2]:
matches = set()
for idx1, card in enumerate(deck1): # O(N)
match = (idx1, deck2.index(card)) # O(N)
matches.add(match)
matches
Out[2]:
Faster solution: O(N log N)¶
In [3]:
# Create a list of (tarot_card, idx), and sort it. This is kind of equivalent to np.argsort
n_cards = len(deck1)
sorted_deck1 = sorted((deck1[idx], idx) for idx in range(n_cards)) # O(N log N)
sorted_deck2 = sorted((deck2[idx], idx) for idx in range(n_cards)) # O(N log N)
matches = set()
for idx in range(n_cards): # O(N)
matches.add((sorted_deck1[idx][1], sorted_deck2[idx][1])) # O(1)
matches
Out[3]:
3. Fastest solution: O(N)¶
In [7]:
# Create a dictionary, mapping cards to the index in deck2
deck2_card_to_idx = {}
for idx2, card in enumerate(deck2): # O(N)
deck2_card_to_idx[card] = idx2
# For each card and index in deck1, look up the index in deck2, and store the match
matches = set()
for idx1, card in enumerate(deck1): # O(N)
idx2 = deck2_card_to_idx[card] # O(1)
matches.add((idx1, idx2)) # O(1)
matches
Out[7]:
In [ ]: