Skip to content

Commit

Permalink
18: changed data structure (since we only needed tuples)
Browse files Browse the repository at this point in the history
  • Loading branch information
squell committed Dec 20, 2021
1 parent 7fb899d commit 4b4b88f
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 155 deletions.
68 changes: 23 additions & 45 deletions 18/read.a68
Original file line number Diff line number Diff line change
@@ -1,58 +1,36 @@
CO data type and some operations for snailfish numbers CO
MODE LISTELEM = STRUCT(UNION(INT,LIST) elem);
MODE LIST = REF[]LISTELEM;
MODE PAIR = STRUCT (NUMBER left, right);
MODE NUMBER = UNION(INT, REF PAIR);

PROC make pair = (UNION(INT,LIST) x, y)LIST:
(HEAP[2]LISTELEM result; elem OF result := (x, y); result);
PROC make pair = (NUMBER x, y)REF PAIR:
HEAP PAIR := (x,y);

PROC append = (REF LIST arr)REF UNION(INT, LIST):
(LIST(arr) IS NIL
| elem OF (arr := HEAP [1]LISTELEM)[1] CO TODO: funny bug in Algol68g if the first [1] is removed; notify Marcel. CO
| HEAP[UPB arr+1]LISTELEM fresh; fresh[1:UPB arr] := arr; arr := fresh; elem OF arr[UPB arr]
);
PROC dump = (NUMBER data)VOID:
CASE data IN
(INT n): printf(($g(0)$, n)),
(REF PAIR p): (print("["); dump(left OF p); print(","); dump(right OF p); print("]"))
ESAC;

PROC dump list = (LIST data)VOID:
PROC parse = (REF STRING s)NUMBER:
BEGIN
print("[");
FOR i TO UPB data DO
IF i > 1 THEN print(",") FI;
CASE elem OF data[i] IN
(INT n) : printf(($g(0)$, n)),
(LIST sub): dump list(sub)
ESAC
OD;
print("]")
END;

PROC parse = (STRING s)LIST:
BEGIN
INT i := 1;

PROC parse elem = UNION(INT, LIST):
IF s[i] = "[" THEN
LIST sublist := NIL;
WHILE s[i] /= "]" DO
i +:= 1;
append(sublist) := parse elem;
i +:= 1
OD;
sublist
ELSE
INT p; char in string(s[i], p, "1234567890");
p MOD 10
FI;

CASE parse elem IN
(LIST result): result
ESAC
CHAR c = s[1]; s := s[2:];
IF c = "[" THEN
NUMBER lt = parse (s); s := s[2:];
NUMBER rt = parse (s); s := s[2:];
make pair (lt, rt)
ELSE
INT p; char in string(c, p, "1234567890");
p MOD 10
FI
END;

LIST homework = BEGIN
LIST lines := NIL;
[]NUMBER homework = BEGIN
FLEX[0]NUMBER lines;
on logical file end(stand in, (REF FILE f)BOOL: done reading);
DO
STRING s; read((s)); read(new line);
append(lines) := parse(s)
([UPB lines+1]NUMBER tmp; tmp[1:UPB lines] := lines; lines := tmp);
lines[UPB lines] := parse(s)
OD;
done reading:
lines
Expand Down
97 changes: 47 additions & 50 deletions 18/solve.a68
Original file line number Diff line number Diff line change
@@ -1,81 +1,78 @@
PR include "read.a68" PR

PROC traverse = (LIST list, PROC(INT,REF UNION(INT,LIST))BOOL visit)VOID:
PROC traverse = (REF NUMBER num, PROC(INT,REF NUMBER)BOOL visit)VOID:
BEGIN
PROC dive into = (INT depth, LIST list)VOID:
FOR i TO UPB list DO
BOOL found = visit(depth, elem OF list[i]);
CASE elem OF list[i] IN
(LIST sub): IF NOT found THEN dive into(depth+1, sub) FI
ESAC
OD;
dive into(0,list)
PROC dive into = (INT depth, REF NUMBER num)VOID:
BEGIN
BOOL found = visit(depth, num);
CASE num IN
(REF PAIR sub): IF NOT found THEN
dive into(depth+1, left OF sub);
dive into(depth+1, right OF sub)
FI
ESAC
END;
dive into(0,num)
END;

PROC is regular = (LIST pair)BOOL:
PROC is regular = (PAIR tuple)BOOL:
(BOOL result := TRUE;
[]NUMBER pair = (left OF tuple, right OF tuple);
FOR i TO UPB pair WHILE result DO
(elem OF pair[i] | (INT n): ~ | result := FALSE)
(pair[i] | (INT n): ~ | result := FALSE)
OD; result);

