Tips for golfing in CJam

43

5

CJam is a GolfScript-inspired stack-based golfing language, created by PPCG user aditsu.

So, in the vein of other language-specific tips questions:

What general tips do you have for golfing in CJam? Please post one tip per answer.

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

4

See also Tips for golfing in GolfScript; the languages are similar enough that many of the tricks can be adapted either way.

– Ilmari Karonen – 2014-10-12T12:38:53.317

2@IlmariKaronen After going through the answers in that question, I'd say only around half of them apply to CJam, due to syntactical or logical differences in the languages. – Optimizer – 2014-10-12T13:16:01.207

Answers

23

Correct modulo for negative numbers

It's often annoying that the result of the modulo operation gives the same sign as the first operand. E.g. -5 3% gives -2 instead of 1. More often than not you want the latter. The naive fix is to apply modulo, add the divisor once and apply modulo again:

3%3+3%

But that's long and ugly. Instead, we can use the fact that array indexing is always modular and does work correctly with negative indices. So we just turn the divisor into a range and access that:

3,=

Applied to -5, this gives 1 as expected. And it's only one byte longer than the built-in %!

If the modulus is a power of 2, you can save another byte using bitwise arihmetic (which is also a lot faster). Compare:

32,=
31&

For the special case of 65536 == 2^16 another byte can be saved by making use of the wrapping behaviour of the character type:

ci

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

13

Pushing concatenated character ranges

  • The string containing all digits "0123456789" can be written as

    A,s
    
  • The uppercase ASCII letters (A-Z) can be pushed as

    '[,65>
    

    which generates the string of all characters up to Z, then discards the first 65 (up to @).

  • All ASCII letters (A-Za-z) can be pushed as

    '[,65>_el+
    

    which works as above, then creates a copy, converts to lowercase and appends.

    But there's a shorter way to do it!

    Then often overlooked ^ operator (symmetric differences for lists) allows to create the same ranges while saving three bytes:

    '[,_el^
    

    '[, creates the range of all ASCII characters up to Z, _el creates a lowercase copy and ^ keeps only characters of both strings that appear in one but not both.

    Since all letters in the first string are uppercase, all in the second are lowercase and all non-letter characters are in both strings, the result in the string of letters.

  • The RFC 1642 Base64 alphabet (A-Za-z0-9+/) can be pushed using the above technique and appending the non-letters:

    '[,_el^A,s+"+/"+
    

    An equally short way of pushing this string makes use solely of symmetric differences:

    "+,/0:[a{A0":,:^
    

    How can we find the string at the beginning?

    All used character ranges (A-Z, a-z, 0-9, +, /) can be pushed as the symmetric difference of to range that start at the null byte, namely 'A,'[,^, 'a,'{,^, '0,':,^, '+,',,^ and '/,'0,^.

    Therefore, executing :,:^ on "A[a{):+,/0" will push the desired characters, but not in the right order.

    How do we find the right order? Brute force to the rescue! The program

    '[,_el^A,s+"+/"+:T;"0:A[a{+,/0"e!{:,:^T=}=
    

    iterates over all possible permutations of the string, applies :,:^ and compares the result to the desired output (permalink).

  • The radix-64 alphabet used, e.g, by crypt (.-9A-Za-z) can be generated using the above method:

    ".:A[a{":,:^
    

    This is the shortest method I know.

    Since all characters in the desired output are in ASCII order, iterating over permutations isn't needed.

  • Not all concatenated character ranges can be pushed in the desired order using :,:^.

    For example, the range 0-9A-Za-z;-? cannot be pushed by executing :,:^ on any permutation of "0:A[a{;@".

    However, we can find a rotated variation of the desired string that can, by using the code

    A,'[,_el^'@,59>]s2*:T;"0:A[a{;@"e!{:,:^T\#:I)}=Ip
    

    which will print (permalink) the following:

    10
    0:@[a{A;
    

    This means that

    "0:@[a{A;":,:^Am>
    

    has the same effect as

    A,'[,_el^'@,59>]s
    

    which can only be used with an empty stack without prepending a [.

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

11

Avoid {…}{…}?

Assume you have an integer on the stack. If it is odd, you want to multiply it by 3 and add 1; otherwise you want to divide it by 2.

A "normal" if/else statement would look like this:

_2%{3*)}{2/}?

However, using blocks is usually not the way to go, since {}{} already adds four bytes. ? can also be used to select one of two items on the stack:

_2%1$3*)@2/?

This is one byte shorter.


Block-? with an empty if statement is always a no-go. For example,

{}{2/}?

is two bytes longer than

{2/}|

If instead you have

{2/}{}?

and the thing you are checking on is non-negative integer, you can do

g)/

The new {}& and {}| are handy, but sometimes problematic if you cannot clutter the stack.

Still, in the case of

_{…}{;}?

you can use a temporary variable instead:

:T{T…}&

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

1!)/ and g)/ are shorter in the examples. – jimmy23013 – 2014-10-25T18:14:07.257

