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)
```