Created
April 11, 2016 17:08
-
-
Save 1328/82f1fc1ecb3489ad944b4c1013fe9ab6 to your computer and use it in GitHub Desktop.
cars
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 numpy as np | |
from itertools import product | |
from random import shuffle,random | |
def blank_road(**args): | |
lanes, cells = args['lanes'], args['cells'] | |
return np.zeros((lanes, cells)) | |
def all_spots(**args): | |
''' | |
this is a bit tricky, but useful: yields out all possible spots on road | |
surface | |
''' | |
return product(range(args['lanes']), range(args['cells'])) | |
def populate(**args): | |
''' | |
populates a blank road with cars number of cars | |
''' | |
road = blank_road(**args) | |
positions = list(all_spots(**args)) | |
shuffle(positions) | |
positions = positions[:args['start_cars']] | |
for position in positions: | |
road[position] = 1 | |
return road | |
def next_positions(current, **args): | |
''' | |
return all future possible positions from position current | |
''' | |
# first possible check is always one car length ahead | |
possibles = [ (current[0], current[1]+1)] # move one forward | |
# next check if can overtake in lane -1 | |
if current[0]-1 >= 0: | |
possibles.append( (current[0]-1, current[1]+1)) | |
# next check if can overtake in lane +1 | |
if current[0]+1 < args['lanes']: | |
possibles.append( (current[0]+1, current[1]+1)) | |
return possibles | |
def path(road, current, **args): | |
''' | |
return the next valid position from current | |
given the road state of road | |
''' | |
for possible in next_positions(current, **args): | |
if road[possible] == 0: | |
return possible | |
# no possible positions, so retun current spot | |
return current | |
def check_stall(**args): | |
return random() < args['stall_chance'] | |
def cycle(road, **args): | |
''' | |
does one cycle walking road forward into a new state | |
return a new road array | |
''' | |
result = blank_road(**args) | |
for current in all_spots(**args): | |
if current[1]+1 == args['cells']: | |
# at final cell, skip b/c we assume that you have a clear shot at | |
# next | |
continue | |
if road[(current)] == 0: | |
# no car at current, so move on | |
continue | |
if check_stall(**args): | |
print('car at {} stalled'.format(current)) | |
new_position = current | |
else: | |
# try and move forward | |
new_position = path(road, current, **args) | |
if new_position == current: | |
print('car at {} blocked'.format(current)) | |
result[new_position] = 1 | |
return result | |
def print_road(road, **args): | |
''' | |
print the current road state to screen | |
''' | |
# here i break out lanes and cells from args to make the comprehension a bit | |
# easier to follow | |
lanes = args['lanes'] | |
cells = args['cells'] | |
for lane in range(lanes): | |
output = ''.join('O' if road[(lane, cell)] else '.' for cell in range(cells)) | |
print(output) | |
def test(): | |
defaults = { | |
'lanes':3, | |
'cells':20, | |
'start_cars': 15, | |
'stall_chance': .4, # chance car will not move in a cycle | |
} | |
road = populate(**defaults) | |
for i in range(10): | |
print_road(road, **defaults) | |
road = cycle(road, **defaults) | |
print() | |
if __name__ == '__main__': | |
test() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment