R에서의 골프 팁 콤팩트하게 만들고

R 통계 언어로 골프 팁을 찾고 있습니다. R은 아마도 골프를위한 비 전통적인 선택 일 것입니다. 그러나 특정 작업 (시퀀스, 임의성, 벡터 및 목록)을 매우 콤팩트하게 만들고 많은 내장 함수는 매우 짧은 이름 을 가지며 선택적 줄 종결 자 (;)가 있습니다. R의 코드 골프 문제를 해결하는 데 도움이되는 팁과 요령은 무엇입니까?



답변

몇 가지 팁 :

  1. R에서는 <-over 를 사용 하는 것이 좋습니다 =. 골프의 경우 반대 입장 =이 짧아 지기 때문에 …
  2. 함수를 두 번 이상 호출하면 짧은 별칭을 정의하는 것이 유리합니다.

    as.numeric(x)+as.numeric(y)
    
    a=as.numeric;a(x)+a(y)
    
  3. 부분 매칭은 친구가 될 수 있습니다. 특히 함수가 하나의 항목 만 필요한 목록을 반환 할 때 더욱 그렇습니다. 비교
    rle(x)$lengthsrle(x)$l

  4. 많은 과제는 입력을 읽어야합니다. scan사용자는 종종 빈 줄을 입력하여 입력을 종료합니다.

    scan()    # reads numbers into a vector
    scan(,'') # reads strings into a vector
    
  5. 강제가 유용 할 수 있습니다. t=1보다 훨씬 짧습니다 t=TRUE. 또는 switch귀중한 문자를 저장할 수도 있지만 0,1 대신 1,2를 사용하는 것이 좋습니다.

    if(length(x)) {} # TRUE if length != 0
    sum(x<3)         # Adds all the TRUE:s (count TRUE)
    
  6. 함수가 복잡한 것을 계산하고 동일한 핵심 값을 기반으로 다양한 다른 유형의 계산이 필요한 경우 a) 작은 함수로 나누고 b) 필요한 모든 결과를 목록으로 반환하거나 c) 함수에 대한 인수에 따라 다른 유형의 값을 반환합니다.

  7. 다른 언어와 마찬가지로 잘 알고 있습니다. R에는 수천 개의 기능이 있으며, 문자가 거의없는 경우 문제를 해결할 수있는 기능이있을 수 있습니다.

애매하지만 유용한 기능들 :

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

일부 내장 데이터 세트 및 기호 :

letters     # 'a','b','c'...
LETTERS     # 'A','B','C'...
month.abb   # 'Jan','Feb'...
month.name  # 'January','Feburary'...
T           # TRUE
F           # FALSE
pi          # 3.14...

답변

  1. 로 패키지를 가져 오는 대신을 library사용하여 패키지에서 변수를 가져옵니다 ::. 다음을 비교하십시오.

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

    물론 패키지에서 하나의 단일 기능을 사용하는 경우에만 유효합니다.

  2. 이것은 사소한이지만 기능을 앨리어싱의 토미의 트릭 @ 사용하는 경우에 대한 엄지 손가락의 규칙 : 함수 이름의 길이가있는 경우 m와 사용 n후 경우에만 별칭 시간을 m*n > m+n+3지출 별칭을 정의 할 때 (때문에 m+3다음 당신은 여전히 지출 별명이 사용될 때마다 1). 예를 들면 :

    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)
    
  3. 기능의 부작용으로 강요 :

    • 를 사용하는 대신 다음을 사용하여 as.integer문자열을 정수로 강제 변환 할 수 있습니다 :.

      as.integer("19")
      ("19":1)[1] #Shorter version using force coercion.
      
    • 정수, 숫자 등은 다음 paste대신에 문자를 사용하여 비슷하게 강제 할 수 있습니다 as.character.

      as.character(19)
      paste(19) #Shorter version using force coercion.
      

답변

매우 구체적인 골프 팁 :

  • 당신이 벡터의 길이를 추출해야하는 경우, sum(x|1)보다 짧은 length(x)만큼 x, 숫자의 정수, 복잡하거나 논리적이다.
  • 당신이 벡터의 마지막 요소를 추출해야하는 경우, 그것은 (가능하다면) 벡터 초기화하는 저렴 수 있습니다 뒤쪽으로 사용 rev()하고 호출 x[1]보다는 x[length(x)](또는 위의 팁을 사용 x[sum(x|1)]) (또는 tail(x,1)— 감사 주세페을!). 이것에 대한 약간의 변형 (두 번째 마지막 요소가 필요한 곳)이 여기에서 볼 수 있습니다 . 벡터를 뒤로 초기화 할 수 없더라도 rev(x)[1]여전히 짧습니다 x[sum(x|1)](및 문자 벡터에서도 작동합니다). 때로는 대신을 rev사용 n:1하는 등의 필요조차 없습니다 1:n.
  • ( 여기에서 볼 수 있듯이 ). 데이터 프레임을 행렬로 강제 변환하려면을 사용하지 마십시오 as.matrix(x). 조옮김의 조옮김 t(t(x)).

  • if공식적인 기능입니다. 예를 들어, "if"(x<y,2,3)보다 짧습니다 if(x<y)2 else 3(물론 3-(x<y)둘 중 하나보다 짧습니다). 이런 식으로 공식화하기 위해 추가 괄호 쌍이 필요하지 않은 경우에만 문자를 저장합니다.

  • 동일하지 않은 숫자 객체를 테스트하는 if(x-y)경우보다 짧습니다 if(x!=y). 0이 아닌 숫자는로 간주됩니다 TRUE. 평등을 테스트하는 경우 대신 if(x==y)a else b시도하십시오 if(x-y)b else a. 또한 이전 요점을 참조하십시오.

  • 이 기능 el은 목록에서 항목을 추출해야 할 때 유용합니다. 가장 일반적인 예는 아마도 strsplit: el(strsplit(x,""))이상 적은 바이트입니다 strsplit(x,"")[[1]].

  • ( 여기에 사용됨 ) 벡터 확장은 문자를 절약 할 수 있습니다. 벡터 v길이가 길면 오류없이 n할당 할 수 있습니다 v[n+1]. 첫 번째 열 계승을 인쇄하고 싶었 예를 들어, 당신은 할 수 : v=1;for(i in 2:10)v[i]=v[i-1]*i보다는 v=1:10:for(...)(언제나처럼, 또 다른, 더 나은 방법이 있지만 : cumprod(1:10))

  • 때로는 텍스트 기반 문제 (특히 2D 문제)의 plot경우 텍스트보다 텍스트가 더 쉽습니다 cat. 어떤 문자가 그려 지는지 pch=plot제어하는 인수 . 이것은 pc=바이트를 절약하기 위해 단축 될 수 있습니다 (경고를 줄 것입니다). 여기에 예가 있습니다 .

  • 숫자를 바닥에 쓰려면을 사용하지 마십시오 floor(x). x%/%1대신 사용하십시오 .

  • 숫자 형 벡터 나 정수형 벡터의 요소가 모두 같은지 테스트하려면 sd과 같은 장황한 것이 아니라 종종 사용할 수 있습니다 all.equal. 모든 요소가 동일하면 표준 편차가 0 ( FALSE) 이고 표준 편차가 양수 ( TRUE)입니다. 여기에 예가 있습니다 .

  • 정수 입력이 필요한 일부 함수는 실제로 필요하지 않습니다. 예를 들어, seq(3.5)리턴합니다 1 2 3( :연산자도 마찬가지입니다 ). 이것은 호출을 피할 수 floor있으며 때로는 /대신 대신 사용할 수 있음을 의미합니다 %/%.


답변

  1. 내장 매크로를 남용 T하고 F. 기본적으로 TRUEand로 평가되며 FALSE숫자 1및 로 자동 변환 0될 수 있으며 마음대로 재정의 할 수 있습니다. 즉, 카운터를 초기화 할 필요가 없습니다 (예 : i=0i=i+1) T또는 F필요에 따라 사용 하거나 F=F+1나중에 바로 이동할 수 있습니다 .
  2. 함수는 마지막으로 return()호출 된 객체를 반환하므로 명시적인 호출이 필요하지 않습니다 .
  3. 일반적으로 사용되는 함수에 대한 짧은 별칭을 정의하는 것이 좋습니다 p=paste. 함수를 많이 사용하고 정확히 두 개의 인수 를 사용하면 별칭이 붙으면 일부 바이트가 절약 될 수 있습니다. 삽입 별명은로 묶어야합니다 %. 예를 들면 다음과 같습니다.

    `%p%`=paste

    그리고 이후 x%p%y1 바이트보다 짧은 것 p(x,y)입니다. 그래도 별명 정의는 비고 정보 다 4 바이트 더 길 p=paste므로 그 가치가 있는지 확인해야합니다.


답변

사용 if, ifelse`if`

R.에서 if-statement를 수행하는 방법은 여러 가지가 있습니다. 골프 최적화 솔루션은 크게 다를 수 있습니다.

기본

  1. if제어 흐름입니다. 벡터화되지 않습니다. 즉, 길이 1의 조건 만 평가할 수 있습니다. else선택적으로 else 값을 반환해야합니다.
  2. ifelse함수입니다. 벡터화되어 임의 길이의 값을 반환 할 수 있습니다. 세 번째 주장 (다른 가치)은 의무적입니다. *
  3. `if`와 구문이 동일한 함수 ifelse입니다. 벡터화되지 않았으며 반환 인수가 의무화되지 않았습니다.

* 기술적으로 의무적 인 것은 아닙니다. ifelse(TRUE,x)잘 작동하지만 세 번째 인수가 비어 있고 조건이로 평가되면 오류가 발생합니다 FALSE. 따라서 조건이 항상 확실하다고 확신하는 경우에만 사용하는 것이 안전하며 TRUE, 그러한 경우 if 문으로 귀찮게하는 이유는 무엇입니까?

이들은 모두 동등합니다 :

if(x)y else z # 13 bytes
ifelse(x,y,z) # 13 bytes
`if`(x,y,z)   # 11 bytes

else코드에서 직접 문자열을 사용하는 경우 공백 이 필요하지 않습니다.

if(x)"foo"else"bar"   # 19 bytes
ifelse(x,"foo","bar") # 21 bytes
`if`(x,"foo","bar")   # 19 bytes

지금까지 `if`입력을 벡터화하지 않은 한 승자가 될 것으로 보입니다. 그러나 else 조건에 관심이없는 경우는 어떻습니까? 조건이 인 경우 일부 코드 만 실행하려고한다고 가정 해보십시오 TRUE. 한 줄의 코드만으로도 if가장 좋습니다.

if(x)z=f(y)         # 11 bytes
ifelse(x,z<-f(y),0) # 19 bytes
`if`(x,z<-f(y))     # 15 bytes

여러 줄의 코드에서 if여전히 승자가됩니다.

if(x){z=f(y);a=g(y)}        # 20 bytes
ifelse(x,{z=f(y);a=g(y)},0) # 27 bytes
`if`(x,{z=f(y);a=g(y)})     # 23 bytes

이 우리가 가능성이기도 않는 다른 조건에 대한 관심은, 우리는 임의의 코드를 실행하는 대신 값을 반환 할 위치. 이러한 경우, if`if`바이트 수에 동일합니다.

if(x)a=b else z=b   # 17 bytes
ifelse(x,a<-b,z<-b) # 19 bytes
`if`(x,a<-b,z<-b)   # 17 bytes

if(x){z=y;a=b}else z=b   # 22 bytes
ifelse(x,{z=y;a=b},z<-b) # 24 bytes
`if`(x,{z=y;a=b},z<-b)   # 22 bytes