11

Golfing common array and string values

There are certain short arrays or strings that crop up every now and then, e.g. to initialise grids. Naively, these can cost 4 or more bytes, so it's worth looking for operations on built-in values which will give the same result. Especially base conversion is often useful.

  • [0 1] can be written as 2,.
  • [1 0] can be written as YYb (i.e. 2 in binary).
  • [1 1] can be written as ZYb (i.e. 3 in binary).
  • The matrix [[0 1] [1 0]] can be written as 2e!.
  • [LL] can be written as SS/ (splitting a single space by spaces).
  • "\"\"" can be written as L`.
  • "{}" can be written as {}s.

The latter can be extended to cases where you want all bracket types to save another byte:

  • "[{<()>}]" can be written as {<()>}a`.
  • "()<>[]{}" can be written as {<()>}a`$.

Especially the base conversion trick can be useful to keep in mind for some obscurer cases that pop up every now and then. E.g. [3 2] would be E4b (14 in base 4).

In even rarer cases you might even find the factorisation operator mf useful. E.g. [2 7] is Emf.

Please feel free to extend this list if you come across any other examples.

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

11

Switch statements

CJam doesn't have switch statements. Nested if statements work just as well, but {{}{}?}{}? is already 12 bytes long...

If we can transform the condition into a small, non-negative integer, we can transform all case statements in a delimited string and evaluate the corresponding result.

For example, if we want to execute code0 if the integer of the stack is 0, code1 if it is 1, and code2 if it is 2, we can either use

_{({code2}{code1}?}{;code0}?

or

[{code0}{code1}{code2}]=~

or

"code0 code1 code2"S/=~

S/ splits the string into ["code0" "code1" "code2"], = extracts the corresponding chunk, and ~ evaluates the code.

Click here to see switch statements in action.

Finally, as suggested by suggested by @jimmy23013 and @RetoKoradi, we can shorten the switch even more in some cases. Say code0, code1 and code2 have lengths L0, L1 and L2, respectively.

If L0 = L1 &geq; L2

"code0code1code2"L/=~

can be used instead, where L is L0. Instead of splitting at a delimiter, / splits the string into chunks of equal length here.

If L0 &geq; L1 &geq; L2 &geq; L0 - 1,

"cccooodddeee012">3%~

can be used instead. > removes 0, 1 or 2 elements from the beginning of the string, and 3% extracts every third element (starting with the first).

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

For the last example, does that have any advantage over "code0code1code2"5/=~? Seems much more straightforward to me, and it's the same length. – Reto Koradi – 2015-10-18T19:12:55.357

@RetoKoradi If all snippets have the same length, there's no advantage. For different length, your method can be both shorter and longer than the modulus method. – Dennis – 2015-10-18T21:16:06.907

10

Clearing the stack

If you just want to clear the entire stack, wrap it in an array and pop it:

];

What's a bit more tricky is, if you've done a lot of computations, but only want to keep the top stack element and discard everything beneath. The naive approach would be to store the top element in a variable, clear the stack, push the variable. But there's a much shorter alternative: wrap the stack in an array and extract the last element:

]W=

(Thanks to Optimizer who showed this to me the other day.)

Of course, if there's only two elements on the stack, \; is shorter.

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

\; would only pop the element below the TOS. Did you mean ;;? – CalculatorFeline – 2017-03-10T15:57:09.847

1@CalculatorFeline the second half of the answer is about clearing everything but the TOS. – Martin Ender – 2017-03-10T16:39:41.177

9

Euclidean norms

The straightforward way of calculating the Euclidean norm of a vector, i.e., the square root of the sum of the squares of its elements, is

2f#:+mq

However, there's a much shorter way.

mh, the hypotenuse operator, pops two integers a and b from the stack and pushes sqrt(a2 + b2).

If we have a vector x := [x1 … xn], n > 1 on the stack, :mh (reduce by hypotenuse) will achieve the following:

  • First x1 and x2 are pushed and mh is executed, leaving sqrt(x12 + x22), on the stack.

  • Then, x3 is pushed and mh is executed again, leaving
    sqrt(sqrt(x12 + x22)2 + x32) = sqrt(x12 + x22 + x32) on the stack.

  • After xn has been processed, we're left with sqrt(x12 + … xn2), the Euclidean norm of x.

If n = 1 and x1 < 0, the above code will produce an incorrect result. :mhz works unconditionally. (Thanks to @MartinBüttner for pointing that out.)

I've used this trick for the first time in this answer.

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

2Of course, this has implications for numerical analysis of your program... – Peter Taylor – 2015-10-17T22:22:12.577

9

e and powers of ten

As in oh-so-many other languages, you can write 1e3 instead of 1000 in CJam.

This works for non-integer bases and even for non-integer exponents as well. For example, 1.23e2 pushes 123.0 and 1e.5 pushes 3.1622776601683795 (square root of 10).

What's not immediately obvious is that 1e3 is actually two tokens:

  • 1 pushes the integer 1 on the stack.

  • e3 multiplies it by 1000.

Why is that important?

  • You can call e<numeric literal> on something that's already on the stack.

    2 3 + e3 e# Pushes 5000.
    
  • You can map e<numeric literal> over an array.

    5 , :e3  e# Pushes [0 1000 2000 3000 4000].
    

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

8

Convert from base n with a list of numbers greater than n

CJam converts a list to a number with this formula: A0*nl + A1*nl-1 + A2*nl-2 + Al*n0 (with nonnegative n). n is the base and l is the list length. This means Ai can be any integer, which doesn't have to be in the range of [0,n).

Some examples:

  • 0b extracts the last item and cast it to integer. Works like W=i and saves a byte if it wasn't integer. But everything else in the list must also be able to cast into integer.
  • 1b returns the sum. Works like :i:+ and saves two bytes if they weren't integers. It also works with empty lists while :+ doesn't.
  • [i{_1&9 32?_@\m2/}16*;]W%:c converts a character to a string of line endings and tabs, which can be converted back with 2bc. The encoding function isn't easy to be golfed in a code-golf program, though. But you don't usually need that.
  • You can use the following code to convert a string to Unicode characters not in 16 bit, which can be converted back with 2A#b128b:c. (Explanations will be added later. Or perhaps I'll write a new version later.)

    128b2A#b         " Convert to base 1024. ";
    W%2/)W%\:+       " Convert to two base 1024 digit groups. ";
    [0X@
    {
      _54+
      @I+_Am>@\-
      _Am<@+ 0@-@1^
    }fI
    ]);)
    @\+[~+]2A#b_2G#<!{2A#b}*
    \W%+:c
    

The similar method works with any set of n integers which have different values mod n, if you can find some way to get rid of the most significant digit.

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042

8

Using $ as ternary if

When you don't mind leaking memory, i.e., leaving unused elements on the stack that you'll later clear with ];, the copy operator $ can be a handy substitute for the ternary operator ?.

? works well if you manage to compute the condition before pushing the two items to choose from, but more often than not, the condition actually depends on those items, and having it on top of them results much more natural.

If you have A B C on the stack, you can execute

!$

instead of

\@?

to copy B if C is truthy and A otherwise.

If C is an actual Boolean (0 or 1), you can execute

$

instead of

@@?

to copy A if C is truthy and B otherwise.

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

In hindsight, this is a rather obvious trick, but I had never thought of it before. I've used it for the first time in this answer.

– Dennis – 2015-07-04T21:36:39.287

7

Map for Nested Lists

Say you've got a nested list, like a matrix:

[[0 1 2][3 4 5][6 7 8]]

Or an array of strings:

["foo""bar"]

And you want to map a block onto the nested level (i.e. apply it to each number or each character). The naive solution is a nested %:

{{...}%}%

However, you can actually push the inner block onto the stack and then use f%. f is "map with additional parameter", so it will map % onto the outer list, using the block as the second parameter:

{...}f%

Saves two bytes.

Another neat trick to do something like for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...} is

5,_f{f{...}}

The outer f will map onto the first range, supplying the second range as an additional parameter. But now, if you use f again, only the top stack element is an array, so you f maps the inner block onto that, supplying the outer "iteration variable" as an additional parameter. This means the inner block is runs with i and j on the stack.

This has the same number of characters as just mapping a block onto a Cartesian product (although the latter gets shorter if you need the pairs as arrays):

5,_m*{~...}%

The difference is that this version yields a single array of results for all pairs, whereas the double-f yields a nested list, which can be useful if you want to store the results in a grid, with the iterator variables being the coordinates.

Thanks to Dennis for showing me this trick.

0.6.4 Update

f and : have now been immensely improved by taking any other operator including themselves. This means you can save even more bytes now. Mapping an operator onto a nested list got even shorter now:

{:x}%
{x}f%
::x

This doesn't really help with mapping blocks onto nested lists though.

As for the applying blocks or operators to the Cartesian product, this also got shorter now, for blocks as well as operators:

5,_f{f{...}}
5,_ff{...}

5,_f{fx}
5,_ffx

What's nice is that you can now nest these. So you can apply an operator just as easily to the third level down a list:

:::x

Or a block with some trickery:

{...}ff%

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

Great update. But there is still no f~... – jimmy23013 – 2015-02-13T17:42:28.977

@user23013 f expects a binary operator, ~ is unary; did you perhaps want :~? Also, we can discuss this in chat

– aditsu quit because SE is EVIL – 2015-02-13T19:13:26.593

Am I missing something about this 0.6.4 update? I still get error messages doing those tricks, like Unhandled char after ':': : (link)

– Runer112 – 2015-02-13T21:40:19.080

2@Runer112 Works for me. Make sure you reload properly (i.e. not from cache). Depending on your browser Ctrl+F5 should work. – Martin Ender – 2015-02-13T21:41:38.230

@MartinBüttner It was indeed caused by silly caching. Thanks. – Runer112 – 2015-02-13T21:43:17.683

7

Vectorized operators for ASCII art

For many ASCII art challenges, it is useful to generate two different patterns to superpose them later. Vectorized operators can be very helpful to achieve different types of superpositions.

One useful property of operator vectorization is that the operator is only executed once for each element of the shorter string/array, while the elements of the larger one that do not have counterparts remain untouched.

  • .e<

    The minimum operator e< work for pairs of strings, characters, arrays and integers; it pops two items from the stack and pushes the lower on e back.

    Since a space has a lower code point than all other printable ASCII characters, .e< can be used to "erase" parts of a generated pattern:

    "\/\/\/\/\/" "    " .e<
    
    e# This pushes "    \/\/\/".
    

    For a full example, see my answer to Me Want Honeycomb.

  • .e>

    The maximum operator e> works as the minimum operator, with the opposite result.

    Again, because of the low code point of the space, .e> can be used to insert a pattern of printable characters in a block of spaces:

    [[" " " " " " " "] [" " " " " " " "]][["+" "" "-" ""]["" "*" "" "/"]] ..e>
    
    e# This pushes [["+" " " "-" " "] [" " "*" " " "/"]].
    

    For a full example, see my answer to Seven Slash Display.

  • .e&

    The logical AND operator e& pushes its left argument if it is falsy and its right argument otherwise.

    If neither pattern contains falsy elements, this can be used to inconditionally impose one pattern over another one:

    "################" " * * * *" .e&
    
    e# This pushes " * * * *########".
    

    For a full example, see my answer to Print the American Flag!.

  • .e|

    The logical OR operator e| can be used as above, with reversed argument order:

    " * * * *" "################" .e|
    
    e# This pushes " * * * *########".
    

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

6

Use & to check if an item is in a list

For

1 [1 2 3] #W>
1 [1 2 3] #)

You can use

1 [1 2 3] &,
1 [1 2 3] &

instead, which returns 0/1 and truthy/falsey respectively.

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042

6

z and non-rectangular arrays

The zip operator z transposes the rows and columns of a two-dimensional1 array A, whose elements can also be iterables.

For non-rectangular arrays – unlike the built-in zip functions in, e.g., Python (truncates the rows to the same length) or Ruby (pads the rows with nil) – CJam simply converts the columns of the array into rows, ignoring their lengths and gaps.

For example, zipping the array

[
  [1]
  [2 4]
  [3 5 6]
]

is equivalent to zipping the array

[
  [1 4 6]
  [2 5]
  [3]
]

or the array

[
  [1]
  [2 4 6]
  [3 5]
]

as all three actions push

[
  [1 2 3]
  [4 5]
  [6]
]

on the stack.

While this means that z is not an involution (which would be useful on occasions), it has a few applications.

For example:

  • We can align the columns of an array to the top (i.e., turn the first array into the second) by zipping twice:

    zz
    
  • Minor modifications of the above method can be used for similar problems.

    For instance, to align the columns of an array to the bottom (i.e., to turn the second array into the first), we can zip twice with reversed row order:

    W%zzW%
    
  • Given an array of strings, we can compute the length of the longest string like this:

    :,:e>
    

    However, by zipping and calculating the number of rows of the result, we can save three bytes:

    z,
    

1 If any of the "rows" of A is not iterable, z treats them as singletons, so zipping works for arbitrary arrays.

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

1Just a different way of visualizing the same thing, but for me the behavior is much more logical if I picture z converting columns into rows, while empty values are skipped. In the example, the first column in the input is 1, 2, 3, the second column is 4, 5 (empty position is skipped), and the third column is 6. These are then the rows of the result. – Reto Koradi – 2015-08-28T02:32:18.297

@RetoKoradi That's a much better way to describe it. – Dennis – 2015-08-28T03:04:35.787

6

Exceptions

All exceptions are fatal in CJam. Since output to STDERR is ignored by default, we can use this to our advantage.

All operator in CJam work by popping zero or more elements from the stack, perform some task and push zero or more elements on the stack. Exceptions occur while the task is performed, so this still pops the elements, but nothing is pushed in return.

Here are a few use cases:

  • Clearing a small stack

    To clear a stack that contains two elements, @ can be used. @ tries to pop three stack elements, but fails after popping the second.

    Any other operator that pops three elements would serve the same purpose.

    See it in action here.

  • Removing two or three elements from the stack

    Any operator that is not implemented for these particular elements can be used to pop two or three elements from the stack right before exiting.

    To pop two elements, b works if one of them is a character or none of them is an integer.

    To pop three elements, t works if none of the bottom-most two is an iterable, the bottom-most iterable is empty or none of them is an integer.

  • Exiting from a loop

    On occasions, we need to exit from a loop when an integer becomes zero or a string becomes too short. Rather than testing for these conditions, if the involved operations fail for zero, the empty string or singletons, we can simply let the program take its natural course.

    For an example involving arithmetic, see here.

    For an example involving strings, see here.

  • Conditional execution

    If the source code should not be executed for certain types of input, we sometimes can use an operator that fails that kind of input.

    For example, i will fail for strings that do not evaluate to an integer and ew will fail for strings of length 0 or 1.

    See it in action here.

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

5

Max/Min from an array

Here is one for starters!

When you need to find the maximum or minimum number from an array, the easiest and smallest way is to sort the array and then take out the first or last element.

So if the array is in variable A

A$W=

is the maximum and

A$0=

is the minimum.

Get both at the same time is also possible

A$)\0=

This might seem obvious after reading, but anyone's first attempt tends to go towards the usage of e< or e> via iterating through the array, which goes like

A{e<}*

which is 2 bytes longer, and even longer if you want both max and min.

Optimizer

Posted 2014-10-11T23:35:22.517

Reputation: 25 836

Now there is :e< and :e> – aditsu quit because SE is EVIL – 2015-06-29T10:51:04.510

@aditsu Though, they are not shorter than the tip above. – Optimizer – 2015-06-29T11:07:49.363

Of course, if you don't mind the rest of the array remaining on the stack, you can actually use ( and ) instead of 0= and W=. – Martin Ender – 2014-10-11T23:57:22.320

5

Use a timestamp for large numbers

If you need a very large, but arbitrary number, you'll usually either use scientific notation like 9e9 or raise one of the large built-in variables to a similar power, like KK#. However, if you don't care what the actual number is, and it doesn't need to be consistently the same (e.g. as the upper bound for a random number), you can do it in two bytes using

es

instead. This gives the current timestamp in milliseconds, and is on the order of 1012

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

3Also note that if you want a large arbitrary number, and want to discard a positive number together, you can use e9. – jimmy23013 – 2014-12-26T15:20:45.487

5

Checking that two strings/arrays are not equal

Sometimes you want a truthy value when two strings or arrays are not equal, and a falsy value if they are. The obvious solution is two bytes:

=!

Check for equality, and invert the result. However, under some conditions you can use

#

When # is applied to two arrays it actually searches for the second array as a subarray of the first (and gives you the index where the subarray starts). So if the two arrays are the same, the subarray will be found right at the start and give 0, which is falsy. But if the second array cannot be found, it will give -1 which is truthy.

The reason we need some additional condition on the two arrays is that this also yields a falsy value if the second array is a non-trivial prefix of the first, e.g.:

"abc""ab"#

gives 0 although the strings are not the same. The simplest condition which rules out this case is if you know that both arrays will be the same length - in that case if one is a prefix of the other, you know that they are equal. But in specific circumstances there may be weaker conditions that are also sufficient. For instance, if you know that the strings are sorted, a prefix would always be the first string, not the second.

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

5

c and 16-bit integers

To add (or subtract) unsigned 16-bit integers with proper wrapping, you can use +65536% or +2G#%.

However,

+ci

is a lot shorter. Characters wrap arround at 65536, so casting to Character (c) then to Long (i) has a similar effect to 65536%, with the added benefit that the result will not be negative.

The same trick can be used to push 65535:

Wci

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

4

Power sets

Say you have an array and you want an array with all possible subsets of that array. The trick is to start with an empty array, and then, for each element, duplicate the subsets you already have, and add the new element to them (keeping previous result where the element wasn't added). Note that you need to initialise the stack with the base case, i.e. an array containing only an empty array: That could look like this:

[1 2 3 4 5]La\{1$f++}/

The nice thing about this is, you can immediately run some computation on the subset, potentially without added characters. Say you want the products of all subsets. In that case, the base case is an array containing 1, and at each step, you take the previous list of possible products, duplicate it, and multiply everything in the duplicate by the new element:

[1 2 3 4 5]1a\{1$f*+}/

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

4

Check if items in a list are all the same

I think this also worth mentioning. Use:

)-

Returns truthy if not all the same, or empty list if all the same. Errors if the list is empty.

In case the item extracted might be an array (or string) itself:

)a-

Use ! or !! to get boolean values. In case the item extracted might be an array, and there are at most two kind of different items, and you want it to be 1 if not all the same, this is shorter:

_|,(

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042

4

0= for strings

To retrieve the first element of an array, you have to use 0= (or (, if you don't mind leaving the rest of the array on the stack).

However, if that array is a string, casting to character is sufficient.

Example

"xyz"c e# Pushes 'x.

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

I don't see why CJam doesn't just let c extract the first element of any array, which would be more useful and consistent. – Esolanging Fruit – 2017-04-16T15:39:10.927

4

Rotating an array (or the stack) one unit to the left

CJam has the rotate left operator m<, which is normally what you should use to rotate an array an arbitrary number of units to the left.

In some cases, you can also use (+ to shift and append:

[1 2 3]       (+ e# Pushes [2 3 1].
[[1] [2] [3]] (+ e# Pushes [[2] [3] 1].

The second example did not work because the arrays first element is also an iterable, so + concatenated instead of appending.

Also, if you want to dump the rotated array on the stack, you can use :\ (reduce by swapping) unconditionally:

[1 2 3]       :\ e# Pushes 2 3 1.
[[1] [2] [3]] :\ e# Pushes [2] [3] [1].

As long as you don't have an open [, this trick can also be used to rotate the entire stack, i.e., to bring the bottom-most stack item to the top:

]:\

Dennis

Posted 2014-10-11T23:35:22.517

Reputation: 196 637

3

Printing a list and clearing the stack

Lets say your stack has a list of strings/numbers/etc. on top and some other extra items below it. i.e.

123 "waste" ["a" "b" "rty" "print" "me" "please"]

Now you are interested in printing the last list only, so you do

S*]W=

which outputs

a b rty print me please

Which seems really smart as we use the clearing the stack trick and only print the list joined with spaces (which might not be the desired way of printing a list at times).

This can be golfed further!

p];

That's 2 bytes shorter!

and if you have only 1 item on stack other than the list, its even shorter!

p;

The beauty of p is that it removes the top most item from stack, stringifies it (also adds a newline at the end) and prints to STDOUT instantly, without waiting for completion of the code.

So the above code will output

["a" "b" "rty" "print" "me" "please"]

which is the exact representation of a list when it was in stack!

Optimizer

Posted 2014-10-11T23:35:22.517

Reputation: 25 836

3

Cartesian products or all possible combinations of two or more sets

CJam has an inbuilt Cartesian product calculator m* which takes the top two arraylists/strings on stack and create all possible pairs from it. For example

[1 2 3 4]"abc"m*

leaves

[[1 'a] [1 'b] [1 'c] [2 'a] [2 'b] [2 'c] [3 'a] [3 'b] [3 'c] [4 'a] [4 'b] [4 'c]]

as the stack

But what if you want all possible combinations from more than 2 lists/strings. You use m* that many times ? For example

[1 2 3 4][5 6]"abc"m*m*

will leave the following on stack

[[1 [5 'a]] [1 [5 'b]] [1 [5 'c]] [1 [6 'a]] [1 [6 'b]] [1 [6 'c]] [2 [5 'a]] [2 [5 'b]] [2 [5 'c]] [2 [6 'a]] [2 [6 'b]] [2 [6 'c]] [3 [5 'a]] [3 [5 'b]] [3 [5 'c]] [3 [6 'a]] [3 [6 'b]] [3 [6 'c]] [4 [5 'a]] [4 [5 'b]] [4 [5 'c]] [4 [6 'a]] [4 [6 'b]] [4 [6 'c]]]

Notice that the products are still pairs, where one of the item is a pair itself. This is not expected and we want flattened combinations.

There is an easy way to do that. Just wrap every list that you want for your cartesian product in an array, pairwise create Cartesian products and flatten it each time:

[1 2 3 4][5 6]"abc"]{m*{(+}%}*

This leaves

[['a 5 1] ['b 5 1] ['c 5 1] ['a 6 1] ['b 6 1] ['c 6 1] ['a 5 2] ['b 5 2] ['c 5 2] ['a 6 2] ['b 6 2] ['c 6 2] ['a 5 3] ['b 5 3] ['c 5 3] ['a 6 3] ['b 6 3] ['c 6 3] ['a 5 4] ['b 5 4] ['c 5 4] ['a 6 4] ['b 6 4] ['c 6 4]]

on stack.

Want the order maintained ?, simply swap the before adding the popped item back to the array. i.e.

{m*{(\+}%}*

Want only permutations ?

{m*{(+$}%_&}*

Want only unique elements in the combinations ?

{m*{(+_&}%}*

That's all folks. for now.

Optimizer

Posted 2014-10-11T23:35:22.517

Reputation: 25 836

1Now you can also do ]:m*:e_, with any number of arrays – aditsu quit because SE is EVIL – 2015-06-29T10:46:54.080

3

Operating on strings

Sometimes if you are working with a complex data structure, while the items in it are simple, converting to strings may help.

For example, if you want to get the first or last few items in a 2D array of bits, and don't care about the returned type, sA< saves a byte from 0=A< or :+A<.

Or if you want to modify some bits in the input, you can modify the string before evaluating it.

Or if you got this structure and want to convert it to a simple list:

[[[[[[[[[1]2]3]4]5]6]7]8]9]

You can do it with many characters in other ways:

[a{~)\}h;]W%

But it can be much shorter with strings:

s:~

It's shorter even if it may have numbers with more than one digit:

[`La`-~]

Or:

`']-~]