PROC snailfish reduce = (LIST n)LIST:
PROC snailfish reduce = (REF NUMBER data)VOID:
BEGIN
LIST data := n;
REF UNION(INT,LIST) last regular;
REF NUMBER last regular;
INT last regular value, add to next regular;
BOOL exploded;

PROC explode = (INT depth, REF UNION(INT,LIST) cell)BOOL:
CASE cell IN (LIST pair):
IF depth >= 3 AND is regular(pair) AND NOT exploded THEN
IF REF UNION(INT,LIST) prev cell = last regular; prev cell ISNT NIL THEN
prev cell := last regular value + (elem OF pair[1] | (INT n): n)
FI;
add to next regular := (elem OF pair[2] | (INT n): n);
cell := 0;
exploded := TRUE
ELSE FALSE
FI,
(INT n):
BEGIN
cell := n + add to next regular;
last regular := cell;
last regular value := n;
IF exploded THEN just start again FI
END
PROC explode = (INT depth, REF NUMBER cell)BOOL:
CASE cell IN (REF PAIR pair):
IF depth >= 4 AND is regular(pair) AND NOT exploded THEN
IF REF NUMBER prev cell = last regular; prev cell ISNT NIL THEN
prev cell := last regular value + (left OF pair | (INT n): n)
FI;
add to next regular := (right OF pair | (INT n): n);
cell := 0;
exploded := TRUE
ELSE FALSE
FI,
(INT n):
BEGIN
cell := n + add to next regular;
last regular := cell;
last regular value := n;
IF exploded THEN just start again FI
END
ESAC;

PROC split = (INT depth, REF UNION(INT,LIST) cell)BOOL:
PROC split = (INT depth, REF NUMBER cell)BOOL:
(cell | (INT n): IF n >= 10 THEN cell := make pair (n%2, (n+1)%2); just start again FI | FALSE);

just start again:
CO dump list(data); print(new line); CO
CO dump(data); print(new line); CO
exploded := FALSE;
last regular := NIL;
add to next regular := 0;
traverse(data, explode);
traverse(data, split);
data
traverse(data, split)
END;

PROC snailfish add = (LIST a,b)LIST:
snailfish reduce(make pair(a,b));
OP +:= = (REF NUMBER x, NUMBER y)VOID:
snailfish reduce(x := make pair(x,y));

PROC snailfish abs = (LIST a)INT:
BEGIN
OP ABS = (UNION(INT,LIST) cell)INT:
CASE cell IN
OP ABS = (NUMBER x)INT:
CASE x IN
(INT n): n,
(LIST pair): 3*ABS elem OF pair[1] + 2*ABS elem OF pair[2]
(REF PAIR pair): 3*ABS left OF pair + 2*ABS right OF pair
ESAC;
ABS a
END;

LIST acc := (elem OF homework[1] | (LIST pair): pair);
NUMBER acc := homework[1];
FOR i FROM 2 TO UPB homework DO
acc := snailfish add(acc, (elem OF homework[i] | (LIST pair): pair))
acc +:= homework[i]
OD;

dump list(acc);
print((snailfish abs(acc), new line))

dump(acc);
print((ABS acc, new line))
117 changes: 57 additions & 60 deletions 18/solve2.a68
Original file line number Diff line number Diff line change
@@ -1,63 +1,66 @@
PR include "read.a68" PR

PROC traverse = (LIST list, PROC(INT,REF UNION(INT,LIST))BOOL visit)VOID:
PROC traverse = (REF NUMBER num, PROC(INT,REF NUMBER)BOOL visit)VOID:
BEGIN
PROC dive into = (INT depth, LIST list)VOID:
FOR i TO UPB list DO
BOOL found = visit(depth, elem OF list[i]);
CASE elem OF list[i] IN
(LIST sub): IF NOT found THEN dive into(depth+1, sub) FI
ESAC
OD;
dive into(0,list)
PROC dive into = (INT depth, REF NUMBER num)VOID:
BEGIN
BOOL found = visit(depth, num);
CASE num IN
(REF PAIR sub): IF NOT found THEN
dive into(depth+1, left OF sub);
dive into(depth+1, right OF sub)
FI
ESAC
END;
dive into(0,num)
END;

