{Start of file Golygon.Pas *************************************************} Program Golygon; { Converted from Apple II+ Pascal to Turbo Pascal 5.0 } { and changed from SextPrime to Golygon } { 90/07/08 by Harry Smith, Saratoga CA } uses Crt, PrimeInt; { Algorithm 357 - Collected Algorithms from ACM } { An Efficient Prime Number Generator } { Driver Generates all the primes < about 2**31 } { and displays Sextet Primes } const Name = 'Golygon - Generates and Records n-Sided Golygon'; Version = 'Version 1.00, last revised: 90/09/02 0600 hours'; Author = 'Copyright (c) 1981-1990 by author: Harry J. Smith,'; Address = '19628 Via Monte Dr., Saratoga CA 95070. All rights reserved.'; {***************************************************************************} { Developed in Turbo Pascal 5.0 } { Generates and records 8-Sided Golygon Integers. See Scientific American, July 1990, Mathematical Recreations. } type SignsType = array[1..128] of Char; { Table of Signs N/S or E/W } var Sides : Integer; GType : String[11]; { Integers, Primes, or Twin Primes } SidesSt : String[3]; FileSt : String[12]; { Integers, Primes, or Twin Primes } GTypeCh : Char; { I = Integers, P = Primes, T = Twin Primes } Verbose : Char; { Limit output flag, L = Limit it, V = Verbose } FoundAn : Integer; { Number of Sum Types found starting with E[1] } FoundBn : Integer; { Number of Sum Types found starting with E[2] } FoundABn: Integer; { Number of Sum Types found with same + and -'s` } AnBn : LongInt; { FoundAn * FoundBn } Total : LongInt; { Total golygons found } TestN : Integer; { Sum Type, 1 thru MaxTest, being tested } MaxTest : Integer; { Max Sum Type for "Sides"} { IP : PrimeStore; . Working storage for primes, defined in Prime4By } Max : LongInt; { Maximum integer tested } MaxIn : LongInt; { Maximum integer tested from command line} I : Integer; { Utility index } J : Integer; K : Integer; L : Integer; N : Integer; A1 : Integer; { Number of sum types in 1st set with = + and - } A2 : Integer; { Number of sum types in 2nd set with <> + and - } B2 : Integer; { Number of sum types in 2st set with <> + and - } Ch : Char; M : Integer; { Number of primes each call } St : String; Disk : Text; OutP : ^Text; Done : Boolean; Done1 : Boolean; TypeA : array[1..1280] of Integer; TypeB : array[1..1280] of Integer; TypeAB : array[1..1280] of Integer; { Ones with the same number of + and - } E : array[1..128] of LongInt; { Elements of set with "Sides" sides } NSEW : SignsType; { Table of Signs N/S, E/W } FirstI : Boolean; { True if E[1] = 1 and GType = Integers } Batch : Boolean; { True if running in batch mode, no pauses } {--------------------------------------} procedure CloseIt; begin Str(E[Sides], St); St:= ConCat('Tested all integers <= ', St); WriteLn(St); WriteLn(Disk, St); Close(Disk) end; { CloseIt } {--------------------------------------} procedure AbortIt; begin St:= 'Program aborted by operator'; WriteLn(St); WriteLn(Disk, St); CloseIt; Halt(0); { 27 = Esc } end; { AbortIt } {--------------------------------------} procedure TestIt; begin while Keypressed do Ch:= ReadKey; WriteLn(E[Sides]:8); if Ord(Ch) = 27 then AbortIt; end; { TestIt } {--------------------------------------} procedure Credits; begin ClrScr; WriteLn; WriteLn( Name); WriteLn( Version); WriteLn( Author); WriteLn( Address); WriteLn; end; { Credits } {--------------------------------------} procedure Init; { Initialize program } begin TextBackground( Black); TextColor( Yellow); Credits; GTypeCh:= GType[1]; Str(Sides, SidesSt); if Sides < 10 then SidesSt:= '0' + SidesSt; FileSt:= 'Goly' + GTypeCh + SidesSt + '.Out'; Write('Will write file: ', FileSt); if Verbose = 'V' then WriteLn(' (Verbose output)'); if Verbose = 'L' then WriteLn(' (Limited output)'); if Verbose = 'M' then WriteLn(' (Minimal output)'); WriteLn; Str(MemAvail, St); St:= ConCat('MemAvail=', St); WriteLn(St); if not Batch then begin WriteLn('Type any key to continue... (or Esc to quit)'); Ch:= ReadKey; if Ord(Ch) = 27 then Halt(0); end; WriteLn; Assign(Disk, FileSt); ReWrite(Disk); WriteLn(Disk, St); OutP:= @OutPut; for K:= 1 to 2 do begin WriteLn(OutP^, 'Tests all integers <= ', Max); WriteLn(OutP^, 'Generates ', Sides, '-Sided Golygon ', GType); WriteLn(OutP^); OutP:= @Disk; end; IP[1]:= -1; M:= Sides - 1; N:= NPrime(M); for I:= 1 to M do E[I]:= IP[I]; M:= 1; E[1]:= 1; {For odd primes} MaxTest:= 1; for I:= 1 to (Sides div 2 - 1) do MaxTest:= 2 * MaxTest; MaxTest:= MaxTest - 1; Done:= False; FoundABn:= 0; Total:= 0; FirstI:= False; if GTypeCh = 'P' then begin end else if GTypeCh = 'I' then begin FirstI:= True; for I:= 1 to Sides do begin E[I]:= I; end; end else if GTypeCh = 'T' then begin repeat N:= NPrime(M); E[Sides]:= IP[1]; Done1:= True; J:= Sides + 1; for I:= 1 to Sides div 2 do begin J:= J - 2; if E[J + 1] - E[J] <> 2 then Done1:= False; end; if not Done1 then begin for I:= 1 to Sides - 1 do E[I]:= E[I + 1]; end; if E[Sides] >= Max then Done:= True; if KeyPressed then TestIt until Done or Done1; end; end; { Init } {--------------------------------------} function SumIt(First, TestN : Integer) : LongInt; var Sum : LongInt; I, J : Integer; begin if KeyPressed then TestIt; Sum:= E[First]; J:= Sides + First; for I:= 0 to Sides div 2 - 2 do begin J:= J - 2; if ((TestN ShR I) mod 2) = 0 then Sum:= Sum + E[J] else Sum:= Sum - E[J]; end; SumIt:= Sum; end; { SumIt } {--------------------------------------} procedure SetSigns(TypeA, TypeB : Integer; var NSEW : SignsType); var I, J : Integer; begin { SetSigns } J:= Sides + 1; for I:= 0 to Sides div 2 - 1 do begin J:= J - 2; if ((TypeA ShR I) mod 2) = 0 then NSEW[J]:= 'N' else NSEW[J]:= 'S'; if ((TypeB ShR I) mod 2) = 0 then NSEW[J + 1]:= 'E' else NSEW[J + 1]:= 'W'; end; end; { SetSigns } {--------------------------------------} procedure Goly; { Main portion of driver } begin { Goly } Init; repeat if GTypeCh = 'P' then begin N:= NPrime(M); E[Sides]:= IP[1]; end else if GTypeCh = 'I' then begin E[Sides]:= 1 + E[Sides - 1]; end else if GTypeCh = 'T' then begin repeat if KeyPressed then TestIt; N:= NPrime(M); E[Sides]:= IP[1]; Done1:= True; J:= Sides + 1; for I:= 1 to Sides div 2 do begin J:= J - 2; if E[J + 1] - E[J] <> 2 then Done1:= False; end; if not Done1 then begin for I:= 1 to Sides - 1 do E[I]:= E[I + 1]; end; if E[Sides] >= Max then Done:= True; until Done or Done1; end; { Diagnostic WriteLn; for I:= 1 to Sides do Write(E[I], ' '); WriteLn(' <-- Primes, Sums -->'); for TestN:= 1 to MaxTest do Write(SumIt(1, TestN), ' '); WriteLn('<- 1st set, 2nd set ->'); for TestN:= 1 to MaxTest do Write(SumIt(2, TestN), ' '); WriteLn; Ch:= ReadKey; } FoundAn:= 0; FoundBn:= 0; for TestN:= 1 to MaxTest do begin { Find zero sums in the N/S set } if SumIt(1, TestN) = 0 then begin FoundAn:= FoundAn + 1; TypeA[ FoundAn]:= TestN; end; end; if FoundAn <> 0 then begin for TestN:= 1 to MaxTest do begin { Find zero sums in the E/W set } if SumIt(2, TestN) = 0 then begin FoundBn:= FoundBn + 1; TypeB[ FoundBn]:= TestN; end; end; end; if FirstI then begin { Save sum-types that are in both TypeA and TypeB, these are the ones with the same number of + and - operations. } FoundABn:= 0; for I:= 1 to FoundAn do begin for J:= 1 to FoundBn do begin if TypeA[I] = TypeB[J] then begin FoundABn:= FoundABn + 1; TypeAB[ FoundABn]:= TypeA[I]; end; end; end; OutP:= @OutPut; for K:= 1 to 2 do begin Write(OutP^, FoundABn, ' Sum type(s) found with the same number of + and - : S = ['); for I:= 1 to FoundABn do Write(OutP^, ' ', TypeAB[I]); WriteLn(OutP^, '].'); WriteLn(OutP^); OutP:= @Disk; end; end; if FoundBn <> 0 then begin A1:= FoundABn; { B1:= A1; } A2:= FoundAn - A1; B2:= FoundBn - A1; OutP:= @OutPut; AnBn:= LongInt(FoundAn) * FoundBn; if not FirstI then AnBn:= AnBn - LongInt(A1) * A1; if AnBn > 0 then begin Total:= Total + AnBn; for K:= 1 to 2 do begin Write(OutP^, 'G', Sides, ',', GTypeCh, E[1], ' '); if FirstI or (A1 = 0) then Write(OutP^, FoundAn, ' x ', FoundBn) else Write(OutP^, A1, ' x ', B2, ' + ', A2, ' x ', A1, ' + ', A2, ' x ', B2); Write(OutP^, ' = ', AnBn, ' Total = ', Total); if Verbose <> 'M' then begin Write(OutP^, ' ['); if A1 <> 0 then Write(OutP^, 'S'); for I:= 1 to FoundAn do begin L := TypeA[I]; for J:= 1 to A1 do if L = TypeAB[J] then L:= 0; if L <> 0 then Write(OutP^, ' ', L); end; Write(OutP^, '] ['); if A1 <> 0 then Write(OutP^, 'S'); for I:= 1 to FoundBn do begin L := TypeB[I]; for J:= 1 to A1 do if L = TypeAB[J] then L:= 0; if L <> 0 then Write(OutP^, ' ', L); end; Write(OutP^, ']'); end; WriteLn(OutP^); OutP:= @Disk; end; end; if Verbose = 'V' then begin for I:= 1 to FoundAn do begin for J:= 1 to FoundBn do begin L := TypeA[I]; if not FirstI then begin for K:= 1 to FoundABn do if L = TypeAB[K] then L:= 0; if L = 0 then begin L := TypeB[J]; for K:= 1 to FoundABn do if L = TypeAB[K] then L:= 0; end; end; if L <> 0 then begin SetSigns(TypeA[I], TypeB[J], NSEW); OutP:= @OutPut; for K:= 1 to 2 do begin Write(OutP^, 'G', Sides, ',', GTypeCh, E[1], ',', TypeA[I], ',', TypeB[J], ' = '); for L:= 1 to Sides do begin Write(OutP^, E[L], NSEW[L]); if L <> Sides then Write(Outp^, ' '); end; WriteLn(OutP^); OutP:= @Disk; end; end; end; end; end; end; for I:= 1 to Sides - 1 do E[I]:= E[I + 1]; FirstI:= False; { Diagnostic WriteLn('IQ JQ'); for I:= 1 to N do WriteLn('I=', I, ' IQ=', IQ[I], ' JQ=', JQ[I]) } if E[Sides] >= Max then Done:= True; until Done; CloseIt; end; { Goly } {--------------------------------------} begin { Golygon } if ParamCount = 0 then begin Credits; WriteLn('Usage: Golygon sides [I, P, T] [max_integer_to_test]', ' [V, L, M] [B]'); WriteLn(' Parameters:'); WriteLn(' 1)'); WriteLn(' 6 <= sides <= 32 and even'); WriteLn(' 2)'); WriteLn(' I -> Integers, P -> Primes, T -> Twin primes'); WriteLn(' 3)'); WriteLn(' 0 <= max_integer_to_test <= ', MaxT, ', 0 -> ', MaxT); WriteLn(' 4)'); WriteLn(' V -> Total output, verbose'); WriteLn(' L -> Limit the output, non-verbose'); WriteLn(' M -> Minimal output'); WriteLn(' 5)'); WriteLn(' B -> Batch mode, no pauses'); WriteLn; Halt(0); end; Val(ParamStr(1), Sides, I); if I <> 0 then Sides:= 0; Sides:= 2 * (Sides div 2); if Sides < 6 then Sides:= 6; if Sides > 32 then Sides:= 32; GType:= 'I'; if ParamCount > 1 then GType:= ParamStr(2); If UpCase(GType[1]) = 'P' then GType:= 'Primes' else If UpCase(GType[1]) = 'T' then Gtype:= 'Twin Primes' else GType:= 'Integers'; Max:= MaxT; MaxIn:= 0; if ParamCount > 2 then begin Val(ParamStr(3), MaxIn, I); if MaxIn > MaxT then MaxIn:= MaxT; if MaxIn < 1 then MaxIn:= MaxT; if I <> 0 then MaxIn:= 0 else Max := MaxIn; end; St:= ParamStr(4); Verbose:= 'V'; if (ParamCount > 3) and (UpCase(St[1]) = 'L') then Verbose:= 'L'; if (ParamCount > 3) and (UpCase(St[1]) = 'M') then Verbose:= 'M'; St:= ParamStr(5); Batch:= False; if (ParamCount > 4) and (UpCase(St[1]) = 'B') then Batch:= True; Goly; end. { Golygon } {End of file Golygon.Pas ***************************************************}