If you don't need another array containing many of such arrays.

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042

There is e_ now – aditsu quit because SE is EVIL – 2015-06-29T10:40:48.650

@aditsu See this answer and comment. Sometimes s still works better.

– jimmy23013 – 2015-06-29T11:51:28.620

Sure, when you can work with a string directly, it's shorter. – aditsu quit because SE is EVIL – 2015-06-29T12:43:58.963

3

Using N instead of La

In many cases you need something initialized to an array containing an empty array as its only element, which is La, seemingly unnecessarily 1 byte longer.

In many cases you also need to add a newline after each element before printing, which would be something like No or N*.

But if both are true, sometimes you may find out that you can just initialize the array with N, which has the newline character as its only element. Make sure you only prepend things to the elements in the rest of your code, and the first thing to prepend is always a character or an array. Or only append, if a leading newline is acceptable and that makes it shorter.

Sometimes S also works if you need to separate the output with spaces.

In rarer cases, the initial element has to be a string. But you still can use Na which might be shorter than appending the newline afterwards.

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042

2

Understand How Array Literals Work

The [ and ] characters in CJam are not part of any special syntax; they are operators.

What [ does is puts a "flag" on the stack. Attempting to pop from the stack will pop from below it, but pushing to the stack will push above it.

This means that this:

1 2 [+]

Will result in the stack looking like this:

[3]

This can be used for golfing. For example, if I wanted to duplicate the final element in an array (i.e. turn ["foo" "bar" "baz"] into ["foo" "bar" "baz" "baz"]), I could do this:

_W=a+

But I can shorten this by 1 byte:

[~_]

If I wanted to put the top two stack elements into an array, I'd do:

a\a\+

But again, I can shorten this:

[\\]

If I was doing some computation earlier that pushed the two values onto the stack, I could wrap part of it in []. This means I don't need the \\, which saves even more bytes.

You can manipulate this in even crazier ways. For example, you can accumulate an array ([1 2 3] -> [1 3 6]) using:

[{1$+}*]

(I still wish CJam had a builtin for that, though, as I find myself needing it oftentimes.)

In general, this technique allows us to treat stack elements as array elements and vice versa.

Esolanging Fruit

Posted 2014-10-11T23:35:22.517

Reputation: 13 542

2

Splitting on one or more occurrences

Say you have a string "abbcdbbfghbdbb" and you want to split it on b

"abbcdbbfghbdbb"'b/

This leaves on stack:

["a" "" "cd" "" "fgh" "d" "" ""]

Notice the empty strings ? Those are there because two b were together and nothing was in between them. At times, you want to avoid this. You can do this by

"abbcdbbfghbdbb"'b/La-

or filtering out empty strings

"abbcdbbfghbdbb"'b/{},

but that is 3 extra bytes.

A little less known operator for this particular use case is %. Apart from doing mod and map and splitting based on number ("abcd"2% = "ac"), % can also split on strings/arrays. So for the above use case:

"abbcdbbfghbdbb"'b%

will leave

["a" "cd" "fgh" "d"]

on stack.

Thanks for @user23013 for pointing this out in one of my answers today.

Optimizer

Posted 2014-10-11T23:35:22.517

Reputation: 25 836

I think this should be named "also learn GolfScript", which has better examples in the documentation. – jimmy23013 – 2015-01-02T09:00:43.407

@user23013 but we are never sure what all is similar to GS and what is not. – Optimizer – 2015-01-02T09:06:45.423

2

Use fold/reduce as infix foreach

We have :x as a shorthand for {x}% and or {x}* (depending on whether x is unary or binary). Unfortunately, there is no equivalent infix operator to shorten {x}/. However, very often when we do {x}/, x is actually a binary operator which repeatedly modifies the item lying underneath on the stack. If that's the case, and said item is not an array, we can save a byte by abusing fold/reduce as foreach:

5 [1 2 3 4]{-}/  e# Gives -5
5 [1 2 3 4]+:-

This works because fold always leaves the first element untouched. Unfortunately, it doesn't save a byte, when the modified element is an array, because adding it would unwrap it. However, sometimes you're lucky enough that your array already contains that element at the front, in which case reduce should be kept in mind (instead of manually removing the element before using {}/ on the remainder).

Martin Ender

Posted 2014-10-11T23:35:22.517

Reputation: 184 808

2

print and println

CJam has print operator: o. It works but stack is printing immediately after all the code has executed. You can stop it if you clear the stack at the end of program. Simply put this at the end:

];

