Take the 2-minute tour ×
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.

I'm looking for tips for golfing in the R statistical language. R is perhaps an unconventional choice for Golf. However, it does certain things very compactly (sequences, randomness, vectors, and lists), many of the built-in functions have very short names, and it has an optional line terminator (;). What tips and tricks can you give to help solve code golf problems in R?

share|improve this question

3 Answers 3

up vote 17 down vote accepted

Some tips:

  1. In R, it's recommended to use <- over =. For golfing, the opposite holds since = is shorter...
  2. If you call a function more than once, it is often beneficial to define a short alias for it:

    as.numeric(x)+as.numeric(y)
    
    a=as.numeric;a(x)+a(y)
    
  3. Partial matching can be your friend, especially when functions return lists which you only need one item of. Compare rle(x)$lengths to rle(x)$l

  4. Many challenges require you to read input. scan is often a good fit for this (the user ends the input by entring an empty line).

    scan()    # reads numbers into a vector
    scan(,'') # reads strings into a vector
    
  5. Coercion can be useful. t=1 is much shorter than t=TRUE. Alternatively, switch can save you precious characters as well, but you'll want to use 1,2 rather than 0,1.

    if(length(x)) {} # TRUE if length != 0
    sum(x<3)         # Adds all the TRUE:s (count TRUE)
    
  6. If a function computes something complicated and you need various other types of calculations based on the same core value, it is often beneficial to either: a) break it up into smaller functions, b) return all the results you need as a list, or c) have it return different types of values depending on an argument to the function.

  7. As in any language, know it well - R has thousands of functions, there is probably some that can solve the problem in very few characters - the trick is to know which ones!

Some obscure but useful functions:

sequence
diff
rle
embed
gl - Like rep(seq(),each=...) but returns a factor

Some built-in data sets and symbols:

letters     # 'a','b','c'...
LETTERS     # 'A','B','C'...
month.abb   # 'Jan','Feb'...
month.name  # 'January','Feburary'...
T           # TRUE
F           # FALSE
pi          # 3.14...
share|improve this answer
  1. You can assign a variable to the current environment while simultaneously supplying it as an argument to a function:

    sum(x <- 4, y <- 5)
    x
    y
    
  2. If you are subseting a data.frame and your condition depends on several of its columns, you can avoid repeating the data.frame name by using with (or subset).

    d <- data.frame(a=letters[1:3], b=1:3, c=4:6, e=7:9)
    with(d, d[a=='b' & b==2 & c==5 & e==8,])
    

    instead of

    d[d$a=='b' & d$b==2 & d$c==5 & d$e==8,]
    

    Of course, this only saves characters if the length of your references to the data.frame exceeds the length of with(,)

  3. if...else blocks can return the value of the final statement in which ever part of the block executes. For instance, instead of

    a <- 3
    if (a==1) y<-1 else
    if (a==2) y<-2 else y<-3
    

    you can write

    y <- if (a==1) 1 else 
         if (a==2) 2 else 3
    
share|improve this answer
1  
Only caution about (1) is that when you do that you're passing it in by order not by named arguments. If f <- function(a,b) cat(a,b), then f(a <- 'A', b <- 'B') is not the same as f(b <- 'B', a <- 'A'). –  Ari B. Friedman Oct 15 '13 at 13:11
  1. Instead of importing a package with library, grab the variable from the package using :: . Compare the followings:

    library(splancs);inout(...)
    splancs::inout(...)
    

    Of course, it is only valid if one single function is used from the package.

  2. This is trivial but a rule of thumb for when to use @Tommy's trick of aliasing a function: if your function name has a length of m and is used n times, then alias only if m*n > m+n+3 (because when defining the alias you spend m+3 and then you still spend 1 everytime the alias is used). An example:

    nrow(a)+nrow(b)     # 4*2 < 4+3+2
    n=nrow;n(a)+n(b)
    length(a)+length(b) # 6*2 > 6+3+2
    l=length;l(a)+l(b)
    
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.