25
Pyth is so similar to Python that it is pretty easy to translate Python programs to Pyth. However, because Pyth is a single-letter-per-command language, it is sometimes hard to write straight Pyth. By writing in Python first, there is less to think about at a time (since Python is a pretty easy language to code in).
22
Pyth has 3 categories of variables: generic pre-initialized variables, variables pre-initialized based on user input, and variables that implicitly generate an assignment on first use.
b = "\n"
d = " "
k = ""
G = "abcdefghijklmnopqrstuvwxyz"
H = {} # (empty dict)
N = '"'
T = 10
Y = []
Z = 0
Q = eval(input())
z = input()
Note that these initializations will only be run in a given program if the associated variable is used outside of a string in the code. In addition, the order is Q
, then z
, if both are used.
J
and K
. If you want to initialize them both to the same value, you can do so with an expression such as KJ0
, which is equivalent to the lengthier J0K0
.
18
Note that this is new software, so it may be buggy. Please report any problems to me.
2Awesome! I couldn't find this with google, just what I needed! – theonlygusti – 2015-04-03T17:31:04.623
12
Strings at the end of the line don't need end quotes. For example:
"Hello, world!
is a completely valid Hello World program.
Quite obvious really, it is the first google result for "Pyth programming language". Did you create your own page on esolangs? – theonlygusti – 2015-04-03T17:30:02.783
3@theonlygusti Yes, I did. Also, it wasn't the first result last October. – isaacg – 2015-04-03T17:33:13.643
10
C
for base compressionThis is actually undocumented, C on a string is actually not direct chr -> int but instead base 256 -> base 10 (which is the same on one char strings). This is hugely helpful in compressing an int, we can use this script to compress:
sCMjQ256
Take 12345678910
, it results in ßÜ>
(some unprintables in there).
Also with an array of ints, you can concatenate them, and with large strings by converting to code points and treating as base 128 number.
Another usage of C
, thanks @xnor for showing me this, is making an arbitrary large number. The naive way is:
^TT
But we can do one byte better with:
CG
this base 256 deconverts the entire alphabet. Results 156490583352162063278528710879425690470022892627113539022649722
= ~1.56e62
.
Added to doc now. – isaacg – 2015-07-19T03:54:08.650
9
When the lambda argument to map
or reduce
just applies one operation to the arguments,, you can use the short forms, M
and F
. fMx
is equivalent to mfdx
, and fFx
is the same thing as .UfbZx
. For instance, say we take a list of numbers as input and output each one incremented. A first approach might be:
mhdQ
However, that can be rewritten as:
hMQ
A similar thing applies to reduce
with F
. As an example, say there's a challenge to calculate the product of a list of integers. Again, a first try may be:
.U*bZQ
However, with F
, that can be shortened to:
*FQ
Shaves off three bytes...not bad!
And you don't need Q
, as it is supplemented when the function is missing an input, making it *F
– Stan Strum – 2017-09-14T06:01:20.113
8
Full documentation will be added later.
7
I'm fairly regularly improving Pyth, removing less useful features and adding more useful ones, so keep an eye out for what's new and update your copy of the implementation regularly.
Some recently added features: (as of 10/19/14)
y
: Acts as *2
on numbers, and as list of all subsets on strings and lists. For instance:
pyth -c 'y"abc'
['', 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc']
f
: f
is normally the filter command. Now, when called with a number as its second argument, it will filter over the infinite sequence starting with that number and counting up by ones, then return the first element of the resulting sequence.
For instance, here's the code to find the smallest prime over a billion:
pyth -c 'f!tPT^T9'
1000000007
@isaacg Sorry if this is off-topic, but I am wondering how to use the root operation @
in Fdr1+1@Q2Iq%Qd0d to make a factor calculator. When I try to use it, it defaults to the index
meaning instead. Is there any way around this behavior? – StardustGogeta – 2016-05-02T03:04:32.353
Those look like useful additions, but what can you use instead of the old yz
? mvdczd
can't be the shortest way... – Dennis – 2014-10-20T02:50:01.577
1@Dennis I threw out the old y
because I don't think Pyth needs to have multiple super-easily parsed input formats, just one, e.g. the Python format. So, yes, I think mvdczd
will have to do, unfortunately. – isaacg – 2014-10-20T02:54:29.740
@Dennis Problem solved, just added this to r
's string processing suite. – isaacg – 2014-10-21T16:06:28.800
r
looks pretty useful. – Dennis – 2014-10-21T17:07:52.980
5
Sometimes, default values in functions can be useful for golfing. Pyth actually supports this (much to my surprise). For example:
DC=Z1RZ;C;C5
Will print:
1
5
You can also use J and K to save characters when doing this:
DgJ1K1R+JKg;g2;g2 3
prints:
2
3
5
This is usually useful for recursive algorithms.
This no longer works, but I have left it here in case someone wants to golf using an old version of Pyth.
16Wow - Even I didn't realize Pyth supported this, and I wrote the language! – isaacg – 2015-01-12T10:19:16.680
Unfortunately, this no longer works in more recent versions of Pyth. – isaacg – 2015-05-06T05:41:07.233
Should this tip be deleted like one of the other out-of-date tips? If not, maybe it should be marked with what version(s) this tip applies to. – mbomb007 – 2015-08-11T18:19:30.653
@mbomb007 I've been meaning to find the version, but I've been too lazy. Ill delete it if you think it is better off that way until I do find it. – FryAmTheEggman – 2015-08-12T12:50:22.760
@FryAmTheEggman I think it's up to you, since it says in the title that it's not supported. – mbomb007 – 2015-08-12T17:01:08.397
5
F
Say you have a 2 element tuple, J = (a, b)
, and you want r(a,b)
, for some 2 arity function r.
The naive way to do this is rhJeJ
.
The fancy way to do this is r.*J
, using the unpack operator.
The really fancy way to do this is rFJ
, using the fold operator.
is it still possible to use .u
for that? .u
seems to be cumulative reduce now. – Ven – 2016-02-18T14:14:05.540
.u -> .* this was a change that was made a while ago, but was never updated. – isaacg – 2016-02-18T16:26:46.253
4
F
: For loop. Just like Python's.
V
: For loop over a range. Neither variable nor range must be given, so 2 characters shorter.
W
: While loop. Just like Python's.
#
: Infinite while loop. Escape with error or explicit break. Only try ... except
feature now in Pyth.
D
: General define. Just like Python.
L
: 1 argument, no assignment function, like Python's lambda, but named. Function name, variable name and return (R
) need not be given, so 3 characters shorter.
f
: Filter - select elements of input sequence that return truthy on input lambda.
f
: First integer greater than or equal to input which gives truthy filter result.
m
: Map - transform elements of input sequence using input lambda.
u
: Reduce - fold input sequence on input lambda, initializing accumulator to third argument.
o
: Order - older elements of input sequence using input lambda as the key.
Usually, there will be multiple possibilities for any given problem, and only by writing test solutions with each of them can you figure out which is shortest.
.x
can more recently be used for try-except blocks. – mbomb007 – 2015-08-11T18:24:55.217
@mbomb007 is there way to neglect except block, I mean can that be left empty? For ex: .x{some_statments}{except_block - can this be empty}
. – Gurupad Mamadapur – 2017-01-02T15:32:33.367
@GurupadMamadapur # ... B
can be used this way if you're not inside an expression – isaacg – 2017-01-02T15:56:47.697
4
map
to generate listsIt's basically an equivalent of the fancy list comprehensions of python. Use an existing list or an range to iterate over and map each value, even if the value doesn't matter.
Two examples:
Generate a list of 8 zeros.
mZ8
instead of *8]Z
Generate a list of 5 random numbers between 0 and 9:
mOT5
instead of V5~Y]OT)
The second one automatically assigns the list to Y
(well actually it appends to Y), but even =YmOTU5
is shorter.
4
h
: Other than returning the first element of a list, it increments a number, e.g. hT
evaluates to 11
. Shorter than +1T
.
t
: This decrements a number (other than return the tail of a list), e.g. tT
evaluates to 9
. Shorter than -T1
.
y
: This doubles a number, e.g. yT
evaluates to 20
, shorter than *T2
or +TT
.
4
This is a new change, as of today.
Q
is the variable which is auto-initialized to the evaluated input. It is implicitly appended to the end of the Pyth program, as many times as is necessary to make the arity work out. To see an example of how to use this for golfing, let's say we want to compute the Collatz function of the input.
A shortest way to write it is like this:
@,/Q2h*3QQ
However, since the Q
s are implicit at the end of the file, we can simply write:
@,/Q2h*3
Saving 2 bytes.
Note that functions with non-required arguments will not have those arguments filled in. For instance, c"12 12"
will not have an implicit Q
, since c
only requires 1 argument.
3
Suppose you need to set a variable to some function of itself, and repeat a certain number of times. Take, for instance, the problem of finding the number 100 later in the Collatz Sequence from the input. The shortest way to find the next number in the sequence, if the initial number is Q
, is
@,/Q2h*Q3Q
The most obvious way to apply this 100 times and print the result would be
V100=Q@,/Q2h*Q3Q;Q
Loop 100 times, updating the value of Q each time, then end the loop and print Q.
Instead, we can use a reduce function which ignores the sequence variable (H
).
u@,/G2h*G3GU100Q
This is 2 characters shorter. It is 3 characters shorter if you are trying to loop as many times as there are elements in a sequence.
3
Switching two elements can be quite an expensive task. So here are two approaches you wanna use.
In preparation we define a list Y
and fill it with some numbers. The goal is to switch the second and third element.
=Y[1 3 5 3 6 7)AGH,1 2
We simply assign the tmp variable J = Q[G]
, do the first list assignment Y[G] = Y[H]
and then the second last assignment Y[H] = J
. The trick here is to nest the two list assignments, so you don't have to suppress printing and don't have to use refer twice to Y
.
J@YGXXYG@YHHJ
instead of
J@YG XYG@YHXYHJ
If the elements, which you want to switch, are unique in the list, use this approach. It's really short. So this time we switch the first and third element (the values 1
and 5
are unique).
=Y[1 3 5 3 6 7)K,Z2
This uses the translation functionality of the list:
XYm@YdK)
This translating replaces every element Y[0]
with Y[1]
and every Y[1]
with Y[0]
. So if the values are not unique, bad things happend. For instance K,1 2
results in [1, 5, 3, 5, 6, 7]
.
Notice that the closing parentheses is optional, if the statement is the last one in your code.
3
<newline>
If your code is written in an imperative programming style, it is quite easy to debug, since you can easily print intermediate results. (permalink)
FN.:Q2 loop
=Y+-Y-FNhN some random command
Y print intermediate result
;Y end for loop and print result
But a large amount of Pyth programs use elements of functional programming, like map, filter and reduce, which don't allow such a simple printing. But it is still possible, using the \n
command.
The same code using u
(reduce) would be: (permalink)
u .:Q2Y reduce .:Q2, start with G = Y
+-G-FHhH random command
If you want to print the intermediate values, simply to insert \n
: (permalink)
u .:Q2Y reduce
\nG print(G)
+-\nG-FHhH random command
\na
prints a
on a newline and returns a
. So you can insert it anywhere without worrying changing the functionality of the program.
You can nowadays use the newline for this, which also prints a newline. – PurkkaKoodari – 2016-06-04T14:27:30.923
@Pietu1998 Yes, I use it all the time. Time to update the post. – Jakube – 2016-06-04T14:33:01.220
3
When you want to find if any of a sequence satisfy a condition, you would usually use .Em
. For example, if you want to find out if any in a list are greater-than-or-equal to 5:
.Emgd5Q
But, if it only needs to be a truthy/falsey, not true/false, sm
would work since sum works on bools.
smgd5Q
We can even do one shorter, with f
ilter:
fgT5Q
The last one looks really ugly though.
For .A
ll, the only thing I can think of is to use the opposite condition and negate it for a one char save over .Am
:
!f<T5Q
3
g#
For instance, suppose you have J=5
and K=12
. Then g#JK
= 12, and g#KJ
= 12 as well.
This was discovered by @Pietu1998, who put it this way:
Not sure if someone has already found it, but there's a cool way to do max(A, B) in 2 bytes, no need to use 3 for eS,AB
. g#AB
does the same thing. (It's very inefficient, though, since it loops max(1, A-B+1) times. An optimization is to put the number likely to be larger as B.)
@Jakube This is true. I apparently misthough something while typing this in chat. – PurkkaKoodari – 2016-06-04T15:01:34.453
2
join
methodThe join
method in Python can be often a little bit annoying, since it only joins strings. Pyth's join
is more generous. It transforms all objects in strings by default.
E.g. jkUT
gives 0123456789
or jb["abc"4,5\f]7
gives
abc
4
(5, 'f')
[7]
Recently, even more transforming-into-string functionality was added - the first argument is coerced to a string as well, e.g. j2\a\b
-> "a2b"
– isaacg – 2015-03-27T15:07:49.550
1
I
and GCDDisclaimer: This only works for non-negative integers.
To check if two non-negative integers are divisible, you can do the following:
iI<divisor><dividend>
If a is divisible by b and a ≥ b ≥ 0, then gcd(a, b) = b.
It doesn't necessarily save bytes over !%<dividend><divisor>
, but it might bring you a saving, because:
Q
), when working with the dividend.<pfn>
, since it is a function on its own.0
.One more advantage: iI
is a function on its own, whereas !%
is not, so you can use it as a prefix function. – Erik the Outgolfer – 2017-12-31T14:50:38.193
@EriktheOutgolfer Thanks, added to the list of advantages :) – Mr. Xcoder – 2017-12-31T14:52:06.173
1
A neat trick is using I
nvariant to tell if a number is a whole number as such:
sI
This checks if the number doesn't change when you truncate it, which it won't if it's a whole number.
For example, you can use this as a perfect square check:
sI@Q2
1
Packed Pyth is a new "programming language" which is exactly the same as Pyth, except that it uses 7 bits per character instead of 8 bits per character.
To use it, clone the pyth repository. The file packed-pyth.py
is the interpreter.
Say your code is "Hello, world!
.
First, put it in a file: echo -n '"Hello, world!' > code.pyth
Next, pack the Pyth code into Packed Pyth file: python3 packed-pyth.py -p code.pyth code.ppyth
Finally, run the Packed Pyth code: python3 packed-pyth.py code.ppyth
When running code, you can provide the -d
flag to see what the Pyth code that's actually being run is, and you can provide input as a second command line argument after the file containing the code.
Upside:
Downside:
ASCII only.
No interactive input.
Full debug options are not availible.
Worse error reporting.
1like we did for the safe mode thing, can we move it into a flag? – Maltysen – 2016-10-06T02:48:10.880
This is awesome btw :D – Maltysen – 2016-10-06T02:48:18.557
@Maltysen I think that would increase the byte score by one. – isaacg – 2016-10-06T04:28:13.800
Can't Pyth be packed further since it only uses printable ASCII? – lirtosiast – 2018-11-15T07:46:08.310
0
If you have a function of arity 1, and want to apply that to a variable and apply to itself, you can use the following syntax:
=<function><variable>
Instead of:
=<variable><function><variable>
For example, if you want to increment the variable Z
, you can do:
=hZ
Which saves one byte over =ZhZ
.
@mbomb007 Download the Pyth interpreter and read through the documents. That's the only reliable way I know for writing a Pyth program. – Justin – 2015-02-24T17:57:30.207
@mbomb007 Sorry; that's the way I learned how to write Pyth (looking through the source code). There is basically no documentation on Pyth; you basically have to learn the syntax by trial and error. – Justin – 2015-02-24T18:22:30.863
1
You could also mention that you can still use Python syntax in Pyth, so you can convert parts of the program individually or just use python if necessary. (As you did here)
– FryAmTheEggman – 2014-10-20T15:07:49.960