-- logic10.mesa

DIRECTORY SystemDefs:FROM"SystemDefs", IODefs:FROM"IODefs";
Logic:PROGRAM IMPORTS SystemDefs, IODefs=BEGIN

Error:SIGNAL=CODE;

Circuit:TYPE=INTEGER;
Gain:TYPE={leftWin,rightWin,bothLose,neutral};

Profit:TYPE=RECORD[lr,ud:Gain];
Bounds:TYPE=RECORD[iMin,iMax,jMin,jMax:INTEGER];
Transistor:TYPE=RECORD[a,b,c:Circuit];
ProfitPair:TYPE=RECORD[a,b,c:Profit];
ValuePair:TYPE=RECORD[l,u:INTEGER];

topCircuit:INTEGER=1000;
nullTransistor:Transistor=[0,0,0];
nullCircuit:INTEGER=topCircuit;
loser:Profit=[bothLose,bothLose];
nothing:Profit=[neutral,neutral];
completeLoss:ProfitPair=[loser,loser,loser];
CR:CHARACTER=’
;
side:INTEGER; --computed side of grid
maxSide:INTEGER=25;
straight,drifting:BOOLEAN;
runNo:INTEGER;

gridType:TYPE=ARRAY [0..maxSide) OF ARRAY[0..maxSide) OF Transistor;
gainType:TYPE=ARRAY [0..maxSide) OF ARRAY [0..maxSide) OF ProfitPair;
ValueType:TYPE=ARRAY [0..maxSide) OF ARRAY [0..maxSide) OF ValuePair;

inputType:TYPE=ARRAY[0..topCircuit+5) OF Transistor;
boundsType:TYPE=ARRAY [0..topCircuit+5) OF Bounds;
FigureType:TYPE=ARRAY [0..topCircuit+5) OF ValuePair;

grid:POINTER TO gridType;
bestGrid:POINTER TO gridType;
printGrid:POINTER TO gridType;
gain:POINTER TO gainType;
values:POINTER TO ValueType;

input:POINTER TO inputType;
bounds:POINTER TO boundsType;
figure:POINTER TO FigureType;


--//////////////TRACK///////////////

--the purpose of track is to efficiently find all the transistors in a circuit
--the track operations are:
--Make Track, which builds the data structures
--EnumerateTrack, which calls you back with each transistor participating
-- in the specified circuit
--Valid Circuit, which returns true if there is some transistor this circuit

Loc:TYPE=[0..128);
Slot:TYPE={a,b,c};
Location:TYPE=RECORD[slot:Slot,a,b:Loc];
nullLoc:Location←[a,127,127];
circuitsType:TYPE=ARRAY [0..topCircuit+5) OF Location;
circuits:POINTER TO circuitsType;

LocationPair:TYPE=RECORD[a,b,c:Location];
trackType:TYPE=ARRAY [0..maxSide) OF ARRAY [0..maxSide) OF LocationPair;
track:POINTER TO trackType;

MakeTrack:PROCEDURE=BEGIN
EnumerateCircuit[ClearCircuit];
EnumerateGrid[ClearTrack];
EnumerateGrid[BuildTrack];
END;

EnumerateTrack:PROCEDURE[i:INTEGER,Call:PROCEDURE[s,t:INTEGER]]=BEGIN
sz,tz:INTEGER;
l:Location;
FOR l←circuits[i],SELECT l.slot FROM
a=>track[sz][tz].a ,b=>track[sz][tz].b, ENDCASE=>track[sz][tz].c
UNTIL l=nullLoc DO sz←l.a; tz←l.b; Call[sz,tz]; ENDLOOP;
END;

