Skip to content

Instantly share code, notes, and snippets.

@fefi95
Last active August 28, 2021 17:40
Show Gist options
  • Save fefi95/2cf2cf5006d211f15df8bd06c070b7bb to your computer and use it in GitHub Desktop.
Save fefi95/2cf2cf5006d211f15df8bd06c070b7bb to your computer and use it in GitHub Desktop.
Pattern Matching in Python
from typing import List
def http_error(status: int) -> str:
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Other"
# The tails function returns all final segments of
# the argument, longest first. For example:
#
# >>> tails([1,2,3,4])
# [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
def tails(initial_list: list) -> List[list]:
match initial_list:
case []:
return []
case [_, *rest] as full_list:
return [full_list] + tails(rest)
# >>> get_data({"data": 100})
# 100
#
# >>> get_data({"other": 2323, "error": "An error msg"})
# Exception: An error msg
#
# >>> get_data({"error": 400})
# Exception: Bad request (400)
def get_data(response: dict):
match response:
case {"data": data}:
return data
case {"error": int(code)}:
raise Exception(f"{http_error(code)} ({code})")
case {"error": str(msg)}:
raise Exception(msg)
case _:
raise Exception("Unknown error")
from dataclasses import dataclass
from typing import List, Union
class Suit:
CLUB = "♣"
DIAMOND = "♦"
SPADE = "♠"
HEART = "♥"
class Symbol:
ACE = "A"
JACK = "J"
QUEEN = "Q"
KING = "K"
@dataclass
class Card:
suit: Suit
symbol: Union[Symbol | int]
def evaluate(self) -> int:
match self:
case Card(_, Symbol.ACE) | Card(Suit.SPADE | Suit.CLUB, Symbol.JACK):
return 11
case Card(_, Symbol.JACK) | Card(_, Symbol.QUEEN) | Card(_, Symbol.KING):
return 10
case Card(_, int(n)) if n > 1 or n < 11:
return n
case _:
raise Exception("Invalid card")
# Use to compare the `case` version with the `if` version
def evaluate_with_if(self) -> int:
if (
self.symbol == Symbol.ACE
or ((self.suit == Suit.SPADE or self.suit == Suit.CLUB)
and self.symbol == Symbol.JACK)
):
return 11
elif (
self.symbol == Symbol.JACK
or self.symbol == Symbol.QUEEN
or self.symbol == Symbol.KING
):
return 10
elif type(self.symbol) is int and self.symbol > 1 and self.symbol < 11:
return self.symbol
else:
raise Exception("Invalid card")
class BlackJackHand:
def __init__(self, cards: List[Card]) -> None:
self.cards = cards
def eval_hand(self) -> int:
aces_count = len([c for c in self.cards if c.symbol == Symbol.ACE])
hand_value = sum([c.evaluate() for c in self.cards])
if aces_count > 0 and hand_value > 21:
return hand_value - aces_count * 10
return hand_value
if __name__ == "__main__":
print(
BlackJackHand(
[Card(Suit.DIAMOND, Symbol.ACE), Card(Suit.DIAMOND, 2)]
).eval_hand()
)
print(
BlackJackHand(
[Card(Suit.DIAMOND, Symbol.ACE), Card(Suit.DIAMOND, Symbol.KING)]
).eval_hand()
)
print(
BlackJackHand(
[Card(Suit.DIAMOND, Symbol.ACE), Card(Suit.SPADE, Symbol.JACK)]
).eval_hand()
)
print(
BlackJackHand(
[Card(Suit.DIAMOND, Symbol.ACE), Card(Suit.DIAMOND, Symbol.ACE)]
).eval_hand()
)
# Exercise: https://www.codewars.com/kata/5a25ac6ac5e284cfbe000111
class Color:
RED = "R"
GREEN = "G"
BLUE = "B"
def next_color(color1: str, color2: str) -> Color:
colors = (color1, color2)
match colors:
case (x, y) if x == y:
return x
case (Color.BLUE, Color.RED) | (Color.RED, Color.BLUE):
return Color.GREEN
case (Color.GREEN, Color.RED) | (Color.RED, Color.GREEN):
return Color.BLUE
case (Color.BLUE, Color.GREEN) | (Color.GREEN, Color.BLUE):
return Color.RED
case _:
raise(Exception("Color is not valid"))
# Use to compare the `case` version with the `if` version
def next_color_with_if(color1: str, color2: str) -> Color:
if color1 == color2:
return color1
elif (color1 == Color.BLUE and color2 == Color.RED) or (
color1 == Color.RED and color2 == Color.BLUE
):
return Color.GREEN
elif (color1 == Color.GREEN and color2 == Color.RED) or (
color1 == Color.RED and color2 == Color.GREEN
):
return Color.BLUE
elif (color1 == Color.BLUE and color2 == Color.GREEN) or (
color1 == Color.GREEN and color2 == Color.BLUE
):
return Color.RED
raise (Exception("Color is not valid"))
def gen_next_row(string: str) -> str:
return "".join(
[next_color(color1, string[i + 1]) for i, color1 in enumerate(string[:-1])]
)
def gen_color_triangle(colors: str) -> str:
match colors:
case "":
raise Exception("Invalid input")
case x if len(x) == 1:
return colors
case _:
next_row = gen_next_row(colors)
return gen_color_triangle(next_row)
if __name__ == "__main__":
print(gen_color_triangle("GG")) # -> G
print(gen_color_triangle("BG")) # -> R
print(gen_color_triangle("GR")) # -> B
print(gen_color_triangle("RRGBRGBB")) # -> G
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment