Abelian sandpile model/Identity: Difference between revisions

m
mNo edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(16 intermediate revisions by 8 users not shown)
Line 75:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">T Sandpile
DefaultDict[(Int, Int), Int] grid
 
Line 149:
print(s3_id + s3_id)
print()
print(s3_id + s3_id == s3_id)</langsyntaxhighlight>
 
{{out}}
Line 186:
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }}
<syntaxhighlight lang="aarch64 assembly">
<lang AArch64 Assembly>
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/* program abelianSum64.s */
Line 497:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 525:
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}}
<syntaxhighlight lang="arm assembly">
<lang ARM Assembly>
/* ARM assembly Raspberry PI or android 32 bits */
/* program abelianSum.s */
Line 820:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 850:
 
The package specification for Abelian_Sandpile is:
<langsyntaxhighlight Adalang="ada">-- Works with Ada 2012
 
package Abelian_Sandpile is
Line 865:
 
end Abelian_Sandpile;
</syntaxhighlight>
</lang>
The package body for Abelian_Sandpile is
<langsyntaxhighlight Adalang="ada">with Ada.Text_Io; use Ada.Text_IO;
 
package body Abelian_Sandpile is
Line 952:
end Print;
end Abelian_Sandpile;
</syntaxhighlight>
</lang>
The main procedure performing the same tests as the C++ example is
<syntaxhighlight lang="ada">
<lang Ada>
with Ada.Text_IO; use Ada.Text_IO;
with Abelian_Sandpile; use Abelian_Sandpile;
Line 1,001:
 
end Main;
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,066:
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68">BEGIN # model Abelian sandpiles #
# represents a sandpile #
INT elements = 3;
Line 1,173:
show sandpile( "s3_id + s3_id:", s3_id + s3_id )
 