ValidCircuit:PROCEDURE[i:INTEGER] RETURNS[BOOLEAN]=
BEGIN RETURN[circuits[i]#nullLoc];END;

ClearCircuit:PROCEDURE[i:INTEGER]=BEGIN circuits[i]←nullLoc; END;

ClearTrack:PROCEDURE[i,j:INTEGER]=
BEGIN track[i][j]←[nullLoc,nullLoc,nullLoc]; END;

BuildTrack:PROCEDURE[i,j:INTEGER]=BEGIN
s,t,w:Circuit;
[s,t,w]←grid[i][j];
IF s ~IN [0..topCircuit]
OR t ~IN [0..topCircuit]
OR w ~IN [0..topCircuit] THEN Error;
track[i][j]←[circuits[s],circuits[t],circuits[w]];
circuits[s]←[a,i,j];
circuits[t]←[b,i,j];
circuits[w]←[c,i,j];
END;

--//////////////CONTROL///////////////

Main:PROCEDURE=BEGIN s,ss:INTEGER;
AllocateStuff[];
FOR runNo IN [2..2] DO --thacker,cell,cell4,cell9,ISB,Stack,Stack4
bestSoFar←20000;
cnt←0;
fullPrinting←TRUE;
FOR s IN [0..10) DO
IF s=0 THEN FakeInput[] ELSE DisturbInput[];
AssignPairsToIntersections[];
BuildGain[];
-- PrintG[grid];
FOR ss IN [0..side) DO
drifting←TRUE;
straight←FALSE;
IF ss#0 THEN Do[3,MakeShakes];
Do[6*side,MakeSwaps];
IF ss>6 THEN BEGIN
drifting←FALSE;
Do[16,MakeSwaps];
straight←TRUE;
Do[16,MakeSwaps];
END;
ENDLOOP;
ENDLOOP;
grid←bestGrid;
drifting←FALSE;
straight←TRUE;
Do[4*side,MakeSwaps];
PrintG[bestGrid];
PrintGSection[bestGrid];
IODefs.WriteChar[CR];
IODefs.WriteString["wire length = "];
IODefs.WriteNumber[bestSoFar, [10,FALSE,TRUE,5]];
ENDLOOP;
END;

--//////////////CONTROL///////////////

AllocateStuff:PROCEDURE=BEGIN OPEN SystemDefs;
grid←AllocateSegment[SIZE[gridType]];
bestGrid←AllocateSegment[SIZE[gridType]];
gain←AllocateSegment[SIZE[gainType]];
track←AllocateSegment[SIZE[trackType]];
input←AllocateSegment[SIZE[inputType]];
circuits←AllocateSegment[SIZE[circuitsType]];
bounds←AllocateSegment[SIZE[boundsType]];
values←AllocateSegment[SIZE[ValueType]];
figure←AllocateSegment[SIZE[FigureType]];
END;

Do:PROCEDURE[k:INTEGER,call:PROCEDURE[i,j:INTEGER]]=BEGIN s:INTEGER;
FOR s IN [0..k) DO
EnumerateGrid[call];
BuildGain[];
PrintBounds[];
IF wireLength<bestSoFar THEN BEGIN
bestSoFar←wireLength;
bestGrid↑←grid↑;
END;
ENDLOOP;
END;

BuildGain:PROCEDURE=BEGIN
MakeTrack[];
EnumerateCircuit[BuildBounds];
bounds[vdd]←bounds[gnd]←bounds[topCircuit]←[0,0,0,0];
EnumerateGrid[ComputeGain];
EnumerateGrid[ComputeValues];
EnumerateCircuit[ComputeFigures];
figure[vdd]←figure[gnd]←figure[topCircuit]←[0,0];
--IODefs.WriteChar[CR];
--EnumerateGrid[PrintGain];
END;

EnumerateGrid:PROCEDURE[call:PROCEDURE[i,j:INTEGER]]=BEGIN
i,j:INTEGER;
FOR i IN [0..side) DO FOR j IN [0..side) DO call[i,j]; ENDLOOP; ENDLOOP;
END;

EnumerateCircuit:PROCEDURE[call:PROCEDURE[i:INTEGER]]=
BEGIN i:INTEGER; FOR i IN [0..topCircuit) DO call[i]; ENDLOOP; END;

--//////////////STARTUP///////////////

m:INTEGER;
n:INTEGER;

AssignPairsToIntersections:PROCEDURE=BEGIN
side←maxSide;
m←n←0;
EnumerateGrid[ClearGrid];
EnumerateCircuit[AddAPair];
IF n=0 THEN m←m-1; -- a hack to handle the perfect square case.
side←MAX[m,n]+1;
--IF side#realSide THEN Error;
END;

ClearGrid:PROCEDURE[i,j:INTEGER]=BEGIN grid[i][j]←nullTransistor; END;

AddAPair:PROCEDURE[i:INTEGER]=BEGIN
IF input[i]=nullTransistor THEN RETURN;
grid[m][n]←input[i];
IF m>n THEN IF (n←n+1)=m THEN m←0 ELSE NULL
ELSE IF (m←m+1)=n+1 THEN n←0 ELSE NULL;
IF m>=maxSide OR n>=maxSide THEN Error;
END;

--//////////////COMPUTE GAIN///////////////

--//////////////COMPUTE GAIN///////////////

BuildBounds:PROCEDURE[i:INTEGER]=BEGIN
SetMaxMin:PROCEDURE[s,t:INTEGER]=BEGIN
sMin←MIN[sMin,s]; sMax←MAX[sMax,s]; tMin←MIN[tMin,t]; tMax←MAX[tMax,t];
END;
sMax,tMax:INTEGER←0;
sMin,tMin:INTEGER←10000;
EnumerateTrack[i,SetMaxMin];
IF sMin=10000 THEN sMin←tMin←0;
bounds[i]←[sMin,sMax,tMin,tMax];
END;

--//////////////COMPUTE GAIN///////////////

ComputeGain:PROCEDURE[i,j:INTEGER]=BEGIN
gain[i][j]←[ComputeOneGain[grid[i][j].a,i,j],
ComputeOneGain[grid[i][j].b,i,j],
ComputeOneGain[grid[i][j].c,i,j]];
END;

ComputeOneGain:PROCEDURE[a,i,j:INTEGER] RETURNS[ans:Profit]=BEGIN
ans←[lr:SELECT TRUE FROM
bounds[a].jMax=bounds[a].jMin => bothLose,
bounds[a].jMax=j => leftWin,
bounds[a].jMin=j => rightWin,
ENDCASE=>neutral,
ud:SELECT TRUE FROM
bounds[a].iMax=bounds[a].iMin => bothLose,
bounds[a].iMax=i => leftWin,
bounds[a].iMin=i => rightWin,
ENDCASE=>neutral];
IF ans=[bothLose,bothLose] THEN ans←nothing;
END;

--//////////////MOVE TRANSISTORS///////////////

ComputeValues:PROCEDURE[i,j:INTEGER]=
BEGIN
values[i][j]←[ValueOfMovingRight[i,j,i,j+1],ValueOfMovingUp[i,j,i+1,j]];
END;

ValueOfMovingRight:PROCEDURE[i,j,s,t:INTEGER] RETURNS[v:INTEGER]=BEGIN
gij:ProfitPair←gain[i][j];
gst:ProfitPair←gain[s][t];
v←Cnt[gij.a.lr, 1]+Cnt[gij.b.lr, 1]+Cnt[gij.c.lr, 1]
+Cnt[gst.a.lr,-1]+Cnt[gst.b.lr,-1]+Cnt[gst.c.lr,-1];
END;

ValueOfMovingUp:PROCEDURE[i,j,s,t:INTEGER] RETURNS[v:INTEGER]=BEGIN
gij:ProfitPair←gain[i][j];
gst:ProfitPair←gain[s][t];
v←Cnt[gij.a.ud, 1]+Cnt[gij.b.ud, 1]+Cnt[gij.c.ud, 1]
+Cnt[gst.a.ud,-1]+Cnt[gst.b.ud,-1]+Cnt[gst.c.ud,-1];
END;

Cnt:PROCEDURE[g:Gain,x:INTEGER] RETURNS[INTEGER]=BEGIN
RETURN[SELECT g FROM leftWin=>-x, rightWin=>x, bothLose=>-1, ENDCASE=>0];
END;

ComputeFigures:PROCEDURE[c:INTEGER]= BEGIN
tl,tu,tc:INTEGER←0;
FigureOneCircuit:PROCEDURE[s,t:INTEGER]= BEGIN
tl←tl+values[s][t].l; tu←tu+values[s][t].u; tc←tc+1;
END;
EnumerateTrack[c,FigureOneCircuit];
SELECT tc FROM
1=>tl←0;
2,3=>IF tl>1 THEN tl←1 ELSE tl←0;
4,5=>IF tl>4 THEN tl←2 ELSE IF tl>2 THEN tl←1 ELSE tl←0;
ENDCASE=>IF tl>5 THEN tl←2 ELSE IF tl>3 THEN tl←1 ELSE tl←0;
SELECT tc FROM
1=>tu←0;
2,3=>IF tu>1 THEN tu←1 ELSE tu←0;
4,5=>IF tu>4 THEN tu←2 ELSE IF tu>2 THEN tu←1 ELSE tu←0;
ENDCASE=>IF tu>5 THEN tu←2 ELSE IF tu>3 THEN tu←1 ELSE tu←0;
figure[c]←[tl,tu];
END;


MakeSwaps:PROCEDURE[i,j:INTEGER]=BEGIN Swap[i,j,i+1,j]; Swap[i,j,i,j+1]; END;

Swap:PROCEDURE[i,j,s,t:INTEGER]=BEGIN c:INTEGER;
c←IF t>j THEN TrueValueL[i,j] ELSE TrueValueU[i,j];
Inside[i,j,s,t,c];
END;

Inside:PROCEDURE[i,j,s,t,c:INTEGER]=BEGIN temp:Transistor;
IF straight AND (gain[i][j]=completeLoss OR gain[s][t]=completeLoss)
THEN RETURN;
IF s NOT IN [0..side) OR t NOT IN [0..side) OR c<=0 THEN RETURN;
temp←grid[i][j]; grid[i][j]←grid[s][t]; grid[s][t]←temp;
gain[i][j]←gain[s][t]←completeLoss;
END;

TrueValueL:PROCEDURE[i,j:INTEGER] RETURNS[s:INTEGER]=BEGIN
ta:INTEGER←figure[grid[i][j].a].l;
tb:INTEGER←figure[grid[i][j].b].l;
tc:INTEGER←figure[grid[i][j].c].l;
s←4*values[i][j].l+(IF drifting THEN ta+tb+tc ELSE 0);
END;

TrueValueU:PROCEDURE[i,j:INTEGER] RETURNS[s:INTEGER]=BEGIN
ta:INTEGER←figure[grid[i][j].a].u;
tb:INTEGER←figure[grid[i][j].b].u;
tc:INTEGER←figure[grid[i][j].c].u;
s←4*values[i][j].u+(IF drifting THEN ta+tb+tc ELSE 0);
END;

--//////////////MOVE TRANSISTORS///////////////

MakeShakes:PROCEDURE[i,j:INTEGER]=
BEGIN Shake[i,j,i+1,j]; Shake[i,j,i,j+1]; END;

Shake:PROCEDURE[i,j,s,t:INTEGER]=BEGIN
Cnt:PROCEDURE[g:Gain,x:INTEGER] RETURNS[INTEGER]=BEGIN
RETURN[SELECT g FROM leftWin=>-x, rightWin=>x, bothLose=>-1, ENDCASE=>0];
END;
gij:ProfitPair←gain[i][j];
gst:ProfitPair←gain[s][t];
c:INTEGER←IF t>j
THEN Cnt[gij.a.lr, 1]+Cnt[gij.b.lr, 1]+Cnt[gij.c.lr, 1]
+Cnt[gst.a.lr,-1]+Cnt[gst.b.lr,-1]+Cnt[gst.c.lr,-1]
ELSE Cnt[gij.a.ud, 1]+Cnt[gij.b.ud, 1]+Cnt[gij.c.ud, 1]
+Cnt[gst.a.ud,-1]+Cnt[gst.b.ud,-1]+Cnt[gst.c.ud,-1];
Inside[i,j,s,t,c+1];
END;


--//////////////MOVE TRANSISTORS///////////////

MakeShakes2:PROCEDURE[i,j:INTEGER]=
BEGIN Shake2[i,j,i+1,j]; Shake2[i,j,i,j+1]; END;

Shake2:PROCEDURE[i,j,s,t:INTEGER]=BEGIN
Cnt:PROCEDURE[g:Gain,x:INTEGER] RETURNS[INTEGER]=BEGIN
RETURN[SELECT g FROM leftWin=>-x, rightWin=>x, bothLose=>-1, ENDCASE=>0];
END;
gij:ProfitPair←gain[i][j];
gst:ProfitPair←gain[s][t];
c:BOOLEAN←IF t>j
THEN Cnt[gij.a.lr, 1]+Cnt[gij.b.lr, 1]+Cnt[gij.c.lr, 1]>=2
OR Cnt[gst.a.lr,-1]+Cnt[gst.b.lr,-1]+Cnt[gst.c.lr,-1]<=-2
ELSE Cnt[gij.a.ud, 1]+Cnt[gij.b.ud, 1]+Cnt[gij.c.ud, 1]>=2
OR Cnt[gst.a.ud,-1]+Cnt[gst.b.ud,-1]+Cnt[gst.c.ud,-1]<=-2;
Inside[i,j,s,t,IF c THEN 1 ELSE -1];
END;

--///////////////PRINTING//////////////

PrintG:PROCEDURE[this:POINTER TO gridType]=BEGIN
printGrid←this;
IODefs.WriteChar[CR];
IODefs.WriteNumber[side,[10,FALSE,TRUE,4]];
IODefs.WriteChar[CR];
EnumerateGrid[PrintGrid];
IODefs.WriteNumber[-100,[10,FALSE,FALSE,4]];
IODefs.WriteChar[CR];
END;

PrintGSection:PROCEDURE[this:POINTER TO gridType]=BEGIN
printGrid←this;
IODefs.WriteChar[CR];
EnumerateGrid[PrintGridSection];
END;

PrintGrid:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs;
WriteNumber[i+1,[10,FALSE,TRUE,3]];
WriteNumber[j+1,[10,FALSE,TRUE,3]];
WriteId[IF printGrid[i][j].a = gnd AND printGrid[i][j].c = vdd THEN
printGrid[i][j].b ELSE printGrid[i][j].a];
WriteId[printGrid[i][j].b];
WriteId[printGrid[i][j].c];
WriteChar[CR];
END;

PrintGridSection:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs;
x:INTEGER;
IF j=0 THEN WriteChar[CR];
x←MAX[FindSectionId[printGrid[i][j].a],
FindSectionId[printGrid[i][j].b],
FindSectionId[printGrid[i][j].c]];
WriteChar[SELECT x FROM -1=>’x,0=>’0,1=>’1,2=>’2,3=>’3,4=>’4,
5=>’5,6=>’6,7=>’7,8=>’8,ENDCASE=>’9];
END;

WriteId:PROCEDURE[a:INTEGER]=BEGIN
IODefs.WriteChar[’ ];
IODefs.WriteChar[ atoms[a].a];
IODefs.WriteChar[ atoms[a].b];
END;

FindSectionId:PROCEDURE[a:INTEGER] RETURNS[INTEGER]=BEGIN
IF a=gnd THEN RETURN[-1];
RETURN[SELECT atoms[a].a FROM
’0,’ =>0, ’1=>1, ’2=>2, ’3=>3, ’4=>4, ’5=>5, ’6=>6, ’7=>7, ’8=>8,
ENDCASE=>-1];
END;

wireLength,bestSoFar:INTEGER;
cnt:CARDINAL;
fullPrinting:BOOLEAN;

PrintBounds:PROCEDURE=BEGIN
cnt←cnt+1;
IF fullPrinting THEN fullPrinting←cnt<500
ELSE IF cnt>20 THEN cnt←0 ELSE RETURN;
wireLength←0;
EnumerateCircuit[CountWire];
-- IODefs.WriteChar[CR];
-- IODefs.WriteString["wire length = "];
IODefs.WriteNumber[wireLength, [10,FALSE,TRUE,5]];
-- IODefs.WriteChar[CR];
END;

PrintGain:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs;
IF j=0 THEN WriteChar[CR];
WriteChar[ShowProfit[gain[i][j].a]];
WriteChar[ShowProfit[gain[i][j].b]];
WriteChar[ShowProfit[gain[i][j].c]];
WriteChar[’ ];
END;

ShowProfit:PROCEDURE[p:Profit] RETURNS[c:CHARACTER]=BEGIN
c←SELECT p.lr FROM leftWin=>’-, rightWin=>’+, bothLose=>’l, ENDCASE=>’n;
END;

CountWire:PROCEDURE[i:INTEGER]=BEGIN
IF ~ValidCircuit[i] THEN RETURN;
wireLength←wireLength+bounds[i].iMax-bounds[i].iMin
+bounds[i].jMax-bounds[i].jMin;
END;

--//////////////INPUT STUFF///////////////

putBackNum:INTEGER;
currentString:STRING;
Id:TYPE=RECORD[a,b:CHARACTER];
atoms:ARRAY[0..maxAtom+3] OF Id;
maxAtom:INTEGER=500;
topAtom,vdd,gnd:INTEGER;
tempString:STRING←[6];
topInput:INTEGER;
maxInput:INTEGER=topCircuit;

DisturbInput:PROCEDURE=BEGIN
EnumerateCircuit[ClearInput];
putBackNum←0;
EnumerateGrid[PutBack];
END;

PutBack:PROCEDURE[i,j:INTEGER]=BEGIN
input[putBackNum]←grid[i][j];
putBackNum←putBackNum+1;
END;

FakeInput:PROCEDURE=BEGIN
topInput←0;
InitAtoms[];
EnumerateCircuit[ClearInput];
SELECT runNo FROM
0=> FakeInputThacker[];
1=> FakeInputCell[];
2=> FakeInputCell4[];
3=> FakeInputCell9[];
4=> FakeInputISB[];
5=> FakeInputStack[];
6=> FakeInputStack4[];
ENDCASE=>Error;
END;

InitAtoms:PROCEDURE=BEGIN
tempString[0]←’A;
tempString[1]←’a;
topAtom←0;
currentString←"gd,vd";
gnd←GetAtom[0];
vdd←GetAtom[3];
END;

ClearInput:PROCEDURE[i:INTEGER]=BEGIN input[i]←nullTransistor; END;

--Legal Parsings
--a=~b
--a=~b+c+...
--a=~b*c*...
--a=~b*c+d*e+...
--a=~b(c+d+...
--a=.b,c
--a=←b,c,d

Parse:PROCEDURE[s:STRING]=BEGIN
l:CARDINAL=s.length;
a0,t1,t2,t3:CARDINAL; q:CARDINAL;
s3:CHARACTER←s[3];
s6:CHARACTER←s[6];
test1:BOOLEAN←s[9]=’+ OR s[9]=’* OR l=10;
test2:BOOLEAN←s6=’+ OR s6=’( OR s6=’* AND test1;
IF l<6 OR 0#l MOD 3 OR
~(l=(SELECT s3 FROM ’.=>9, ’←=>12, ’~=>6, ENDCASE=>0)
OR s3=’~ AND test2)
THEN BEGIN Error; RETURN END;
currentString←s;
a0←GetAtom[0];
IF s3#’. THEN Pull[a0];
SELECT TRUE FROM
s3=’.=>Set[GetAtom[4],GetAtom[7],a0];
s3=’←=>BEGIN
t1←GetTemp[]; t2←GetTemp[]; t3←GetTemp[];
Set[GetAtom[4],GetAtom[7],t1];
Set[gnd,t1,t2];
Pull[t2];
Set[t2,GetAtom[10],t3];
Set[gnd,t3,a0];
END;
l=6 OR s6=’+ =>
FOR q←4,q+3 UNTIL q>l DO Set[gnd,GetAtom[q],a0]; ENDLOOP;
s6=’( =>BEGIN
t1←GetTemp[];
Set[t1,GetAtom[4],a0];
FOR q←7,q+3 UNTIL q>l DO Set[gnd,GetAtom[q],t1]; ENDLOOP;
END;
s[9]=’* OR l=9=>BEGIN
t1←gnd;
FOR q←4,q+3 UNTIL q+3>l
DO Set[t1,GetAtom[q],t2←GetTemp[]]; t1←t2; ENDLOOP;
Set[t1,GetAtom[q],a0];
END;
ENDCASE=>FOR q←4,q+6 UNTIL q>l DO
t1←GetTemp[];
Set[gnd,GetAtom[q],t1];
Set[t1,GetAtom[q+3],a0];
ENDLOOP;
END;

Set:PROCEDURE[a,b,c:INTEGER]=BEGIN
IF a=b OR b=c OR c=a THEN Error;
input[topInput]←[a,b,c];
topInput←topInput+1;
IF topInput>maxInput THEN Error;
END;

Pull:PROCEDURE[a:INTEGER]=BEGIN Set[gnd,a,vdd]; END;

GetAtom:PROCEDURE[a:INTEGER] RETURNS[b:INTEGER]=BEGIN
RETURN[RealGetAtom[currentString,a]]; END;

GetTemp:PROCEDURE RETURNS[INTEGER]=BEGIN
IF tempString[1]#’z THEN tempString[1]←tempString[1]+1 ELSE
BEGIN tempString[1]←’a; tempString[0]←tempString[0]+1; END;
RETURN[RealGetAtom[tempString,0]];
END;

RealGetAtom:PROCEDURE[s:STRING,a:INTEGER] RETURNS[b:INTEGER]=BEGIN
id:Id←[s[a],s[a+1]];
i:INTEGER;
FOR i IN [0..topAtom) DO IF id=atoms[i] THEN RETURN[i]; ENDLOOP;
atoms[topAtom]←id;
topAtom←topAtom+1;
IF topAtom>maxAtom THEN Error;
RETURN[topAtom-1];
END;

--ca’=~ca
--01=~(ca+own)
--cao=~(01+wa)
--wa=~wa’
--foo=~(wa.ca’+wa.ow’+ow’.ca+own.na’)
--ow’=~own
--wa’=~(fm+goo)
--bh=Pass[Gnd,fm,ow’]
--na’=~na
--nao=~(na’+own)
--sb=Pass[gnd,own]
--bv=Pass[bh,own]
--dv=Pass[dh,own]
--own=~6
--6=Pass[5,c1]
--5=~4
--4=Pass[foo,c0]
--fm=flop[sss,c0,c1]
--sss=~tt
--tt=~moo*(f1x+f2x+f3x+try’)
--moo=~fm*st*run
--goo=~try’
--try’=Flop[st,c0,c1]

--Vert: ca cao na nao bv dv sb (aemn43o)
--hor: bh dh f1x f2x f3x st run (kqvwxp5)
--Both: c0 c1 (12)

--a ca
b ca’c 01d own
--e cao
f wag wa’h ow’
--i fm
j gook bhl na’
--m na
n naoo sbp st
--q dh
r moos ssst tt
--u poo
v f1xw f2xx f3x
--y try’
z foo1 c02 c1
--3 dv
4 bv5 run

FakeInputStack:PROCEDURE=BEGIN
Parse[" a=.il,sr"];
Parse["or=. a,tl"];
Parse[" b=.ir,sl"];
Parse["ol=. b,tr"];
Parse["ol←~ a" ];
Parse["or←~ b" ];
END;

FakeInputStack4:PROCEDURE=BEGIN
Parse[" a=.il,sr"];
Parse["om=. a,tl"];
Parse[" b=.im,sl"];
Parse["ol=. b,tr"];
Parse["ol←~ a" ];
Parse["om←~ b" ];
Parse[" c=.jl,sr"];
Parse["pm=. c,tl"];
Parse[" d=.jm,sl"];
Parse["pl=. d,tr"];
Parse["pl←~ c" ];
Parse["pm←~ d" ];
Parse[" e=.om,sr"];
Parse["or=. e,tl"];
Parse[" f=.ir,sl"];
Parse["im=. f,tr"];
Parse["im←~ e" ];
Parse["or←~ f" ];
Parse[" g=.pm,sr"];
Parse["pr=. g,tl"];
Parse[" h=.jr,sl"];
Parse["jm=. h,tr"];
Parse["jm←~ g" ];
Parse["pr←~ h" ];
END;

FakeInputISB:PROCEDURE=BEGIN
Parse[" t←~ i" ];
Parse["vd=. o, t"];
Parse[" o=.gd, i"];
END;

FakeInputCell:PROCEDURE=BEGIN
Parse[" b←~ a" ];
Parse[" c=~ a+ d"];
Parse[" e=~ c+ f"];
Parse[" z=~ f* b+ f* h+ h* a+ d* l"];
Parse[" h=~ d" ];
Parse[" g=~ i+ j"];
Parse[" u=.gd, i"];
Parse[" k=. u, h"];
Parse[" l=~ m" ];
Parse[" n=~ l+ d"];
Parse[" o=.gd, d"];
Parse[" 4=. k, d"];
Parse[" 3=. q, d"];
Parse[" d=← z, 1, 2"];
Parse[" i=← s, 1, 2"];
Parse[" s=~ t" ];
Parse[" t=~ r( v+ w+ x+ y"];
Parse[" r=~ i* p* 5"];
Parse[" j=~ y" ];
Parse[" y=← p, 1, 2"];
END;

FakeInputCell4:PROCEDURE=BEGIN
Parse["0b←~0a" ];
Parse["0c=~0a+0d"];
Parse["0e=~0c+0f"];
Parse["0z=~0f*0b+0f*0h+0h*0a+0d*0l"];
Parse["0h=~0d" ];
Parse["0g=~0i+0j"];
Parse["0u=.gd,0i"];
Parse["0k=.0u,0h"];
Parse["0l=~0m" ];
Parse["0n=~0l+0d"];
Parse["0o=.gd,0d"];
Parse["04=.0k,0d"];
Parse["03=.0q,0d"];
Parse["0d=←0z,01,02"];
Parse["0i=←0s,01,02"];
Parse["0s=~0t" ];
Parse["0t=~0r(0v+0w+0x+0y"];
Parse["0r=~0i*0p*05"];
Parse["0j=~0y" ];
Parse["0y=←0p,01,02"];
Parse["1b←~1a" ];
Parse["1c=~1a+1d"];
Parse["1e=~1c+1f"];
Parse["1z=~1f*1b+1f*1h+1h*1a+1d*1l"];
Parse["1h=~1d" ];
Parse["1g=~1i+1j"];
Parse["1u=.gd,1i"];
Parse["0k=.1u,1h"];
Parse["1l=~1m" ];
Parse["1n=~1l+1d"];
Parse["1o=.gd,1d"];
Parse["14=.0k,1d"];
Parse["13=.0q,1d"];
Parse["1d=←1z,01,02"];
Parse["1i=←1s,01,02"];
Parse["1s=~1t" ];
Parse["1t=~1r(0v+0w+0x+1y"];
Parse["1r=~1i*0p*05"];
Parse["1j=~1y" ];
Parse["1y=←0p,01,02"];
Parse["2b←~0e" ];
Parse["2c=~0e+2d"];
Parse["2e=~2c+2f"];
Parse["2z=~2f*2b+2f*2h+2h*0e+2d*2l"];
Parse["2h=~2d" ];
Parse["2g=~2i+2j"];
Parse["2u=.gd,2i"];
Parse["2k=.2u,2h"];
Parse["2l=~0n" ];
Parse["2n=~2l+2d"];
Parse["0o=.gd,2d"];
Parse["04=.2k,2d"];
Parse["03=.2q,2d"];
Parse["2d=←2z,01,02"];
Parse["2i=←2s,01,02"];
Parse["2s=~2t" ];
Parse["2t=~2r(2v+2w+2x+2y"];
Parse["2r=~2i*2p*25"];
Parse["2j=~2y" ];
Parse["2y=←2p,01,02"];
Parse["3b←~1e" ];
Parse["3c=~1e+3d"];
Parse["3e=~3c+3f"];
Parse["3z=~3f*3b+3f*3h+3h*1e+3d*3l"];
Parse["3h=~3d" ];
Parse["3g=~3i+3j"];
Parse["3u=.gd,3i"];
Parse["2k=.3u,3h"];
Parse["3l=~1n" ];
Parse["3n=~3l+3d"];
Parse["1o=.gd,3d"];
Parse["14=.2k,3d"];
Parse["13=.2q,3d"];
Parse["3d=←3z,01,02"];
Parse["3i=←3s,01,02"];
Parse["3s=~3t" ];
Parse["3t=~3r(2v+2w+2x+3y"];
Parse["3r=~3i*2p*25"];
Parse["3j=~3y" ];
Parse["3y=←2p,01,02"];
END;

FakeInputCell9:PROCEDURE=BEGIN
Parse["0b←~0a" ];
Parse["0c=~0a+0d"];
Parse["0e=~0c+0f"];
Parse["0z=~0f*0b+0f*0h+0h*0a+0d*0l"];
Parse["0h=~0d" ];
Parse["0g=~0i+0j"];
Parse["0u=.gd,0i"];
Parse["0k=.0u,0h"];
Parse["0l=~0m" ];
Parse["0n=~0l+0d"];
Parse["0o=.gd,0d"];
Parse["04=.0k,0d"];
Parse["03=.0q,0d"];
Parse["0d=←0z,01,02"];
Parse["0i=←0s,01,02"];
Parse["0s=~0t" ];
Parse["0t=~0r(0v+0w+0x+0y"];
Parse["0r=~0i*0p*05"];
Parse["0j=~0y" ];
Parse["0y=←0p,01,02"];
Parse["1b←~1a" ];
Parse["1c=~1a+1d"];
Parse["1e=~1c+1f"];
Parse["1z=~1f*1b+1f*1h+1h*1a+1d*1l"];
Parse["1h=~1d" ];
Parse["1g=~1i+1j"];
Parse["1u=.gd,1i"];
Parse["0k=.1u,1h"];
Parse["1l=~1m" ];
Parse["1n=~1l+1d"];
Parse["1o=.gd,1d"];
Parse["14=.0k,1d"];
Parse["13=.0q,1d"];
Parse["1d=←1z,01,02"];
Parse["1i=←1s,01,02"];
Parse["1s=~1t" ];
Parse["1t=~1r(0v+0w+0x+1y"];
Parse["1r=~1i*0p*05"];
Parse["1j=~1y" ];
Parse["1y=←0p,01,02"];
Parse["2b←~0e" ];
Parse["2c=~0e+2d"];
Parse["2e=~2c+2f"];
Parse["2z=~2f*2b+2f*2h+2h*0e+2d*2l"];
Parse["2h=~2d" ];
Parse["2g=~2i+2j"];
Parse["2u=.gd,2i"];
Parse["2k=.2u,2h"];
Parse["2l=~0n" ];
Parse["2n=~2l+2d"];
Parse["0o=.gd,2d"];
Parse["04=.2k,2d"];
Parse["03=.2q,2d"];
Parse["2d=←2z,01,02"];
Parse["2i=←2s,01,02"];
Parse["2s=~2t" ];
Parse["2t=~2r(2v+2w+2x+2y"];
Parse["2r=~2i*2p*25"];
Parse["2j=~2y" ];
Parse["2y=←2p,01,02"];
Parse["3b←~1e" ];
Parse["3c=~1e+3d"];
Parse["3e=~3c+3f"];
Parse["3z=~3f*3b+3f*3h+3h*1e+3d*3l"];
Parse["3h=~3d" ];
Parse["3g=~3i+3j"];
Parse["3u=.gd,3i"];
Parse["2k=.3u,3h"];
Parse["3l=~1n" ];
Parse["3n=~3l+3d"];
Parse["1o=.gd,3d"];
Parse["14=.2k,3d"];
Parse["13=.2q,3d"];
Parse["3d=←3z,01,02"];
Parse["3i=←3s,01,02"];
Parse["3s=~3t" ];
Parse["3t=~3r(2v+2w+2x+3y"];
Parse["3r=~3i*2p*25"];
Parse["3j=~3y" ];
Parse["3y=←2p,01,02"];

Parse["4b←~4a" ];
Parse["4c=~4a+4d"];
Parse["4e=~4c+4f"];
Parse["4z=~4f*4b+4f*4h+4h*4a+4d*4l"];
Parse["4h=~4d" ];
Parse["4g=~4i+4j"];
Parse["4u=.gd,4i"];
Parse["0k=.4u,4h"];
Parse["4l=~4m" ];
Parse["4n=~4l+4d"];
Parse["4o=.gd,4d"];
Parse["44=.0k,4d"];
Parse["43=.0q,4d"];
Parse["4d=←4z,01,02"];
Parse["4i=←4s,01,02"];
Parse["4s=~4t" ];
Parse["4t=~4r(0v+0w+0x+4y"];
Parse["4r=~4i*0p*05"];
Parse["4j=~4y" ];
Parse["4y=←0p,01,02"];

Parse["5b←~2e" ];
Parse["5c=~2e+5d"];
Parse["5e=~5c+5f"];
Parse["5z=~5f*5b+5f*5h+5h*2e+5d*5l"];
Parse["5h=~5d" ];
Parse["5g=~5i+5j"];
Parse["5u=.gd,5i"];
Parse["5k=.5u,5h"];
Parse["5l=~2n" ];
Parse["5n=~5l+5d"];
Parse["0o=.gd,5d"];
Parse["04=.5k,5d"];
Parse["03=.5q,5d"];
Parse["5d=←5z,01,02"];
Parse["5i=←5s,01,02"];
Parse["5s=~5t" ];
Parse["5t=~5r(5v+5w+5x+5y"];
Parse["5r=~5i*5p*55"];
Parse["5j=~5y" ];
Parse["5y=←5p,01,02"];

Parse["6b←~4e" ];
Parse["6c=~4e+6d"];
Parse["6e=~6c+6f"];
Parse["6z=~6f*6b+6f*6h+6h*4e+6d*6l"];
Parse["6h=~6d" ];
Parse["6g=~6i+6j"];
Parse["6u=.gd,6i"];
Parse["2k=.6u,6h"];
Parse["6l=~4n" ];
Parse["6n=~6l+6d"];
Parse["4o=.gd,6d"];
Parse["44=.2k,6d"];
Parse["43=.2q,6d"];
Parse["6d=←6z,01,02"];
Parse["6i=←6s,01,02"];
Parse["6s=~6t" ];
Parse["6t=~6r(2v+2w+2x+6y"];
Parse["6r=~6i*2p*25"];
Parse["6j=~6y" ];
Parse["6y=←2p,01,02"];

Parse["7b←~3e" ];
Parse["7c=~3e+7d"];
Parse["7e=~7c+7f"];
Parse["7z=~7f*7b+7f*7h+7h*3e+7d*7l"];
Parse["7h=~7d" ];
Parse["7g=~7i+7j"];
Parse["7u=.gd,7i"];
Parse["5k=.7u,7h"];
Parse["7l=~3n" ];
Parse["7n=~7l+7d"];
Parse["1o=.gd,7d"];
Parse["14=.5k,7d"];
Parse["13=.5q,7d"];
Parse["7d=←7z,01,02"];
Parse["7i=←7s,01,02"];
Parse["7s=~7t" ];
Parse["7t=~7r(5v+5w+5x+7y"];
Parse["7r=~7i*5p*55"];
Parse["7j=~7y" ];
Parse["7y=←5p,01,02"];

Parse["8b←~6e" ];
Parse["8c=~6e+8d"];
Parse["8e=~8c+8f"];
Parse["8z=~8f*8b+8f*8h+8h*6e+8d*8l"];
Parse["8h=~8d" ];
Parse["8g=~8i+8j"];
Parse["8u=.gd,8i"];
Parse["5k=.8u,8h"];
Parse["8l=~6n" ];
Parse["8n=~8l+8d"];
Parse["4o=.gd,8d"];
Parse["44=.5k,8d"];
Parse["43=.5q,8d"];
Parse["8d=←8z,01,02"];
Parse["8i=←8s,01,02"];
Parse["8s=~8t" ];
Parse["8t=~8r(5v+5w+5x+8y"];
Parse["8r=~8i*5p*55"];
Parse["8j=~8y" ];
Parse["8y=←5p,01,02"];
END;

FakeInputThacker:PROCEDURE=BEGIN
Parse[" f=~ j+ b+ d"];
Parse[" g=~ k+ a+ d"];
Parse[" d=~ c" ];
Parse[" h=~ l+ b+ c"];
Parse[" i=~ m+ a+ c"];
Parse[" b=~ a" ];
Parse[" e=~ f+ g+ h+ i"];
END;


Main[];
END..