{"id":17897603,"url":"https://github.com/darshanime/sandpiles","last_synced_at":"2025-03-23T07:32:10.426Z","repository":{"id":18166169,"uuid":"83588271","full_name":"darshanime/sandpiles","owner":"darshanime","description":"Generalized Sandpiles for eyegasms","archived":false,"fork":false,"pushed_at":"2022-06-21T21:07:24.000Z","size":1618,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T18:45:39.616Z","etag":null,"topics":["python-script","sandpiles","sandpiles-fractal","visualization"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darshanime.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-01T18:39:31.000Z","updated_at":"2022-10-24T13:38:58.000Z","dependencies_parsed_at":"2022-09-02T07:41:39.988Z","dependency_job_id":null,"html_url":"https://github.com/darshanime/sandpiles","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darshanime%2Fsandpiles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darshanime%2Fsandpiles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darshanime%2Fsandpiles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darshanime%2Fsandpiles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darshanime","download_url":"https://codeload.github.com/darshanime/sandpiles/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245072095,"owners_count":20556352,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python-script","sandpiles","sandpiles-fractal","visualization"],"created_at":"2024-10-28T15:11:35.402Z","updated_at":"2025-03-23T07:32:10.055Z","avatar_url":"https://github.com/darshanime.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Generalized Sandpiles\n\n\u003cimg src=\"https://github.com/darshanime/sandpiles/blob/master/images/sandpiles.gif\" width=\"500\" height=\"250\"\u003e\n\nSandpiles are a very interesting construct to play with. Guided by 2 simple rules, they make _for fun_ (noticed the alliteration?) visualizations. \n\nHere are the vanilla sandpile rules:\n\n 1.  You have a grid of blocks (may or may not be a square). Each square in the grid can hold maximum of 3 sand particles.\n\n 2.  When any grid exceeds 3 sand particles, they topple\n\n\n\u003cimg src=\"https://github.com/darshanime/sandpiles/blob/master/images/sandpiles_1.png\" width=\"250\" height=\"250\"\u003e\n\u003cimg src=\"https://github.com/darshanime/sandpiles/blob/master/images/sandpiles_2.png\" width=\"250\" height=\"250\"\u003e\n\u003cimg src=\"https://github.com/darshanime/sandpiles/blob/master/images/sandpiles_3.png\" width=\"250\" height=\"250\"\u003e\n\nThis happens forever until we have a stable sandpile. Pretty neat eh?\n\n## Generalized sandpiles\n\nIn this project, I have generalized the maximum that any square can hold. \nSo, you can choose the maximum for any one square to be say, 10 while everone else is at 3. \n\nThis can make for some pretty graphics when done on a large sandpile.\n\n```\n$ pip install sandpiles\n```\n\n## Demo visualization\n\n### Gifs\n\nThe gif above is created with 100 grains on the four corners of a 6x12 board. It ran for 29 iterations before stabilizing.\n\n```python\n\nIn [1]: from sandpiles.visualize import sandpile, run_pile, create_gif\n\nIn [2]: pile = sandpile(size=\"6x12\", initial_max=0, initial_min=0)\n\nIn [3]: pile[(1, 12)][\"#\"] = 100\n\nIn [4]: pile[(6, 1)][\"#\"] = 100\n\nIn [5]: pile[(6, 12)][\"#\"] = 100\n\nIn [6]: pile[(1, 1)][\"#\"] = 100\n\nIn [7]: run_pile(pile, picture=False, gif=True)\nCreated sandpiles.gif\nRan for 29 iterations\n\n```\n\n### Images\n\n\nUse it like so:\n\n```python\n\nIn [1]: from sandpiles.visualize import sandpile, run_pile\n\n# creating an empty 30x100 grid\nIn [2]: pile = sandpile(size=\"30x100\", initial_max=0, initial_min=0)\n\n# adding 10,000 grains at bottom center square\nIn [3]: pile[(30, 50)][\"#\"] = 10000\n\n# simulating the pile\nIn [4]: run_pile(pile, save=True)\nRan for 3644 iterations\n\nIn [5]: !ls sandpile.png\nsandpile.png\n\n```\n\nThe script will produce this image\n\n![img](https://github.com/darshanime/sandpiles/blob/master/images/sandpiles_4.png)\n\n\nor print labels too:\n```python\nIn [1]: pile = sandpile(size=\"10x50\", initial_max=10, initial_min=10)\nIn [2]: run_pile(pile, labels=True)\nRan for 139 iterations\n```\n\n![img](https://github.com/darshanime/sandpiles/blob/master/images/sandpiles_5.png)\n\n\n## Implementation details\n\n### `sandpile` definition\n\nDefine a sandpile by giving the dimensions and characteristics of the grid. The max of each square in the grid is chosen by random and lies between `sand_min` and `sand_max`. The initial sand grains on each square are chosen randomly too and lie between `initial_min` and `initial_max`\n\n`sandpile` argument signature:\n```python\nsandpile(size=\"3x3\", sand_min=3, sand_max=3, initial_min=10, initial_max=10):\n```\n\nAlso, `run_pile` can print labels on the image if required\n`run_pile` argument signature:\n```python\nrun_pile(pile, save=False, labels=False):\n```\n\n### `pile` structure\n- The primary data structure used is the `pile` hashtable (python dict). It is *1-indexed*, and has the following structure:\n\n```python\n\nIn [1]: pile = sandpile(size=\"2x2\")\n\nIn [2]: pile\nOut[2]:\ndefaultdict(dict,\n            {'c': 2,\n             'r': 2,\n             (1, 1): {'#': 10, 'max': 3},\n             (1, 2): {'#': 10, 'max': 3},\n             (2, 1): {'#': 10, 'max': 3},\n             (2, 2): {'#': 10, 'max': 3}})\n```\n\nSo, each square in the grid has 2 parameters -\n - \\# --\u003e the number of sand grains on that square\n - max --\u003e the maximum number of grains that square can hold, after which it topples\n\n\n### Toppling order\n\nSince the maximum for any square is not 3 but can be decided by the user, I have defined a clockwise toppling order for each square. \n\nThat means, if any square has a \"max\" of 2, and \"#\" is 3; it will topple the first grain to the square on it's left, then the one above it, next to the one to it's right. It cannot topple to the one below it because it has no more grains left now.\n\n______\n\nInspired by this amazing video - \u003chttps://www.youtube.com/watch?v=1MtEUErz7Gg\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarshanime%2Fsandpiles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarshanime%2Fsandpiles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarshanime%2Fsandpiles/lists"}