<jupyter_start><jupyter_text>main() Computes how the "sand" would fall if a 'start_value' amount of sand were placed on a single field.<jupyter_code>%%cython
import numpy as np
import time
cimport numpy as np
from cython import wraparound, boundscheck

DTYPE = np.int64
ctypedef np.int64_t DTYPE_t

@boundscheck(False)
@wraparound(False)
def main(int start_value):
    cdef np.ndarray[DTYPE_t, ndim=2] z = np.array([[start_value]], dtype=DTYPE)
    cdef Py_ssize_t shapeZ = z.shape[0]
    cdef np.ndarray[DTYPE_t, ndim=2] X2
    cdef np.ndarray[DTYPE_t, ndim=2] Y2
    cdef np.ndarray[DTYPE_t, ndim=1] X
    cdef np.ndarray[DTYPE_t, ndim=1] Y
    cdef np.ndarray[DTYPE_t, ndim=1] to_change
    while True:
        X2, Y2 = np.unravel_index(np.where(z.ravel()>3),(shapeZ, shapeZ))
        X = X2[0]
        Y = Y2[0]
        if X.size == 0: break
        if X[0] == 0:
            z = np.pad(z, 1, 'constant', constant_values=0)
            X += 1
            Y += 1
            shapeZ += 2
        to_change = z[X, Y]
        np.add.at(z, ([X+1, X-1, X, X], [Y, Y, Y+1, Y-1]), np.floor_divide(to_change, 4))
        z[X, Y] = to_change % 4
    return z
t = main(50)
display(t, colorbar=True)<jupyter_output><empty_output><jupyter_text>Compute sandpiles with a single field with "i" amount of sand, iterating from "start_from" up to "stop_at", and saves all images created in the process to disk (under "path").<jupyter_code>path = Path('Sandpiles')
path.mkdir(exist_ok=True)
plt.ioff()
cmap = mpl.cm.rainbow
time_history = []
t3 = 0
start_from = 0
stop_at = 100
for i in range(start_from, stop_at):
    t1 = time.time()
    file = path/f'Sandpile_{i}.png'
    print(f'{i}/{stop_at}\n{round(100*(i/stop_at), 2)}%')
    print(f'loop took {round(t3, 4)} seconds')
    if not file.is_file():
        z = main(i)
        plt.imsave(fname=file, arr=z, format='png', cmap = cmap)
        t3 = time.time()-t1
        time_history.append(t3)
    else:
        print(f'{i} already exists')
    disp.clear_output(wait=True)
print('100%\ndone')
plt.plot(time_history)
plt.show()
plt.figure(figsize=(18, 5))
plt.plot(time_history)
plt.grid()
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1470723835869064, 'fraction_numerical': 0.026740433379437527, 'mean_word_length': 3.3486973947895793, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '128682', 'license': 'MIT', 'n_tokens_mistral': 912, 'n_tokens_neox': 873, 'n_words': 208, 'path': 'Abelian sandpile.ipynb', 'repo_name': 'flpeters/abelian_sandpile', 'size': '2169'}