Created
December 7, 2015 19:51
-
-
Save CAridorc/a26f8f44ed0248d46044 to your computer and use it in GitHub Desktop.
A pair of necessary modules
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Simlates Conway's game of life. | |
""" | |
import doctest | |
import time | |
def in_chunks_of(n, list_): | |
""" | |
Yield successive n-sized chunks from l. | |
Credit to: http://stackoverflow.com/users/14343/ned-batchelder | |
>>> list(in_chunks_of(3, [1, 2, 3, 4, 5, 6, 7])) | |
[[1, 2, 3], [4, 5, 6], [7]] | |
""" | |
for i in xrange(0, len(list_), n): | |
yield list_[i:i+n] | |
def neightbors(x, y, matrix): | |
""" | |
>>> list(sorted(neightbors(1, 1, [ [1,2,3], [4,5,6], [7,8,9] ]))) | |
[1, 2, 3, 4, 6, 7, 8, 9] | |
""" | |
for x_, y_ in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1), | |
(x + 1, y + 1), (x + 1, y - 1), (x - 1, y + 1), (x - 1, y - 1)): | |
if x_ < 0 or y_ < 0: | |
continue | |
try: | |
yield matrix[x_][y_] | |
except IndexError: | |
pass | |
def with_neightbors(matrix): | |
""" | |
>>> list(with_neightbors( [ [1, 2, 3], [4, 5, 6] ] )) | |
[(1, [4, 2, 5]), (2, [5, 3, 1, 6, 4]), (3, [6, 2, 5]), (4, [1, 5, 2]), (5, [2, 6, 4, 3, 1]), (6, [3, 5, 2])] | |
""" | |
for x in range(len(matrix)): | |
for y in range(len(matrix[0])): | |
yield (matrix[x][y], list(neightbors(x, y, matrix))) | |
def rules(x, nears): | |
""" | |
>>> rules(True, [True, True, False, False, False, True, False, False]) | |
True | |
""" | |
return sum(nears) in (2, 3) if x else sum(nears) == 3 | |
def next_generation(universe): | |
""" | |
>>> next_generation([ [0,0,1], [1,1,0], [0, 0, 1] ]) | |
[[False, True, False], [False, True, True], [False, True, False]] | |
""" | |
return list(in_chunks_of(len(universe[0]), | |
[rules(x, neightbors) for x, neightbors in with_neightbors(universe)])) | |
def stringify_board(board): | |
""" | |
>>> start = " \\n ** \\n ** \\n " | |
>>> start == '\\n'.join(stringify_board(read_board(start))) | |
True | |
""" | |
for row in board: | |
yield ''.join('*' if i else ' ' for i in row) | |
def read_board(string_board): | |
""" | |
>>> read_board(" \\n ** \\n ** \\n ") | |
[[False, False, False, False], [False, True, True, False], [False, True, True, False], [False, False, False, False]] | |
""" | |
board = [] | |
for line in string_board.split("\n"): | |
board.append( [True if i == '*' else False for i in line] ) | |
return board | |
def ascii_life(board = None, generations=10**6): | |
board=read_board(board) | |
for _ in xrange(generations): | |
print('\n'.join(stringify_board(board))) | |
board = next_generation(board) | |
time.sleep(0.2) | |
print('\n'*50) | |
def main(): | |
doctest.testmod() | |
TOAD = """ | |
*** | |
*** | |
""" | |
RANDOM = """ | |
*** *** | |
**** | |
**** | |
** *** | |
""" | |
for figure in (TOAD, RANDOM): | |
try: | |
ascii_life(figure) | |
except KeyboardInterrupt: | |
continue | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
input = raw_input if sys.version_info[0] == 2 else input | |
def general_input(prompt="", type_=str, min_=None, max_=None, | |
max_length=None, set_=None, cap_sensitive=True, | |
help_=lambda: 0, costum_validation=lambda x: True, | |
costum_validation_error="Error in input"): | |
""" | |
Takes care of input validation, by diplaying meaningful | |
messages to the user in case of invalid input. | |
@ prompt: The text to be shown to the user. | |
@ type_: The type the input must be convertible to. (And will be converted to). | |
@ max_length: The maximum length of the input. | |
@ set_: The set of things the input must in. (This may be a `range` object or any iterable). | |
@ cap_sensitive: If False the input will be lowercased. (Defult True) | |
@ help_: What to do when the user types in `help` | |
@ costum_validation: A costum way to check if the input is valid. | |
@ costum_validation_error: Error to show when costum_validation fails | |
""" | |
while True: | |
input_ = input(prompt) | |
input_ = input_ if cap_sensitive else input_.lower() | |
if not costum_validation(input_): | |
print(costum_validation_error) | |
continue | |
if input_ == "help": | |
help_() | |
continue | |
try: | |
if not type_: | |
type_ = type(input_) | |
input_ = type_(input_) | |
except ValueError: | |
print("Expected input of type {} but got {}".format( | |
type_, type(input_))) | |
continue | |
if max_length and len(input_) > max_length: | |
print("Input is too long, the max length allowed is {}".format( | |
max_length)) | |
continue | |
if set_ and input_ not in set_: | |
# Fixing that the last item in ranges is exclusive (weird for normal users) | |
to_print_set = None | |
if type(set_) == range: | |
to_print_set = range(min(set_), max(set_)) | |
print("Input is not in the set of possible inputs, enter one of {}".format( | |
to_print_set or set_)) | |
continue | |
return input_ | |
def menu(functions): | |
""" | |
Allows for easy presentation to the user of functions, also | |
allowing him to get fast help. | |
""" | |
functions = list(sorted(functions, key=lambda fun: fun.__name__)) | |
for index, func in enumerate(functions): | |
print("{} - {}".format( | |
index + 1, func.__name__)) | |
def help_(): | |
function_to_be_explained = general_input("Which function do you want help on? ", | |
type_=int, set_=range(0,len(functions))) - 1 | |
help(functions[function_to_be_explained]) | |
user_choice = general_input("Which function do you want to execute? (Type `help` for help). ", | |
type_=int, set_=range(0,len(functions)+1), | |
help_= help_) - 1 | |
print(functions[user_choice](eval(input("Comma separated args for `{}`: ".format( | |
functions[user_choice].__name__))))); print() | |
def menu_for_module(module, private_shown=False): | |
""" | |
Shows a menu containing all the functions in a module | |
""" | |
priv_cond = lambda fun: fun.__name__.startswith('_') if not private_shown else False | |
menu([i for i in module.__dict__.values() if type(i) == type(lambda:0) and not priv_cond(i)]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment