R 통계 언어로 골프 팁을 찾고 있습니다. R은 아마도 골프를위한 비 전통적인 선택 일 것입니다. 그러나 특정 작업 (시퀀스, 임의성, 벡터 및 목록)을 매우 콤팩트하게 만들고 많은 내장 함수는 매우 짧은 이름 을 가지며 선택적 줄 종결 자 (;)가 있습니다. R의 코드 골프 문제를 해결하는 데 도움이되는 팁과 요령은 무엇입니까?
답변
몇 가지 팁 :
- R에서는
<-
over 를 사용 하는 것이 좋습니다=
. 골프의 경우 반대 입장=
이 짧아 지기 때문에 … -
함수를 두 번 이상 호출하면 짧은 별칭을 정의하는 것이 유리합니다.
as.numeric(x)+as.numeric(y) a=as.numeric;a(x)+a(y)
-
부분 매칭은 친구가 될 수 있습니다. 특히 함수가 하나의 항목 만 필요한 목록을 반환 할 때 더욱 그렇습니다. 비교
rle(x)$lengths
에rle(x)$l
-
많은 과제는 입력을 읽어야합니다.
scan
사용자는 종종 빈 줄을 입력하여 입력을 종료합니다.scan() # reads numbers into a vector scan(,'') # reads strings into a vector
-
강제가 유용 할 수 있습니다.
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)
-
함수가 복잡한 것을 계산하고 동일한 핵심 값을 기반으로 다양한 다른 유형의 계산이 필요한 경우 a) 작은 함수로 나누고 b) 필요한 모든 결과를 목록으로 반환하거나 c) 함수에 대한 인수에 따라 다른 유형의 값을 반환합니다.
-
다른 언어와 마찬가지로 잘 알고 있습니다. 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...
답변
-
로 패키지를 가져 오는 대신을
library
사용하여 패키지에서 변수를 가져옵니다::
. 다음을 비교하십시오.library(splancs);inout(...) splancs::inout(...)
물론 패키지에서 하나의 단일 기능을 사용하는 경우에만 유효합니다.
-
이것은 사소한이지만 기능을 앨리어싱의 토미의 트릭 @ 사용하는 경우에 대한 엄지 손가락의 규칙 : 함수 이름의 길이가있는 경우
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)
-
기능의 부작용으로 강요 :
-
를 사용하는 대신 다음을 사용하여
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
있으며 때로는/
대신 대신 사용할 수 있음을 의미합니다%/%
.
답변
- 내장 매크로를 남용
T
하고F
. 기본적으로TRUE
and로 평가되며FALSE
숫자1
및 로 자동 변환0
될 수 있으며 마음대로 재정의 할 수 있습니다. 즉, 카운터를 초기화 할 필요가 없습니다 (예 :i=0
…i=i+1
)T
또는F
필요에 따라 사용 하거나F=F+1
나중에 바로 이동할 수 있습니다 . - 함수는 마지막으로
return()
호출 된 객체를 반환하므로 명시적인 호출이 필요하지 않습니다 . -
일반적으로 사용되는 함수에 대한 짧은 별칭을 정의하는 것이 좋습니다
p=paste
. 함수를 많이 사용하고 정확히 두 개의 인수 를 사용하면 별칭이 붙으면 일부 바이트가 절약 될 수 있습니다. 삽입 별명은로 묶어야합니다%
. 예를 들면 다음과 같습니다.`%p%`=paste
그리고 이후
x%p%y
1 바이트보다 짧은 것p(x,y)
입니다. 그래도 별명 정의는 비고 정보 다 4 바이트 더 길p=paste
므로 그 가치가 있는지 확인해야합니다.
답변
사용 if
, ifelse
및`if`
R.에서 if-statement를 수행하는 방법은 여러 가지가 있습니다. 골프 최적화 솔루션은 크게 다를 수 있습니다.
기본
if
제어 흐름입니다. 벡터화되지 않습니다. 즉, 길이 1의 조건 만 평가할 수 있습니다.else
선택적으로 else 값을 반환해야합니다.ifelse
함수입니다. 벡터화되어 임의 길이의 값을 반환 할 수 있습니다. 세 번째 주장 (다른 가치)은 의무적입니다. *`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
요약
-
ifelse
길이가 1보다 큰 입력을 사용하는 경우 사용하십시오 . -
많은 코드 줄을 실행하지 않고 간단한 값을 반환하는 경우
`if`
함수를 사용하는 것이 fullif
…else
문 보다 짧을 수 있습니다. -
언제 단일 값을 원하면을
TRUE
사용하십시오if
. -
임의의 코드를 실행
`if`
하고if
일반적 바이트 개수의 관점에서 동일하다; 나는if
주로 읽기 쉽기 때문에 추천 합니다.
답변
-
변수를 함수에 대한 인수로 제공하면서 동시에 현재 환경에 변수를 지정할 수 있습니다.
sum(x <- 4, y <- 5) x y
-
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(,)
-
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 연산자를 사용하면 !
숫자가 암시 적으로 논리 벡터로 다시 캐스팅 됩니다 . 여기서 0
is FALSE
및 0이 아닌 값은 TRUE
입니다. !
그런 다음 반전시킵니다.
x=!x
x=0:3;x=!x
을 반환합니다 TRUE FALSE FALSE FALSE
.
숫자 또는 논리 (7 바이트)에서 문자로 변환
이것은 재미있는 것입니다. ( 이 트윗 에서)
x[0]=''
R 은 클래스 의 인 벡터 x
를 업데이트하고 있음을 알았습니다 . 따라서 새로운 데이터 포인트와 호환되도록 클래스에 캐스트 됩니다 . 다음으로, 넣어 간다 적절한 장소에 …하지만 인덱스 (이 트릭도 함께 작동 존재하지 않는 , , , , 등). 결과적으로 클래스에서만 수정됩니다.''
character
x
character
''
0
Inf
NaN
NA
NULL
x
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
.