PROC is regular = (LIST pair)BOOL:
PROC is regular = (PAIR tuple)BOOL:
(BOOL result := TRUE;
[]NUMBER pair = (left OF tuple, right OF tuple);
FOR i TO UPB pair WHILE result DO
(elem OF pair[i] | (INT n): ~ | result := FALSE)
(pair[i] | (INT n): ~ | result := FALSE)
OD; result);

PROC snailfish reduce = (LIST n)LIST:
BEGIN
PROC deep copy = (LIST data)LIST:
(HEAP[UPB data]LISTELEM copy;
FOR i TO UPB data DO
(elem OF data[i] | (LIST pair): elem OF copy[i] := deep copy(pair)
| copy[i] := data[i])
OD;
copy);
PRIO COPY = 1;
OP COPY = (NUMBER x)NUMBER:
CASE x IN
(REF PAIR pair): make pair(COPY left OF pair, COPY right OF pair)
OUT x
ESAC;

LIST data := deep copy(n);
REF UNION(INT,LIST) last regular;
PROC snailfish reduce = (NUMBER n)NUMBER:
BEGIN
NUMBER data := COPY n;
REF NUMBER last regular;
INT last regular value, add to next regular;
BOOL exploded;

PROC explode = (INT depth, REF UNION(INT,LIST) cell)BOOL:
CASE cell IN (LIST pair):
IF depth >= 3 AND is regular(pair) AND NOT exploded THEN
IF REF UNION(INT,LIST) prev cell = last regular; prev cell ISNT NIL THEN
prev cell := last regular value + (elem OF pair[1] | (INT n): n)
FI;
add to next regular := (elem OF pair[2] | (INT n): n);
cell := 0;
exploded := TRUE
ELSE FALSE
FI,
(INT n):
BEGIN
cell := n + add to next regular;
last regular := cell;
last regular value := n;
IF exploded THEN just start again FI
END
PROC explode = (INT depth, REF NUMBER cell)BOOL:
CASE cell IN (REF PAIR pair):
IF depth >= 4 AND is regular(pair) AND NOT exploded THEN
IF REF NUMBER prev cell = last regular; prev cell ISNT NIL THEN
prev cell := last regular value + (left OF pair | (INT n): n)
FI;
add to next regular := (right OF pair | (INT n): n);
cell := 0;
exploded := TRUE
ELSE FALSE
FI,
(INT n):
BEGIN
cell := n + add to next regular;
last regular := cell;
last regular value := n;
IF exploded THEN just start again FI
END
ESAC;

PROC split = (INT depth, REF UNION(INT,LIST) cell)BOOL:
PROC split = (INT depth, REF NUMBER cell)BOOL:
(cell | (INT n): IF n >= 10 THEN cell := make pair (n%2, (n+1)%2); just start again FI | FALSE);

just start again:
CO dump list(data); print(new line); CO
CO dump(data); print(new line); CO
exploded := FALSE;
last regular := NIL;
add to next regular := 0;
Expand All @@ -66,34 +69,28 @@ just start again:
data
END;

PROC snailfish add = (LIST a,b)LIST:
snailfish reduce(make pair(a,b));
CO note: because "INT" is directly convertible into a number, we can't overload "OP +" easily CO
PROC add = (NUMBER x,y)NUMBER:
snailfish reduce(LOC PAIR:=(x,y));

PROC snailfish abs = (LIST a)INT:
BEGIN
OP ABS = (UNION(INT,LIST) cell)INT:
CASE cell IN
OP ABS = (NUMBER x)INT:
CASE x IN
(INT n): n,
(LIST pair): 3*ABS elem OF pair[1] + 2*ABS elem OF pair[2]
(REF PAIR pair): 3*ABS left OF pair + 2*ABS right OF pair
ESAC;
ABS a
END;

INT max magnitude := -1000;
LIST x1, x2;
NUMBER x1, x2;

FOR i TO UPB homework DO FOR j TO UPB homework DO
IF i /= j THEN
INT this = snailfish abs(
snailfish add((elem OF homework[i] | (LIST pair): pair),
(elem OF homework[j] | (LIST pair): pair))
);
INT this = ABS add(homework[i], homework[j]);
(this > max magnitude | max magnitude := this;
x1 := (elem OF homework[i] | (LIST pair): pair);
x2 := (elem OF homework[j] | (LIST pair): pair))
x1 := homework[i];
x2 := homework[j])
FI
OD OD;

dump list(x1); print(new line);
dump list(x2); print(new line);
dump(x1); print(new line);
dump(x2); print(new line);
print((max magnitude, new line))

0 comments on commit 4b4b88f

Please sign in to comment.