줄리아에서의 골프 팁


20

줄리아 골프에 대한 일반적인 팁은 무엇입니까? Julia에 대해 다소 특정한 코드 골프 문제에 적용 할 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다).

답변:


19

참고 : Julia는 구조 측면에서 아직 안정화되지 않았으므로 아래에 오래된 팁이 포함될 수 있습니다.

몇 문자를 저장하는 몇 가지 트릭

  1. 자주 사용되는 이진 함수를 사용하는 과부하 연산자 . 예를 들어, 많은 정수 나누기를 수행해야하고 역 나누기가 필요하지 않은 경우을 사용 \ =div하고 a\b대신 을 입력 할 수 있습니다 div(a,b). 공백에 유의하십시오- "\ ="연산자로 구문 분석되지 않도록해야합니다. 또한 REPL 프롬프트 레벨에서 오버로드 된 경우 (\)=Base.(\)또는 \ =Base. \을 사용 하여 재설정하십시오. 참고 : Alex A에서 언급 한 것처럼 일부 함수에는 ÷for 와 같이 미리 정의 된 기존 UTF-8 연산자가 있습니다 div.
  2. 조건부 출력을 위해 ^를 문자열과 함께 사용하십시오 . 즉, 1 바이트를 저장 a>0?"Hi":""하는 "Hi"^(a>0)데 사용 하거나 부울 a의 경우 "Hi"^a3 바이트를 저장 하는 데 사용 합니다.
  3. (때로는) 작은 고정 크기 벡터를 별도의 변수로 저장하십시오 . 예를 들어,보다는 a=split("Hi there"," "), 당신은 방지 할 수 있습니다 a[1]a[2]사용하여 a,b=split("Hi there"," ")로 참조 될 수있는 ab할당에서 두 추가 문자의 비용으로, 각 사용을위한 3 바이트를 절약. 벡터 연산으로 작업 할 수있는 경우에는이 작업을 수행하지 마십시오.
  4. []-for arrays를 사용하여 Array의 첫 번째 요소에 액세스 하면 표현식 A[]은와 동일합니다 A[1]. 첫 번째 문자를 얻으려면 문자열이나 Tuples에서는 작동하지 않습니다.
  5. 배열, 튜플 또는 문자열에 대해서는 빈 공간을 사용하지 마십시오. 대신 ==[]배열 및 ==()튜플에 사용하십시오. 마찬가지로, 음의 경우 !=[]및을 사용하십시오 !=(). 문자열의 경우 ""가 다른 문자열보다 사전 식으로되어 ==""있으므로 비어있는 경우 에는 사용 하고 비어 있지 않은 경우에는 사용하십시오 >"".
  6. "if"대신 올바른 단락 부울 연산자를 사용하십시오 . 줄리아 고유의 경우는 다소 적을 지 모르지만 염두에 둘 가치가 있습니다. 부울의 반환이 중요하지 않은 한, 문자를 저장하여 x<=1&&"Hi"로 쓸 수 있습니다 x>1||"Hi".
  7. 하지 마십시오 사용은 문자열에서 문자의 존재를 확인하기 위해 포함 - 당신은 기본 ASCII로 제한하는 경우, 사용 in('^',s)하기보다는 contains(s,"^"). 다른 문자를 사용할 수 있으면을 사용하여 조금 더 절약 할 수 '^'∈s있지만 UTF-8에서는 3 바이트입니다.
  8. 배열에서 최소 / 최대 값을 찾고 있습니까? 최소 또는 최대를 사용하지 마십시오 대신 사용하는 것보다 - minimum(x)또는 maximum(x), 사용 min(x...)또는 max(x...)당신이 알고있는 경우에, 당신의 코드를 해제 한 문자를 면도, x두 개 이상의 요소가됩니다. 또는 모든 요소가 x음이 아닌 것으로 알고 있다면 minabs(x)또는maxabs(x)
  9. 가능하고 도전 과제에 의해 허용되는 경우 \ n 대신 실제 줄 바꿈을 사용 하십시오. 이렇게하면 코드를 읽기가 어려워지고 사람들이 실제로 이해할 수 있도록 "고용되지 않은"버전을 제공해야 할 수도 있습니다. 그것.
  10. 정규식 문자열 뒤에 옵션을 입력하십시오. 예를 들어, 다중 문자 모드에서 정규식 문자열을 사용하려는 경우, type r"(?m)match^ this", type r"match^ this"m, 3자를 저장 하지 마십시오 .
  11. flipud를 사용하여 1-D 배열 역 - reverse(x)한 바이트 이상이고 flipud(x)후자가 더 때문에, 동일한 작업을 수행합니다.
  12. 가능하면 push !, unshift !, append! 또는 prepend 대신 배열 연결을 사용하십시오! -일반 배열의 경우 쉽게 수행 할 수 있습니다. 배열 요소가있는 Any 유형의 배열의 경우 추가 된 배열 주위에 중괄호가 필요합니다 (즉 {[1,2]}, 아님 {1,2}). Julia 0.4의 경우 필요합니다 Any[[1,2]].
  13. 배열 색인을 사용하여 배열 또는 문자열의 크기를 가져옵니다.end 배열 색인 내에서 사용할 경우 배열 / 문자열의 길이로 자동 변환됩니다. 대신 3자를 저장 k=length(A)하는 A[k=end]데 사용하십시오 . k를 즉시 사용하려면이 방법이 도움이되지 않을 수 있습니다. 이것은 다차원의 경우에도 작동합니다- A[k=end,l=end]각 차원의 크기를 얻 A습니다. 그러나이 (k,l)=size(A)경우에는 1 바이트 씩 짧아 지므로 동시에 마지막 요소에 즉시 액세스하려는 경우에만 사용하십시오.
  14. 배열 인덱싱을 사용하여 인덱스 반복자 가져 오기 – 13과 유사 하게을 사용하여 배열 의 길이와 일치하는 반복자를 얻을 수 있습니다 A[k=1:end].이 경우 k반복자 일치를 유지합니다 1:length(A). A동시에 배열 을 사용하려는 경우에 유용 할 수 있습니다 .
  15. 문자열을 char 배열로 변환하기 위해 collect를 사용하지 마십시오. 대신을 collect(A)사용 [A...]하십시오. 동일한 작업을 수행하고 4 바이트를 절약 할 수 있습니다.
  16. 숫자를 문자열로 변환해야합니까? 사용 "$(s[i])"또는 dec(s[i])표현 또는 멀티 문자 변수, 및 "$i"단일 문자 변수.
  17. 조건부 할당 ?:대신 &&또는 ||조건부 할당에 사용 합니다. 즉, 특정 조건에서만 할당을 수행하려는 cond?A=B:1경우 cond&&(A=B), 또는 cond?1:A=B대신 쓰기로 1 바이트를 절약 할 수 있습니다 cond||(A=B). (가) 있습니다 1, 여기에 더미 값이다.
  18. 사용 union또는 대신은unique - union(s)같은 일을 할 것 unique(s), 그리고 그 과정에서 바이트를 저장합니다. 비 ASCII 문자를 사용할 수 ∪(s)있는 경우 동일한 작업을 수행하며 의 5 바이트 대신 3 바이트 만 소요됩니다 union.

