From 9f041e9cc82dab21401359d4cfa1b966fc30ddc4 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 2 Jan 2023 05:15:14 -0800 Subject: [PATCH] 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 --- fractals/sierpinski_triangle.py | 110 +++++++++++++++++--------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/fractals/sierpinski_triangle.py b/fractals/sierpinski_triangle.py index 084f6661f..c28ec00b2 100644 --- a/fractals/sierpinski_triangle.py +++ b/fractals/sierpinski_triangle.py @@ -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 sets—that 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 - -Credits: This code was written by editing the code from -https://www.riannetrujillo.com/blog/python-fractal/ +Usage: python sierpinski_triangle.py +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 " + "Correct format for using this script: " + "python fractals.py " ) 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]))