An attempt to solve FizzBuzz with 100 print()
statement—with extra steps.
Inspiration came from the first chapter in this book. Do it with Python’s abstract syntax tree.
This function creates an ast.Module
to which all print statements are appended. These statements are created and extracted on the first couple of lines.
The print-statements are appended in the most trivial way possible with if/elif/else block.
import copy
import ast
fizz = ast.parse("print('fizz')").body[0]
buzz = ast.parse("print('buzz')").body[0]
fizzbuzz = ast.parse("print('fizzbuzz')").body[0]
# Three alone is an expression; not _ast.Constant
constant = ast.parse('3').body[0].value
ast_print = ast.parse('print()').body[0]
def create_ast():
print_stmt = copy.deepcopy(ast_print)
print_stmt.value.args.append(None)
cur_const = copy.deepcopy(constant)
i = ast.Module()
i.type_ignores = []
i.body = []
for j in range(100):
if not j % 15:
i.body.append(fizzbuzz)
elif not j % 3:
i.body.append(fizz)
elif not j % 5:
i.body.append(buzz)
else:
cur_const.value = j
print_stmt.value.args[0] = cur_const
# Create a deep-copy, otherwise it's all by reference
i.body.append(copy.deepcopy(print_stmt))
ast.fix_missing_locations(i)
return i
if __name__ == '__main__':
exec(compile(create_ast(), filename="<ast>", mode="exec"))
References
https://greentreesnakes.readthedocs.io/
Open Questions
- Is it possible to have self-modifying code in Python?
- The AST isn’t growing but looping and modifying itself.