2
오, 파이썬에서 첫 트릭을 어떻게 좋아할까요?
seequ

split("Hi there")pattern 인수의 기본값이 공백 이므로 간단히 공백을 사용하여 분할 할 수 있습니다 .
Alex A.

@AlexA. -알지만 팁의 요점은 아니며 팁이 어느 쪽이든 똑같이 적용됩니다.
Glen O

포인트 12가 0.5로 변경되었습니다.
Lyndon White

@Oxinabox-놀랍지는 않지만, 지금까지 몇 개가 구식이라고 확신합니다. 원래 0.3에 대한 대부분의 팁을 썼습니다.
Glen O

15

연산자를 재정 의하여 함수 정의

재정의 연산자는 괄호와 쉼표로 많은 바이트를 저장할 수 있습니다.

재귀적인 단항 연산자

단항 예제의 경우 다음과 같은 피보나치 시퀀스의 반복 구현을 비교하십시오.

F(n)=n>1?F(n-1)+F(n-2):n # 24 bytes
!n=n>1?!~-n+!(n-2):n     # 20 bytes
!n=n>1?!~-n+!~-~-n:n     # 20 bytes

온라인으로 사용해보십시오!

재정의 된 연산자는 초기 우선 순위를 유지합니다.

이미 정수에 대해 정의되어 있고 부울에 대해서만 정의되어 있기 때문에 !를 대신하여 간단히 바꿀 수는 없습니다 .~~!

이진 연산자