To println you can use oNo or p (works as `oNo)

username.ak

Posted 2014-10-11T23:35:22.517

Reputation: 411

3There's a larger difference between o and p. p starts by converting the item to be printed to an unambiguous string representation. p is equvalent to executing ​`oNo. – Dennis – 2016-02-11T15:52:46.260

2

Modify an element instead of deleting it

If you need the sum of a list except for the last element, increased by T, instead of:

W<:+T+

You can use:

WTt:+

Or if you just need the sum of a list except for element K, which isn't the first or last element, you can use:

K0t:+

Except for the case there are only 3 elements and K=1, where this is shorter:

2%:+

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042

1

Check if array contains sub-array

Note: If you're only looking for a single element use jimmy's method.

If you want to see if an array contains a specific sub-array, use #). # is "index of" and ) increases it by 1. If the sub-array is not in the array # returns -1. When you increment it by 1, you get 0 which is falsey. If the sub-array is in the array # returns a number that is at least 0, which when incremented by 1 returns a truthy value.

& and e= don't work for sub-arrays.

geokavel

Posted 2014-10-11T23:35:22.517

Reputation: 6 352

1

Index into an array, use a default value or run code if not in range

This could be done using a single character: j.

For example, this code would output GolfScript, CJam, Pyth for 0, 1, 2, and Seriously for all other cases:

ri"GolfScript CJam Pyth"S/{;"Seriously"}j

Compared to:

ri3,#"GolfScript CJam Pyth Seriously"S/=

Actually used more characters. But it might be considerable if the type is not string or you have to run code in a block anyway.

jimmy23013

Posted 2014-10-11T23:35:22.517

Reputation: 34 042