38
\$\begingroup\$

What general tips do you have for golfing in Mathematica? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to Mathematica (e.g. "remove comments" is not an answer).

\$\endgroup\$

28 Answers 28

29
\$\begingroup\$

Tips below vary from the most economical to the most often used:

  1. Use Mathematica's high-level commands where possible, even bulky ones:

  2. Use Graphics and Text for Ascii art: e.g Star programming! and Build an analog clock

  3. Dedicated symbols:

    • logic and set operations symbols instead of their long form names: ⋂, ⋃, ∧, ∨

    • Map and Apply: /@, //@. @@, @@@

  4. Prefix and infix notation:

    • Print@"hello" in place of Print["hello"]

    • a~f~b in place of f[a,b]

  5. When a function is used only once, a pure function may economize a character or two.

  6. Joining strings in a list. ""<>{"a","b","c"} instead of StringJoin@{"a","b","c"}

  7. Exploit listable functions. The longer the lists the better.

    {a, b, c} + {x, y, z}= {a+x, b+y, c+z}

    {2, 3, 4} {5, 6, 7}= {10, 18, 28}

    {{a, b}, {c, d}}^{2, 3} = {{a^2, b^2}, {c^3, d^3}}

\$\endgroup\$
  • 1
    \$\begingroup\$ It's always shorter to write (Norm[#-#2]&) instead of EuclideanDistance. \$\endgroup\$ – user202729 May 18 '18 at 9:36
32
\$\begingroup\$

Some built-in functions with long names can be replaced with shorter expressions.