if(x)a=b else{z=b;a=y}   # 22 bytes
ifelse(x,a<-b,{z=b;a=y}) # 24 bytes
`if`(x,a<-b,{z=b;a=y})   # 22 bytes

if(x){z=y;a=b}else{z=b;a=y}   # 27 bytes
ifelse(x,{z=y;a=b},{z=b;a=y}) # 29 bytes
`if`(x,{z=y;a=b},{z=b;a=y})   # 27 bytes

요약

  1. ifelse길이가 1보다 큰 입력을 사용하는 경우 사용하십시오 .

  2. 많은 코드 줄을 실행하지 않고 간단한 값을 반환하는 경우 `if`함수를 사용하는 것이 full ifelse문 보다 짧을 수 있습니다.

  3. 언제 단일 값을 원하면을 TRUE사용하십시오 if.

  4. 임의의 코드를 실행 `if`하고 if일반적 바이트 개수의 관점에서 동일하다; 나는 if주로 읽기 쉽기 때문에 추천 합니다.


답변

  1. 변수를 함수에 대한 인수로 제공하면서 동시에 현재 환경에 변수를 지정할 수 있습니다.

    sum(x <- 4, y <- 5)
    x
    y
  2. a를 부분 집합하고 data.frame조건이 여러 열에 의존 data.frame하는 경우 with(또는 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,])

    대신에

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

    물론 이것은 참조 data.frame길이가 길이를 초과하는 경우에만 문자를 저장합니다.with(,)

  3. if...else블록은 블록의 일부가 실행되는 최종 명령문의 값을 리턴 할 수 있습니다. 예를 들어

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

    당신은 쓸 수 있습니다

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

답변

암시 적 유형 변환

기능은 as.character, as.numeric그리고 as.logical너무 바이트 무겁습니다. 그것들을 다듬어 봅시다.

숫자 (4 바이트)에서 논리로 변환

x숫자 형 벡터 라고 가정하십시오 . 논리 not 연산자를 사용하면 !숫자가 암시 적으로 논리 벡터로 다시 캐스팅 됩니다 . 여기서 0is FALSE및 0이 아닌 값은 TRUE입니다. !그런 다음 반전시킵니다.

x=!x

x=0:3;x=!x을 반환합니다 TRUE FALSE FALSE FALSE.

숫자 또는 논리 (7 바이트)에서 문자로 변환

이것은 재미있는 것입니다. ( 이 트윗 에서)

x[0]=''

R 은 클래스 의 인 벡터 x를 업데이트하고 있음을 알았습니다 . 따라서 새로운 데이터 포인트와 호환되도록 클래스에 캐스트 됩니다 . 다음으로, 넣어 간다 적절한 장소에 …하지만 인덱스 (이 트릭도 함께 작동 존재하지 않는 , , , , 등). 결과적으로 클래스에서만 수정됩니다.''characterxcharacter''0InfNaNNANULLx

x=1:3;x[0]=''반환 "1" "2" "3"x=c(TRUE,FALSE);x[0]=''반환 "TRUE" "FALSE".

작업 공간에 이미 문자 오브젝트가 정의되어 있으면 ''바이트를 저장하는 대신이 를 사용할 수 있습니다 . 예 x[0]=y!

특정 조건 (6 바이트)에서 숫자 또는 논리 문자로 변환

J.Doe 는 주석에서 6 바이트 솔루션을 지적했습니다.

c(x,"")

x원자 인 경우 원자 벡터가 필요한 함수에 전달하려는 경우 작동합니다 . 이 함수는 인수의 요소를 무시하는 것에 대한 경고를 표시 할 수 있습니다.

논리 (4 바이트)에서 숫자로 변환

위에서 펑키 인덱싱 트릭을 사용할 수 x[0]=3있지만 실제로 더 빠른 방법이 있습니다.

x=+x

양의 연산자는 암시 적으로 벡터를 숫자 벡터로 다시 캐스팅하므로이 TRUE FALSE됩니다 1 0.