Hot answers tagged

45

Some tips: In R, it's recommended to use <- over =. For golfing, the opposite holds since = is shorter... 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) Partial matching can be your friend, especially when functions return lists which you only need ...


25

72 96 characters. `c`<-function(...){list(...)[[-1]];}->>`c`;`[`=0;`]`=10;c(c,c)(c,c)(c,invisible)(`[`[]:`]`[])[]; Ugliness: Reusing a standard function name Using symbols as variable names Global assignment Right assignment Self-redefinition of function Unnecessary trailing semicolon(s) Unnecessary sub-scripting numbers Unnecessary quoting of ...


23

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. This is trivial but a rule of thumb for when to use @Tommy's trick of aliasing a function: if your function name has ...


20

Some very specific golfing tips: if you need to extract the length of a vector, sum(x|1) is shorter than length(x) as long as x is numeric, integer, complex or logical. if you need to extract the last element of a vector, it may be cheaper (if possible) to initialise the vector backwards using rev() and then calling x[1] rather than x[length(x)] (or using ...


18

Abuse the builtins T and F. By default, they evaluate to TRUE and FALSE, which can be automatically converted to numerics 1 and 0, and they can be re-defined at will. This means that you don't need to initialize a counter (e.g. i=0 ... i=i+1), you can just use T or F as needed (and jump straight to F=F+1 later). Remember that functions return the last object ...


14

Using if, ifelse, and `if` There are several ways to do if-statements in R. Golf-optimal solutions can vary a lot. The basics if is for control flow. It is not vectorized, i.e. can only evaluate conditions of length 1. It requires else to (optionally) return an else value. ifelse is a function. It is vectorized, and can return values of arbitrary length. ...


13

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 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=...


11

Implicit type conversion The functions as.character, as.numeric, and as.logical are too byte-heavy. Let's trim them down. Conversion to logical from numeric (4 bytes) Suppose x is a numeric vector. Using the logical not operator ! implicitly recasts the numeric to a logical vector, where 0 is FALSE and nonzero values are TRUE. ! then inverts that. x=!x ...


11

Do-while loops in R Occasionally, I find myself wishing R had a do-while loop, because: some_code while(condition){ some_code # repeated } is far too long and very un-golfy. However, we can recover this behavior and shave off some bytes with the power of the { function. { and ( are each .Primitive functions in R. The documentation for them reads: ...


11

My best two attempts so far only got me down to 11 characters. I'd love to see fewer than @Spacedman's 10! >sum( `[<-`(x,,,1) ) [1] 15600 >sum(!(F&x)) [1] 15600 Got it! sum(x^0) [1] 15600


10

Naive: > nrow(x)*ncol(x) [1] 15600 First idea: > prod(dim(x)) [1] 15600 Best I can do so far: > length(!x) [1] 15600 SimonO10 on the R chat had an idea (sum(!(F&x))), which I modded to get: > sum(T|x) [1] 15600 Note this doesn't work on factors, but you excepted those.


10

Abuse outer to apply an arbitrary function to all the combinations of two lists. Imagine a matrix with i, j indexed by the first args, then you can define an arbitrary function(i,j) for each pair. Use Map as a shortcut for mapply. My claim is that mapply is cheaper than a for loop in situations where you need to access the index. Abuse the list structure in ...


10

Save values in-line: Others have mentioned that you can pass values in-order and assign them for use elsewhere, i.e. sum(x<- 1:10, y<- seq(10,1,2)) However, you can also save values inline for use in the same line! For instance n=scan();(x=1:n)[abs(x-n/2)<4] reads from stdin, creates a variable x=1:n, then indexes into x using that value of x. ...


8

Some basic concepts but should be somewhat useful: In control flow statements you can abuse that any number not equal to zero will be evaluated as TRUE, e.g.: if(x) is equivalent to if(x!=0). Conversely, if(!x) is equivalent to if(x==0). When generating sequences using : (e.g. 1:5) one can abuse the fact that the exponentiation operator ^ is the only ...


8

Change the meaning of operators R operators are just functions that get special treatment by the parser. For example < is actually a function of two variables. These two lines of code do the same thing: x < 3 `<`(x, 3) You can reassign another function to an operator, and the parser will still do it's thing, including respecting operator ...


7

Generate a sequence from 0 to 10. 100 characters {.=0;for(`~1` in c(1,2,3,4,5,6,7,8,9,10)){.=c(., `~1`,recursive=F)};print(unname(.[drop=T]));rm(.)} [1] 0 1 2 3 4 5 6 7 8 9 10


7

R, 24 23 22 20 bytes diag(0,6)+c(!-1:4,1) Try it online! Just use R's recycling! This does give a warning, but otherwise is fine. Thanks to Robin Ryder for the 2 byte golf.


6

Mathematica This is done in Mathematica, but it may give you some ideas as to how to implement it in R. hearts = Table[ With[{v = RotationTransform[\[Theta], {0, 0, 1}][{3, 0, -.2}]}, ContourPlot3D[(2 (4/3 x)^2 + 2 y^2 + z^2 - 1)^3 - (4/3 x)^2 z^3/ 10 - y^2 z^3, {x, -2, 2}, {y, -2, 2}, {z, -2, 2}, MaxRecursion -> 6, Mesh -> None, ...


5

When you do need to use a function, use pryr::f() instead of function(). Example: function(x,y){x+y} is equivalent to pryr::f(x,y,x+y) or, even better, pryr::f(x+y) Since If there is only one argument, the formals are guessed from the code.


5

R, 30 27 bytes +!abs(outer(1:6,1:6,`-`))-1 Try it online! Another alternative. Note this matrix shows which integers between 1 and 6 are exactly 1 apart. (i.e. \$|i - j| = 1\$). Thanks to @RobinRyder for saving a byte! I was forgetting + could be used as a unary operator. Thanks also to @Giuseppe for saving 2 bytes! If a matrix of logical values is ...


5

100 characters: Generate a sequence from 1 to 10. Note that the numbers 2-10 are NOT in the code... - Bonus points? :-) Also note that it uses lapply for maximum performance :) unlist(lapply(LETTERS[-(11:26)],function(x) as.integer(charToRaw(x))-as.integer(charToRaw('A'))+1L)) #[1] 1 2 3 4 5 6 7 8 9 10


5

Alternatives to rep() Sometimes rep() can be avoided with the colon operator : and R's vector recycling. For repeating n zeroes, where n>0, 0*1:n is 3 bytes shorter than rep(0,n) and !1:n, an array of FALSE, is 4 bytes shorter, if the use case allows it. To repeat x n times, x+!1:n is 2 bytes shorter than rep(x,n). For n ones, use !!1:n if you can use ...


5

Scenarios where you can avoid paste(...,collapse="") and strsplit These are a pain in the usual string challenges. There are some workarounds. Reduce(paste0,letters) for -5 bytes from paste0(letters,collapse="") A 2-byte golf where you have a list containing two vectors c(1,2,3) and c(4,5,6) and want to concatenate them element-wise to a string "142536". ...


4

R, 34 bytes x=cbind(rbind(0,diag(5)),0) x+t(x) Try it online! Outputs [,1] [,2] [,3] [,4] [,5] [,6] [1,] 0 1 0 0 0 0 [2,] 1 0 1 0 0 0 [3,] 0 1 0 1 0 0 [4,] 0 0 1 0 1 0 [5,] 0 0 0 1 0 1 [6,] 0 0 0 0 1 0 Builds a \$5\times5\$ diagonal matrix, ...


4

Some ways to find the first non-zero element of an array. If it has a name x: x[!!x][1] Returns NA if no non-zero elements (including when x is empty, but not NULL which errors.) Anonymously: Find(c, c(0,0,0,1:3)) Returns NULL if no non-zero elements, or empty or NULL.


3

Surviving challenges involving strings As mentioned in another answer, unlist(strsplit(x,split="") and paste(...,collapse="") can be depressing. But don't just walk away from these, there are workarounds! utf8ToInt converts a string to a vector, intToUtf8 does the reverse operation. You're getting a vector of int, not a vector of char but sometimes this is ...


2

100 characters assign("a",1:10);b<<-paste(c(a),collapse=";");unlist(lapply(strsplit(b,";")[[1]],function(c)c[[1]])) Not sure if lapply on strsplit is a negative example but it sure should be. Returns as a character: [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"


2

Tips for restricted source challenges : Characters in R literals constants can be replaced by hex codes, octal codes and unicodes. e.g. the string "abcd" can be written : # in octal codes "\141\142\143\144" # in hex codes "\x61\x62\x63\x64" # in unicodes "\u61\u62\u63\u64" # or "\U61\U62\U63\U64" We can also mix ...


1

Do computation in default arguments This can save on braces if the function can be reduced to one statement. A silly example function(x,y,a=x*x+y*y,b=a+x+y)a*b+a+b


1

I(cumsum(Reduce("sum", replicate(paste0(as.integer(T),as.integer(T)), T), accumulate=1-F) - T >0)) should have slightly less than 100 characters and somehow produce 0:10


Only top voted, non community-wiki answers of a minimum length are eligible