END</langsyntaxhighlight>
{{out}}
<pre>
Line 1,228:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <array>
#include <cassert>
Line 1,364:
 
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 1,424:
=={{header|F_Sharp|F#}}==
This task uses [http://www.rosettacode.org/wiki/Abelian_sandpile_model#F.23 Abelian Sandpile Model (F#)]
<langsyntaxhighlight lang="fsharp">
let s1=Sandpile(3,3,[|1;2;0;2;1;1;0;1;3|])
let s2=Sandpile(3,3,[|2;1;3;1;0;1;0;1;0|])
Line 1,440:
let e2=Array.zeroCreate<int> 25 in e2.[12]<-16
printfn "%s\n" ((Sandpile(5,5,e1)+Sandpile(5,5,e2)).toS)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,481:
I wouldn't call it a translation, but the idea of storing sandpiles as flat arrays came from the Wren entry.
{{works with|Factor|0.99 2020-07-03}}
<langsyntaxhighlight lang="factor">USING: arrays grouping io kernel math math.vectors prettyprint
qw sequences ;
 
Line 1,527:
 
"s3_id + s3_id = s3_id" print nl
id id .s+</langsyntaxhighlight>
{{out}}
<pre>
Line 1,557:
1 0 1 + 1 0 1 = 1 0 1
2 1 2 2 1 2 2 1 2
</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
void local fn SandpilePrint( s(2,2) as ^long )
long r, c
for r = 0 to 2
for c = 0 to 2
printf @"%ld\t",s(r,c)
next
print
next
print
end fn
 
void local fn SandpileTopple( s(2,2) as ^long )
BOOL stable = NO
long r, c, value
while ( stable == NO )
stable = YES
for r = 0 to 2
for c = 0 to 2
value = s(r,c)
if ( value > 3 )
s(r,c) -= 4
if ( r > 0 ) then s(r-1,c)++
if ( r < 2 ) then s(r+1,c)++
if ( c > 0 ) then s(r,c-1)++
if ( c < 2 ) then s(r,c+1)++
print @"⇣ ⇣ ⇣ ⇣ ⇣"
print
fn SandpilePrint( s(0,0) )
stable = NO : break
end if
next
if ( stable == NO ) then break
next
wend
end fn
 
void local fn SandpileLoad( s(2,2) as ^long, values as CFStringRef )
long r, c, i = 0
for r = 0 to 2
for c = 0 to 2
s(r,c) = intval(mid(values,i,1))
i++
next
next
end fn
 
void local fn DoIt
long r, c, s(2,2), s1(2,2), s2(2,2), s3(2,2), s3_id(2,2)
// s
text @"Menlo-Bold" : print @"avalanche"
text @"Menlo" : print @"----------"
fn SandpileLoad( s(0,0), @"433312023" )
fn SandpilePrint( s(0,0) )
fn SandpileTopple( s(0,0) )
// s1
fn SandpileLoad( s1(0,0), @"120211013" )
// s2
fn SandpileLoad( s2(0,0), @"213101010" )
// s1 + s2
for r = 0 to 2
for c = 0 to 2
s(r,c) = s1(r,c) + s2(r,c)
next
next
text @"Menlo-Bold" : print @"s1 + s2"
text @"Menlo" : print @"----------"
fn SandpileTopple( s(0,0) )
fn SandpilePrint( s(0,0) )
// s2 + s1
for r = 0 to 2
for c = 0 to 2
s(r,c) = s2(r,c) + s1(r,c)
next
next
text @"Menlo-Bold" : print @"s2 + s1"
text @"Menlo" : print @"----------"
fn SandpileTopple( s(0,0) )
fn SandpilePrint( s(0,0) )
// s3
fn SandpileLoad( s3(0,0), @"333333333" )
text @"Menlo-Bold" : print @"s3"
text @"Menlo" : print @"----------"
fn SandpilePrint( s3(0,0) )
// s3_id
fn SandpileLoad( s3_id(0,0), @"212101212" )
text @"Menlo-Bold" : print @"s3_id"
text @"Menlo" : print @"----------"
fn SandpilePrint( s3_id(0,0) )
// s3 + s3_id
for r = 0 to 2
for c = 0 to 2
s(r,c) = s3(r,c) + s3_id(r,c)
next
next
text @"Menlo-Bold" : print @"s3+s3_id"
text @"Menlo" : print @"----------"
fn SandpilePrint( s(0,0) )
fn SandpileTopple( s(0,0) )
// s3_id + s3_id
for r = 0 to 2
for c = 0 to 2
s(r,c) = s3_id(r,c) + s3_id(r,c)
next
next
text @"Menlo-Bold" : print @"s3_id+s3_id"
text @"Menlo" : print @"-----------"
fn SandpilePrint( s(0,0) )
fn SandpileTopple( s(0,0) )
end fn
 
fn DoIt
 
HandleEvents
</syntaxhighlight>
 
{{out}}
<pre style="height:50ex">
avalanche
----------
4 3 3
3 1 2
0 2 3
 
⇣ ⇣ ⇣ ⇣ ⇣
 
0 4 3
4 1 2
0 2 3
 
⇣ ⇣ ⇣ ⇣ ⇣
 
1 0 4
4 2 2
0 2 3
 
⇣ ⇣ ⇣ ⇣ ⇣
 
1 1 0
4 2 3
0 2 3
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 1 0
0 3 3
1 2 3
 
s1 + s2
----------
3 3 3
3 1 2
0 2 3
 
s2 + s1
----------
3 3 3
3 1 2
0 2 3
 
s3
----------
3 3 3
3 3 3
3 3 3
 
s3_id
----------
2 1 2
1 0 1
2 1 2
 
s3+s3_id
----------
5 4 5
4 3 4
5 4 5
 
⇣ ⇣ ⇣ ⇣ ⇣
 
1 5 5
5 3 4
5 4 5
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 1 6
5 4 4
5 4 5
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 2 2
5 4 5
5 4 5
 
⇣ ⇣ ⇣ ⇣ ⇣
 
3 2 2
1 5 5
6 4 5
 
⇣ ⇣ ⇣ ⇣ ⇣
 
3 3 2
2 1 6
6 5 5
 
⇣ ⇣ ⇣ ⇣ ⇣
 
3 3 3
2 2 2
6 5 6
 
⇣ ⇣ ⇣ ⇣ ⇣
 
3 3 3
3 2 2
2 6 6
 
⇣ ⇣ ⇣ ⇣ ⇣
 
3 3 3
3 3 2
3 2 7
 
⇣ ⇣ ⇣ ⇣ ⇣
 
3 3 3
3 3 3
3 3 3
 
s3_id+s3_id
----------
4 2 4
2 0 2
4 2 4
 
⇣ ⇣ ⇣ ⇣ ⇣
 
0 3 4
3 0 2
4 2 4
 
⇣ ⇣ ⇣ ⇣ ⇣
 
0 4 0
3 0 3
4 2 4
 
⇣ ⇣ ⇣ ⇣ ⇣
 
1 0 1
3 1 3
4 2 4
 
⇣ ⇣ ⇣ ⇣ ⇣
 
1 0 1
4 1 3
0 3 4
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 0 1
0 2 3
1 3 4
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 0 1
0 2 4
1 4 0
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 0 2
0 3 0
1 4 1
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 0 2
0 4 0
2 0 2
 
⇣ ⇣ ⇣ ⇣ ⇣
 
2 1 2
1 0 1
2 1 2
</pre>
 
=={{header|Go}}==
{{trans|Wren}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,657 ⟶ 1,962:
}
fmt.Printf("%s\nplus\n\n%s\nequals\n\n%s", s3_id, s3_id, s5)
}</langsyntaxhighlight>
 
{{out}}
Line 1,757 ⟶ 2,062:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">{-# LANGUAGE TupleSections #-}
 
import Data.List (findIndex, transpose)
Line 1,849 ⟶ 2,154:
lng = length s
pad = replicate lng ' '
(q, r) = quotRem (2 + lng) 2</langsyntaxhighlight>
<pre>Cascade:
4 3 3 0 4 3 1 0 4 1 1 0 2 1 0
Line 1,875 ⟶ 2,180:
 
=={{header|J}}==
<syntaxhighlight lang="j">
<lang J>
While=:2 :'u^:(0-.@:-:v)^:_'
index_of_maximum=: $ #: (i. >./)@:,
Line 1,885 ⟶ 2,190:
avalanche=: (AVALANCHE + {)`[`]}~ ([: <"1 NEIGHBORS +"1 index_of_maximum)
erode=: avalanche&.:frame While(3 < [: >./ ,)
</syntaxhighlight>
</lang>
<pre>
NB. common ways to construct a matrix in j from directly entered vectors
Line 1,932 ⟶ 2,237:
└─────────┴─────────┘
</pre>
 
=={{header|Java}}==
<syntaxhighlight lang="java>
 
import java.util.ArrayList;
import java.util.List;
 
public final class AbelianSandpileModel {
 
public static void main(String[] aArgs) {
Sandpile avalanche = new Sandpile(List.of( 4, 3, 3, 3, 1, 2, 0, 2, 3 ));
System.out.println("Avalanche reduction to stable state:");
avalanche.display();
System.out.println(" ==> ");
avalanche.stabilise();
avalanche.display();
Sandpile s1 = new Sandpile(List.of( 1, 2, 0, 2, 1, 1, 0, 1, 3 ));
Sandpile s2 = new Sandpile(List.of( 2, 1, 3, 1, 0, 1, 0, 1, 0 ));
Sandpile sum1 = s1.add(s2);
Sandpile sum2 = s2.add(s1);
System.out.println(System.lineSeparator() + "Commutativity of addition" + System.lineSeparator());
System.out.println("Sandpile1 + Sandpile2:");
sum1.display();
System.out.println("Sandpile2 + Sandpile1:");
sum2.display();
System.out.println("Sandpile1 + Sandpile2 = Sandpile2 + Sandpile1: " + sum1.equals(sum2));
Sandpile s3 = new Sandpile(List.of( 3, 3, 3, 3, 3, 3, 3, 3, 3 ));
Sandpile s3_id = new Sandpile(List.of( 2, 1, 2, 1, 0, 1, 2, 1, 2 ));
Sandpile sum3 = s3.add(s3_id);
Sandpile sum4 = s3_id.add(s3_id);
System.out.println(System.lineSeparator() + "Identity Sandpile" + System.lineSeparator());
System.out.println("Sandpile3 + Sandpile3_id:");
sum3.display();
System.out.println("Sandpile3_id + Sandpile3_id:");
sum4.display();
}
 
}
 
final class Sandpile {
public Sandpile(List<Integer> aList) {
if ( aList.size() != CELL_COUNT ) {
throw new IllegalArgumentException("Initialiser list must contain " + CELL_COUNT + " elements");
}
cells = new ArrayList<Integer>(aList);
}
public void stabilise() {
while ( ! isStable() ) {
topple();
}
}
public boolean isStable() {
return cells.stream().noneMatch( i -> i >= CELL_LIMIT );
}
public void topple() {
for ( int i = 0; i < CELL_COUNT; i++ ) {
if ( cells.get(i) >= CELL_LIMIT ) {
cells.set(i, cells.get(i) - CELL_LIMIT);
final int row = rowIndex(i);
final int col = colIndex(i);
if ( row > 0 ) {
increment(row - 1, col);
}
if ( row + 1 < ROW_COUNT ) {
increment(row + 1, col);
}
if ( col > 0 ) {
increment(row, col - 1);
}
if ( col + 1 < COL_COUNT ) {
increment(row, col + 1);
}
}
}
}
public Sandpile add(Sandpile aOther) {
List<Integer> list = new ArrayList<Integer>();
for ( int i = 0; i < CELL_COUNT; i++ ) {
list.add(cells.get(i) + aOther.cells.get(i));
}
Sandpile result = new Sandpile(list);
result.stabilise();
return result;
}
public boolean equals(Sandpile aOther) {
return cells.equals(aOther.cells);
}
public void display() {
for ( int i = 0; i < CELL_COUNT; i++ ) {
System.out.print(cells.get(i));
System.out.print( ( colIndex(i + 1) == 0 ) ? System.lineSeparator() : " ");
}
}
private void increment(int aRow, int aCol) {
final int index = cellIndex(aRow, aCol);
cells.set(index, cells.get(index) + 1);
}
private static int cellIndex(int aRow, int aCol) {
return aRow * COL_COUNT + aCol;
}
private static int rowIndex(int aCellIndex) {
return aCellIndex / COL_COUNT;
}
private static int colIndex(int aCellIndex) {
return aCellIndex % COL_COUNT;
}
private List<Integer> cells;
 
private static final int ROW_COUNT = 3;
private static final int COL_COUNT = 3;
private static final int CELL_COUNT = ROW_COUNT * COL_COUNT;
private static final int CELL_LIMIT = 4;
}
</syntaxhighlight>
{{ out }}
<pre>
Avalanche reduction to stable state:
4 3 3
3 1 2
0 2 3
==>
2 1 0
0 3 3
1 2 3
 
Commutativity of addition
 
Sandpile1 + Sandpile2:
3 3 3
3 1 2
0 2 3
Sandpile2 + Sandpile1:
3 3 3
3 1 2
0 2 3
Sandpile1 + Sandpile2 = Sandpile2 + Sandpile1: true
 
Identity Sandpile
 
Sandpile3 + Sandpile3_id:
3 3 3
3 3 3
3 3 3
Sandpile3_id + Sandpile3_id:
2 1 2
1 0 1
2 1 2
</pre>
 
=={{header|jq}}==
''Adapted from [[#Wren|Wren]]''
 
'''Works with jq and gojq, the C and Go implementations of jq'''
<syntaxhighlight lang=jq>
# `whilst/2` is like `while/2` but emits the final term rather than the first one
def whilst(cond; update):
def _whilst:
if cond then update | (., _whilst) else empty end;
_whilst;
 
# module Sandpile
 
def new($a): {$a};
 
def neighbors: [
[1, 3], [0, 2, 4], [1, 5],
[0, 4, 6], [1, 3, 5, 7], [2, 4, 8],
[3, 7], [4, 6, 8], [5, 7]
];
 
def add($other):
. as $in
| reduce range(0; .a|length) as $i ($in; .a[$i] += $other.a[$i] );
 
def isStable:
all(.a[]; . <= 3);
 
# just topple once so we can observe intermediate results
def topple:
last(
label $out
| foreach range(0; .a|length) as $i (.;
if .a[$i] > 3
then .a[$i] += -4
| reduce neighbors[$i][] as $j (.; .a[$j] += 1)
| ., break $out
else .
end ) );
 
def tos:
. as $in
| reduce range(0;3) as $i ("";
reduce range(0;3) as $j (.;
. + " \($in.a[3*$i + $j])" )
| . +"\n" );
 
# Some sandpiles:
def s1: new([1, 2, 0, 2, 1, 1, 0, 1, 3]);
def s2: new([2, 1, 3, 1, 0, 1, 0, 1, 0]);
def s3: new([range(0;9)|3]);
def s4: new([4, 3, 3, 3, 1, 2, 0, 2, 3]);
 
def s3_id: new([2, 1, 2, 1, 0, 1, 2, 1, 2]);
 
# For brevity
def report_add($s1; $s2):
"\($s1|tos)\nplus\n\n\($s2|tos)\nequals\n\n\($s1 | add($s2) | until(isStable; topple) | tos)";
 
def task1:
"Avalanche of topplings:\n",
(s4
| (., whilst(isStable|not; topple))
| tos ) ;
 
def task2:
def s3_a: s1 | add(s2);
def s3_b: s2 | add(s1);
 
"Commutative additions:\n",
( (s3_b | until(isStable; topple)) as $s3_b
| report_add(s1; s2),
"and\n\n\(s2|tos)\nplus\n\n\(s1|tos)\nalso equals\n\n\($s3_b|tos)" ) ;
 
def task3:
"Addition of identity sandpile:\n",
report_add(s3; s3_id);
 
def task4:
"Addition of identities:\n",
report_add(s3_id; s3_id);
 
task1, task2, task3, task4
</syntaxhighlight>
{{output}}
As for [[#Wren|Wren]].
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">import Base.+, Base.print
 
struct Sandpile
Line 2,008 ⟶ 2,563:
println(s3_id, " +\n", s3_id, " =\n", s3_id + s3_id, "\n")
 
</langsyntaxhighlight>{{out}}
<pre>
Avalanche reduction to group:
Line 2,058 ⟶ 2,613:
2 1 2
</pre>
 
=={{header|Lua}}==
Uses Abelian sandpile model [[Abelian_sandpile_model#Lua|here]], then extends..
<langsyntaxhighlight Lualang="lua">sandpile.__index = sandpile
sandpile.new = function(self, vals)
local inst = setmetatable({},sandpile)
Line 2,104 ⟶ 2,660:
print("\ns3 + s3_id =") s3ps3_id:draw()
local s3_idps3_id = s3_id:add(s3_id)
print("\ns3_id + s3_id =") s3_idps3_id:draw()</langsyntaxhighlight>
{{out}}
<pre>s1 =
Line 2,157 ⟶ 2,713:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[sp]
sp[s_List] + sp[n_Integer] ^:= sp[s] + sp[ConstantArray[n, Dimensions[s]]]
sp[s_List] + sp[t_List] ^:= Module[{dim, r, tmp, neighbours}, dim = Dimensions[s];
Line 2,182 ⟶ 2,738:
sp[{{4, 3, 3}, {3, 1, 2}, {0, 2, 3}}] + sp[0]
s3 + s3id === s3
s3id + s3id === s3id</langsyntaxhighlight>
{{out}}
<pre>3 3 3
Line 2,202 ⟶ 2,758:
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">
<lang Nim>
import sequtils
import strutils
Line 2,308 ⟶ 2,864:
echo "s3_id + s3_id = s3_id\n"
printSum(s3_id, s3_id, s3_id + s3_id)
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,348 ⟶ 2,904:
 
=={{header|OCaml}}==
<syntaxhighlight lang="ocaml">
<lang OCaml>
 
(* https://en.wikipedia.org/wiki/Abelian_sandpile_model *)
Line 2,491 ⟶ 3,047:
; print (s3_id +. s3_id)
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,560 ⟶ 3,116:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #008080;">constant</span> <span style="color: #000000;">s1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"1 2 0"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"2 1 1"</span><span style="color: #0000FF;">,</span>
Line 2,644 ⟶ 3,200:
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"4. Show that s3_id + s3_id == s3_id\n\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">shout</span><span style="color: #0000FF;">({</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s3_id</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" + "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s3_id</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" = "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">topple</span><span style="color: #0000FF;">(</span><span style="color: #000000;">add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s3_id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s3_id</span><span style="color: #0000FF;">))})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 2,678 ⟶ 3,234:
=={{header|Python}}==
===Object Oriented===
<langsyntaxhighlight lang="python">from itertools import product
from collections import defaultdict
 
Line 2,757 ⟶ 3,313:
s3 = Sandpile("3 3 3 3 3 3 3 3 3")
s3_id = Sandpile("2 1 2 1 0 1 2 1 2")
</syntaxhighlight>
</lang>
 
;Command line session to complete task.
Line 2,828 ⟶ 3,384:
 
===Functional===
<langsyntaxhighlight lang="python">'''Abelian Sandpile – Identity'''
 
from operator import add, eq
Line 3,056 ⟶ 3,612:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Cascade:
Line 3,087 ⟶ 3,643:
Most of the logic is lifted straight from the [[Abelian_sandpile_model#Raku|Abelian sandpile model]] task.
 
<syntaxhighlight lang="raku" perl6line>class ASP {
has $.h = 3;
has $.w = 3;
Line 3,151 ⟶ 3,707:
 
put '';
}</langsyntaxhighlight>
{{out}}
<pre> identity test pile toppled plus identity toppled
Line 3,186 ⟶ 3,742:
 
=={{header|Red}}==
<syntaxhighlight lang="rebol">
<lang Rebol>
Red [Purpose: "implement Abelian sandpile model"]
 
Line 3,210 ⟶ 3,766:
if stable = false [break]
]
eitherunless stable = truefalse [print trim/with mold/only pile "[]" exit]
spill pile row col
print trim/with mold/only pile "[]"
] [
spill pile row col
]
]
spill: func [pile [series!] r [integer!] c [integer!]] [
Line 3,265 ⟶ 3,818:
sadd/comb copy/deep s3 copy/deep s3_id
sadd/comb copy/deep s3_id copy/deep s3_id
</syntaxhighlight>
</lang>
 
{{out}}
Line 3,297 ⟶ 3,850:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program demonstrates a 3x3 sandpile model by addition with toppling & avalanches.*/
@.= 0; size= 3 /*assign 0 to all grid cells; grid size*/
call init 1, 1 2 0 2 1 1 0 1 3 /* " grains of sand──► sandpile 1. */
Line 3,355 ⟶ 3,908:
end /*c*/
say ind pad $ /*display a row.*/
end /*r*/; shows= shows + 1; if shows==1 then say; return</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
 
Line 3,403 ⟶ 3,956:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class Sandpile
def initialize(ar) = @grid = ar
Line 3,459 ⟶ 4,012:
puts "s3 + s3_id == s3: #{s3 + s3_id == s3}"
puts "s3_id + s3_id == s3_id: #{s3_id + s3_id == s3_id}"
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,489 ⟶ 4,042:
s3_id + s3_id == s3_id: true
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">#[derive(Clone)]
struct Box {
piles: [[u8; 3]; 3],
}
 
impl Box {
fn init(piles: [[u8; 3]; 3]) -> Box {
let a = Box { piles };
 
if a.piles.iter().any(|&row| row.iter().any(|&pile| pile >= 4)) {
return a.avalanche();
} else {
return a;
}
}
 
fn avalanche(&self) -> Box {
let mut a = self.clone();
for (i, row) in self.piles.iter().enumerate() {
for (j, pile) in row.iter().enumerate() {
if *pile >= 4u8 {
if i > 0 {
a.piles[i - 1][j] += 1u8
}
if i < 2 {
a.piles[i + 1][j] += 1u8
}
if j > 0 {
a.piles[i][j - 1] += 1u8
}
if j < 2 {
a.piles[i][j + 1] += 1u8
}
a.piles[i][j] -= 4;
}
}
}
Box::init(a.piles)
}
 
fn add(&self, a: &Box) -> Box {
let mut b = Box {
piles: [[0u8; 3]; 3],
};
for (row, columns) in b.piles.iter_mut().enumerate() {
for (col, pile) in columns.iter_mut().enumerate() {
*pile = self.piles[row][col] + a.piles[row][col]
}
}
Box::init(b.piles)
}
}
 
fn main() {
println!(
"The piles demonstration avalanche starts as:\n{:?}\n{:?}\n{:?}",
[4, 3, 3],
[3, 1, 2],
[0, 2, 3]
);
let s0 = Box::init([[4u8, 3u8, 3u8], [3u8, 1u8, 2u8], [0u8, 2u8, 3u8]]);
println!(
"And ends as:\n{:?}\n{:?}\n{:?}",
s0.piles[0], s0.piles[1], s0.piles[2]
);
let s1 = Box::init([[1u8, 2u8, 0u8], [2u8, 1u8, 1u8], [0u8, 1u8, 3u8]]);
let s2 = Box::init([[2u8, 1u8, 3u8], [1u8, 0u8, 1u8], [0u8, 1u8, 0u8]]);
let s1_2 = s1.add(&s2);
let s2_1 = s2.add(&s1);
println!(
"The piles in s1 + s2 are:\n{:?}\n{:?}\n{:?}",
s1_2.piles[0], s1_2.piles[1], s1_2.piles[2]
);
println!(
"The piles in s2 + s1 are:\n{:?}\n{:?}\n{:?}",
s2_1.piles[0], s2_1.piles[1], s2_1.piles[2]
);
let s3 = Box::init([[3u8; 3]; 3]);
let s3_id = Box::init([[2u8, 1u8, 2u8], [1u8, 0u8, 1u8], [2u8, 1u8, 2u8]]);
let s4 = s3.add(&s3_id);
println!(
"The piles in s3 + s3_id are:\n{:?}\n{:?}\n{:?}",
s4.piles[0], s4.piles[1], s4.piles[2]
);
let s5 = s3_id.add(&s3_id);
println!(
"The piles in s3_id + s3_id are:\n{:?}\n{:?}\n{:?}",
s5.piles[0], s5.piles[1], s5.piles[2]
);
}
</syntaxhighlight>
{{out}}
<pre>
The piles demonstration avalanche starts as:
[4, 3, 3]
[3, 1, 2]
[0, 2, 3]
And ends as:
[2, 1, 0]
[0, 3, 3]
[1, 2, 3]
The piles in s1 + s2 are:
[3, 3, 3]
[3, 1, 2]
[0, 2, 3]
The piles in s2 + s1 are:
[3, 3, 3]
[3, 1, 2]
[0, 2, 3]
The piles in s3 + s3_id are:
[3, 3, 3]
[3, 3, 3]
[3, 3, 3]
The piles in s3_id + s3_id are:
[2, 1, 2]
[1, 0, 1]
[2, 1, 2]
</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">import strings
 
struct Sandpile {
mut:
a [9]int
}
const (
neighbors = [
[1, 3], [0, 2, 4], [1, 5], [0, 4, 6], [1, 3, 5, 7], [2, 4, 8], [3, 7], [4, 6, 8], [5, 7]
]
)
// 'a' is in row order
fn new_sandpile(a [9]int) Sandpile { return Sandpile{a} }
fn (s &Sandpile) plus(other &Sandpile) Sandpile {
mut b := [9]int{}
for i in 0..9 {
b[i] = s.a[i] + other.a[i]
}
return Sandpile{b}
}
fn (s &Sandpile) is_stable() bool {
for e in s.a {
if e > 3 {
return false
}
}
return true
}
// just topples once so we can observe intermediate results
fn (mut s Sandpile) topple() {
for i in 0..9 {
if s.a[i] > 3 {
s.a[i] -= 4
for j in neighbors[i] {
s.a[j]++
}
return
}
}
}
fn (s Sandpile) str() string {
mut sb := strings.new_builder(64)
for i in 0..3 {
for j in 0..3 {
sb.write_string("${u8(s.a[3*i+j])} ")
}
sb.write_string("\n")
}
return sb.str()
}
fn main() {
println("Avalanche of topplings:\n")
mut s4 := new_sandpile([4, 3, 3, 3, 1, 2, 0, 2, 3]!)
println(s4)
for !s4.is_stable() {
s4.topple()
println(s4)
}
println("Commutative additions:\n")
s1 := new_sandpile([1, 2, 0, 2, 1, 1, 0, 1, 3]!)
s2 := new_sandpile([2, 1, 3, 1, 0, 1, 0, 1, 0]!)
mut s3_a := s1.plus(s2)
for !s3_a.is_stable() {
s3_a.topple()
}
mut s3_b := s2.plus(s1)
for !s3_b.is_stable() {
s3_b.topple()
}
println("$s1\nplus\n\n$s2\nequals\n\n$s3_a")
println("and\n\n$s2\nplus\n\n$s1\nalso equals\n\n$s3_b")
println("Addition of identity sandpile:\n")
s3 := new_sandpile([3, 3, 3, 3, 3, 3, 3, 3, 3]!)
s3_id := new_sandpile([2, 1, 2, 1, 0, 1, 2, 1, 2]!)
s4 = s3.plus(s3_id)
for !s4.is_stable() {
s4.topple()
}
println("$s3\nplus\n\n$s3_id\nequals\n\n$s4")
println("Addition of identities:\n")
mut s5 := s3_id.plus(s3_id)
for !s5.is_stable() {
s5.topple()
}
print("$s3_id\nplus\n\n$s3_id\nequals\n\n$s5")
}</syntaxhighlight>
 
{{out}}
<pre>
Same as Go entry
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
 
class Sandpile {
Line 3,565 ⟶ 4,343:
var s5 = s3_id + s3_id
while (!s5.isStable) s5.topple()
Fmt.write("$s\nplus\n\n$s\nequals\n\n$s", s3_id, s3_id, s5)</langsyntaxhighlight>
 
{{out}}
Line 3,662 ⟶ 4,440:
1 0 1
2 1 2
</pre>
 
=={{header|Rust}}==
<lang Rust>#[derive(Clone)]
struct Box {
piles: [[u8; 3]; 3],
}
 
impl Box {
fn init(piles: [[u8; 3]; 3]) -> Box {
let a = Box { piles };
 
if a.piles.iter().any(|&row| row.iter().any(|&pile| pile >= 4)) {
return a.avalanche();
} else {
return a;
}
}
 
fn avalanche(&self) -> Box {
let mut a = self.clone();
for (i, row) in self.piles.iter().enumerate() {
for (j, pile) in row.iter().enumerate() {
if *pile >= 4u8 {
if i > 0 {
a.piles[i - 1][j] += 1u8
}
if i < 2 {
a.piles[i + 1][j] += 1u8
}
if j > 0 {
a.piles[i][j - 1] += 1u8
}
if j < 2 {
a.piles[i][j + 1] += 1u8
}
a.piles[i][j] -= 4;
}
}
}
Box::init(a.piles)
}
 
fn add(&self, a: &Box) -> Box {
let mut b = Box {
piles: [[0u8; 3]; 3],
};
for (row, columns) in b.piles.iter_mut().enumerate() {
for (col, pile) in columns.iter_mut().enumerate() {
*pile = self.piles[row][col] + a.piles[row][col]
}
}
Box::init(b.piles)
}
}
 
fn main() {
println!(
"The piles demonstration avalanche starts as:\n{:?}\n{:?}\n{:?}",
[4, 3, 3],
[3, 1, 2],
[0, 2, 3]
);
let s0 = Box::init([[4u8, 3u8, 3u8], [3u8, 1u8, 2u8], [0u8, 2u8, 3u8]]);
println!(
"And ends as:\n{:?}\n{:?}\n{:?}",
s0.piles[0], s0.piles[1], s0.piles[2]
);
let s1 = Box::init([[1u8, 2u8, 0u8], [2u8, 1u8, 1u8], [0u8, 1u8, 3u8]]);
let s2 = Box::init([[2u8, 1u8, 3u8], [1u8, 0u8, 1u8], [0u8, 1u8, 0u8]]);
let s1_2 = s1.add(&s2);
let s2_1 = s2.add(&s1);
println!(
"The piles in s1 + s2 are:\n{:?}\n{:?}\n{:?}",
s1_2.piles[0], s1_2.piles[1], s1_2.piles[2]
);
println!(
"The piles in s2 + s1 are:\n{:?}\n{:?}\n{:?}",
s2_1.piles[0], s2_1.piles[1], s2_1.piles[2]
);
let s3 = Box::init([[3u8; 3]; 3]);
let s3_id = Box::init([[2u8, 1u8, 2u8], [1u8, 0u8, 1u8], [2u8, 1u8, 2u8]]);
let s4 = s3.add(&s3_id);
println!(
"The piles in s3 + s3_id are:\n{:?}\n{:?}\n{:?}",
s4.piles[0], s4.piles[1], s4.piles[2]
);
let s5 = s3_id.add(&s3_id);
println!(
"The piles in s3_id + s3_id are:\n{:?}\n{:?}\n{:?}",
s5.piles[0], s5.piles[1], s5.piles[2]
);
}
</lang>
{{out}}
<pre>
The piles demonstration avalanche starts as:
[4, 3, 3]
[3, 1, 2]
[0, 2, 3]
And ends as:
[2, 1, 0]
[0, 3, 3]
[1, 2, 3]
The piles in s1 + s2 are:
[3, 3, 3]
[3, 1, 2]
[0, 2, 3]
The piles in s2 + s1 are:
[3, 3, 3]
[3, 1, 2]
[0, 2, 3]
The piles in s3 + s3_id are:
[3, 3, 3]
[3, 3, 3]
[3, 3, 3]
The piles in s3_id + s3_id are:
[2, 1, 2]
[1, 0, 1]
[2, 1, 2]
</pre>
9,476

edits