재귀 없이도 연산자를 재정의하는 것이 이진 함수를 정의하는 것보다 짧습니다. 단순 분할 성 테스트에 대한 다음 정의를 비교하십시오.

f(x,y)=x==0?y==0:y%x==0 # 23 bytes
(x,y)->x==0?y==0:y%x==0 # 23 bytes
x->y->x==0?y==0:y%x==0  # 22 bytes
x\y=x==0?y==0:y%x==0    # 20 bytes

온라인으로 사용해보십시오!

재귀 이진 연산자

다음은 이진 연산자를 재정 의하여 Ackermann 함수를 계산하는 방법을 보여줍니다.

A(m,n)=m>0?A(m-1,n<1||A(m,n-1)):n+1    # 35 bytes
^ =(m,n)->m>0?(m-1)^(n<1||m^~-n):n+1   # 36 bytes
| =(m,n)->m>0?m-1|(n<1||m|~-n):n+1     # 34 bytes
m\n=m>0?~-m\(n<1||m\~-n):n+1           # 28 bytes

온라인으로 사용해보십시오!

^의 우선 순위가 너무 높기 때문에, 더 오래 일반 식별자를 사용하는 것보다.

전에 언급했듯이

m|n=m>0?m-1|(n<1||m|~-n):n+1           # 28 bytes

|이 경우 이미 정의되어 있기 때문에 정수 인수에는 작동하지 않습니다 . 정수의 정의 다음과 같이 변경할 있습니다

m::Int|n::Int=m>0?m-1|(n<1||m|~-n):n+1 # 38 bytes

그러나 그것은 엄청나게 길다. 그러나, 하지 우리가 왼쪽 인자과 오른쪽 인수로 정수로 부동 소수점을 전달하는 경우 작업을.


11
  1. factor (n)에 의해 너무 쉽게 유혹받지 마십시오 . 유혹 기본 라이브러리 함수 factor(n)에는 치명적인 결함이 있습니다. 정수의 인수 분해를 순서가없는 Dict유형으로 반환합니다 . 따라서, 비용이 필요 collect(keys())하고 collect(values())잠재적 또한 cata는 sort당신이 그것을 밖으로 원하는 데이터를 얻을 수 있습니다. 많은 경우에 시험 부문별로 고려하는 것이 더 저렴할 수 있습니다. 슬프지만 사실이야.

  2. 맵 사용 map 은 루핑의 훌륭한 대안입니다. 의 차이에주의 map하고 map!후자의 현재 위치에서 기능 수있을 때를 이용한다.

  3. mapreduce를 사용하면 mapreduce map의 기능이 더욱 확장되고 바이트를 크게 절약 할 수 있습니다.

  4. 익명의 기능은 훌륭합니다! .. 특히 위에서 언급 한 map기능에 전달 될 때 .

  5. 누적 배열 함수 cumprod , cumsumflavourful cummin및 기타 유사한 이름이 지정된 함수는 n 차원 배열의 지정된 차원을 따라 누적 연산을 수행 할 수 있습니다. (또는 배열이 1-d이면 * un * 지정됨)

  6. Any에 대한 짧은 표기법 예를 들어 다차원 배열 (또는 Dict)의 특정 차원을 모두 선택하려는 A[Any,2]경우 다음을 사용하여 바이트를 절약 할 수 있습니다.A[:,2]

  7. 기능에 대한 한 줄 표기법을 사용 하는 대신 function f(x) begin ... end당신이 종종 단순화 할 수 있습니다f(x)=(...)

  8. 삼항 연산자 사용 단일 표현식 If-Then-Else 구조의 경우 공간 절약이 될 수 있습니다. 주의 사항 : 다른 언어로는 가능하지만 Julia에서 콜론 다음 부분은 생략 할 수 없습니다. 또한 Julia의 연산자는 식 수준이므로 전체 코드 블록을 조건부로 실행하는 데 사용할 수 없습니다.
    if x<10 then true else false endvs
    x<10?true:false


3
지구상에서 어떻게 "삼항 연산자 사용"이 Julia에게 다소 특정한가? 모든 언어와 관련이 있습니다.
피터 테일러

5
그것과 관련이 있습니다. 많은 언어에는지도, 익명 또는 순수 함수, 모든 / 전체의 축약 형, 누적 함수 등이 있습니다. 모든 팁 스레드를 해당 언어에 고유 한 기능으로 만 줄이면 팁 내용이 거의 없습니다. .
Jonathan Van Matre

