Abelian sandpile model/Identity: Difference between revisions
Content deleted Content added
(23 intermediate revisions by 13 users not shown) | |||
Line 71:
* https://en.wikipedia.org/wiki/Abelian_sandpile_model
<br><br>
=={{header|11l}}==
{{trans|Python}}
<syntaxhighlight lang="11l">T Sandpile
DefaultDict[(Int, Int), Int] grid
F (gridtext)
V array = gridtext.split_py().map(x -> Int(x))
L(x) array
.grid[(L.index I/ 3, L.index % 3)] = x
Set[(Int, Int)] _border = Set(cart_product(-1 .< 4, -1 .< 4).filter((r, c) -> !(r C 0..2) | !(c C 0..2)))
_cell_coords = cart_product(0.<3, 0.<3)
F topple()
V& g = .grid
L(r, c) ._cell_coords
I g[(r, c)] >= 4
g[(r - 1, c)]++
g[(r + 1, c)]++
g[(r, c - 1)]++
g[(r, c + 1)]++
g[(r, c)] -= 4
R 1B
R 0B
F stabilise()
L .topple() {}
L(row_col) ._border.intersection(Set(.grid.keys()))
.grid.pop(row_col)
F ==(other)
R all(._cell_coords.map(row_col -> @.grid[row_col] == @other.grid[row_col]))
F +(other)
V ans = Sandpile(‘’)
L(row_col) ._cell_coords
ans.grid[row_col] = .grid[row_col] + other.grid[row_col]
ans.stabilise()
R ans
F String()
[String] txt
L(row) 3
txt.append((0.<3).map(col -> String(@.grid[(@row, col)])).join(‘ ’))
R txt.join("\n")
V unstable = Sandpile(‘4 3 3
3 1 2
0 2 3’)
V s1 = Sandpile(‘1 2 0
2 1 1
0 1 3’)
V s2 = Sandpile(‘2 1 3
1 0 1
0 1 0’)
V s3 = Sandpile(‘3 3 3 3 3 3 3 3 3’)
V s3_id = Sandpile(‘2 1 2 1 0 1 2 1 2’)
print(unstable)
print()
unstable.stabilise()
print(unstable)
print()
print(s1 + s2)
print()
print(s2 + s1)
print()
print(s1 + s2 == s2 + s1)
print()
print(s3 + s3_id)
print()
print(s3 + s3_id == s3)
print()
print(s3_id + s3_id)
print()
print(s3_id + s3_id == s3_id)</syntaxhighlight>
{{out}}
<pre>
4 3 3
3 1 2
0 2 3
2 1 0
0 3 3
1 2 3
3 3 3
3 1 2
0 2 3
3 3 3
3 1 2
0 2 3
1B
3 3 3
3 3 3
3 3 3
1B
2 1 2
1 0 1
2 1 2
1B
</pre>
=={{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">
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/* program abelianSum64.s */
Line 385 ⟶ 497:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
{{Output}}
<pre>
Line 410 ⟶ 522:
2 1 2
</pre>
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}}
<syntaxhighlight lang="arm assembly">
/* ARM assembly Raspberry PI or android 32 bits */
/* program abelianSum.s */
Line 707 ⟶ 820:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
{{Output}}
<pre>
Line 737 ⟶ 850:
The package specification for Abelian_Sandpile is:
<
package Abelian_Sandpile is
Line 752 ⟶ 865:
end Abelian_Sandpile;
</syntaxhighlight>
The package body for Abelian_Sandpile is
<
package body Abelian_Sandpile is
Line 839 ⟶ 952:
end Print;
end Abelian_Sandpile;
</syntaxhighlight>
The main procedure performing the same tests as the C++ example is
<syntaxhighlight lang="ada">
with Ada.Text_IO; use Ada.Text_IO;
with Abelian_Sandpile; use Abelian_Sandpile;
Line 888 ⟶ 1,001:
end Main;
</syntaxhighlight>
{{out}}
<pre>
Line 947 ⟶ 1,060:
s3_id + s3_id =
2 1 2
1 0 1
2 1 2
</pre>
=={{header|ALGOL 68}}==
<syntaxhighlight lang="algol68">BEGIN # model Abelian sandpiles #
# represents a sandpile #
INT elements = 3;
MODE SANDPILE = [ 1 : elements, 1 : elements ]INT;
# returns TRUE if the sandpiles a and b have the same values, FALSE otherwise #
OP = = ( SANDPILE a, b )BOOL:
BEGIN
BOOL result := TRUE;
FOR i TO elements WHILE result DO
FOR j TO elements WHILE ( result := a[ i, j ] = b[ i, j ] ) DO SKIP OD
OD;
result
END # = # ;
# returns TRUE if the sandpile s is stable, FALSE otherwise #
OP STABLE = ( SANDPILE s )BOOL:
BEGIN
BOOL result := TRUE;
FOR i TO elements WHILE result DO
FOR j TO elements WHILE result := s[ i, j ] < 4 DO SKIP OD
OD;
result
END # STABLE # ;
# returns the sandpile s after avalanches #
OP AVALANCHE = ( SANDPILE s )SANDPILE:
BEGIN
SANDPILE result := s;
WHILE BOOL had avalanche := FALSE;
FOR i TO elements DO
FOR j TO elements DO
IF result[ i, j ] >= 4 THEN
# unstable pile #
had avalanche := TRUE;
result[ i, j ] -:= 4;
IF i > 1 THEN result[ i - 1, j ] +:= 1 FI;
IF i < elements THEN result[ i + 1, j ] +:= 1 FI;
IF j > 1 THEN result[ i, j - 1 ] +:= 1 FI;
IF j < elements THEN result[ i, j + 1 ] +:= 1 FI
FI
OD
OD;
had avalanche
DO SKIP OD;
result
END # AVALANCHE # ;
# returns the result of adding the sandpile b to a, handling avalanches #
OP + = ( SANDPILE a, b )SANDPILE:
BEGIN
SANDPILE result;
FOR i TO elements DO
FOR j TO elements DO result[ i, j ] := a[ i, j ] + b[ i, j ] OD
OD;
# handle avalanches #
AVALANCHE result
END # + # ;
# prints the sandpile s #
PROC show sandpile = ( STRING title, SANDPILE s )VOID:
BEGIN
print( ( title, newline ) );
FOR i TO elements DO
FOR j TO elements DO
print( ( " ", whole( s[ i, j ], 0 ) ) )
OD;
print( ( newline ) )
OD
END # show sandpile # ;
# task test cases #
SANDPILE us = ( ( 4, 3, 3 )
, ( 3, 1, 2 )
, ( 0, 2, 3 )
);
SANDPILE s1 = ( ( 1, 2, 0 )
, ( 2, 1, 1 )
, ( 0, 1, 3 )
);
SANDPILE s2 = ( ( 2, 1, 3 )
, ( 1, 0, 1 )
, ( 0, 1, 0 )
);
SANDPILE s3 = ( ( 3, 3, 3 )
, ( 3, 3, 3 )
, ( 3, 3, 3 )
);
SANDPILE s3_id = ( ( 2, 1, 2 )
, ( 1, 0, 1 )
, ( 2, 1, 2 )
);
SANDPILE t := us;
WHILE NOT STABLE t DO
show sandpile( "unstable:", t );
t := AVALANCHE t
OD;
show sandpile( "stable: ", t );
print( ( newline ) );
show sandpile( "s1:", s1 );
show sandpile( "s2:", s2 );
show sandpile( "s1 + s2:", s1 + s2 );
show sandpile( "s2 + s1:", s2 + s1 );
print( ( newline ) );
show sandpile( "s3:", s3 );
show sandpile( "s3_id:", s3_id );
print( ( newline ) );
print( ( "s3 + s3_id = s3 is ", IF s3 + s3_id = s3 THEN "TRUE" ELSE "FALSE" FI, newline ) );
show sandpile( "s3 + s3_id", s3 + s3_id );
print( ( "s3_id + s3 = s3 is ", IF s3 + s3_id = s3 THEN "TRUE" ELSE "FALSE" FI, newline ) );
show sandpile( "s3_id + s3", s3_id + s3 );
show sandpile( "s3_id + s3_id:", s3_id + s3_id )
END</syntaxhighlight>
{{out}}
<pre>
unstable:
4 3 3
3 1 2
0 2 3
stable:
2 1 0
0 3 3
1 2 3
s1:
1 2 0
2 1 1
0 1 3
s2:
2 1 3
1 0 1
0 1 0
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 = s3 is TRUE
s3 + s3_id
3 3 3
3 3 3
3 3 3
s3_id + s3 = s3 is TRUE
s3_id + s3
3 3 3
3 3 3
3 3 3
s3_id + s3_id:
2 1 2
1 0 1
Line 953 ⟶ 1,228:
=={{header|C++}}==
<
#include <array>
#include <cassert>
Line 1,089 ⟶ 1,364:
return 0;
}</
{{out}}
Line 1,145 ⟶ 1,420:
1 0 1
2 1 2
</pre>
=={{header|EasyLang}}==
<syntaxhighlight lang=text>
proc out s[] . .
for r = 0 to 2
for c to 3
write s[c + 3 * r] & " "
.
print ""
.
print ""
.
proc stab . m[] .
n = sqrt len m[]
repeat
stable = 1
for p to len m[]
if m[p] >= 4
stable = 0
m[p] -= 4
if p > n
m[p - n] += 1
.
if p mod n <> 0
m[p + 1] += 1
.
if p <= len m[] - n
m[p + n] += 1
.
if p mod n <> 1
m[p - 1] += 1
.
.
.
until stable = 1
.
.
func[] add s1[] s2[] .
for i to len s1[]
r[] &= s1[i] + s2[i]
.
stab r[]
return r[]
.
print "avalanche:"
s4[] = [ 4 3 3 3 1 2 0 2 3 ]
stab s4[]
out s4[]
#
s1[] = [ 1 2 0 2 1 1 0 1 3 ]
s2[] = [ 2 1 3 1 0 1 0 1 0 ]
if add s1[] s2[] = add s2[] s1[]
print "s1 + s2 = s2 + s1"
.
#
s3[] = [ 3 3 3 3 3 3 3 3 3 ]
s3_id[] = [ 2 1 2 1 0 1 2 1 2 ]
if add s3[] s3_id[] = s3[]
print "s3 + s3_id = s3"
.
if add s3_id[] s3_id[] = s3_id[]
print "s3_id + s3_id = s3_id"
.
</syntaxhighlight>
{{out}}
<pre>
avalanche:
2 1 0
0 3 3
1 2 3
s1 + s2 = s2 + s1
s3 + s3_id = s3
s3_id + s3_id = s3_id
</pre>
=={{header|F_Sharp|F#}}==
This task uses [http://www.rosettacode.org/wiki/Abelian_sandpile_model#F.23 Abelian Sandpile Model (F#)]
<
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,165 ⟶ 1,515:
let e2=Array.zeroCreate<int> 25 in e2.[12]<-16
printfn "%s\n" ((Sandpile(5,5,e1)+Sandpile(5,5,e2)).toS)
</syntaxhighlight>
{{out}}
<pre>
Line 1,206 ⟶ 1,556:
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}}
<
qw sequences ;
Line 1,252 ⟶ 1,602:
"s3_id + s3_id = s3_id" print nl
id id .s+</
{{out}}
<pre>
Line 1,282 ⟶ 1,632:
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}}
<
import (
Line 1,382 ⟶ 2,037:
}
fmt.Printf("%s\nplus\n\n%s\nequals\n\n%s", s3_id, s3_id, s5)
}</
{{out}}
Line 1,482 ⟶ 2,137:
=={{header|Haskell}}==
<
import Data.List (findIndex, transpose)
Line 1,574 ⟶ 2,229:
lng = length s
pad = replicate lng ' '
(q, r) = quotRem (2 + lng) 2</
<pre>Cascade:
4 3 3 0 4 3 1 0 4 1 1 0 2 1 0
Line 1,600 ⟶ 2,255:
=={{header|J}}==
<syntaxhighlight lang="j">
While=:2 :'u^:(0-.@:-:v)^:_'
index_of_maximum=: $ #: (i. >./)@:,
Line 1,610 ⟶ 2,265:
avalanche=: (AVALANCHE + {)`[`]}~ ([: <"1 NEIGHBORS +"1 index_of_maximum)
erode=: avalanche&.:frame While(3 < [: >./ ,)
</syntaxhighlight>
<pre>
NB. common ways to construct a matrix in j from directly entered vectors
Line 1,657 ⟶ 2,312:
└─────────┴─────────┘
</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}}==
<
struct Sandpile
Line 1,733 ⟶ 2,638:
println(s3_id, " +\n", s3_id, " =\n", s3_id + s3_id, "\n")
</
<pre>
Avalanche reduction to group:
Line 1,783 ⟶ 2,688:
2 1 2
</pre>
=={{header|Lua}}==
Uses Abelian sandpile model [[Abelian_sandpile_model#Lua|here]], then extends..
<
sandpile.new = function(self, vals)
local inst = setmetatable({},sandpile)
Line 1,829 ⟶ 2,735:
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()</
{{out}}
<pre>s1 =
Line 1,882 ⟶ 2,788:
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
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 1,907 ⟶ 2,813:
sp[{{4, 3, 3}, {3, 1, 2}, {0, 2, 3}}] + sp[0]
s3 + s3id === s3
s3id + s3id === s3id</
{{out}}
<pre>3 3 3
Line 1,927 ⟶ 2,833:
=={{header|Nim}}==
<syntaxhighlight lang="nim">
import sequtils
import strutils
Line 2,033 ⟶ 2,939:
echo "s3_id + s3_id = s3_id\n"
printSum(s3_id, s3_id, s3_id + s3_id)
</syntaxhighlight>
{{out}}
Line 2,073 ⟶ 2,979:
=={{header|OCaml}}==
<syntaxhighlight lang="ocaml">
(* https://en.wikipedia.org/wiki/Abelian_sandpile_model *)
Line 2,216 ⟶ 3,122:
; print (s3_id +. s3_id)
end
</syntaxhighlight>
{{out}}
Line 2,285 ⟶ 3,191:
=={{header|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,369 ⟶ 3,275:
<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>
<!--</
{{out}}
<pre>
Line 2,403 ⟶ 3,309:
=={{header|Python}}==
===Object Oriented===
<
from collections import defaultdict
Line 2,482 ⟶ 3,388:
s3 = Sandpile("3 3 3 3 3 3 3 3 3")
s3_id = Sandpile("2 1 2 1 0 1 2 1 2")
</syntaxhighlight>
;Command line session to complete task.
Line 2,553 ⟶ 3,459:
===Functional===
<
from operator import add, eq
Line 2,781 ⟶ 3,687:
# MAIN ---
if __name__ == '__main__':
main()</
{{Out}}
<pre>Cascade:
Line 2,812 ⟶ 3,718:
Most of the logic is lifted straight from the [[Abelian_sandpile_model#Raku|Abelian sandpile model]] task.
<syntaxhighlight lang="raku"
has $.h = 3;
has $.w = 3;
Line 2,876 ⟶ 3,782:
put '';
}</
{{out}}
<pre> identity test pile toppled plus identity toppled
Line 2,908 ⟶ 3,814:
│ 2 │ 3 │ 2 │ 3 │ 2 │ │ 4 │ 2 │ 2 │ 4 │ 0 │ │ 3 │ 2 │ 3 │ 2 │ 1 │ │ 5 │ 5 │ 5 │ 5 │ 3 │ │ 3 │ 2 │ 3 │ 2 │ 1 │
╰───┴───┴───┴───┴───╯ ╰───┴───┴───┴───┴───╯ ╰───┴───┴───┴───┴───╯ ╰───┴───┴───┴───┴───╯ ╰───┴───┴───┴───┴───╯
</pre>
=={{header|Red}}==
<syntaxhighlight lang="rebol">
Red [Purpose: "implement Abelian sandpile model"]
sadd: make object! [
comb: function [pile1 [series!] pile2 [series!]] [
repeat r 3 [
repeat c 3 [
pile2/:r/:c: pile2/:r/:c + pile1/:r/:c
]
]
check pile2
]
check: func [pile [series!]] [
stable: true row: col: none
repeat r 3[
repeat c 3[
if pile/:r/:c >= 4 [
stable: false
pile/:r/:c: pile/:r/:c - 4
row: r col: c
break]
]
if stable = false [break]
]
unless stable = false [print trim/with mold/only pile "[]" exit]
spill pile row col
]
spill: func [pile [series!] r [integer!] c [integer!]] [
neigh: reduce [
right: reduce [r c - 1] up: reduce [r + 1 c]
left: reduce [r c + 1] down: reduce [r - 1 c]
]
foreach n neigh [
unless any [(pile/(n/1) = none) (pile/(n/1)/(n/2) = none)] [
pile/(n/1)/(n/2): pile/(n/1)/(n/2) + 1
]
]
check pile
]
]
s1: [
[1 2 0]
[2 1 1]
[0 1 3]
]
s2: [
[2 1 3]
[1 0 1]
[0 1 0]
]
s3: [
[3 3 3]
[3 3 3]
[3 3 3]
]
s3_id: [
[2 1 2]
[1 0 1]
[2 1 2]
]
ex: [
[4 3 3]
[3 1 2]
[0 2 3]
]
sadd/check copy/deep ex
sadd/comb copy/deep s1 copy/deep s2
sadd/comb copy/deep s2 copy/deep s1
sadd/comb copy/deep s3 copy/deep s3_id
sadd/comb copy/deep s3_id copy/deep s3_id
</syntaxhighlight>
{{out}}
<pre>
2 1 0
0 3 3
1 2 3
3 3 3
3 1 2
0 2 3
3 3 3
3 1 2
0 2 3
3 3 3
3 3 3
3 3 3
2 1 2
1 0 1
2 1 2
</pre>
=={{header|REXX}}==
<
@.= 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 2,969 ⟶ 3,983:
end /*c*/
say ind pad $ /*display a row.*/
end /*r*/; shows= shows + 1; if shows==1 then say; return</
{{out|output|text= when using the default inputs:}}
Line 3,013 ⟶ 4,027:
2 1 2
comparison of sum4 and s3_id: same.
</pre>
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">class Sandpile
def initialize(ar) = @grid = ar
def to_a = @grid.dup
def + (other)
res = self.to_a.zip(other.to_a).map{|row1, row2| row1.zip(row2).map(&:sum) }
Sandpile.new(res)
end
def stable? = @grid.flatten.none?{|v| v > 3}
def avalanche
topple until stable?
self
end
def == (other) = self.avalanche.to_a == other.avalanche.to_a
def topple
a = @grid
a.each_index do |row|
a[row].each_index do |col|
next if a[row][col] < 4
a[row+1][col] += 1 unless row == a.size-1
a[row-1][col] += 1 if row > 0
a[row][col+1] += 1 unless col == a.size-1
a[row][col-1] += 1 if col > 0
a[row][col] -= 4
end
end
self
end
def to_s = "\n" + @grid.map {|row| row.join(" ") }.join("\n")
end
puts "Sandpile:"
puts demo = Sandpile.new( [[4,3,3], [3,1,2],[0,2,3]] )
puts "\nAfter the avalanche:"
puts demo.avalanche
puts "_" * 30,""
s1 = Sandpile.new([[1, 2, 0], [2, 1, 1], [0, 1, 3]] )
puts "s1: #{s1}"
s2 = Sandpile.new([[2, 1, 3], [1, 0, 1], [0, 1, 0]] )
puts "\ns2: #{s2}"
puts "\ns1 + s2 == s2 + s1: #{s1 + s2 == s2 + s1}"
puts "_" * 30,""
s3 = Sandpile.new([[3, 3, 3], [3, 3, 3], [3, 3, 3]] )
s3_id = Sandpile.new([[2, 1, 2], [1, 0, 1], [2, 1, 2]] )
puts "s3 + s3_id == s3: #{s3 + s3_id == s3}"
puts "s3_id + s3_id == s3_id: #{s3_id + s3_id == s3_id}"
</syntaxhighlight>
{{out}}
<pre>
4 3 3
3 1 2
0 2 3
After the avalanche:
2 1 0
0 3 3
1 2 3
______________________________
s1:
1 2 0
2 1 1
0 1 3
s2:
2 1 3
1 0 1
0 1 0
s1 + s2 == s2 + s1: true
______________________________
s3 + s3_id == s3: true
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}}
<
class Sandpile {
Line 3,091 ⟶ 4,418:
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)</
{{out}}
Line 3,188 ⟶ 4,515:
1 0 1
2 1 2
</pre>
|