Wiki: Prolog

Tips for golfing in Prolog on codegolf.stackexchange.com

Handling arguments

Use feature(argv,A) or '$argv'(A) instead of prolog_flag(argv,A).
'$argv'(A) has extra arguments at the beginning, you can filter them by index:

:-feature(argv,A),nth0(I,A,X),code(X).
:-'$argv'(A),nth0(I,A,X),I>3,code(X).

unix(argv(A)) is equivalent to '$argv'(A), but arguments that are syntactically valid numbers are passed as a number. You can filter them using number(X) or atom(X).

Because integers are less than atoms in the standard ordering of terms, X@<'' (or maybe X@<a if you're really lucky) works as a shorter alternative to number(X).

re_split with /n flag converts output atoms to numbers if possible:

:- S='2 3 4', re_split(' '/n,S,L), L=[2,' ',3,' ',4].

Iterating over an array

Instead of using maplist over an array, you can use member with careful backtracking. You can also use nth0 or nth1 to get the index of the element as well:

maplist(+,A). +A:-code.
member(V,A),code,0=1.
nth0(I,A,V),code,0=1.
nth1(I,A,V),code,0=1.

Printing

format can accept an arithmetic expression for numeric conversions.

:-X is 1+2,write(X).
:-format('~d',1+2).
:-X is 1+2,writeln(X).
:-format('~d
',1+2).

Failing

:-member(X,[2,3]),write(X),0=1.
:-member(X,[2,3]),\+write(X).

Packing

Use backticks to get a list of character codes:

:- `0{𞉀` = [48,123,123456].

Big numbers can be written using <radix>'<number> syntax or 0'<character> syntax:

:- 36'PROLOG = 1558151872.
:- 0'𞉀 = 123456.

Lists of one integer or one-character atom (e.g., [97], `a`, [a]), and strings of length 1 (e.g., "a") in arithmetic expression are interpreted as integers:

:-X is 100.
:-X is 0'd.
:-X is"d".

Managing predicates

Predicates can be written using operators (CGSE for more details):

2+2. 1+b.
:-X+Y,write(X),\+write(Y). % prints '221b'

You can add predicates dynamically using assert:

:-X=2,Y=3,assert(X+Y),2+3,write('success'),2+5,write('unreachable').

Generators

Some predicates generate solutions if the arguments are unbound:

nth0(X,_,_).  % between(X,0,inf)
nth1(X,_,_).  % between(X,1,inf)

Rational numbers

You don't need rdiv if at least one argument is rational:

:- X is 1/2r3. % X = 3r2

A rational number literal, rdiv result, or the value of an arithmetic expression (if it's a rational number) is converted to an integer if possible:

:- X is 4r2,      Y is 1/X. % X = 2 (integer), Y = 0.5 (float)
:- X is 4 rdiv 2, Y is 1/X. % X = 2 (integer), Y = 0.5 (float)
:- X is 4r7/2r7,  Y is 1/X. % X = 2 (integer), Y = 0.5 (float)
:- X =  4r7/2r7,  Y is 1/X. % X = 4r7/2r7 (expression), Y = 1r2 (rational)