Tell me more ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

What, this post doesn't exist yet?

Of course, GolfScript is made for golfing, so you might think that no specific tips are really needed. But to make full use of GolfScript's features, you need to learn some non-obvious tricks. This post is for collecting such helpful tips and tricks.

To start with, here are the official GolfScript reference pages. You should really familiarize yourself with these first:

In particular, I would very much suggest reading the pages in this order — the quick reference is of little use until you're already reasonably familiar with the built-ins, and the tutorial includes some important details that are not explained on the other pages.


Ps. For the sake of inspiration and personal interest, here are some questions I'd like to see nice answers to:

  • How to do limited transliteration in GolfScript? {FROM?TO=}% works if you can be sure all the inputs are found in FROM (or don't mind them all being mapped to the last element of TO), but all the ways I've seen for leaving unmapped values unchanged have been more or less klugey.

  • How to best convert a string into an array of ASCII codes and back? Which operations do this as a side effect? What's the best way to dump the characters in a string onto the stack (like ~ does for arrays)?

share|improve this question
Converted to Community Wiki. – dmckee Mar 26 '12 at 15:36
Another question: is there a nice way to transform ... x into ... [x]? The best I can see is [.;]. – Peter Taylor Jun 8 '12 at 12:51
@Peter: If x is a number, then []+ works and is one char shorter. And of course, if x is the only thing on stack, then just ] will do. – Ilmari Karonen Jun 9 '12 at 12:32

7 Answers

Shuffling an array

The easiest way to shuffle an array in GolfScript is to sort it by a random sort key. If you only need to crudely shuffle a few values, the following code will do:

{;9rand}$

Due to the birthday paradox, to get a reasonably uniform shuffle, the argument to rand needs to be much greater than the square of the length of the list being shuffled. The following code, which uses 99 = 387,420,489 possible values, is good for up to about 1000 items or so (and acceptable for up to about 20,000):

{;9.?rand}$

For really long lists, add one more 9 for 9999 ≈ 3.7 × 10197 values:

{;99.?rand}$
share|improve this answer
2  
I remember I once skeptically did the math for the birthday paradox after my brother told me about it, he was right :( – ajax333221 Mar 25 '12 at 19:52

If your program mysteriously breaks, check your variables

I just spent a while debugging an apparently correct program which used ! as a variable (on the grounds that I wasn't going to use it again). Unfortunately I did use if, and it turns out that the implementation of if calls ! to decide which branch to follow.

share|improve this answer

Limited transliteration

To address a specific subquestion: given a string, what's the best way to perform a tr? E.g. tr/ABC/abc/

If all of the characters in the string will be affected, this is quite easy: {'ABC'?'abc'=}% (overhead: 9 chars).

However, that breaks if some of the characters aren't transliterated and 'ABC'? gives -1.

If the transliteration is non-cyclic it can be done one replacement at a time with string splits and joins: 'AaBbCc'1/2/{~@@/\*}/ (overhead: 15 chars). This may be improvable, but there's an alternative approach which is currently better and works for cyclic transliterations.

The current best general approach involves an escape character: {.'ABC'?'abc0'=\or}% (overhead: 14 chars).

share|improve this answer
Using the last approach, for the input string 'ABCDEF' I get the result 'abc000', but the right result would be 'abcDEF'. Am I missing something? – w0lf Jun 8 '12 at 14:32
1  
@w0lf, that 0 is in bold because it's the escape character previously mentioned - i.e. the byte 0. – Peter Taylor Jun 8 '12 at 15:33

Final output manipulation

By default, when your program ends, the GolfScript interpreter outputs everything on the stack, plus a final newline, exactly as if your program ended with:

]puts

What the documentation doesn't directly mention is that the interpreter literally calls the built-in puts to produce this output, and that this built-in is literally defined as:

{print n print}:puts;

Thus, you can suppress or manipulate the final output by redefining puts, print and/or n (or   if you're feeling really twisted). Here are some examples:

Suppress final newline:

'':n;

(Of course you can leave out the ; if you don't mind an extra empty string on the stack.)

Suppress final output completely:

:puts

This overwrites puts with whatever happens to be on top of the stack. If that happens to be something you don't want to execute, you can use e.g. 0:puts; instead. Note that this also suppresses p (which is defined as {`puts}:p;), but you can still use print for output if you want.

share|improve this answer

Negating a number

One thing GolfScript lacks is a built-in negation operator. The obvious ways to convert a number on the stack to its negative, like -1* or 0\-, need three chars. However, there's a way to do it in two:

~)

This works because GolfScript uses two's complement arithmetic, so that ~x equals −x−1.

Of course, the variant (~ also works; choosing between them is generally a matter of taste.

share|improve this answer

To address a specific subquestion:

How to best convert a string into an array of ASCII codes and back? Which operations do this as a side effect? What's the best way to dump the characters in a string onto the stack (like ~ does for arrays)?

For those who don't understand the problem, GolfScript's type system gives priority to the types in the order integer, array, string, block. This means that ordinary array operations applied to a string almost always give you a string. E.g.

'ABC123'{)}%

will leave 'BCD234' on the stack.

As a result, the best way to convert a string into an array of ASCII codes is almost certainly to dump the characters on the stack and then gather them into an array.

What's the best way to dump the characters in a string onto the stack? {}/

What's the best way to convert a string into an array of ASCII codes? [{}/] (with the usual caveat that if there's nothing else on the stack you can skip the [)

What's the best way to convert an array of ASCII codes into a string? ''+ (Note that this also flattens the array, so e.g. [65 [66 67] [[[49] 50] 51]]''+ gives 'ABC123')

share|improve this answer

Wrapping the top item of the stack into an array

Is there a nice way to transform ... x into ... [x]?

For full generality, the best option appears to be 4 chars. However, in certain special cases it's possible to reduce this.

1 char

] works in the special case that xis the only thing on the stack.

3 chars

[]+ works in the special case that x is an integer.

.,/ works in the special case that x is a truthy array or string. E.g. "AB".,/ gives ["AB"]; 3,.,/ gives [[0 1 2]]. However, "".,/ and [].,/ both give [].

4 chars

[.;] works unconditionally.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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