8
\$\begingroup\$

What general tips do you have for golfing code in Pascal?

I know this is a tricky language very few people use this but I would like to know any tips from the professionals out there :)

I'm looking for tips that can reduce code size (every byte counts!) with special functions or even crazy combinations

Please post each tip as a separate answer, and avoid tips not specific to Pascal (e.g. remove whitespace, etc.)

\$\endgroup\$
0

10 Answers 10

7
\$\begingroup\$

Avoid Integer

VAR var1: Integer; (* Signed, 16 bits in TP7, 32 bits in FPC, It costs 7 bytes. *)
    var2: Word;    (* Unsigned 16 bit, works in most cases. *)
    var3: Int64;   (* Signed 64 bits, Only available in FPC. *)
    var4: 0..9;    (* TP7: same as ShortInt (-128..127), FPC: same as Byte (0..255) *)

Use ^J for line break

WriteLn('abc');Write('def');
Write('abc',chr(10),'def');
Write('abc'#10'def');
Write('abc'^J'def');        (* Both in TP7 and FPC *)

^J is two bytes ^ followed by J, not single byte for Ctrl-J.

\$\endgroup\$
3
\$\begingroup\$

Numbers before keywords

for i:=69 to 420 do writeln(i);
for i:=69to 420do writeln(i);

save you 2 byte on for loop

\$\endgroup\$
1
  • 1
    \$\begingroup\$ NB: Some compilers will reject this, so you will need to write “compiled with <compiler>” when handing in solutions. The ISO standards 7185 (“Standard Pascal”) and 10206 “Extended Pascal” expect a token separator between keywords and numbers. \$\endgroup\$ Nov 2, 2022 at 10:01
3
\$\begingroup\$

use (already existing) parentheses as token separators

A loop determining the length of input without processing it

while not EOF do begin get(input);i:=i+1 end

can be rearranged into

while not EOF do begin i:=i+1;get(input)end

Similarly in expressions

if ord(c)=32 then

is the same as

if 32=ord(c)then

Since this only saves you one character, it does not make sense to introduce extra parentheses.

\$\endgroup\$
3
\$\begingroup\$

use string as an array[1‥n] of 0‥ord(maxChar)

In Pascal string literals may contain arbitrary values from the domain of char. Even chr(0) is permitted. The only illegal component is the value denoting a newline (in ASCII chr(10) [“line feed”] and/or chr(13) [“carriage return”]). In other words, multi-line string literals are not allowed. Furthermore the string delimiting character ' (ASCII chr(39)) needs to be escaped (conventionally ''). Example:

program stringArrayDemo(output);
begin
    writeLn(ord(('€Bÿ')[3]))
end.

Since it’s not properly displayed, the above string literal consists of the following four characters (ordinal value in hexadecimal base):

80 42 FF 12

Therefore the above program will print 255 as it’s the third character’s ordinal value. Obviously in your challenge at hand the constant index 3 will be some variable expression and the string literal will have different values.

Since the maxChar value introduced in ISO standard 10206 “Extended Pascal” documents an implementation characteristic, it is imperative that your solution mentions the processor used. The above program will work adequately if compiled with the GNU Pascal Compiler (GPC) or the Free Pascal Compiler (FPC).

\$\endgroup\$
3
\$\begingroup\$

Variable declaration of same type

var i:word;j:word;
var i,j:word;

Furthermore, all variables can be declared in one var block:

var i,j:word;a,b,c:string;x,y:char;
\$\endgroup\$
2
\$\begingroup\$

prefer repeat … until … loops over while … do begin … end loops

Consideration for guaranteed iteration count ≥ 1: If the loop body of a while loop contains multiple statements, i. e. is surrounded by a proper begin … end, you may consider turning it into a repeat … until loop where the repeat … until by itself constitutes a begin … end frame.

while condition do begin statement;statement end

becomes

repeat statement;statement until not condition

Since a repeat loop’s body is executed at least once, this works fine if it’s guaranteed that the while’s loop body would be executed at least once, too. If condition can legitimately cause zero iterations, this tip does not make sense.

\$\endgroup\$
1
\$\begingroup\$

Prefer upcase over lowercase

That's 3 whole bytes. Handy for case-insensitive string comparisons.

\$\endgroup\$
1
\$\begingroup\$

Use the short form of if and for

If your if condition/ for loop only does one statement, omit begin and end.

if <boolean> then begin <statement>;end; 🚫

if <boolean> then <statement>;

for <condition> do begin <statement>;end; 🚫

for <condition> do <statement>;

You can also string them together, e.g.

for <condition> do if <boolean> then <statement>;

\$\endgroup\$
2
  • 2
    \$\begingroup\$ This is a bit of a misconception: Both for and if require one statement. The begin … end frame represents one statement. There is no “short” or “long” form of either of them. \$\endgroup\$ Mar 6, 2023 at 19:47
  • \$\begingroup\$ The formal construct (e.g. if x>y then begin;inc(k);writeln(a);end;) allows one or more statements. But if there's only one statement, begin and end are optional.. maybe this is too elemental \$\endgroup\$
    – roblogic
    Mar 6, 2023 at 20:10
1
\$\begingroup\$

Iterating over the alphabet (or other contiguous ASCII range)

Iterate over the string:

var c:char;begin
for c in'abcdefghijklmnopqrstuvwxyz'do writeln(c);

Or, use an ASCII range (uppercase alphabet)

var j:word;begin
for j:=65to 90do writeln(chr(j));

BUT! Here's the most compact approach, for 50 bytes:

var j:char;begin for j:=#65to#90do writeln(j)end. 
\$\endgroup\$
2
  • 2
    \$\begingroup\$ It should be highlighted that this is a Delphi extension. It is also supported by the FreePascal Compiler (since 2.4.2). ISO standard 10206 ”Extended Pascal“ only provides for … in for sets. \$\endgroup\$ Mar 6, 2023 at 19:53
  • 1
    \$\begingroup\$ wont var j:char;begin for j:=#65to#90do writeln(j)end. simply work? \$\endgroup\$
    – tsh
    Aug 14, 2023 at 3:53
0
\$\begingroup\$

use index for in membership test

Introduction: All Pascal variants support at least to some extent the in membership operator (in mathematical notation ∊). Extended Pascal, ISO standard 10206, introduces the index function. It requires two char or string arguments (any combination thereof).

index(sample, pattern)

The index function returns the index of the first complete occurrence of pattern in sample. If no such index exists, 0 is returned (an invalid index for any string).

Application: The index function can be utilized to abbreviate set-membership operations. For example

c in['X','Y','Z']       { `c` is a variable possessing the data type `char` }

becomes

index('XYZ',c)>0

Synergies: You can combine this with the string as array[1‥n] of 0‥ord(maxChar) tip. For example

index(')/;CGaek•—§³µãåéïñ', chr(241)) > 0

performs a test whether chr(241) is a Ramanujan prime less than 256. Note, the string literal consists of 23 char values and are not properly displayed on this site.

Dialects: Delphi users want to use pos. The Free Pascal Compiler supports pos, too.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.