PROGRAM palindromes (input,output); {THis version reverses and adds by copying the number The command language is greatly simplified to:- = set starter * set (further) number of steps; = ? print current number * ? how many steps so far @ stop} CONST max=20; {number of digits that can be accommodated} setch = '='; timesch = '*'; query = '?'; printch = '/'; quietch = '\'; {used after * to indicate intermediate printing} stopch= '@'; undefined = -1; {for crucial integer variables} TYPE decdigit = 0..9; longnumber = array [0..max] of decdigit; pstring = packed array [1..15] of char; VAR NUM :longnumber; msd :integer; {the power of ten of the Most Significant Digit} revs :integer; {the number of steps to be tried} pos :integer; {the number tried so far} stopped :boolean; {global indicator} PROCEDURE pprompt (s :pstring); extern; FUNCTION palindromic :boolean; VAR l,r :0..max; {left & right inidices} res :boolean; {ultimate result} BEGIN l:=msd; r:=0; res:=true; {provisionally} while res and (l>r) do begin res:= NUM[l] = NUM[r]; l:=l-1; r:=r+1; end; palindromic:=res; END; {palindromic functn} FUNCTION digit :boolean; {is next character a digit?} BEGIN digit:= ('0'<=input^) and (input^<='9') END; PROCEDURE readnum; {reads digits to array and sets msd} VAR ix :integer; {an index into num} dch :char; {each digit character in turn} BEGIN ix:=max+1; {fill from most significant end} {ASSUME digit initially} repeat read(dch); ix:=ix-1; NUM[ix]:= ord(dch)-ord('0'); until not digit or (ix=0); {now shift it right in array:-} msd:=-1; repeat msd:=msd+1; NUM[msd]:=NUM[ix]; ix:=ix+1; until ix>max; if (msd=max) and digit then begin {number too large for array} msd:=max+1; end; END; {of readnum} PROCEDURE writenum; VAR ix :integer; BEGIN for ix:=msd downto 0 do write(NUM[ix]:1); END; {of writing num} PROCEDURE skipspaces; {but not over line boundaries} VAR ch :char; BEGIN while not eoln and (input^=' ') do read(ch) END; {space skipping} PROCEDURE revadd; {adds number to its reverse by copying it initially!} VAR TEMP :longnumber; ix :integer; acc :integer; {working variable} carry :boolean; {carry during addition} BEGIN for ix:=0 to msd do TEMP[ix] := NUM[msd-ix]; {forms up the reverse} carry:=false; ix:=0; while msd>=ix do begin acc:= NUM[ix] + TEMP[ix]; if carry then acc:=acc+1; NUM[ix]:=acc mod 10; carry:= acc>9; ix:=ix+1; end; {forms the sum, except for:-} if carry then begin msd:=msd+1; if msdmax then begin writeln('Number too long'); msd:=undefined; end; end; skipspaces; if not eoln then begin writeln('Not a number'); msd:=undefined; end; revs:=undefined; {new starter, nothing to aim at} {Everything now done so :-} readln; {get next line} END; {of get starter} PROCEDURE dosteps; {after successfully reading the number in} VAR cy :char; increment :integer; {the (further) revs to be attempted} printing :boolean; {or not as iterations proceed} FUNCTION moretogo :boolean; {determines if another iteration possible} BEGIN moretogo:=false; if msd<=max then if not palindromic and (posundefined then begin { a seed exists} skipspaces; if not digit then begin writeln('Not a number'); increment:=undefined; {indicating (further) steps impossible} end else begin read(increment); {further steps required} skipspaces; if not eoln then begin read(cy); {can only be print or quiet} if cy=printch then printing:=true else if cy = quietch then printing:=false else begin writeln('Invalid print control'); increment:=undefined; {scrub everything so far} end; end else printing:=true; {by default} end; {input now vetted pos indicates number of iterations} if increment<>undefined then begin {O.K. to go ahead} if revs=undefined then revs:=0; pos:=revs; {the number completed so far} revs:=revs+increment; {the number to be aimed at completing} {THIS IS THE BUSINESS BIT} while moretogo do begin if printing then begin writenum; writeln; end; revadd; pos:=pos+1; {one more iteration} if pos mod 10 = 0 then writeln; end; if msd<=max then begin {normal termination} writenum; writeln; if not palindromic then write('No ') else revs:=undefined; {finished a series} write('Palindrome '); end else write('Overflow '); writeln('generated after', pos:6, ' iterations'); end; {of doing it properly} end else begin writeln('Start is not defined'); end; readln; {get the next line} END; {of dosteps} PROCEDURE verifystopped; BEGIN stopped:=eoln; if not stopped then begin writeln(stopch,' must not be followed by anything else'); readln; end; END; {of verify stopper} BEGIN read(controlch); {the controlling character} if controlch = setch then getstarter else if controlch = timesch then dosteps else if controlch = stopch then verifystopped else begin writeln('Unknown command'); readln; end; END; { of doinstruction} BEGIN {of main program} pprompt('Palin: '); revs:=undefined; pos:=undefined; msd:=undefined; stopped:=false; repeat skipspaces; if not eoln then begin doinstruction; end else readln; until stopped; END.