PKêb¨H.f n!n! rule_n.py#!/usr/bin/python3 # -*- coding: utf-8 -*- # rule_n - Elementary cellular automata in Python # Copyright (C) 2016 randomdude999 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Elementary cellular automata in Python. (See ) Usage: import rule_n rule_110 = rule_n.RuleN(110) rule_30 = rule_n.RuleN(30) rule_184 = rule_n.RuleN(184) # Works with anything from 1 to 255 rule_110 = rule_n.RuleN() # Default rule is 110 from rule_n import rule_90 # Shorthand for rule_90 = rule_n.RuleN(90) # Works with 110, 30, 90, 184 # You can also specify a list of rules rule_110 = rule_n.RuleN([False, True, True, False] + [True] * 3 + [False]) # Or a string that summarizes the rule rule_110 = rule_n.RuleN("01101110") # See # You can also have a finite canvas rule_110_finite_canvas = rule_n.RuleN(110, canvas_size=5) # A canvas is finite if its size is over 0 data = rule_110.process([True, False, True]) len(data) == 5 # because a False is added to both sides data == [True, True, True, True, False] data_2 = rule_110.process([1, 0, 1]) # You can use any data type, as long data == data_2 # as the boolean values of these are # correct # Return values are always in boolean # With a finite canvas, the output is always as big as the canvas data = rule_110_finite_canvas.process([0, 0, 0, 0, 1]) data == [False, False, False, True, True] data_3 = rule_110([True, False, True]) # Shorthand for # rule_110.process(state) data == data_3 i = 0 for x in rule_110.iterate([1, 0, 1]): # Repeatedly process a state print x i += 1 if i == 10: break # Please do this # Note: Iteration on an infinte canvas seems to have some problems # I recommend using a finite canvas for x in rule_110_finite_canvas.iterate([0, 0, 0, 0, 1]): print x # This breaks automatically if the current state is equal to the # previous, which will probably happen at some point on a finite canvas """ def _process_cell(i, state, finite=False): """Process 3 cells and return a value from 0 to 7. """ op_1 = state[i - 1] op_2 = state[i] if i == len(state) - 1: if finite: op_3 = state[0] else: op_3 = 0 else: op_3 = state[i + 1] result = 0 for i, val in enumerate([op_3, op_2, op_1]): if val: result += 2**i return result def _remove_lead_trail_false(bool_list): """Remove leading and trailing false's from a list""" # The internet can be a wonderful place... for i in (0, -1): while bool_list and not bool_list[i]: bool_list.pop(i) return bool_list def _crop_list_to_size(l, size): """Make a list a certain size""" for x in range(size - len(l)): l.append(False) for x in range(len(l) - size): l.pop() return l def _rules_from_int(inp): rules = [] for i in range(8): rules.append(bool(inp & 2**i)) return rules def _rules_from_list(l): rules = _crop_list_to_size(list(l), 8) rules.reverse() return rules def _rules_from_str(s): rules = [] if len(s) < 8: s += "0" * (8 - len(s)) null_chars = " 0" for x in range(8): if s[x] in null_chars: rules.append(False) else: rules.append(True) rules.reverse() return rules def _proc_rules(rule_descriptor): if type(rule_descriptor) is int: return _rules_from_int(rule_descriptor) elif type(rule_descriptor) is list or type(rule_descriptor) is tuple: return _rules_from_list(rule_descriptor) elif type(rule_descriptor) is str: return _rules_from_str(rule_descriptor) else: raise TypeError("Invalid rule_descriptor type (must be int, list, " "str or tuple)") class RuleN(object): """Elementary cellular automata "interpreter". Usage: rule_110 = rule_n.RuleN(110) # Create Rule 110 interpreter Default rule is 110, so the example could be shortened to: rule_110 = rule_n.RuleN() This works with any numbered rule numbered in this manner, see to learn more. You can also specify a list of actions directly. In this case, 110 would become [False, True, True, False, True, True, True, False]. See the abovementioned link for explanation. You can also specify the list of actions as a string of 0's and 1's. 110 would be "01101110". rule_110 = rule_n.RuleN("01101110") You can also have a finite canvas: rule_110 = rule_n.RuleN(110, canvas_size=5) A canvas is finite if its size is more than 0. """ def __init__(self, rule_descriptor=110, canvas_size=0): self.rules = _proc_rules(rule_descriptor) if canvas_size <= 0: if bool(self.rules[0]) and not bool(self.rules[7]): raise ValueError("111 can't turn to 0 when 000 turns to 1") self.default_val = self.rules[7] self.finite_canvas = False self.canvas_size = 0 else: self.canvas_size = canvas_size self.finite_canvas = True def __call__(self, state): return self.process(state) def __repr__(self): descriptor = 0 for i, x in enumerate(self.rules): descriptor += 2**i if x else 0 return "%s.%s(%s)" % (self.__class__.__module__, self.__class__.__name__, descriptor) def __eq__(self, other): if self.__class__ is other.__class__: return (self.rules == other.rules and self.canvas_size == other.canvas_size) return False def __ne__(self, other): return not self.__eq__(other) def process(self, state): """Process a state and return the next state Usage: out = rule_110.process([True, False, True]) len(out) # 5, because a False is added to either side out == [True, True, True, True, False] out = rule_110.process([False, True, False, True]) len(out) # still 5, because leading / trailing False's are removed out2 = rule_110.process([1, 0, 1]) # Any data type in the list is okay, as # long as it's boolean value is correct out == out2 """ if not isinstance(state, list): raise TypeError("state must be list") if self.finite_canvas: state = _crop_list_to_size(state, self.canvas_size) else: state = _remove_lead_trail_false(state) state.insert(0, self.default_val) state.append(self.default_val) new_state = [] for i in range(0, len(state)): result = _process_cell(i, state, finite=self.finite_canvas) new_state.append(self.rules[result]) return new_state def iterate(self, state): """Process a starting state over and over again. Example: for x in rule_110.iterate(state): # Do something with the current state here # Note: You should break this yourself # This breaks automatically if the previous state was the same as the # current one, but that's not gonna happen on an infinite canvas """ cur_state = state old_state = cur_state while True: cur_state = self.process(cur_state) if old_state == cur_state: break old_state = cur_state yield cur_state # 4 most common ones get shorthands rule_110 = RuleN(110) rule_30 = RuleN(30) rule_90 = RuleN(90) rule_184 = RuleN(184) PKVd¨Hú”íÔl l $rule_n-0.2.dist-info/DESCRIPTION.rst======== rule_n ======== .. image:: https://travis-ci.org/randomdude999/rule_n.svg :target: https://travis-ci.org/randomdude999/rule_n :alt: Travis CI .. image:: https://coveralls.io/repos/github/randomdude999/rule_n/badge.svg :target: https://coveralls.io/github/randomdude999/rule_n :alt: Coveralls .. image:: https://codeclimate.com/github/randomdude999/rule_n/badges/gpa.svg :target: https://codeclimate.com/github/randomdude999/rule_n :alt: Code Climate .. image:: https://img.shields.io/pypi/v/rule_n.svg :target: https://pypi.python.org/pypi/rule_n :alt: PyPI .. image:: https://img.shields.io/pypi/dm/rule_n.svg :target: https://pypi.python.org/pypi/rule_n#downloads :alt: Downloads .. image:: https://img.shields.io/pypi/l/rule_n.svg :target: https://raw.githubusercontent.com/randomdude999/rule_n/master/LICENSE :alt: License .. image:: https://img.shields.io/github/issues-raw/randomdude999/rule_n.svg :target: https://github.com/randomdude999/rule_n/issues :alt: Issues This is a Python implementation of `elementary cellular automata`_. .. _elementary cellular automata: https://en.wikipedia.org/wiki/Elementary_cellular_automaton Installation ============ Pip --- :: pip install rule_n Manual ------ Download |rule_n.py|_ and put it somewhere in your Python path. .. |rule_n.py| replace:: ``rule_n.py`` .. _rule_n.py: https://raw.githubusercontent.com/randomdude999/rule_n/master/rule_n.py Usage ===== :: import rule_n rule_110 = rule_n.RuleN(110) rule_30 = rule_n.RuleN(30) rule_184 = rule_n.RuleN(184) # Works with anything from 1 to 255 rule_110 = rule_n.RuleN() # Default rule is 110, as that is the most common from rule_n import rule_90 # Shorthand for rule_90 = rule_n.RuleN(90) # Works with 110, 30, 90, 184 # You can also specify a list of rules rule_110 = rule_n.RuleN([False, True, True, False, True, True, True, False]) # Or a string that summarizes the rule rule_110 = rule_n.RuleN("01101110") # See # You can also have a finite canvas rule_110_finite_canvas = rule_n.RuleN(110, canvas_size=5) # A canvas is finite if its size is over 0 data = rule_110.process([True, False, True]) len(data) == 5 # because a False is added to both sides data == [True, True, True, True, False] data_2 = rule_110.process([1, 0, 1]) # You can use any data type, as long data == data_2 # as the boolean values of these are # correct # Return values are always in boolean # With a finite canvas, the output is always as big as the canvas data = rule_110_finite_canvas.process([0, 0, 0, 0, 1]) data == [False, False, False, True, True] data_3 = rule_110([True, False, True]) # Shorthand for # rule_110.process(state) data == data_3 i = 0 for x in rule_110.iterate([1, 0, 1]): # Repeatedly process a state print x i += 1 if i == 10: break # Please do this # Note: Iteration on an infinte canvas seems to have some problems # I recommend using a finite canvas for x in rule_110_finite_canvas.iterate([0, 0, 0, 0, 1]): print x # This breaks automatically if the current state is equal to the # previous, which will probably happen at some point on a finite canvas PKVd¨H³¢›ÙÛÛ"rule_n-0.2.dist-info/metadata.json{"classifiers": ["Development Status :: 4 - Beta", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Scientific/Engineering :: Mathematics", "Topic :: Software Development :: Libraries :: Python Modules"], "extensions": {"python.details": {"contacts": [{"email": "just.so.you.can.email.me@gmail.com", "name": "randomdude999", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/randomdude999/rule_n"}}}, "generator": "bdist_wheel (0.26.0)", "license": "GPLv3", "metadata_version": "2.0", "name": "rule-n", "summary": "Elementary cellular automata in Python", "version": "0.2"}PKVd¨HÉÙ‘"rule_n-0.2.dist-info/top_level.txtrule_n PKVd¨Hìndªnnrule_n-0.2.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any PKVd¨Hùºò|èèrule_n-0.2.dist-info/METADATAMetadata-Version: 2.0 Name: rule-n Version: 0.2 Summary: Elementary cellular automata in Python Home-page: https://github.com/randomdude999/rule_n Author: randomdude999 Author-email: just.so.you.can.email.me@gmail.com License: GPLv3 Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Topic :: Scientific/Engineering :: Mathematics Classifier: Topic :: Software Development :: Libraries :: Python Modules ======== rule_n ======== .. image:: https://travis-ci.org/randomdude999/rule_n.svg :target: https://travis-ci.org/randomdude999/rule_n :alt: Travis CI .. image:: https://coveralls.io/repos/github/randomdude999/rule_n/badge.svg :target: https://coveralls.io/github/randomdude999/rule_n :alt: Coveralls .. image:: https://codeclimate.com/github/randomdude999/rule_n/badges/gpa.svg :target: https://codeclimate.com/github/randomdude999/rule_n :alt: Code Climate .. image:: https://img.shields.io/pypi/v/rule_n.svg :target: https://pypi.python.org/pypi/rule_n :alt: PyPI .. image:: https://img.shields.io/pypi/dm/rule_n.svg :target: https://pypi.python.org/pypi/rule_n#downloads :alt: Downloads .. image:: https://img.shields.io/pypi/l/rule_n.svg :target: https://raw.githubusercontent.com/randomdude999/rule_n/master/LICENSE :alt: License .. image:: https://img.shields.io/github/issues-raw/randomdude999/rule_n.svg :target: https://github.com/randomdude999/rule_n/issues :alt: Issues This is a Python implementation of `elementary cellular automata`_. .. _elementary cellular automata: https://en.wikipedia.org/wiki/Elementary_cellular_automaton Installation ============ Pip --- :: pip install rule_n Manual ------ Download |rule_n.py|_ and put it somewhere in your Python path. .. |rule_n.py| replace:: ``rule_n.py`` .. _rule_n.py: https://raw.githubusercontent.com/randomdude999/rule_n/master/rule_n.py Usage ===== :: import rule_n rule_110 = rule_n.RuleN(110) rule_30 = rule_n.RuleN(30) rule_184 = rule_n.RuleN(184) # Works with anything from 1 to 255 rule_110 = rule_n.RuleN() # Default rule is 110, as that is the most common from rule_n import rule_90 # Shorthand for rule_90 = rule_n.RuleN(90) # Works with 110, 30, 90, 184 # You can also specify a list of rules rule_110 = rule_n.RuleN([False, True, True, False, True, True, True, False]) # Or a string that summarizes the rule rule_110 = rule_n.RuleN("01101110") # See # You can also have a finite canvas rule_110_finite_canvas = rule_n.RuleN(110, canvas_size=5) # A canvas is finite if its size is over 0 data = rule_110.process([True, False, True]) len(data) == 5 # because a False is added to both sides data == [True, True, True, True, False] data_2 = rule_110.process([1, 0, 1]) # You can use any data type, as long data == data_2 # as the boolean values of these are # correct # Return values are always in boolean # With a finite canvas, the output is always as big as the canvas data = rule_110_finite_canvas.process([0, 0, 0, 0, 1]) data == [False, False, False, True, True] data_3 = rule_110([True, False, True]) # Shorthand for # rule_110.process(state) data == data_3 i = 0 for x in rule_110.iterate([1, 0, 1]): # Repeatedly process a state print x i += 1 if i == 10: break # Please do this # Note: Iteration on an infinte canvas seems to have some problems # I recommend using a finite canvas for x in rule_110_finite_canvas.iterate([0, 0, 0, 0, 1]): print x # This breaks automatically if the current state is equal to the # previous, which will probably happen at some point on a finite canvas PKVd¨H[1…Ôrule_n-0.2.dist-info/RECORDrule_n.py,sha256=dIASCa4LEqd2pLgjbtCcbVnbK5DrsMpMBxeyLwVPoEo,8558 rule_n-0.2.dist-info/DESCRIPTION.rst,sha256=vZINaHp6MUEJdKoNCxAuTyZ3YWE5vQMmPW_v4pq8H7k,3436 rule_n-0.2.dist-info/METADATA,sha256=VO7nC6gbJVQe4ZvngScz4IPzrI0LdcowwnS30yHiWsk,4328 rule_n-0.2.dist-info/RECORD,, rule_n-0.2.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110 rule_n-0.2.dist-info/metadata.json,sha256=o6zz_GKHDyD25_y4Bvb5TzDL3x43vLU09wO4LND6jpA,987 rule_n-0.2.dist-info/top_level.txt,sha256=nJRqrTXzjZJmb5qAclUKmwlE6HZ32mE2xp7TRodaRTc,7 PKêb¨H.f n!n! rule_n.pyPKVd¨Hú”íÔl l $•!rule_n-0.2.dist-info/DESCRIPTION.rstPKVd¨H³¢›ÙÛÛ"C/rule_n-0.2.dist-info/metadata.jsonPKVd¨HÉÙ‘"^3rule_n-0.2.dist-info/top_level.txtPKVd¨Hìndªnn¥3rule_n-0.2.dist-info/WHEELPKVd¨Hùºò|èèK4rule_n-0.2.dist-info/METADATAPKVd¨H[1…ÔnErule_n-0.2.dist-info/RECORDPKÅG