Algebraic data types: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (Thundergnat moved page Pattern matching to Algebraic data types: Reanme page instead of manual move to preserve history) |
(Added Python) |
||
Line 1,792: | Line 1,792: | ||
insert(X,S,t(b,A,Y,B)) :- ins(X,S,t(_,A,Y,B)). |
insert(X,S,t(b,A,Y,B)) :- ins(X,S,t(_,A,Y,B)). |
||
</pre> |
|||
=={{header|Python}}== |
|||
{{trans|C sharp}} |
|||
Structural pattern matching was added to Python in version 3.10. |
|||
<lang python>from __future__ import annotations |
|||
from enum import Enum |
|||
from typing import NamedTuple |
|||
from typing import Optional |
|||
class Color(Enum): |
|||
B = 0 |
|||
R = 1 |
|||
class Tree(NamedTuple): |
|||
color: Color |
|||
left: Optional[Tree] |
|||
value: int |
|||
right: Optional[Tree] |
|||
def insert(self, val: int) -> Tree: |
|||
return self._insert(val).make_black() |
|||
def _insert(self, val: int) -> Tree: |
|||
match compare(val, self.value): |
|||
case _ if self == EMPTY: |
|||
return Tree(Color.R, EMPTY, val, EMPTY) |
|||
case -1: |
|||
assert self.left is not None |
|||
return Tree( |
|||
self.color, self.left._insert(val), self.value, self.right |
|||
).balance() |
|||
case 1: |
|||
assert self.right is not None |
|||
return Tree( |
|||
self.color, self.left, self.value, self.right._insert(val) |
|||
).balance() |
|||
case _: |
|||
return self |
|||
def balance(self) -> Tree: |
|||
match self: |
|||
case (Color.B, (Color.R, (Color.R, a, x, b), y, c), z, d): |
|||
return Tree(Color.R, Tree(Color.B, a, x, b), y, Tree(Color.B, c, z, d)) |
|||
case (Color.B, (Color.R, a, x, (Color.R, b, y, c)), z, d): |
|||
return Tree(Color.R, Tree(Color.B, a, x, b), y, Tree(Color.B, c, z, d)) |
|||
case (Color.B, a, x, (Color.R, (Color.R, b, y, c), z, d)): |
|||
return Tree(Color.R, Tree(Color.B, a, x, b), y, Tree(Color.B, c, z, d)) |
|||
case (Color.B, a, x, (Color.R, b, y, (Color.R, c, z, d))): |
|||
return Tree(Color.R, Tree(Color.B, a, x, b), y, Tree(Color.B, c, z, d)) |
|||
case _: |
|||
return self |
|||
def make_black(self) -> Tree: |
|||
return self._replace(color=Color.B) |
|||
def __str__(self) -> str: |
|||
if self == EMPTY: |
|||
return "[]" |
|||
return f"[{'R' if self.color == Color.R else 'B'}{self.value}]" |
|||
def print(self, indent: int = 0) -> None: |
|||
if self != EMPTY: |
|||
assert self.right is not None |
|||
self.right.print(indent + 1) |
|||
print(f"{' ' * indent * 4}{self}") |
|||
if self != EMPTY: |
|||
assert self.left is not None |
|||
self.left.print(indent + 1) |
|||
EMPTY = Tree(Color.B, None, 0, None) |
|||
def compare(x: int, y: int) -> int: |
|||
if x > y: |
|||
return 1 |
|||
if x < y: |
|||
return -1 |
|||
return 0 |
|||
def main(): |
|||
tree = EMPTY |
|||
for i in range(1, 17): |
|||
tree = tree.insert(i) |
|||
tree.print() |
|||
if __name__ == "__main__": |
|||
main() |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
[] |
|||
[R16] |
|||
[] |
|||
[B15] |
|||
[] |
|||
[B14] |
|||
[] |
|||
[B13] |
|||
[] |
|||
[B12] |
|||
[] |
|||
[B11] |
|||
[] |
|||
[B10] |
|||
[] |
|||
[B9] |
|||
[] |
|||
[B8] |
|||
[] |
|||
[B7] |
|||
[] |
|||
[B6] |
|||
[] |
|||
[B5] |
|||
[] |
|||
[B4] |
|||
[] |
|||
[B3] |
|||
[] |
|||
[B2] |
|||
[] |
|||
[B1] |
|||
[] |
|||
</pre> |
</pre> |
||
Line 2,540: | Line 2,674: | ||
{{omit from|Pascal}} |
{{omit from|Pascal}} |
||
{{omit from|Processing}} |
{{omit from|Processing}} |
||
{{omit from|Python}} |
|||
{{omit from|TI-83 BASIC}} |
{{omit from|TI-83 BASIC}} |
||
{{omit from|TI-89 BASIC}} |
{{omit from|TI-89 BASIC}} |