Ctrl+P again to print, arrows/tab to navigate results, Enter to confirm, Ctrl+Enter to open in new tab.

    The following covers some common tricks for golfing R on code.golf. In general it is recommended to check out the documentation pages as well (Type ?name into an R REPL or view the online version). Many functions have a collection of optional parameters that can come in useful at times. While this guide tries to be somewhat complete, you might find some additional ideas on "Tips for golfing in R" on CGSE. Also browse that site for public solutions in R.

    Looping

    The usual for(x in ...) is usually used, but array manipulation is often used to golf bytes off. For example:

    for(x in commandArgs(T))write(x*50,1)
    write(commandArgs(T)*50,1,1)
    

    If explicit loops are required, sometimes Map, Reduce, lapply and related functions can be shorter than a for loop.

    Strings

    Type Conversion

    Some examples of using coercion to avoid using long functions:

    as.integer("19")
    strtoi("19")
    ("19":1)[1]
    el("19":1)
    x="19";x:x
    
    # x:x also often replaces x[1] to get the first element of a list of integers
    
    as.character(19)
    x=19;x[0]="";x
    c("",19)[2]
    paste(19)
    

    Splitting Strings

    For parsing a sequence of numbers from a single input string, scan is quite useful:

    # numbers separated by whitespace
    scan(t="1 2\n3")
    
    # other separator
    scan(t="1,2,3",se=",")
    

    Depending on the scenario, you can add extra commas to pad out the arguments. This saves bytes only if there are other arguments besides sep, and works for both scan and write.

    write(x,1,se=",")
    write(x,1,,,",")
    

    If you need to split a string into multiple strings:

    # separated by whitespace
    scan(,"",t="abc def") # "" can be any string
    
    # other separator
    el(strsplit("abc,def",","))
    scan(,"","abc,def",se=",")
    

    Iterating over characters

    If you need to iterate over the characters in a string, it is often advantageous to work with Unicode code points instead:

    y=utf8ToInt("the lazy fox ...")
    # transform y, then back to string:
    cat(intToUtf8(y))
    

    Otherwise you can split the string into characters (see above) and join back into a string:

    Reduce(paste0,c("a","b","c"))
    paste0(c("a","b","c"),collapse="")
    
    # or, ideally print without joining:
    write(c("a","b","c"),1,9,,"")
    cat(c("a","b","c"),"\n",sep="")
    

    Regex

    Regular expressions are quite useful because they can be directly applied to strings without first needing to split them.

    gsub and grepl are probably the most useful, see the docs page for a full list of available functions.

    Output

    There are multiple functions commonly used to produce output:

    # write the values of X to STDOUT (1)
    # for strings, this writes one value per line, for numbers multiple per line
    write(X,1)
    # write the values of X to STDOUT, 2 per line, separated by a comma
    write(X,1,2,,",")
    
    # conditionally write the values of X to
    # STDOUT (1), if cond is FALSE
    # STDERR (2), if cond is TRUE, these values are ignored by the judge on this site
    write(X,1+cond)
    # same idea, inverted condition:
    write(X,2-cond)
    
    # cat does not implicitly print a newline, and takes multiple arguments to print
    # by default it separates values by a space
    cat(1:4,"
    ")
    # cat has some keyword-only parameters:
    cat(...,fill=1) # print one value per line
    cat(...,sep=",") # separate values by comma
    
    # dput prints a representation of the value to STDOUT, and returns the value
    y=2*dput(x)
    # this is especially useful for printing integers, but you might need to convince the value to have the right internal type:
    dput(0+x)
    # Because dput returns a value that can be used in a boolean context, it allows for this form of conditional output:
    cond&&dput(x)
    

    When outputting with paste0 to join a vector into a string by nothing:

    write(paste0(vector),1)
    cat(vector,"
    ",sep="")
    

    If you are outputting three args to cat, you can abuse the sep function, but note that only strings can be used in it and that x and y cannot be vectors and have to be strings or this won't work:

    cat(x,"/",y,sep="")
    cat(x,y,sep="/")
    

    Conditional statements

    The if statements that are commonly used:

    "if"(cond,x,y)
    c(y,x)[1+(cond)] # often equivalent: c(y,x)[2-!cond]
    

    "if" usually beats using vector indexing because you don't need to put >0, and using a list requires turning the condition into an integer and adding 1 since R uses base 1-index vectors.

    Vector indexing is occasionally used though in replacement of rep. Say we want to print a string if a condition is true:

    rep(str,cond)
    str[cond]
    

    Using [] will ensure that if the condition is true it will return the entire string and if not nothing. This works with multiple items too:

    cat(paste0(rep(c("o",str),cond)))
    cat(paste0(c("o",str)[cond]))
    cat(c("o",str)[cond],sep="")
    

    For conditionally printing one value, see the Output section.

    Builtins

    R, as a statistical language, has tons of builtins and functions that are very useful when golfing. Sometimes these can be creatively repurposed, for example: !sd(x) is TRUE if all values in x are the same.

    Here are is a list of potentially useful builtins:

    seq
    diff
    rle                # Run Length Encoding
    embed
    gl                 # Generate factors by specifying the pattern of their levels
    letters            # 'a','b','c'...
    LETTERS            # 'A','B','C'...
    month.abb          # 'Jan','Feb','Mar'...
    month.name         # 'January','February','March'...
    T, F               # TRUE, FALSE
    filter             # 1-d convolution & autoregressive filter
    cumsum             
    

    T and F can be used as variables that are already initialized to 1 or 0 at the start of your code.

    Aliases

    We can define short aliases for functions using backticks for two arguments using primitive operators:

    `+`=paste
    x+y                # paste(x,y)
    

    (There is a way to define a short alias for functions with 3 or more arguments)

    The defined aliases will inherit the precedence/parsing rules from the symbols they are defined to; an overview of the precedences can be found on the Syntax page. Choosing the right symbol can therefore minimize the number of required parentheses. One particularly interesting case is ?, which can be called with one or two arguments and binds lower than almost anything else in the language, apart from punctuation like ,, ; and newlines. One use case is aliasing Map if you have a lot of loops (you need to avoid the implicit output though):

    `?`=Map
    \(x)do_stuff(x)?1:10      # parses as `?`(\(x)do_stuff(x),1:10)
    # vs
    for(x in 1:10)do_stuff(x)
    

    Arrays

    While R allows writing solutions like in other languages with for and while loops or recursive functions, it can be shorter in some cases to use R's array processing capabilities instead.

    x%o%y computes the outer product of two arrays, basically a multiplication table for two vectors. outer is the generalized version of this where you can replace the multiplication with any other arithmetic operation:

    > x=1:3
    > x%o%x
         [,1] [,2] [,3]
    [1,]    1    2    3
    [2,]    2    4    6
    [3,]    3    6    9
    > outer(x,x,"+")
         [,1] [,2] [,3]
    [1,]    2    3    4
    [2,]    3    4    5
    [3,]    4    5    6
    

    %*% implements matrix multiplication. Besides the usual matrix-matrix and matrix-vector product, it also computes the inner product for two vectors: x%*%y == sum(x*y). Syntactically these operators (and %x% for Kronecker product) bind with the same strength as %% and %/%, only x^y and unary -x and +x bind tighter among arithmetic operations.

    Applying normal arithmetic operations between two vectors of different lengths cycles the shorter vector to match the other length:

    > 1:10 * 0:1
     [1]  0  2  0  4  0  6  0  8  0 10
    

    As an exercise, using these techniques it is possible to do the following in 15 bytes: Given a single-letter variable holding 1:n, compute a vector containing $\sigma(i), i=1..n$, the sums of divisors of these numbers

    > x=1:10
    > ???????????????
    [1] 1  3  4  7  6 12  8 15 13 18
    

    Many sequence holes have solutions that look like write(...,x<-1:100,1).

    rep() alternatives

    Even though rep() is already fairly short, we can save a few more bytes by using : and vector recycling.

    Repeating n zeroes (n>0) - !1:n or 0*1:n instead of rep(0,n)

    Repeating n ones - !!1:n instead of rep(1,n)

    Repeating x n times - x+!1:n instead of rep(x,n)

    Using modular arithmetic to avoid each args in rep

    There aren't too many uses of this, but when you encounter one, you will probably need some creativity to come up with some "formula".

    Generating the vector c(-1,-1,-1,0,0,0,1,1,1) is easily done with rep(-1:1,e=3), but you can use modular arithmetic to save bytes:

    -3:5%/%3
    

    Datasets

    Random Tips

    Packers

    3:1

    eval(parse(t=intToUtf8(rep(utf8ToInt("..."),e=3)%%97:99+32)))
    

    2:1

    eval(parse(t=iconv("...",,"ucs2")))