Abelian sandpile model: Difference between revisions
Content added Content deleted
(add task to aarch64 assembly) |
|||
Line 2,459: | Line 2,459: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
===Python: Original, with output=== |
|||
<lang Python> |
<lang Python> |
||
import numpy as np |
import numpy as np |
||
Line 2,624: | Line 2,625: | ||
0 0 0 0 0 0 0 0 0 0 |
0 0 0 0 0 0 0 0 0 0 |
||
0 0 0 0 0 0 0 0 0 0 |
0 0 0 0 0 0 0 0 0 0 |
||
</lang> |
|||
===Python: using tkinter=== |
|||
<lang python> |
|||
''' Python 3.6.5 code using Tkinter graphical user |
|||
interface (Canvas widget) to display final results.''' |
|||
from tkinter import * |
|||
# given a grid, display it on a tkinter Canvas: |
|||
class Sandpile: |
|||
def __init__(self, wn, grid): |
|||
self.window = wn |
|||
self.grid = grid |
|||
self.canvas = Canvas(wn, bg='lemon chiffon') |
|||
self.canvas.pack(fill=BOTH, expand=1) |
|||
colors = {0:'dodger blue', |
|||
1:'red', |
|||
2:'green', |
|||
3:'lemon chiffon'} |
|||
x = 10 |
|||
y = 10 |
|||
d = 5 |
|||
for row in self.grid: |
|||
for value in row: |
|||
clr = colors[value] |
|||
self.canvas.create_rectangle( |
|||
x, y, x+d, y+d, |
|||
outline=clr, |
|||
fill = clr) |
|||
x += 5 |
|||
x = 10 |
|||
y += 5 |
|||
class Grid: |
|||
def __init__(self, size, center): |
|||
self.size = size # rows/cols in (best if odd) |
|||
self.center = center # start value at center of grid |
|||
self.grid = [[0]*self.size for i in range(self.size)] |
|||
self.grid[self.size // 2][self.size // 2] = self.center |
|||
# print the grid: |
|||
def show(self, msg): |
|||
print(' ' + msg + ':') |
|||
for row in self.grid: |
|||
print(' '.join(str(x) for x in row)) |
|||
print() |
|||
return |
|||
# dissipate piles of sand as required: |
|||
def abelian(self): |
|||
while True: |
|||
found = False |
|||
for r in range(self.size): |
|||
for c in range(self.size): |
|||
if self.grid[r][c] > 3: |
|||
self.distribute(self.grid[r][c], r, c) |
|||
found = True |
|||
if not found: |
|||
return |
|||
# distribute sand from a single pile to its neighbors: |
|||
def distribute(self, nbr, row, col): |
|||
qty, remain = divmod(nbr, 4) |
|||
self.grid[row][col] = remain |
|||
for r, c in [(row+1, col), |
|||
(row-1, col), |
|||
(row, col+1), |
|||
(row, col-1)]: |
|||
self.grid[r][c] += qty |
|||
return |
|||
# display the grid using tkinter: |
|||
def display(self): |
|||
root = Tk() |
|||
root.title('Sandpile') |
|||
root.geometry('700x700+100+50') |
|||
sp = Sandpile(root, self.grid) |
|||
root.mainloop() |
|||
# execute program for size, center value pair: |
|||
# just print results for a small grid |
|||
g = Grid(9,17) |
|||
g.show('BEFORE') |
|||
g.abelian() # scatter the sand |
|||
g.show('AFTER') |
|||
# just show results in tkinter for a large grid |
|||
# I wish there was a way to attach a screen shot |
|||
# of the tkinter result here |
|||
g = Grid(131,25000) |
|||
g.abelian() # scatter the sand |
|||
g.display() # display result using tkinter |
|||
## OUTPUT: |
|||
## |
|||
## BEFORE: |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 17 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## |
|||
## AFTER: |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 1 0 0 0 0 |
|||
## 0 0 0 2 1 2 0 0 0 |
|||
## 0 0 1 1 1 1 1 0 0 |
|||
## 0 0 0 2 1 2 0 0 0 |
|||
## 0 0 0 0 1 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
## 0 0 0 0 0 0 0 0 0 |
|||
</lang> |
</lang> |
||