3
모든 것이 가치를 반환하므로 삼항 연산이 중복됩니다. Go, Haskell, Scala, Lua, VB, Prolog, PL / SQL과 같은 특정 예가 있어야하는 경우 Python은 많은 버전에서 사용하지 않았습니다. 스레드가 3 진 연산자를 언급하는 거의 12 개 언어 중, 당신이 내 지방에만 오기로 선택한 이유가 있습니까?
Jonathan Van Matre

3
글쎄요, 적어도 당신은 동등한 기회를 가진 교육 기관입니다. ヘ ( ̄ ー  ̄ ヘ)
Jonathan Van Matre

1
팁 3 조정을 제안 할 수 있습니까? mapreduce는 mapfoldl 또는 mapfoldr보다 길며 구현에 따라 다양한 동작을 수행 할 수 있습니다. mapfoldl과 mapfoldr는 (각각) 일관되게 왼쪽 및 오른쪽 연결이므로 더 나은 선택입니다. 이것은 또한 더 일반적으로 축소 (폴더 또는 폴더 사용)에 적용됩니다.
Glen O

9

함수 반복

이것은 다른 언어에서도 가능하지만 일반적으로 간단한 방법보다 깁니다. 그러나, 단항 및 이항 연산자를 재정의 할 수있는 Julia의 능력은 상당히 골치 거리가됩니다.

예를 들어 1에서 10까지의 자연수에 대한 더하기, 빼기, 곱하기 및 나누기 테이블을 생성하려면

[x|y for x=1:10,y=1:10,| =(+,-,*,÷)]

재정의되는 이진 연산자 |+, -, *÷, 그때 연산 x|y각각 동작하고 x그리고 y원하는 범위이다.

이것은 단항 연산자에도 적용됩니다. 예를 들어, 복소수 1 + 2i , 3-4i , -5 + 6i-7-8i , 음수, 복소수 복소수 및 곱셈의 역수를 계산하려면

[~x for~=(+,-,conj,inv),x=(1+2im,3-4im,-5+6im,-7-8im)]

이는 재정의 단항 연산자 ~+, -, conjinv다음 계산 ~x원하는 모든 복소수.

실제 콘테스트의 예


6
  1. 키워드는 공백이나 세미콜론 없이도 상수를 즉시 따를 수 있습니다. 예를 들면 다음과 같습니다.

    n->(for i=1:n n-=1end;n)

    1와 사이에 공백이 없습니다 end. 이것은 또한 end가까운 paren 후에 발생하는 경우에도 마찬가지입니다 )end.

  2. 연산자를 오버로드하거나 오버로드 ÷하지 않고 정수 나누기를 수행하십시오 div(). 주 ÷2 가치는 UTF-8 바이트.

  3. 가능할 때마다 대신 vec()또는 A[:](일부 배열의 경우 A) 를 사용하십시오 reshape().

  4. 챌린지 규칙에 허용 된 경우 전체 프로그램이 아닌 함수를 작성하십시오. stdin에서 읽음으로써 변수를 정의하는 대신 입력을 받아들이는 함수를 정의하는 것이 더 짧습니다. 예를 들면 다음과 같습니다.

    n->(n^2-1)
    n=read(STDIN,Int);n^2-1
  5. 변수는 함수의 인수 내에서 증분 될 수 있습니다. 예를 들어, 다음은 내 대답 받는 사람 찾기 다음 1 스파 스 이진 번호 도전 :

    n->(while contains(bin(n+=1),"11")end;n)

    이것은 n루프 내부에서 증가하는 것보다 짧습니다 .


6
  1. 유형return f(x)=x+4 은와 동일하지만보다 짧습니다 f(x)=return x+4. Julia는 항상 마지막 문장의 결과를 반환합니다.
  2. 에서 대신 =를 사용하십시오 . [x for x in 1:4]3 자보다 길지만[x for x=1:4]

5

방송 기능 호출을 사용하십시오.

Julia 0.5에 도입되었습니다. 그것은지도와 같지만 적은 문자를 사용하며, 그 인수에 대해 방송 동작을 수행합니다. 즉, 사물을 다루기 위해 람다를 적게 작성할 수 있습니다.

오히려 :

  • map(f,x) -8 자
  • f.(x) -5 자

그래도 낫다:

  • map(a->g(a,y),x) -16 자
  • g.(x,[y]) -9 자
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.