Refactor sierpinski_triangle.py (#8068)

* updating DIRECTORY.md

* Update sierpinski_triangle.py header doc

* Remove unused PROGNAME var in sierpinski_triangle.py

The PROGNAME var was used to print an image description in the reference
code that this implementation was taken from, but it's entirely unused
here

* Refactor triangle() function to not use list of vertices

Since the number of vertices is always fixed at 3, there's no need to
pass in the vertices as a list, and it's clearer to give the vertices
distinct names rather than index them from the list

* Refactor sierpinski_triangle.py to use tuples

Tuples make more sense than lists for storing coordinate pairs

* Flip if-statement condition in sierpinski_triangle.py to avoid nesting

* Add type hints to sierpinski_triangle.py

* Add doctests to sierpinski_triangle.py

* Fix return types in doctests

* Update fractals/sierpinski_triangle.py

Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
Tianyi Zheng 2023-01-02 05:15:14 -08:00 committed by GitHub
parent 725731c8d2
commit 9f041e9cc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,76 +1,84 @@
#!/usr/bin/python
"""
Author Anurag Kumar | anuragkumarak95@gmail.com | git/anuragkumarak95
"""Author Anurag Kumar | anuragkumarak95@gmail.com | git/anuragkumarak95
Simple example of fractal generation using recursion.
Simple example of Fractal generation using recursive function.
What is the Sierpiński Triangle?
The Sierpiński triangle (sometimes spelled Sierpinski), also called the
Sierpiński gasket or Sierpiński sieve, is a fractal attractive fixed set with
the overall shape of an equilateral triangle, subdivided recursively into
smaller equilateral triangles. Originally constructed as a curve, this is one of
the basic examples of self-similar setsthat is, it is a mathematically
generated pattern that is reproducible at any magnification or reduction. It is
named after the Polish mathematician Wacław Sierpiński, but appeared as a
decorative pattern many centuries before the work of Sierpiński.
What is Sierpinski Triangle?
>>The Sierpinski triangle (also with the original orthography Sierpinski), also called
the Sierpinski gasket or the Sierpinski Sieve, is a fractal and attractive fixed set
with the overall shape of an equilateral triangle, subdivided recursively into smaller
equilateral triangles. Originally constructed as a curve, this is one of the basic
examples of self-similar sets, i.e., it is a mathematically generated pattern that can
be reproducible at any magnification or reduction. It is named after the Polish
mathematician Wacław Sierpinski, but appeared as a decorative pattern many centuries
prior to the work of Sierpinski.
Requirements(pip):
- turtle
Python:
- 2.6
Usage:
- $python sierpinski_triangle.py <int:depth_for_fractal>
Credits: This code was written by editing the code from
https://www.riannetrujillo.com/blog/python-fractal/
Usage: python sierpinski_triangle.py <int:depth_for_fractal>
Credits:
The above description is taken from
https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle
This code was written by editing the code from
https://www.riannetrujillo.com/blog/python-fractal/
"""
import sys
import turtle
PROGNAME = "Sierpinski Triangle"
points = [[-175, -125], [0, 175], [175, -125]] # size of triangle
def get_mid(p1: tuple[float, float], p2: tuple[float, float]) -> tuple[float, float]:
"""
Find the midpoint of two points
>>> get_mid((0, 0), (2, 2))
(1.0, 1.0)
>>> get_mid((-3, -3), (3, 3))
(0.0, 0.0)
>>> get_mid((1, 0), (3, 2))
(2.0, 1.0)
>>> get_mid((0, 0), (1, 1))
(0.5, 0.5)
>>> get_mid((0, 0), (0, 0))
(0.0, 0.0)
"""
return (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2
def get_mid(p1, p2):
return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2) # find midpoint
def triangle(points, depth):
def triangle(
vertex1: tuple[float, float],
vertex2: tuple[float, float],
vertex3: tuple[float, float],
depth: int,
) -> None:
"""
Recursively draw the Sierpinski triangle given the vertices of the triangle
and the recursion depth
"""
my_pen.up()
my_pen.goto(points[0][0], points[0][1])
my_pen.goto(vertex1[0], vertex1[1])
my_pen.down()
my_pen.goto(points[1][0], points[1][1])
my_pen.goto(points[2][0], points[2][1])
my_pen.goto(points[0][0], points[0][1])
my_pen.goto(vertex2[0], vertex2[1])
my_pen.goto(vertex3[0], vertex3[1])
my_pen.goto(vertex1[0], vertex1[1])
if depth > 0:
triangle(
[points[0], get_mid(points[0], points[1]), get_mid(points[0], points[2])],
depth - 1,
)
triangle(
[points[1], get_mid(points[0], points[1]), get_mid(points[1], points[2])],
depth - 1,
)
triangle(
[points[2], get_mid(points[2], points[1]), get_mid(points[0], points[2])],
depth - 1,
)
if depth == 0:
return
triangle(vertex1, get_mid(vertex1, vertex2), get_mid(vertex1, vertex3), depth - 1)
triangle(vertex2, get_mid(vertex1, vertex2), get_mid(vertex2, vertex3), depth - 1)
triangle(vertex3, get_mid(vertex3, vertex2), get_mid(vertex1, vertex3), depth - 1)
if __name__ == "__main__":
if len(sys.argv) != 2:
raise ValueError(
"right format for using this script: "
"$python fractals.py <int:depth_for_fractal>"
"Correct format for using this script: "
"python fractals.py <int:depth_for_fractal>"
)
my_pen = turtle.Turtle()
my_pen.ht()
my_pen.speed(5)
my_pen.pencolor("red")
triangle(points, int(sys.argv[1]))
vertices = [(-175, -125), (0, 175), (175, -125)] # vertices of triangle
triangle(vertices[0], vertices[1], vertices[2], int(sys.argv[1]))