Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

IPython notebook 2015-03-02-092902.ipynb

49 views
Kernel: Unknown Kernel
""" When I read the specs for this project I immediately spotted a graph theory problem, where the dungeon is the graph and each room within the dungeon is a node. At that point I felt I had two choices: code it all out or use an existing/established library for graphs. Since this is not homework and in the "real world" reinventing the wheel is frowned upon, I went with the Networkx Python library. I created a Dungeon class that has attributes of an identity matrix and start/end rooms. The class consists of a constructor and methods for setting start/end nodes, validating the dungeon for a 3 node cycles, validating the dungeon for rooms that have more than 6 adjacent rooms, and solving the escape route out of the dungeon. Checking for the maximum number of adjacent rooms was a matter of examining each row of the identify matrix. To check for 3 node cycles, the cycle_basis method from the Networkx method was used. Any resulting cycle that had 3 nodes was flagged. The escape route was computed by using Dijkstra's algorithm, which was part of the Networkx library as well. Since the adjacency matrix supplied are even weights, it works out the same, but if the Dungeon Master wanted to make rooms larger, and reflect those weights within the adjacency matrix, the flexibility is there Time complexity: O(V^2), V = number of nodes/verticies/rooms Space complexity: O(E*log E + V), where E = edges/paths, V = number of nodes/verticies/rooms The test program tests various matricies that will yield a successful exit of the dungeon and those that will fail due to not being up to the dungeon code. The output results are: Dungeon Created Dungeon Created Dungeon Created Dungeon Created Dungeon Has To Have At Least Two Rooms Error: 3 Node Cycle Invalid Dungeon [0, 1, 2] Too Many Adjacent Rooms Invalid Dungeon [0, 4, 5, 6, 7] """ import networkx as nx import numpy as np """ maximum adjacent nodes """ CONST_MAX_PATHS = 6 """ minimum cycle """ CONST_MIN_CYCLE = 3 class Dungeon: """ Holds the graph """ layout=[] """ start node """ start=0 """ end node """ end=0 """ Constructor """ def __init__(self,idMat): try: if len(idMat) >= 2: self.layout=nx.from_numpy_matrix(idMat, create_using=nx.Graph()) print "Dungeon Created" else: print "Dungeon Has To Have At Least Two Rooms" except: print "Invalid Dungeon Matrix" """ sets the start node/room """ def setStart(self,s): self.start =s """sets the end node/room """ def setEnd(self,e): self.end =e """ makes sure room does not have more than 6 adjacent nodes """ def validateRoomCount(self): for x in range(0, len(self.layout)): if len(self.layout[x]) > CONST_MAX_PATHS: print "Too Many Adjacent Rooms" return False return True """ makes sure room does not have 3 node cycles """ def validateCycle(self): arr = nx.cycle_basis(self.layout) for row in arr: if len(row)==CONST_MIN_CYCLE: print "Error: 3 Node Cycle" return False return True """ prints the path to exit dungeon """ def getOut(self): print nx.dijkstra_path(self.layout, self.start, self.end) """ Matrix A: used to test the case that a graph where A adjacent to B, B adjacent to C, and C adjacent to A is not allowed """ A = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) """ Matrix B: a valid matrix with no 3 node cycles """ B = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) """ Matrix C: used to test the case that a graph containing a node with more than 6 adjacent nodes is not valid """ C = np.array([[0,1,0,0,0,0,0,1], [1,0,1,0,0,0,0,0], [0,1,0,1,0,0,0,0], [0,0,1,0,1,0,0,0], [0,0,0,1,0,1,0,0], [0,0,0,0,1,0,1,0], [0,1,1,1,1,1,1,1], [1,0,0,0,0,0,1,0] ]) """ Matrix D: valid matrix """ D = np.array([[0,1,0,0,1,0,0,0], [1,0,1,0,0,0,0,0], [0,1,0,1,0,0,0,0], [0,0,1,0,1,0,0,0], [1,0,0,1,0,1,0,0], [0,0,0,0,1,0,1,0], [0,0,0,0,0,1,0,1], [0,0,0,0,0,0,1,0] ]) """ Matrix E: Invalid 1 room matrix """ E = np.array([[0]]) testCase1 = Dungeon(A) testCase2 = Dungeon(B) testCase3 = Dungeon(C) testCase4 = Dungeon(D) testCase5 = Dungeon(E) """ Setting start and end rooms/nodes """ testCase1.setStart(0) testCase2.setStart(0) testCase3.setStart(0) testCase4.setStart(0) testCase1.setEnd(2) testCase2.setEnd(2) testCase3.setEnd(7) testCase4.setEnd(7) """ Attempting to solve each dungeon """ if testCase1.validateCycle()==True and testCase1.validateRoomCount()==True: testCase1.getOut() else: print "Invalid Dungeon" if testCase2.validateCycle()==True and testCase2.validateRoomCount()==True: testCase2.getOut() else: print "Invalid Dungeon" if testCase3.validateRoomCount()==True and testCase3.validateCycle()==True: testCase3.getOut() else: print "Invalid Dungeon" if testCase4.validateRoomCount()==True and testCase4.validateCycle()==True: testCase4.getOut() else: print "Invalid Dungeon"
Dungeon Created Dungeon Created Dungeon Created Dungeon Created Dungeon Has To Have At Least Two Rooms Error: 3 Node Cycle Invalid Dungeon [0, 1, 2] Too Many Adjacent Rooms Invalid Dungeon [0, 4, 5, 6, 7]
import pip installed_packages = pip.get_installed_distributions() installed_packages_list = sorted(["%s==%s" % (i.key, i.version) for i in installed_packages]) print(installed_packages_list)
['apsw==3.8.2.post1', 'apt-xapian-index==0.46', 'astropy==1.0', 'babel==1.3', 'backports.ssl-match-hostname==3.4.0.2', 'basemap==1.0.8', 'beautifulsoup4==4.3.2', 'beautifulsoup==3.2.1', 'biopython==1.61', 'bitarray==0.8.1', 'boto==2.36.0', 'brewer2mpl==1.4.1', 'bzr==2.7.0.dev1', 'certifi==14.5.14', 'characteristic==0.1.0', 'chardet==2.2.1', 'cherrypy==3.5.0', 'clawpack==5.2.2', 'colorpy==0.1.1', 'configobj==4.7.2', 'cryptoplus==1.0', 'cssselect==0.9.1', 'cssutils==0.9.10', 'cvxopt==1.1.7', 'cypari==1.2', 'cython==0.21.1', 'dblatex==0.3.5-1', 'decorator==3.4.0', 'dnspython==1.11.1', 'docutils==0.12', 'dot2tex==2.9.0.dev0', 'ecdsa==0.11', 'ez-setup==0.9', 'fabric==1.10.1', 'feedparser==5.1.3', 'ffc==1.5.0', 'fiat==1.5.0', 'fipy==3.1', 'flake8==2.1.0', 'flask-autoindex==0.5', 'flask-babel==0.9', 'flask-oldsessions==0.10', 'flask-openid==1.2.4', 'flask-silk==0.2', 'flask==0.10.1', 'folium==0.1.3', 'fuse-python==0.2.1', 'gdal==1.11.2', 'gdmodule==0.56', 'ggplot==0.6.5', 'gmpy2==2.0.5', 'gmpy==1.15', 'gnuplot-py==1.8', 'goslate==1.3.2', 'greenlet==0.4.5', 'guppy==0.1.8', 'gyp==0.1', 'h5py==2.4.0', 'html5lib==0.999', 'httplib2==0.9', 'idna==0.9', 'instant==1.5.0', 'iotop==0.6', 'ipython==2.3.0', 'ipythonblocks==1.7.0', 'itsdangerous==0.24', 'jinja2==2.5.5', 'joblib==0.8.4', 'jsanimation==0.1', 'keyring==4.0', 'kwant==1.0.1', 'landscape-client==14.12', 'launchpadlib==1.10.2', 'lazr.restfulclient==0.13.3', 'lazr.uri==1.0.3', 'lhapdf==5.9.1', 'line-profiler==1.0', 'lxml==3.4.2', 'mahotas==1.2.4', 'markdown==2.5.1', 'matplotlib==1.3.1', 'mccabe==0.2.1', 'mechanize==0.2.5', 'meld==3.12.0', 'mercurial==3.3', 'mmh3==2.3', 'mock==1.0.1', 'mpld3==0.2', 'mpmath==0.18', 'mrjob==0.4.2', 'munkres==1.0.7', 'mygene==2.2.0', 'mysql-python==1.2.5', 'netcdf4==1.1.4.1', 'netifaces==0.10.4', 'networkx==1.8.1', 'neuron==7.4', 'nose==1.3.3', 'numexpr==2.4', 'numpy==1.8.1', 'nzmath==1.1.0', 'oauth==1.0.1', 'obspy==0.9.2-dirty', 'oct2py==3.1.0', 'openpyxl==1.7.0', 'ore-algebra==0.2', 'pam==0.4.2', 'pandas==0.15.2', 'pandasql==0.6.2', 'paramiko==1.15.2', 'patsy==0.3.0', 'pattern==2.6', 'pep8==1.5.6', 'pexpect==2.0', 'pgroupcohomology==2.1.4', 'pillow==2.2.2', 'pint==0.6', 'pip==6.0.8', 'pkgconfig==1.1.0', 'plink==1.7.1', 'plotly==1.6.8', 'psutil==2.2.1', 'psycopg2==2.6', 'pyasn1-modules==0.0.5', 'pyasn1==0.1.7', 'pybtex==0.16', 'pycrypto==2.6.1', 'pycurl==7.19.5', 'pydelay==0.1.1', 'pyflakes==0.8.1', 'pyglet==1.1.4', 'pygments==1.3.1', 'pygobject==3.14.0', 'pygpgme==0.3', 'pylibacl==0.5.2', 'pymongo==2.8', 'pyopenssl==0.13.1', 'pyparse==1.1.7', 'pyparsing==1.5.6', 'pypng==0.0.17', 'pyproj==1.9.4', 'pyro==3.14', 'pysal==1.9.1', 'pyserial==2.6', 'pystan==2.6.0.0', 'python-apt==0.9.3.10ubuntu1', 'python-dateutil==2.2', 'python-debian==0.1.22', 'python-igraph==0.7.1-2', 'python-openid==2.2.5', 'pytz==2013b0', 'pyx==0.10', 'pyxattr==0.5.3', 'pyyaml==3.10', 'pyzmq==14.3.0', 'quantlib-python==1.4', 'qutip==3.1.0', 'redis==2.10.3', 'repoze.lru==0.6', 'requests==2.5.1', 'roman==2.0.0', 'rootpy==0.7.1', 'routes==2.0', 'rpy2==2.5.6', 'sage==6.5', 'sagenb==0.11.4', 'sagetex==2.3.4', 'scientificpython==2.9.4', 'scikit-image==0.10.1', 'scikit-learn==0.15.2', 'scipy==0.14.0', 'seaborn==0.5.1', 'secretstorage==2.1.1', 'service-identity==1.0.0', 'setuptools==3.6', 'shapely==1.5.6', 'simplegeneric==0.8.1', 'simplejson==3.6.5', 'simpy==3.0.6', 'singledispatch==3.4.0.3', 'six==1.4.1', 'snappy==2.2', 'speaklater==1.3', 'spherogram==1.3', 'sphinx==1.2.2', 'sqlalchemy==0.9.7', 'ssh-import-id==3.21', 'statsmodels==0.6.1', 'suds==0.4.1', 'sympy==0.7.5', 'system-service==0.1.6', 'tables==3.1.1', 'tabulate==0.7.4', 'theano==0.6.0', 'tinyarray==1.0.5', 'tornado==4.1', 'twisted-core==14.0.2', 'twisted==14.0.2', 'ufl==1.5.0', 'urllib3==1.8.3', 'utidylib==0.2', 'virtualenv==1.11.6', 'wadllib==1.3.2', 'webassets==0.10.1', 'webob==1.4', 'werkzeug==0.9.6', 'xlrd==0.9.3', 'xlwt==0.7.5', 'zope.interface==4.1.2']