For example:

  • Total => Tr
  • Transpose => Thread or \[Transpose]
  • True => 1<2
  • False => 1>2
  • Times => 1##&
  • Alternatives => $|##&
  • IntegerQ => ⌊#⌋==#&
  • a[[1]] => #&@@a
  • a[[All,1]] => #&@@@a
  • ConstantArray[a,n] => Array[a&,n] or Table[a,{n}]
  • Union@a => {}⋃a or a⋃a
  • ToExpression@n => FromDigits@n if n is a number
  • Divisible[n,m] => m∣n
  • FromDigits[n,2] => Fold[#+##&,n] if n is a list of 0s and 1s
  • Complex@z => {1,I}.z where z is a list of the form {x,y}
\$\endgroup\$
  • 5
    \$\begingroup\$ @belisarius Thread[{{a,b},{c,d}}]==Thread[List[{a,b},{c,d}]]=={List[a,c],List[b,d]}=={{a,c},{b,d}}==Transpose[{{a,b},{c,d}}] \$\endgroup\$ – alephalpha Oct 10 '14 at 4:29
  • 2
    \$\begingroup\$ I think your Fold trick for FromDigits also works for any other base except 10. E.g. FromDigits[n,5] --> Fold[4#+##&,n] (with the bonus of saving an extra byte for bases 100 and 1000). \$\endgroup\$ – Martin Ender Nov 11 '15 at 16:07
  • 1
    \$\begingroup\$ @mbomb007 3 bytes in UTF-8. In fact this character is U+F3C7. \$\endgroup\$ – alephalpha Nov 14 '15 at 3:38
  • 1
    \$\begingroup\$ I finally installed 10.3. If we're considering full programs, I don't think Echo is an option, because it prints >> (and a space) to STDOUT before printing the actual string. \$\endgroup\$ – Martin Ender Dec 9 '15 at 10:30
  • 2
    \$\begingroup\$ For Complex[x,y] => {1,I}.{x,y}, I think x+y*I is much shorter with the same effect? \$\endgroup\$ – Shieru Asakoto Feb 27 '18 at 1:54
22
+500
\$\begingroup\$

Lists with repeated values

This is quite a common vector to work with:

{0,0}

It turns out this can be shortened by a byte:

0{,}

Even more bytes are saved if the vector is longer than two zeros. This can also be used to initialise zero matrices, e.g. the following gives a 2x2 matrix of zeros:

0{{,},{,}}

This can also be used for non-zero values if they're sufficiently large or sufficiently many or negative. Compare the following pairs:

{100,100}
0{,}+100
{-1,-1}
0{,}-1
{3,3,3,3}
0{,,,}+3

But remember that starting at 6 values, you're better off with 1~Table~6 in this case (potentially earlier, depending on precedence requirements).

The reason this works is that , introduces two arguments to the list, but omitted arguments (anywhere in Mathematica) are implicit Nulls. Furthermore, multiplication is Listable, and 0*x is 0 for almost any x (except for things like Infinity and Indeterminate), so here is what's happening:

  0{,}
= 0*{,}
= 0*{Null,Null}
= {0*Null,0*Null}
= {0,0}

For lists of 1s, you can use a similar trick by making use of exponentiation rules. There are two different ways to save bytes if you have at least three 1s in the list:

{1,1,1}
1^{,,}
{,,}^0
\$\endgroup\$
  • 7
    \$\begingroup\$ +1; this just goes to show that while Mathematica may have a built-in for everything, golfing in it can be a real challenge. \$\endgroup\$ – LegionMammal978 Nov 21 '16 at 17:10
  • \$\begingroup\$ If you want an array that's ultimately filled with 1s, then 1^{,,,} is one byte smaller than 0{,,,}+1. \$\endgroup\$ – Misha Lavrov Nov 12 '18 at 2:29
  • \$\begingroup\$ @MishaLavrov Oh, good catch. That makes it shorter at three values and you can also use {,,}^0. I'll edit the post. \$\endgroup\$ – Martin Ender Nov 12 '18 at 9:30
19
\$\begingroup\$

Know your pure function arguments

When golfing code, you'll often employ a functional approach, where you use anonymous (pure) functions with the & shorthand syntax. There are a lot of different ways to access the arguments of such a function, and you can often shave off a couple of bytes by having a good grasp on the possibilities.

Accessing single arguments

You probably know this if you've used pure functions before. The nth argument is referred to as #n, and # acts as an alias for #1. So if, say, you want to write a function that takes as parameters another function and its argument (to pass the argument to that function), use

#@#2&

This does not work with negative numbers (such as you might use when accessing lists).

Accessing named arguments (new in V10)

One of the major new language features in Mathematica 10 is Associations, which are basically key-value maps with arbitrary key types, written like

<| x -> 1, "abc" -> 2, 5 -> 3 |>

If such an association is passed in as the first argument to a pure function, you can access some if its arguments as named parameters:

{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)

Note that # still refers to the entire association as expected. For the named parameters to work, the keys have to be strings (it won't work if you use undefined variables for instance), and those strings must begin with a letter and only contain letters and digits.

The "self" argument #0

A lesser known feature is that #0 also exists, and gives you the function object itself. This can be really useful in quines and generalised quines. In fact, the shortest Mathematica quine (I know of) is

ToString[#0][] & []

What's slightly annoying is that it won't give you the exact characters you entered. E.g. if use @ for function application, it will still render as [...] and spaces will be inserted in some places. This will usually make the quine a bit longer than you'd like it to be, but it will always work, by golfing the quine first, and then just copying its output - which should now be a real quine.

Apart from quines, this also means that you can write recursive code without having to name your function. Compare these three (naive but golfed) Fibonacci implementations:

f@0=0;f@1=1;f@n_:=f[n-1]+f[n-2]
f@n_:=If[n<2,n,f[n-1]+f[n-2]]
If[#<2,#,#0[#-1]+#0[#-2]]&

Sequences of arguments

Now this is where the real magic starts. Sequences aren't used often in golfing, because Sequence it's just too long a name to be worth it most of the time. But in pure functions is where they shine. If you're not familiar with sequences, they are basically like splats in some other languages, if you use a sequence in a List or the argument list of a function, it's elements will automatically be expanded into separate slots. So

{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]

Now, in pure functions ## or ##1 is a sequence of all the arguments. Likewise, ##2 is a sequence of all arguments starting from the second, ##3 all arguments starting from the third etc. So for a start, we can just reimplement Sequence as ##&, saving 5 bytes. As an example usage, this provides us with an alternative to Join@@list (see this tip), which doesn't save any bytes, but is good to know about anyway:

 ##&@@@list

This effectively flattens the first level of a nested list. What else can we do with this? Here is a 2 bytes shorter alternative to RotateLeft:

 RotateLeft@list
 {##2,#}&@list

For these things alone it's worth keeping this feature in mind. However, we can do better! Sequences get really interesting when consider that operators are actually implemented as functions under the hood. E.g. a+b actually evaluates to Plus[a,b]. So if we give that a sequence...

1+##&[1,2,3]
=> Plus[1,##] 
=> Plus[1,1,2,3]
=> 7

This trick has been use in this tip to save a byte on Times, because juxtaposition is technically also just an operator:

1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6

You can also use it to save a byte on Unequal if you have a single-character value or variable you know is not in your arguments (N will probably work in 99% of the cases):

Unequal[a,b,c]
N!=##&[a,b,c]

This gets even more interesting with unary operators and - and / - the latter two are actually implemented in terms of multiplication and exponentiation. Here is a list of things you can do, where the last column assumes that the function was passed the arguments a, b, c:

Operator    Function                Expanded                    Equivalent to

+##         Plus[##]                Plus[a,b,c]                 a+b+c
1##         Times[1,##]             Times[1,a,b,c]              a*b*c
-##         Times[-1,##]            Times[-1,a,b,c]             -a*b*c
x+##        Plus[x,##]              Plus[x,a,b,c]               x+a+b+c
x-##        Plus[x,Times[-1,##]]    Plus[x,Times[-1,a,b,c]]     x-a*b*c
x##         Times[x,##]             Times[x,a,b,c]              x*a*b*c
x/##        Times[x,Power[##,-1]]   Times[x,Power[a,b,c,-1]]    x*a^b^c^-1
##/x        Times[##,Power[x,-1]]   Times[a,b,c,Power[x,-1]]    a*b*c/x
x^##        Power[x,##]             Power[x,a,b,c]              x^a^b^c
##^x        Power[##,x]             Power[a,b,c,#]              a^b^c^x
x.##        Dot[x,##]               Dot[x,a,b,c]                x.a.b.c

Other common operators are !=, ==, &&, ||. Less common ones to keep in mind are |, @*, /*. To conclude, here is a little bonus trick:

####        Times[##,##]            Times[a,b,c,a,b,c]          (a*b*c)^2

Keep experimenting with these, and let me know if you find any other useful or particularly interesting applications!

\$\endgroup\$
15
\$\begingroup\$

Sqrt@2 or 2^.5 => √2

a[[1]]=>a〚1〛

#+#2&=>+##&

Flatten@a=>Join@@a (sometimes)

Function[x,x^2]=>xx^2 or #^2&

a〚1;;-1;;2〛=>a〚;;;;2〛

a〚2;;-1 ;;2〛=>a〚2;;;;2〛

a〚All,1〛=>a〚;;,1〛

{{1}}〚1,1〛=>Tr@{{1}}

0&~Array~10=>0Range@10

Range[10^3]=>Range@1*^3

\$\endgroup\$
  • \$\begingroup\$ Note that when measuring by bytes, using and takes 3 bytes each (assume UTF8) \$\endgroup\$ – user202729 May 18 '18 at 10:12
12
\$\begingroup\$

Operators as Functions

Inspired by Dennis's recent discovery for Julia I thought I'd look into this for Mathematica. I was aware that Mathematica defines a large number of unused operators, but never paid much attention to it.

For reference, the list of all operators can be found here in the form of a precedence table. The triangle in the last column indicates whether that operator has a built-in meaning or not. While not all of those that don't can be defined easily, most of them can.

Conveniently, there are two unused operators with a codepoint less than 256, such that they can be used as single bytes in an ISO 8859-1 encoded source file:

  • ± (0xB1) can be used either as a unary prefix operator or a binary infix operator.
  • · (0xB7) can be used as a variadic or n-ary infix operator, for n > 2.

There's one more catch though: for some weird reason when defining these operators you need one space in front of them, or else Mathematica tries to parse a multiplication. When using them you don't need any spaces though:

±x_:=2x
x_ ±y_:=x+y
x_ ·y_ ·z_:=x*y+z
Print[±5]  (* 10 *)
Print[3±4] (*  7 *)
Print[3·4·5] (* 17 *)

Compare this with:

f@x_:=2x
x_~g~y_:=x+y
h[x_,y_,z_]:=x*y+z
Print[f@5]   (* 10 *)
Print[3~g~4] (*  7 *)
Print[h[x,y,z]] (* 17 *)

So this saves one byte when defining the function and two bytes when using it. Note that the definition of · will not save bytes for four operands and will start costing bytes for more operands, but the usage may still save bytes, depending the precedence of operators used in the arguments. It's also good to note that you can cheaply define a variadic function that can then be called much more efficiently:

x_ ·y__:={y}
Print[1·2·3·4·5] (* {2, 3, 4, 5} *)

But note that it's not easily possible to call these variadic functions with a single argument. (You could do CenterDot[x] or ##&[]·x but if you actually need that there's a good chance you're better off with a different solution.)

Of course, this isn't saving anything for solutions where an unnamed function suffices, but sometimes you need to define helper functions for use later on, and sometimes it's shorter to define named functions e.g. to set up different definitions for different parameters. In those cases, using an operator instead can save a decent amount of bytes.

Note that using these ISO 8859-1 encoded files requires $CharacterEncoding to be set to a compatible value, like the Windows default WindowsANSI. On some systems this defaults to UTF-8 which won't be able to read these code points from single bytes.

\$\endgroup\$
  • \$\begingroup\$ This is really great, I did not know Mathematica had a list of operators, and even included their precedence. Those two operators you found I'm sure will come in handy. \$\endgroup\$ – miles Jun 17 '16 at 9:03
8
\$\begingroup\$

Alternatives to Length

This has been entirely rewritten with some suggestions from LegionMammal978 and Misha Lavrov. Many thanks to both of them.

In many cases, Length can be shortened a bit by making use of Tr. The basic idea is to turn the input into a list of 1s, so that Tr sums them up which will then equal the length of the list.

The most common way to do this is to use 1^x (for a list x). This works because Power is Listable and 1^n for most atomic values n is just 1 (including all numbers, strings and symbols). So we can already save one byte with this:

Length@x
Tr[1^x]

Of course, this assumes that x is an expression with higher precedence than ^.

If x contains only 0s and 1s, we can save another byte using Factorial (assuming x has higher precedence than !):

Length@x
Tr[x!]

In some rare cases, x might have lower precedence than ^ but still higher precedence than multiplication. In that case it will also have lower precedence than @, so we really need to compare with Length[x]. An example of such an operator is .. In those cases, you can still save a byte with this form:

Length[x.y]
Tr[0x.y+1]

Finally, some remarks about what kind of lists this works on:

As mentioned at the top, this works on flat lists containing only numbers, strings and symbols. However, it will also work on some deeper lists, although it actually computes something slightly different. For an n-D rectangular array, using Tr gives you the shortest dimension (as opposed to the first). If you know that the outermost dimension is the shortest, or you know they're all the same, than the Tr-expressions are still equivalent to Length.

\$\endgroup\$
  • 2
    \$\begingroup\$ Just found an even shorter solution: Length@x == Tr[1^x]. Should work with most lists. \$\endgroup\$ – LegionMammal978 Dec 30 '16 at 13:28
  • \$\begingroup\$ @LegionMammal978 that's amazing, thanks :). I'll edit it in soon. \$\endgroup\$ – Martin Ender Dec 30 '16 at 13:33
  • \$\begingroup\$ Twice now, I've found myself using Tr[x!] instead of Tr[1^x] to save one byte in the special case where x only contains zeroes and ones. \$\endgroup\$ – Misha Lavrov Nov 17 '17 at 7:29
  • \$\begingroup\$ @MishaLavrov That's really neat! :) \$\endgroup\$ – Martin Ender Nov 17 '17 at 7:30
7
\$\begingroup\$
  1. Explore recursive solutions - Mathematica is multi-paradigm, but the functional approach is often the most economical. NestWhile can be a very compact solution to searching problems, and NestWhileList and FoldList are powerful when you need to return or process the results of intermediate iterations. Map (/@), Apply (@@, @@@), MapThread, and really everything on Wolfram's Functional Programming documentation page is potent stuff.

  2. Shortened form for increment/decrement - For example, instead of While[i<1,*code*;i++] you can do
    While[i++<1,*code*]

  3. Don't forget you can pre-increment/decrement - For example, --i instead of i--. This can sometimes save you a few bytes in the surrounding code by eliminating a preparatory operation.

  4. Corollary to David Carraher's #5: When the same function is used many times, assigning a symbol to it can save bytes. For example, if you are using ToExpression 4 times in a solution, t=ToExpression enables you to use t@*expression* thereafter. However, before you do this consider whether the repeated application of the same function indicates an opportunity for a more economical recursive approach.

\$\endgroup\$
  • \$\begingroup\$ MapThread can often be replaced by \[Transpose]. TIO. \$\endgroup\$ – user202729 Jun 30 '18 at 16:16
7
\$\begingroup\$

Choosing values based on integer

The naive approach to choose between y and z, depending on whether x is 0 or 1 is

If[x<1,y,z]

However, there's a shorter way:

y[z][[x]]

This works because [[0]] gives the Head of an expression, in this case y, whereas [[1]] just gives the first element - in this case the first argument, z.

You can even use this to choose between more than two values:

u[v,w][[x]]

Note that this won't work if u is a function that actually evaluates to something. It's important that Mathematica keeps u[v,w] as it is. However, this works in most cases, including if u is a is a number, a string or a list.

Credits for this trick go to alephalpha - I discovered this in one of his answer.

If x is 1-based instead of zero-based, just use

{y,z}[[x]]

or

{u,v,w}[[x]]

In some rare cases, you can even make use of the fact that multiplication is not evaluated for some values:

{"abc","def"}[[x]]
("abc""def")[[x]]

Note though that Mathematica will actually reorder the arguments, of a multiplication if it remains unevaluated, so the above is identical to

("def""abc")[[x]]
\$\endgroup\$
7
\$\begingroup\$

Don't use {} if you are using @@@.

In some cases, you may encounter an expression like:

f@@@{{a,b},{c,d}}

It is possible to reduce bytes by writing:

f@@@{a|b,c|d}

Alternatives has a very low precedence, so it's generally okay to write expressions (a notable exception is pure functions; you can use it only in the leftmost element of Alternatives).

f@@@{f@a|b~g~1,#^2&@c|d@2}

Note that f@@a|b|c (instead of f@@{a,b,c}) does not work because Apply has a higher precedence than Alternative.

In this case, you should simply use f@@{a,b,c}.

\$\endgroup\$
6
\$\begingroup\$

Mathematica 10 only

Operator forms

Mathematica 10 supports so-called "operator forms", which basically means some functions can be curried. Currying a function is to create a new function by fixing one of its operators. Say, you're using SortBy[list, somereallylongfunction&] a lot of different lists. Before, you probably would have assigned SortBy to s and the pure function to f so

s=SortBy;
f=somereallylongfunction&;
list1~s~f;
list2~s~f;
list3~s~f;

Now you can curry SortBy, which means you can now do

s=SortBy[somereallylongfunction&];
s@list1;
s@list2;
s@list3;

The same works for a lot of other functions, which take a list or function argument, including (but not limited to) Select, Map, Nearest, etc.

ybeltukov over on Mathematica.SE was able to produce a complete list of these:

{"AllTrue", "AnyTrue", "Append", "Apply", "AssociationMap", "Cases", 
 "Count", "CountDistinctBy", "CountsBy", "Delete", "DeleteCases", 
 "DeleteDuplicatesBy", "Extract", "FirstCase", "FirstPosition", 
 "FreeQ", "GroupBy", "Insert", "KeyDrop", "KeyExistsQ", "KeyMap", 
 "KeySelect", "KeySortBy", "KeyTake", "Map", "MapAt", "MapIndexed", 
 "MatchQ", "MaximalBy", "MemberQ", "Merge", "MinimalBy", "NoneTrue", 
 "Position", "Prepend", "Replace", "ReplacePart", "Scan", "Select", 
 "SelectFirst", "SortBy", "StringCases"}

Composition and RightComposition

There are new shorthands for Composition (@*) and RightComposition (/*). An obviously contrived example where these can save characters is seen in the following three equivalent lines

Last@Range@# & /@ Range[5]
Last@*Range /@ Range[5]
Range /* Last /@ Range[5]
\$\endgroup\$
5
\$\begingroup\$

Don't write 0-argument functions

There is no need for code like this:

f[]:=DoSomething[1,2]
(*...*)
f[]
(*...*)
f[]

You can simply use a variable with := to force re-evaluation of the right-hand side:

f:=DoSomething[1,2]
(*...*)
f
(*...*)
f

This also means that you can alias any action that you perform often (even if it's just something like n++) to a single character at the cost of 5 bytes. So in the case of n++ it pays back after the fourth use:

n++;n++;n++;n++
f:=n++;f;f;f;f
\$\endgroup\$
5
\$\begingroup\$

Use % to get a free variable

This tip is only applicable if Mathematica's REPL environment can be assumed. % is not defined when code is run as a script.

When you can make use of the REPL features, don't do this:

a=someLongExpression;some[other*a,expression@a,using^a]

Instead, remember that Mathematica stores the last evaluated (newline-terminated) expression in %:

someLongExpression;
some[other*%,expression@%,using^%]

The added newline costs a byte, but you are saving two by removing a=, so overall this saves one byte.

In some cases (e.g. when you want to print the value of a anyway), you can even leave off the ;, saving two bytes:

someLongExpression
some[other*%,expression@%,using^%]

One or two bytes may seem fairly minor, but this is an important case, because it makes extraction of repeated expressions (which is a very common technique) much more useful when golfing:

The normal technique of extracting repeated expressions costs four bytes of overhead, which need to be saved by further uses of the expression. Here is a short table of the minimum number of uses of an expression (by length of the expression) for extraction into a named variable to save anything:

Length   Min. Uses
2        6
3        4
4        3
5        3
6        2
...      2

By using the unnamed variable, it will be possible to save a couple of bytes much more often:

When ; is required                        When ; can be omitted

Length   Min. Uses                        Length   Min. Uses
2        5                                2        4
3        3                                3        3
4        3                                4        2
5        2                                ...      2
...      2

I don't think %% or %n can be used for golfing, because if you don't use them at least twice, you can just put the expression right where it's needed. And if you use it twice, the additional character in the variable name cancels out the savings from omitting some x=.

\$\endgroup\$
  • \$\begingroup\$ Note that it doesn't work in script mode. \$\endgroup\$ – alephalpha Nov 30 '15 at 16:10
  • \$\begingroup\$ @alephalpha What is script mode? \$\endgroup\$ – Martin Ender Nov 30 '15 at 16:13
  • \$\begingroup\$ A mathematica script. \$\endgroup\$ – alephalpha Nov 30 '15 at 16:19
  • \$\begingroup\$ @alephalpha Oh right, I shut off my brain there for a second... so that would mean it can't be really be used at all, unless the REPL environment can be assumed. \$\endgroup\$ – Martin Ender Nov 30 '15 at 16:26
5
\$\begingroup\$

Checking if a list is sorted

This is essentially a corollary of this tip but this is a sufficiently common task that I think it warrants its own answer.

The naive way to check if a list is in order is to use

OrderedQ@a

We can do one byte better with

Sort@a==a

However, this doesn't work if we don't have the thing we want to check in a variable already. (We'd need something like Sort[a=...]==a which is unnecessarily long.) However, there's another option:

#<=##&@@a

The best thing is that this can be used to check whether the input is reverse sorted for the same byte count:

#>=##&@@a

One more byte can be saved if a) we know that the list elements are distinct and b) we know a lower bound between 0 and 9 (inclusive; or upper bound for reverse sorted order):

0<##&@@a
5>##&@@a

To see why this works, check out "Sequences of arguments" in the tip linked at the top.

\$\endgroup\$
  • \$\begingroup\$ Alternatively, (strict) lower-bound for reverse-sorted also work: ##>0&@@a. Similar for upper-bound for sorted. \$\endgroup\$ – user202729 Oct 6 '17 at 9:59
  • \$\begingroup\$ @user202729 Oh good point, feel free to edit (otherwise I'll try to do it on the weekend if I remember). \$\endgroup\$ – Martin Ender Oct 6 '17 at 10:00
5
\$\begingroup\$

Repeating a string

Instead of StringRepeat[str,n] use (0Range[n]+str)<>"". Or if str doesn't depend on any slot arguments, even better is Array[str&,n]<>"" as per this tip.

\$\endgroup\$
  • 1
    \$\begingroup\$ Corollary: instead of StringRepeat[s,n+1] use Array[s&,n]<>s (even when you already have n+1 in a variable, too). \$\endgroup\$ – Martin Ender Aug 31 '16 at 13:49
  • \$\begingroup\$ Better, Table[str,n]<>"" \$\endgroup\$ – attinat Jul 18 at 0:02
5
\$\begingroup\$

If you need a list of numbers sorted in reverse, don't use

Reverse@Sort@x

but

-Sort@-x

to save six bytes. Sorting by a negative value is also useful for SortBy scenarios:

Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]
\$\endgroup\$
  • 2
    \$\begingroup\$ What about -Sort@-x? \$\endgroup\$ – JungHwan Min Jul 8 '17 at 3:12
  • 1
    \$\begingroup\$ @JungHwanMin Oh, uhhh, yeah, that's much better. :) \$\endgroup\$ – Martin Ender Jul 8 '17 at 6:39
4
\$\begingroup\$

You can stick an expression in Break which can save one or two characters. Example (other details not golfed for clarity):

result = False;
Break[]

can be turned into

Break[result = False]

to save one character. If the expression in question does not have lower precedence than function application you can even save another character:

Print@x;
Break[]

can be turned into

Break@Print@x

Although undocumented, the argument to Break seems to be returned by the surrounding loop, which can potentially lead to even more savings.

\$\endgroup\$
4
\$\begingroup\$

To remove all whitespace from a string s, use

StringSplit@s<>""

That is, use StringSplit's default (split into non-whitespace components) and simply join them back together. The same is probably still the shortest if you want to get rid of any other character or substring:

s~StringSplit~"x"<>""
\$\endgroup\$
4
\$\begingroup\$

Alternatives to Range

A very common task is to apply some sort of function to all numbers from 1 to a n (usually given as input). There are essentially 3 ways to do this (using an unnamed identity function as an example):

#&/@Range@n
Array[#&,n]
Table[i,{i,n}]

I tend to go for the first one (for whatever reason), but this is rarely the best choice.

Using Array instead

The above example shows that using Array has the same byte count. However, it has the advantage that it is a single expression. In particular, if you want to further process the result with a function f you can use prefix notation, which saves a byte over Range:

f[#&/@Range@n]
f@Array[#&,n]

Furthermore, you may be able omit parentheses around your unnamed function which you might have needed with Range, e.g.

15/(#&)/@Range@n
15/Array[#&,n]

If you don't want to use it further (or with an operator which has lesser precedence), you can instead write Array itself in infix notation and also save a byte:

#&/@Range@n
#&~Array~n

Hence, Array is almost certainly better than Range.

Using Table instead

Now table has to make up for 3 bytes, or at least 2 when infix notation is an option:

#&/@Range@n
i~Table~{i,n}

When not using infix notation, Table might allow you to omit parentheses if your function consists of several statements:

(#;#)&/@Range@n
Table[i;i,{i,n}]

This is still longer, but gives extra savings with in the case mentioned below.

The real savings stem from the fact that Table gives the running variable a name should not be dismissed. Often, you'll have nested unnamed functions where you want to use the outer variable inside one of the inner functions. When that happens, Table is shorter than Range:

(i=#;i&[])&/@Range@n
Table[i&[],{i,n}]
i&[]~Table~{i,n}

Not only do you save the characters for assigning i, you might also be able to reduce the function to a single statement in the process, which allows you to use infix notation on top of it. For reference, Array is also longer in this case, but still shorter than Range:

(i=#;i&[])&~Array~n

When would you actually use Range?

Whenever you don't need a function call to process the values, e.g. when the mapping can be performed via a vectorised operation. For instance:

5#&~Array~n
5Range@n
#^2&~Array~n
Range@n^2

Of course, it's also shorter if you don't want to map any function at all, e.g.

Mean@Array[#&,n]
Mean@Range@n
\$\endgroup\$
  • \$\begingroup\$ Finally someone else who uses f/@Range[x] regularly... \$\endgroup\$ – LegionMammal978 Oct 24 '15 at 15:05
4
\$\begingroup\$

Finding the smallest number that satisfies a condition

Some construct like i=1;While[cond[i],i++] is fine as is, but there is an alternative that is two bytes shorter:

1//.i_/;cond[i]:>i+1

The above code repeatedly replaces a number i with i+1 while it meets the condition cond[i]. In this case, i starts at 1.

Note that the default maximum number of iterations is 2^16 (= 65536). If you need more iterations than that, While would be better. (MaxIterations->∞ is too long)

\$\endgroup\$
4
\$\begingroup\$

Abuse short-circuit evaluation

You can sometimes replace If with a logical operator.

For instance, let's say you want to make a function that checks whether a number is prime, and print 2*(number) - 1 is if it's true:

If[PrimeQ@#,Print[2#-1]]&

It's shorter if you use && instead:

PrimeQ@#&&Print[2#-1]&

Even when you have multiple expressions, you still save byte(s):

If[PrimeQ@#,a++;Print[2#-1]]&

PrimeQ@#&&a++&&Print[2#-1]&
(* or *)
PrimeQ@#&&(a++;Print[2#-1])&

You can use || for cases when you want the condition to be False:

If[!PrimeQ@#,Print[2#-1]]&
(* or *)
If[PrimeQ@#,,Print[2#-1]]&
(* can become *)
PrimeQ@#||Print[2#-1]&

These tricks work because logical operators can be short-circuited; the second argument and thereafter don't even need to be valid boolean expressions.

Of course, this does not work if you need the return value of If or when you need both truthy and falsy arguments of If.

\$\endgroup\$
3
\$\begingroup\$

Using Optional (:)

Optional (:) can be used to expand lists in replacements, without having to define a separate rule for the expansion.

This answer by me and this answer by @ngenisis are examples.

Usage

... /. {p___, a_: 0, b_, q___} /; cond[b] :> ...

The above replacement first uses the pattern {p___, a_, b_, q___} and finds a match such that b meets a certain condition.

When no such match is find, it omits a_ and instead searches for {p___, b_, q___}. a is not included in the search and is assumed to have the value 0.

Note that the second pattern search would only work for b that occurs at the beginning of the list; if a b value satisfying a condition is in the middle, then {p___, a_, b_, q___} (which has a higher precedence) would match it instead.

The replacement is equivalent to prepending a 0 when a b satisfying a condition occurs at the beginning of the list. (i.e. there is no need to define a separate rule, {b_, q___} /; cond[b] :> ...)

\$\endgroup\$
2
\$\begingroup\$

Here is a list with loads of operator input forms which can shorten a lot of things. Some of these have been mentioned in other posts, but the list is long and I'm always surprised to find a few new things on there:

\$\endgroup\$
  • \$\begingroup\$ However, this only works when the operator uses less UTF-8 bytes. \$\endgroup\$ – LegionMammal978 Oct 24 '15 at 15:03
2
\$\begingroup\$

You can save a byte by working around Prepend or PrependTo:

l~Prepend~x
{x}~Join~l
{x,##}&@@l

or

l~PrependTo~x
l={x}~Join~l
l={x,##}&@@l

Unfortunately, this doesn't help for the more common Append, which seems to be the shortest equivalent of an Array.push() in other languages.

\$\endgroup\$
2
\$\begingroup\$

Mathematica 10.2: BlockMap is Partition+Map

This tip could also be titled, "Read the release notes, all of them". (For reference, here are the release notes for 10.2 and here of today's 10.3 release.)

Anyway, even minor releases contain a wealth of new features, and one of the more useful ones (for golfing) from 10.2 is the new BlockMap function. It essentially combines Partition and Map, which is great for is golfers, because Partition is used quite often, and it's a really annoyingly long function name. The new function won't shorten Partition by itself, but whenever you want to map a function onto the partitions (which probably happens more often than not), you can now save a byte or two:

#&/@l~Partition~2
BlockMap[#&,l,2]
#&/@Partition[l,3,1]
BlockMap[#&,l,3,1]

The savings get even bigger when the new position of the unnamed function allows you to save yourself some parentheses:

#&@@(#&/@Partition[l,3,1])
#&@@BlockMap[#&,l,3,1]

Unfortunately, I have no idea why didn't also add BlockApply while they were at it...

Also note that BlockMap does not support the 4th parameter you can use with Partition to get a cyclic list:

Partition[Range@5, 2, 1, 1]
(* Gives {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 1}} *)
BlockMap[f, Range@5, 2, 1, 1]
(* Nope... *)
\$\endgroup\$
2
\$\begingroup\$

Storing functions and expressions in a variable

If your answer ends up using the same functions or expressions multiple times, you may want to consider storing them in variables.

If your expression is length l and you use it n times, it would normally use up l * n bytes.

However, if you store it in a length-1 variable, it would take only 3 + l + n bytes (or 2 + l + n bytes, if you assign the variable where you won't need CompoundExpression (;) or parentheses).


For example, let's consider a simple problem, finding twin primes less than N.

One could write this 54 byte solution:

Select[Range@#,PrimeQ@#&&(PrimeQ[#+2]||PrimeQ[#-2])&]&

In this example, the function PrimeQ is used three times.

By assigning PrimeQ a variable name, the byte count can be reduced. Both of the following are 48 bytes (54 - 6 bytes):

Select[p=PrimeQ;Range@#,p@#&&(p[#+2]||p[#-2])&]&
Select[Range@#,(p=PrimeQ)@#&&(p[#+2]||p[#-2])&]&
\$\endgroup\$
2
\$\begingroup\$

To achieve an ascending key-value list, use Sort instead of SortBy

For lists such as list = {{1, "world"}, {0, "universe"}, {2, "country"}}, the following three statements are almost equivalent.

SortBy[list,#[[1]]&]
list~SortBy~First
Sort@list

Combine Select and SortBy

Sometimes we need to pick entries out of a larger set and sort them to find a minimum / maximum. Under some circumstances, two operations could be combined into one.

For example, for a minimum, the following two statements are almost equivalent.

SortBy[Select[l,SomeFormula==SomeConstant&],SortValue&]
SortBy[l,SortValue+99!(SomeFormula-SomeConstant)^2&]

and

SortBy[Select[l,SomeFormula!=SomeConstant&],SortValue&]
SortBy[l,SortValue+1/(SomeFormula-SomeConstant)&]

1/0 is ComplexInfinity, which is "larger" than all real numbers.

For a key-value list, for example:

{SortValue,#}&/@SortBy[Select[l,SomeFormula==SomeConstant],SortValue&]
Sort[{SortValue+99!(SomeFormula-SomeConstant)^2,#})&/@l]
\$\endgroup\$
2
\$\begingroup\$

Know when (and when not) to use named pure function arguments

For code golf, pure Function arguments are most commonly referenced using Slots; e.g. # for the first argument, #2 for the second, etc. (see this answer for more details).

In many cases, you will want to nest Functions. For example, 1##&@@#& is a Function which takes a list as its first argument and outputs the product of its elements. Here is that function in TreeForm:

enter image description here

Arguments passed to the top level Function can only fill Slots and SlotSequences present at the top level, which in this case means that the SlotSequence in the inner Function will not have any way of accessing arguments to the top level Function.

In some cases, though, you may want a Function nested within another Function to be able to reference arguments to the outer Function. For example, you may want something like Array[fun,...]&, where the function fun depends on an argument to the top level Function. For concreteness, let's say that fun should give the remainder of the square of its input modulo the input to the top level Function. One way to accomplish this is to assign the top level argument to a variable:

(x=#;Array[Mod[#^2,x]&,...])&

Wherever x appears in the inner Function Mod[#^2,x]&, it will refer to the first argument to the outer Function, whereas # will refer to the first argument to the inner Function. A better approach is to use the fact that Function has a two argument form where the first argument is a symbol or list of symbols that will represent named arguments to the Function (as opposed to unnamed Slots). This ends up saving us three bytes in this case:

xArray[Mod[#^2,x]&,...]

is the three byte private use character U+F4A1 representing the binary infix operator \[Function]. You may also use the binary form of Function within another Function:

Array[xMod[x^2,#],...]&

This is equivalent to the above. The reason is that, if you are using named arguments, then Slots and SlotSequences are assumed to belong to next Function above which does not use named arguments.

Now just because we can nest Functions in this way, doesn't mean we always should. For example, if we wanted to pick out those elements of a list that are less than the input, we might be tempted to do something like the following:

Select[...,xx<#]&

It would actually be shorter to use Cases and avoid the need for a nested Function entirely:

Cases[...,x_/;x<#]&
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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