Mathematica에서의 골프 팁


41

Mathematica에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 나는 Mathematica에 대해 다소 특정한 코드 골프 문제에 적용될 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다).

답변:


30

아래 팁은 가장 경제적이거나 가장 많이 사용되는 팁에 따라 다릅니다.

  1. 가능한 경우 Mathematica의 고급 명령을 사용하십시오.

  2. Graphics and Text아스키 아트에 사용 : 예 : 스타 프로그래밍! 아날로그 시계를 구축

  3. 전용 기호 :

    • 긴 형식 이름 대신 논리 및 집합 연산 기호 : ⋂, ⋃, ∧, ∨

    • MapApply: /@, //@. @@,@@@

  4. 접두사 및 접두사 표기법 :

    • Print@"hello" 대신에 Print["hello"]

    • a~f~b 대신에 f[a,b]

  5. 함수가 한 번만 사용되면 순수한 함수는 문자를 절약 할 수 있습니다.

  6. 목록에서 문자열 조인 ""<>{"a","b","c"}대신에StringJoin@{"a","b","c"}

  7. 나열 가능한 기능을 악용하십시오. 목록이 길수록 좋습니다.

    {a, b, c} + {x, y, z}= {a+x, b+y, c+z}

    {2, 3, 4} {5, 6, 7}= {10, 18, 28}

    {{a, b}, {c, d}}^{2, 3} = {{a^2, b^2}, {c^3, d^3}}


2
그건 항상 쓰기에 짧은 (Norm[#-#2]&)대신 EuclideanDistance.
user202729

32

이름이 긴 일부 내장 함수는 더 짧은 표현식으로 대체 할 수 있습니다.

예를 들면 다음과 같습니다.

  • Total => Tr
  • Transpose=> Thread또는\[Transpose]
  • True => 1<2
  • False => 1>2
  • Times => 1##&
  • Alternatives => $|##&
  • IntegerQ => ⌊#⌋==#&
  • a[[1]] => #&@@a
  • a[[All,1]] => #&@@@a
  • ConstantArray[a,n]=> Array[a&,n]또는Table[a,{n}]
  • Union@a=> {}⋃a또는a⋃a
  • ToExpression@n=> FromDigits@n만약 n숫자 인
  • Divisible[n,m] => m∣n
  • FromDigits[n,2]=> s 및 s 목록 인 Fold[#+##&,n]경우n01
  • Complex@z=> {1,I}.z여기서 z양식의 목록은{x,y}

5
@belisarius Thread[{{a,b},{c,d}}]== Thread[List[{a,b},{c,d}]]== {List[a,c],List[b,d]}== {{a,c},{b,d}}==Transpose[{{a,b},{c,d}}]
alephalpha

2
Fold대한 귀하의 트릭은를 FromDigits제외한 다른 모든 기지에서도 작동 한다고 생각합니다 10. 예를 들어 FromDigits[n,5]-> Fold[4#+##&,n](베이스에 대한 여분의 바이트를 저장하는 보너스 1001000).
Martin Ender

1
@ mbomb007 UTF-8의 3 바이트. 실제로이 캐릭터는 U+F3C7입니다.
alephalpha

1
마침내 10.3을 설치했습니다. 전체 프로그램을 고려하고 있다면 실제 문자열을 인쇄하기 전에 STDOUT에 (및 공백)을 Echo인쇄하기 때문에 옵션 이라고 생각하지 않습니다 >>.
Martin Ender

2
에 대해 동일한 효과로 훨씬 짧다고 Complex[x,y] => {1,I}.{x,y}생각 x+y*I합니까?
Shieru Asakoto

22

반복되는 값이있는 목록

이것은 다음과 같이 작동하는 일반적인 벡터입니다.

{0,0}

바이트 단위로 단축 할 수 있습니다.

0{,}

벡터가 두 개의 0보다 길면 더 많은 바이트가 저장됩니다. 이것은 또한 제로 행렬을 초기화하는 데 사용될 수 있습니다. 예를 들어 다음은 0의 2x2 행렬을 나타냅니다.

0{{,},{,}}

값이 충분히 크거나 충분히 많거나 음수 인 경우 0이 아닌 값에도 사용할 수 있습니다. 다음 쌍을 비교하십시오.

{100,100}
0{,}+100
{-1,-1}
0{,}-1
{3,3,3,3}
0{,,,}+3

그러나 6 개 값부터 시작하면 1~Table~6이 경우 (우선 순위 요구 사항에 따라 잠재적으로 더 빠름)가 더 좋습니다 .

이것이 작동하는 이유 ,는 목록에 두 개의 인수를 소개하지만 생략 된 인수 (Mathematica의 모든 위치)는 암시 적 Null입니다. 또한, 곱셈은 Listable하고 0*x있습니다 0거의 모든에 대해 x(같은 것들을 제외 Infinity하고 Indeterminate, 그래서 여기에) 무슨 일이 일어나고 있습니다 :

  0{,}
= 0*{,}
= 0*{Null,Null}
= {0*Null,0*Null}
= {0,0}

의 목록에 1대해 지수 규칙을 사용하여 유사한 트릭을 사용할 수 있습니다. 1목록에 3 개 이상이 있으면 바이트를 저장하는 방법에는 두 가지가 있습니다 .

{1,1,1}
1^{,,}
{,,}^0

7
+1; 이것은 Mathematica가 모든 것을위한 빌트인 기능을 가지고 있지만 실제로 골프를 치는 것은 어려운 일이라는 것을 보여줍니다.
LegionMammal978

궁극적으로 1로 채워진 배열을 원하면 1^{,,,}보다 1 바이트 작습니다 0{,,,}+1.
Misha Lavrov

@MishaLavrov 오, 잘 잡아. 따라서 세 값이 짧아지고 사용할 수도 있습니다 {,,}^0. 글을 수정하겠습니다.
Martin Ender

19

순수한 함수 인수를 알고

골프 코드를 만들 때 종종 간단한 &구문으로 익명의 (순수한) 함수를 사용하는 기능적 접근 방식을 사용 합니다. 이러한 함수의 인수에 액세스하는 방법에는 여러 가지가 있으며 가능성을 잘 이해하여 몇 바이트를 줄일 수 있습니다.

단일 인수에 액세스

이전에 순수한 기능을 사용한 적이 있다면 아마 이것을 알 것입니다. N은 번째 인수라고 #n하며 #별명 역할 #1. 예를 들어, 다른 함수와 인수를 매개 변수로 사용하는 함수를 작성하려면 (그 인수를 해당 함수에 전달하기 위해)

#@#2&

음수 에서는 작동 하지 않습니다 (예 : 목록에 액세스 할 때 사용할 수 있음).

명명 된 인수에 액세스 (V10의 새로운 기능)

Mathematica 10의 주요 새로운 언어 기능 중 하나는 Associations입니다. 기본적으로 다음과 같이 작성된 임의의 키 유형이있는 키-값 맵입니다.

<| x -> 1, "abc" -> 2, 5 -> 3 |>

이러한 연관이 순수 함수에 대한 첫 번째 인수로 전달되면 이름 지정된 매개 변수로 해당 인수에 액세스 할 수 있습니다.

{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)

참고 #예상대로 여전히 전체 연결을 의미합니다. 작업에 대한 명명 된 매개 변수의 경우, 키가 있어야 문자열 (그 것이다 당신이 예를 들어 정의되지 않은 변수를 사용하는 경우하지 작업), 이러한 문자열은 문자로 시작하고 문자와 숫자를 포함해야합니다.

"자기"논쟁 #0

덜 알려진 기능은 #0또한 존재하며 함수 객체 자체를 제공한다는 것입니다. 이것은 quines와 generalized quines에서 실제로 유용 할 수 있습니다. 사실, 가장 짧은 Mathematica quine (내가 아는 것)은

ToString[#0][] & []

약간 성가신 것은 입력 한 정확한 문자를 제공하지 않는다는 것입니다. 예를 들어 @함수 응용 프로그램에 사용 하는 경우 에도 그대로 렌더링되고 [...]일부 위치에 공백이 삽입됩니다. 이렇게하면 일반적으로 퀴를 원하는 것보다 조금 더 길게 만들 수 있지만, 퀴니를 먼저 골프로 칠한 다음 출력을 복사하면 항상 작동합니다. 실제 퀴인이어야합니다.

quines 외에도 함수 이름을 지정하지 않고도 재귀 코드를 작성할 수 있습니다. 이 세 가지 (순진하지만 골프) 피보나치 구현을 비교하십시오.

f@0=0;f@1=1;f@n_:=f[n-1]+f[n-2]
f@n_:=If[n<2,n,f[n-1]+f[n-2]]
If[#<2,#,#0[#-1]+#0[#-2]]&

인수 순서

이제 진짜 마법이 시작됩니다. 시퀀스는 골프에 자주 사용되지 않습니다. 왜냐하면 Sequence이름이 너무 길어서 대부분의 시간에 가치가 있기 때문입니다. 그러나 순수한 기능에는 빛이 비추는 곳이 있습니다. 시퀀스에 익숙하지 않은 경우 기본적으로 시퀀스는 다른 언어의 표시와 비슷 List합니다. 함수 또는 인수 목록 에서 시퀀스를 사용하면 요소가 자동으로 별도의 슬롯으로 확장됩니다. 그래서

{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]

이제 순수 함수에서 ##또는 ##1모든 인수의 시퀀스입니다. 마찬가지로, ##2두 번째에서 ##3시작하는 모든 인수, 세 번째에서 시작 하는 모든 인수의 시퀀스입니다 . 따라서 시작을 위해 5 바이트를 절약 Sequence하면서 다시 구현할 수 있습니다 ##&. 예를 들어, 이것은 바이트를 저장하지 않지만 어쨌든 알아두면 좋은 Join@@list( 이 팁 참조) 의 대안을 제공 합니다.

 ##&@@@list

이렇게하면 중첩 목록의 첫 번째 수준이 효과적으로 평탄화됩니다. 우리는 이것으로 무엇을 할 수 있습니까? 다음은 2 바이트 더 짧은 대안입니다 RotateLeft.

 RotateLeft@list
 {##2,#}&@list

이러한 것만으로는이 기능을 염두에 두어야합니다. 그러나 우리는 더 잘할 수 있습니다! 연산자가 실제로 함수 아래에서 함수로 구현된다고 생각하면 시퀀스는 정말 흥미로워집니다. 예를 들어 a+b실제로로 평가됩니다 Plus[a,b]. 시퀀스를 주면 ...

1+##&[1,2,3]
=> Plus[1,##] 
=> Plus[1,1,2,3]
=> 7

이 트릭은 이 팁 에서 바이트를 절약하기 위해 사용되었습니다. Timesjuxtaposition은 기술적으로 연산자 일뿐입니다.

1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6

Unequal단일 문자 값이나 변수가 인수에없는 경우 바이트를 저장하는 데 사용할 수도 있습니다 ( N99 %의 경우 작동 할 수 있음).

Unequal[a,b,c]
N!=##&[a,b,c]

이 훨씬 더 흥미 단항 연산자와에 도착 -하고 /- 후자의 두 가지가 실제로 곱셈과 지수의 관점에서 구현됩니다. 다음은 수행 할 수있는 작업의 목록입니다. 마지막 열은 함수에 인수가 전달 된 것으로 가정합니다 a, b, c.

Operator    Function                Expanded                    Equivalent to

+##         Plus[##]                Plus[a,b,c]                 a+b+c
1##         Times[1,##]             Times[1,a,b,c]              a*b*c
-##         Times[-1,##]            Times[-1,a,b,c]             -a*b*c
x+##        Plus[x,##]              Plus[x,a,b,c]               x+a+b+c
x-##        Plus[x,Times[-1,##]]    Plus[x,Times[-1,a,b,c]]     x-a*b*c
x##         Times[x,##]             Times[x,a,b,c]              x*a*b*c
x/##        Times[x,Power[##,-1]]   Times[x,Power[a,b,c,-1]]    x*a^b^c^-1
##/x        Times[##,Power[x,-1]]   Times[a,b,c,Power[x,-1]]    a*b*c/x
x^##        Power[x,##]             Power[x,a,b,c]              x^a^b^c
##^x        Power[##,x]             Power[a,b,c,#]              a^b^c^x
x.##        Dot[x,##]               Dot[x,a,b,c]                x.a.b.c

다른 일반적인 사업자이다 !=, ==, &&, ||. 염두에 두어야 덜 흔한 것들이다 |, @*, /*. 결론적으로 다음은 약간의 보너스 요령입니다.

####        Times[##,##]            Times[a,b,c,a,b,c]          (a*b*c)^2

이것들을 계속 실험 해보고, 유용하거나 특히 흥미로운 다른 응용 프로그램을 찾으면 알려주십시오!


15

Sqrt@2또는 2^.5=>√2

a[[1]]=>a〚1〛

#+#2&=>+##&

Flatten@a=> Join@@a(때로는)

Function[x,x^2]=> xx^2또는#^2&

a〚1;;-1;;2〛=>a〚;;;;2〛

a〚2;;-1 ;;2〛=>a〚2;;;;2〛

a〚All,1〛=>a〚;;,1〛

{{1}}〚1,1〛=>Tr@{{1}}

0&~Array~10=>0Range@10

Range[10^3]=>Range@1*^3


1
바이트 단위로 측정 할 때 각각 3 바이트를 사용 하고 3 바이트를 사용합니다 (UTF8 가정)
user202729

12

함수로서의 연산자

Julia의 Dennis의 최근 발견에서 영감을 얻은 나는 Mathematica를 위해 이것을 조사 할 것이라고 생각했습니다. Mathematica는 많은 수의 사용하지 않는 연산자를 정의하지만 그에 많은 관심을 기울이지 않았다는 것을 알고있었습니다.

참고 로 모든 연산자 목록은 우선 순위 표 형식으로 여기 에서 찾을 수 있습니다 . 마지막 열의 삼각형은 해당 연산자에 기본 제공 의미가 있는지 여부를 나타냅니다. 쉽게 정의 할 수없는 것은 아니지만 대부분을 정의 할 수 있습니다.

편리하게, 코드 포인트가 256보다 작은 두 개의 사용되지 않는 연산자가있어 ISO 8859-1로 인코딩 된 소스 파일에서 단일 바이트로 사용할 수 있습니다.

  • ± (0xB1)은 단항 접두사 연산자 또는 이진수 접두사 연산자로 사용할 수 있습니다.
  • · (0xB7)은 n이> 2 인 경우 가변 또는 n 항 접두사 연산자로 사용될 수 있습니다.

그러나 한 가지 더 중요한 점이 있습니다.이 연산자를 정의 할 때 이상한 이유가 있기 때문에 앞에 공백이 필요합니다. 그렇지 않으면 Mathematica는 곱셈을 구문 분석하려고합니다. 그것들을 사용할 때 공백이 필요하지 않습니다.

±x_:=2x
x_ ±y_:=x+y
x_ ·y_ ·z_:=x*y+z
Print[±5]  (* 10 *)
Print[3±4] (*  7 *)
Print[3·4·5] (* 17 *)

이것을 다음과 비교하십시오.

f@x_:=2x
x_~g~y_:=x+y
h[x_,y_,z_]:=x*y+z
Print[f@5]   (* 10 *)
Print[3~g~4] (*  7 *)
Print[h[x,y,z]] (* 17 *)

따라서 함수를 정의 할 때 1 바이트, 함수를 사용할 때 2 바이트가 절약됩니다. 의 정의는 ·4 개의 피연산자에 대한 바이트를 저장하지 않으며 더 많은 피연산자에 대한 비용을 청구하기 시작하지만 인수에 사용 된 연산자의 우선 순위에 따라 사용량이 여전히 바이트를 절약 할 수 있습니다. 또한 variadic 함수를 저렴하게 정의하여 훨씬 더 효율적으로 호출 할 수 있습니다.

x_ ·y__:={y}
Print[1·2·3·4·5] (* {2, 3, 4, 5} *)

그러나 이러한 가변 함수를 단일 인수로 쉽게 호출 할 수는 없습니다. (당신은 할 수 CenterDot[x]또는 ##&[]·x당신이 실제로 당신이 더 떨어져 다른 솔루션에있어 좋은 기회가 있다고해야 할 경우 만.)

물론 이것은 명명되지 않은 함수가 충분한 솔루션을 위해 아무것도 저장하지 않지만 때로는 나중에 사용할 도우미 함수를 정의해야하며 때로는 명명 된 함수를 정의하는 것이 더 짧습니다 (예 : 다른 매개 변수에 대해 다른 정의를 설정하는 경우). 이러한 경우, 대신 연산자를 사용하면 적절한 양의 바이트를 절약 할 수 있습니다.

이 ISO 8859-1로 인코딩 된 파일을 사용하려면 $CharacterEncodingWindows 기본값과 같은 호환 가능한 값으로 설정해야합니다 WindowsANSI. 일부 시스템에서는 기본적으로 UTF-8단일 바이트에서 이러한 코드 포인트를 읽을 수 없습니다.


이것은 정말 훌륭합니다. Mathematica에 연산자 목록이 있다는 것을 몰랐으며 심지어 우선 순위도 포함했습니다. 당신이 찾은 두 연산자는 유용 할 것입니다.
마일

8

정수를 기준으로 값 선택

순진 접근 방식 사이에서 선택을 y하고 z있는지 여부에 따라 x입니다 0또는 1이다

If[x<1,y,z]

그러나 더 짧은 방법이 있습니다.

y[z][[x]]

이 경우에는 표현식을 [[0]]제공 하기 때문에 작동 하지만 첫 번째 요소 (이 경우 첫 번째 인수) 만 제공하기 때문 입니다.Heady[[1]]z

이것을 사용하여 둘 이상의 값 중에서 선택할 수도 있습니다.

u[v,w][[x]]

u실제로 무언가로 평가되는 함수 인 경우에는 작동하지 않습니다 . Mathematica를 그대로 유지 u[v,w]하는 것이 중요합니다 . 그러나 이것은 uis가 숫자, 문자열 또는 목록 인 경우를 포함하여 대부분의 경우 작동 합니다.

이 속임수에 대한 크레딧은 alephalpha로 이동합니다-나는 그의 대답 중 하나에서 이것을 발견했습니다.

경우 x이다 제로, 단지 사용하는 대신 1 기반

{y,z}[[x]]

또는

{u,v,w}[[x]]

드문 경우이지만 곱셈이 일부 값에 대해 평가되지 않는다는 사실을 활용할 수도 있습니다.

{"abc","def"}[[x]]
("abc""def")[[x]]

참고 티카 실제로 인수 순서를,이 평가되지 않은 남아있는 경우 곱셈의, 위에서 인 것입니다 그래서하지만 동일

("def""abc")[[x]]

8

대안 Length

이것은 LegionMammal978과 Misha Lavrov의 제안으로 완전히 다시 작성되었습니다. 둘 다 감사합니다.

대부분의 Length경우을 사용하여 조금 단축 할 수 있습니다 Tr. 기본 아이디어는 입력을 1s 목록으로 바꾸어 목록의 Tr길이와 같은 것을 합산하는 것입니다.

이를 수행하는 가장 일반적인 방법은 1^x(list x) 를 사용 하는 것 입니다. 때문에 작품 Power입니다 Listable1^n대부분의 원자 값을 n그냥 1(모든 숫자, 문자열 및 기호 포함). 그래서 우리는 이미 이것으로 1 바이트를 저장할 수 있습니다 :

Length@x
Tr[1^x]

물론 이것은 이것이 x보다 우선 순위가 높은 표현식 이라고 가정합니다 ^.

s와 s x만 포함하는 경우 다음을 사용하여 다른 바이트를 저장할 수 있습니다 ( 우선 순위가 ).01Factorialx!

Length@x
Tr[x!]

드문 경우 이지만 곱셈보다 우선 x순위가 낮을 수 ^있지만 여전히 우선 순위가 높습니다. 이 경우 우선 순위가 우선 순위가 낮 @으므로 실제로 비교해야합니다 Length[x]. 이러한 연산자의 예는 .입니다. 이 경우에도 다음 형식으로 바이트를 저장할 수 있습니다.

Length[x.y]
Tr[0x.y+1]

마지막으로, 어떤 종류의 목록에서 작동하는지에 대한 설명이 있습니다.

맨 위에서 언급했듯이 이것은 숫자, 문자열 및 기호 만 포함 된 플랫 목록에서 작동합니다. 그러나 실제로는 약간 다른 것을 계산하지만 더 깊은 목록에서도 작동합니다. 들어 N -D 직사각형 배열 사용은 Tr당신에게 제공 최단 (제 반대) 사이즈. 가장 바깥 쪽 치수가 가장 짧거나 치수가 모두 같다는 것을 알고 있다면 Tr-식은 여전히와 같습니다 Length.


3
더 짧은 해결책을 찾았습니다 Length@x == Tr[1^x]. 대부분의 목록에서 작동합니다.
LegionMammal978

@ LegionMammal978 정말 놀랍습니다. :). 곧 수정하겠습니다.
Martin Ender

1
두 번, 나는 0과 1 만 포함 하는 특별한 경우에 1 바이트를 저장 하는 Tr[x!]대신 사용 하는 것을 발견 했습니다. Tr[1^x]x
Misha Lavrov

@MishaLavrov 정말 깔끔합니다! :)
Martin Ender

7
  1. 재귀 솔루션 탐색-Mathematica 는 다중 패러다임이지만 기능적 접근 방식이 가장 경제적 인 경우가 많습니다. NestWhile검색 문제에 매우 컴팩트 한 솔루션이 될 수 있습니다 NestWhileList그리고 FoldList당신은 반환 또는 중간 반복의 결과를 처리해야 할 때 강력하다. Map (/@), Apply (@@, @@@), MapThread볼프람의에, 정말 모든 기능 프로그래밍 문서 페이지는 강력한 물건입니다.

  2. 증가 / 감소를 위해 양식을 단축 - 예를 들어, 대신 While[i<1,*code*;i++]당신이 할 수있는
    While[i++<1,*code*]

  3. 미리 증분 / 감소 할 수 있다는 것을 잊지 마십시오 . 예를 들어 --i대신 i--. 이렇게하면 준비 작업을 제거하여 주변 코드에서 몇 바이트를 절약 할 수 있습니다.

  4. David Carraher의 # 5에 대한 결론 : 동일한 기능이 여러 번 사용될 때 심볼을 할당하면 바이트를 절약 할 수 있습니다. 예를 들어, ToExpression솔루션에서 4 번 t=ToExpression사용하는 경우 t@*expression*이후 에 사용할 수 있습니다 . 그러나이 작업을 수행하기 전에 동일한 기능을 반복적으로 적용하면보다 경제적 인 재귀 적 접근 방법이 있는지 여부를 고려해야합니다.


MapThread종종로 대체 될 수 있습니다 \[Transpose]. 티오 .
user202729 2016 년

7

를 사용하는 {}경우 사용하지 마십시오 @@@.

경우에 따라 다음과 같은 표현이 나타날 수 있습니다.

f@@@{{a,b},{c,d}}

다음과 같이 작성하여 바이트를 줄일 수 있습니다.

f@@@{a|b,c|d}

Alternatives우선 순위가 매우 낮으므로 일반적으로 표현식을 작성하는 것이 좋습니다 (눈에 띄는 예외는 순수한 함수입니다.의 가장 왼쪽 요소에서만 사용할 수 있습니다 Alternatives).

f@@@{f@a|b~g~1,#^2&@c|d@2}

그 주 f@@a|b|c(대신이 f@@{a,b,c}있기 때문에) 일을하지 않는 Apply것보다 더 높은 우선 순위를 갖습니다 Alternative.

이 경우 간단히을 사용해야 f@@{a,b,c}합니다.


6

Mathematica 10 만

연산자 양식

Mathematica 10은 소위 "연산자 양식"을 지원합니다. 이는 기본적으로 일부 기능이 커리 될 수 있음을 의미합니다. 함수를 커리하는 것은 연산자 중 하나를 수정하여 새 함수를 만드는 것입니다. SortBy[list, somereallylongfunction&]여러 가지를 사용 하고 있다고 가정 해보십시오 list. 전에, 당신은 아마 할당 한 것 SortBy으로 s하고 순수한 기능 f때문에

s=SortBy;
f=somereallylongfunction&;
list1~s~f;
list2~s~f;
list3~s~f;

지금 당신은 카레 수 있습니다 SortBy당신이 지금 할 수있는 것을 의미한다,

s=SortBy[somereallylongfunction&];
s@list1;
s@list2;
s@list3;

포함 목록 또는 함수 인수를 가지고 (그러나 이에 국한되지 않음) 다른 기능의 많은에 대한 동일 작품 Select, Map, Nearest, 등

Mathematica.SE의 ybeltukov 는 다음의 전체 목록을 생성 할 수있었습니다 .

{"AllTrue", "AnyTrue", "Append", "Apply", "AssociationMap", "Cases", 
 "Count", "CountDistinctBy", "CountsBy", "Delete", "DeleteCases", 
 "DeleteDuplicatesBy", "Extract", "FirstCase", "FirstPosition", 
 "FreeQ", "GroupBy", "Insert", "KeyDrop", "KeyExistsQ", "KeyMap", 
 "KeySelect", "KeySortBy", "KeyTake", "Map", "MapAt", "MapIndexed", 
 "MatchQ", "MaximalBy", "MemberQ", "Merge", "MinimalBy", "NoneTrue", 
 "Position", "Prepend", "Replace", "ReplacePart", "Scan", "Select", 
 "SelectFirst", "SortBy", "StringCases"}

구성과 올바른 구성

Composition( @*) 및 RightComposition( /*)에 대한 새로운 속기가 있습니다 . 문자를 저장할 수있는 명백한 예는 다음 세 줄에 나와 있습니다.

Last@Range@# & /@ Range[5]
Last@*Range /@ Range[5]
Range /* Last /@ Range[5]

5

인수가 0 인 함수를 쓰지 마십시오

다음과 같은 코드가 필요하지 않습니다.

f[]:=DoSomething[1,2]
(*...*)
f[]
(*...*)
f[]

변수를 사용 :=하여 오른쪽의 재평가를 강제 할 수 있습니다 .

f:=DoSomething[1,2]
(*...*)
f
(*...*)
f

또한 n++5 바이트의 비용으로 자주 수행하는 모든 작업을 단일 문자에 별칭으로 지정할 수 있습니다 . 따라서 n++네 번째 사용 후 지불하면 다음과 같습니다.

n++;n++;n++;n++
f:=n++;f;f;f;f

5

%자유 변수를 얻는 데 사용

이 팁은 Mathematica의 REPL 환경을 가정 할 수있는 경우에만 적용됩니다. %코드가 스크립트로 실행될 때는 정의되지 않습니다.

이 때 REPL 기능을 사용할 수 있도록,이 작업을 수행하지 않습니다

a=someLongExpression;some[other*a,expression@a,using^a]

대신 Mathematica는 마지막으로 평가 된 (줄 바꿈으로 끝나는) 표현식을 %다음에 저장합니다 .

someLongExpression;
some[other*%,expression@%,using^%]

추가 된 줄 바꿈에는 1 바이트가 필요하지만을 제거하여 2를 절약 a=하므로 전체적으로 1 바이트를 절약합니다.

경우에 따라 (예 : a어쨌든 값을 인쇄하려는 경우 ) ;2 바이트를 절약 할 수도 있습니다 .

someLongExpression
some[other*%,expression@%,using^%]

1-2 바이트는 아주 작게 보일 수 있지만 골프를 할 때 반복되는 식 (매우 일반적인 기술)의 추출이 훨씬 유용하기 때문에 중요한 경우입니다.

반복되는 표현식을 추출하는 일반적인 기술에는 4 바이트의 오버 헤드가 소요되며,이 표현식을 더 사용하여 저장해야합니다. 다음은 명명 된 변수로 추출하여 표현식을 저장하기위한 표현식의 최소 사용 횟수 (표현식 길이)에 대한 간단한 표입니다.

Length   Min. Uses
2        6
3        4
4        3
5        3
6        2
...      2

명명되지 않은 변수를 사용하면 몇 바이트를 훨씬 더 자주 저장할 수 있습니다.

When ; is required                        When ; can be omitted

Length   Min. Uses                        Length   Min. Uses
2        5                                2        4
3        3                                3        3
4        3                                4        2
5        2                                ...      2
...      2

나는 생각하지 않는다 %%또는 %n당신이 적어도 두 번을 사용하지 않는 경우, 당신은 단지이 필요한 표현의 권리를 넣을 수 있기 때문에, 골프에 사용할 수 있습니다. 그리고 두 번 사용하면 변수 이름에 추가 문자가 있으면 절약 효과가 일부 생략 x=됩니다.


스크립트 모드에서는 작동하지 않습니다.
alephalpha

@alephalpha 스크립트 모드 란 무엇입니까?
Martin Ender


@alephalpha 아 맞다. 나는 뇌를 잠시 잠깐 멈췄다. 그래서 REPL 환경을 가정 할 수 없다면 그것은 실제로 사용될 수 없다는 것을 의미한다.
Martin Ender

5

목록이 정렬되어 있는지 확인

이것은 본질적 으로이 팁 의 추론 이지만 이것은 자체 답변이 필요하다고 생각되는 충분히 일반적인 작업입니다.

목록이 올바른지 확인하는 순진한 방법은

OrderedQ@a

우리는 1 바이트 더 잘 할 수 있습니다

Sort@a==a

그러나 변수를 체크인하고 싶은 것이 없다면 작동하지 않습니다. (우리 Sort[a=...]==a는 불필요하게 긴 것과 같은 것이 필요합니다.) 그러나 다른 옵션이 있습니다.

#<=##&@@a

가장 좋은 점은 입력이 동일한 바이트 수에 대해 역 정렬되었는지 여부를 확인하는 데 사용할 수 있다는 것입니다.

#>=##&@@a

a) 목록 요소가 서로 다르다는 것을 알고 b) 0과 9 사이의 하한 (포함 또는 역 정렬 순서의 상한)을 알고 있으면 한 바이트를 더 저장할 수 있습니다.

0<##&@@a
5>##&@@a

이것이 왜 작동하는지 보려면 상단에 링크 된 팁에서 "인수 순서"를 확인하십시오.


또는, 역 분류에 대한 (엄격한) 하한도 작동 ##>0&@@a합니다. 정렬 된 상한과 유사합니다.
user202729 년

@ user202729 오, 좋은 점, 자유롭게 편집하십시오 (그렇지 않으면 나는 주말에 그것을 기억하려고 노력할 것입니다).
Martin Ender

5

문자열 반복

대신에 StringRepeat[str,n]사용 (0Range[n]+str)<>"". 또는 str슬롯 인수에 의존하지 않는 경우이 팁에 Array[str&,n]<>""따라 더 좋습니다 .


1
추론 : 대신 StringRepeat[s,n+1]사용 Array[s&,n]<>s(당신이 이미 가지고있는 경우에도 n+1변수에 너무).
Martin Ender

더 나은,Table[str,n]<>""
attinat

5

반대로 정렬 된 숫자 목록이 필요한 경우 사용하지 마십시오

Reverse@Sort@x

그러나

-Sort@-x

6 바이트를 절약 할 수 있습니다. 음수 값으로 정렬하면 SortBy시나리오에 유용합니다 .

Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]

2
무엇에 대해 -Sort@-x?
JungHwan Min

1
@JungHwanMin 오, 그래, 훨씬 낫다. :)
Martin Ender

4

Break하나 또는 두 개의 문자를 저장할 수 있는 표현식을 붙일 수 있습니다 . 예 ( 명확하게하기 위해 다른 세부 정보가 제공되지 않음 ) :

result = False;
Break[]

로 변할 수있다

Break[result = False]

하나의 문자를 저장합니다. 해당 표현식이 함수 애플리케이션보다 우선 순위가 낮 으면 다른 문자를 저장할 수도 있습니다.

Print@x;
Break[]

로 변할 수있다

Break@Print@x

문서화되지 않았지만에 대한 인수 Break는 주변 루프에 의해 반환되는 것으로 보이며 이로 인해 더 많은 비용을 절약 할 수 있습니다.


4

문자열에서 모든 공백을 제거하려면 s, 사용

StringSplit@s<>""

즉, StringSplit의 기본값을 사용하고 (공백이 아닌 구성 요소로 분리) 간단히 다시 결합하십시오. 다른 문자 또는 부분 문자열을 제거하려는 경우에도 여전히 가장 짧습니다.

s~StringSplit~"x"<>""

4

대안 Range

가장 일반적인 작업은 1에서 a까지 n(일반적으로 입력으로 제공되는) 모든 숫자에 일종의 함수를 적용하는 것입니다 . 이를 수행하는 방법에는 기본적으로 3 가지 방법이 있습니다 (이름없는 ID 기능을 예로 사용).

#&/@Range@n
Array[#&,n]
Table[i,{i,n}]

나는 어떤 이유로 든 첫 번째 것을 선호하지만 이것이 최선의 선택은 아닙니다.

사용 Array하는 대신

위의 예는 사용 Array이 동일한 바이트 수를 가짐을 보여줍니다 . 그러나 단일 표현식이라는 장점이 있습니다. 특히 함수 f를 사용 하여 결과를 추가로 처리 하려면 접두사 표기법을 사용하여 바이트를 절약 할 수 있습니다 Range.

f[#&/@Range@n]
f@Array[#&,n]

또한, 당신은 당신이 필요했을 수도 당신의 이름이 기능의 주위에 수 생략 괄호 될 수있다 Range예를 들면,

15/(#&)/@Range@n
15/Array[#&,n]

당신이 경우 하지 않는 (또는 낮은 우선 순위를 가진 연산자) 더 그것을 사용하려면, 대신 쓸 수있는 Array중위 표기법으로도 바이트 저장 자체를 :

#&/@Range@n
#&~Array~n

따라서 Array거의 확실히보다 낫습니다 Range.

사용 Table하는 대신

이제 표는 3 바이트를 구성해야합니다. 또는 부호 표기법이 옵션 인 경우 2 이상이어야합니다.

#&/@Range@n
i~Table~{i,n}

하지 중위 표기법을 사용하여, Table함수가 여러 문장으로 구성되어있는 경우 괄호를 생략 할 수 있습니다 :

(#;#)&/@Range@n
Table[i;i,{i,n}]

이것은 여전히 ​​더 길지만 아래 언급 된 경우에 추가 비용을 절약합니다.

실제 절약 Table은 실행 변수에 이름 을 부여 한다는 사실에서 비롯됩니다 . 내부 함수 중 하나에서 외부 변수를 사용하려는 명명되지 않은 함수가 중첩되어있는 경우가 종종 있습니다. 이런 일 Table이 발생하면 Range다음 보다 짧습니다 .

(i=#;i&[])&/@Range@n
Table[i&[],{i,n}]
i&[]~Table~{i,n}

대입을 위해 문자를 저장할뿐만 아니라 i프로세스에서 단일 명령문으로 함수를 줄일 수도 있습니다.이를 통해 대괄호를 그 위에 사용할 수 있습니다. 참고 Array로이 경우에도 더 길지만 여전히 다음보다 짧습니다 Range.

(i=#;i&[])&~Array~n

실제로 언제 사용 Range하시겠습니까?

값을 처리하기 위해 함수 호출이 필요하지 않을 때마다 (예 : 벡터화 된 연산을 통해 매핑을 수행 할 수있는 경우) 예를 들어 :

5#&~Array~n
5Range@n
#^2&~Array~n
Range@n^2

물론 어떤 함수도 매핑하고 싶지 않다면 더 짧습니다.

Mean@Array[#&,n]
Mean@Range@n

마지막으로 f/@Range[x]정기적으로 사용하는 누군가가 ...
LegionMammal978

4

조건을 만족하는 가장 작은 숫자 찾기

일부 구조 i=1;While[cond[i],i++]는 그대로는 좋지만 2 바이트 더 짧은 대안이 있습니다.

1//.i_/;cond[i]:>i+1

위의 코드 는 조건을 만족하는 동안 숫자 i를 반복해서 바꿉니다 . 이 경우에서 시작합니다 .i+1cond[i]i1

기본 최대 반복 횟수는 2 ^ 16 (= 65536)입니다. 그보다 더 많은 반복이 필요한 경우 While더 좋습니다. ( MaxIterations->∞너무 길다)


4

남용 단락 평가

때로는 If논리 연산자로 바꿀 수 있습니다 .

예를 들어, 숫자가 소수인지 확인하는 함수를 만들고 싶을 때 인쇄 2*(number) - 1하는 경우를 가정 해 보겠습니다 .

If[PrimeQ@#,Print[2#-1]]&

&&대신 사용하면 짧아집니다 .

PrimeQ@#&&Print[2#-1]&

여러 표현식이 있어도 여전히 바이트를 저장합니다.

If[PrimeQ@#,a++;Print[2#-1]]&

PrimeQ@#&&a++&&Print[2#-1]&
(* or *)
PrimeQ@#&&(a++;Print[2#-1])&

당신은 사용할 수 있습니다 ||당신은 조건이되고 싶어 할 때 경우에 False:

If[!PrimeQ@#,Print[2#-1]]&
(* or *)
If[PrimeQ@#,,Print[2#-1]]&
(* can become *)
PrimeQ@#||Print[2#-1]&

논리 연산자는 단락 될 수 있기 때문에 이러한 트릭이 작동합니다 . 두 번째 인수 이후에는 유효한 부울 식일 필요조차 없습니다.

물론, 반환 값 If이 필요하거나의 진실되고 허위 주장이 모두 필요한 경우에는 작동하지 않습니다 If.



3

사용 Optional (:)

Optional (:) 확장에 대한 별도의 규칙을 정의 할 필요없이 대체 목록을 확장하는 데 사용할 수 있습니다.

이 답변@ngenisis의 답변 이 예입니다.

용법

... /. {p___, a_: 0, b_, q___} /; cond[b] :> ...

위의 대체는 먼저 패턴을 사용하고 특정 조건에 {p___, a_, b_, q___}맞는 일치를 찾습니다 b.

일치하는 것이 없으면 생략 a_하고 대신 검색합니다 {p___, b_, q___}. a는 검색에 포함되지 않으며 값을 갖는 것으로 간주됩니다 0.

두 번째 패턴 검색은 b목록의 시작 부분 에서만 발생합니다. b조건을 만족 하는 값이 중간에 {p___, a_, b_, q___}있으면 우선 순위가 높은 값이 대신 일치합니다.

대체는 목록의 시작 부분에서 만족스러운 조건이 발생할 0때 앞에 붙는 것과 같습니다 b. (즉, 별도의 규칙을 정의 할 필요가 없습니다. {b_, q___} /; cond[b] :> ...)


3

명명 된 순수 함수 인수를 언제 그리고 언제 사용하는지 알아야합니다.

코드 골프의 경우 순수 Function인수는 Slots를 사용하여 가장 일반적으로 참조됩니다 . 예 #를 들어 첫 번째 인수, #2두 번째 인수 등 ( 자세한 내용 은 이 답변 참조).

대부분의 경우을 중첩하고 싶을 것 Function입니다. 예를 들어, 1##&@@#&Function첫 번째 인수로 목록을 가져와 해당 요소의 곱을 출력합니다. 그 기능은 다음과 같습니다 TreeForm.

여기에 이미지 설명을 입력하십시오

최상위 수준으로 전달 된 인수는 최상위 수준에 Function있는 Slots 및 SlotSequences 만 채울 수 있으며,이 경우 SlotSequence내부 Function의 최상위에 인수에 액세스 할 수있는 방법이 없습니다 Function.

그러나 어떤 경우에는 Function다른 안에 중첩되어 Function인수를 outer 참조 할 수 있기를 원할 수 있습니다 Function. 예를 들어, Array[fun,...]&함수 fun가 최상위 레벨의 인수에 의존 하는 것과 같은 것을 원할 수 있습니다 Function. 구체적으로, fun입력 모듈로의 제곱의 나머지 부분에 입력을 최상위 레벨로 제공해야 한다고 가정 해 봅시다 Function. 이를 수행하는 한 가지 방법은 최상위 인수를 변수에 지정하는 것입니다.

(x=#;Array[Mod[#^2,x]&,...])&

목적지 x나타난다는 내부에 Function Mod[#^2,x]&, 그 외측에 상기 제 인수를 참조한다 Function반면 #내부에 첫번째 인수를 참조한다 Function. 더 나은 방법은 Function첫 번째 인수가 Function(이름이없는 Slots 와 반대로) 명명 된 인수를 나타내는 기호 또는 기호 목록 인 두 개의 인수 형식 을 갖는 사실을 사용 하는 것 입니다. 이 경우이 경우 3 바이트가 절약됩니다.

xArray[Mod[#^2,x]&,...]

U+F4A1이진 접두사 연산자를 나타내는 3 바이트 개인용 문자 \[Function]입니다. Function다른 형식의 이진 형식을 사용할 수도 있습니다 Function.

Array[xMod[x^2,#],...]&

이것은 위와 같습니다. 그 이유는 명명 된 인수를 사용하는 경우 Slots 및 명명 된 인수를 사용하지 않는 SlotSequences다음에 속한다고 가정하기 Function때문입니다.

이제 우리가 Functions를 이런 식으로 중첩 할 수 있다고해서 항상해야한다는 것을 의미하지는 않습니다. 예를 들어, 입력보다 작은 목록의 요소를 선택하려면 다음과 같은 작업을 수행 할 수 있습니다.

Select[...,xx<#]&

Cases중첩 된 Function전체 를 사용할 필요가없고 사용 을 피하는 것이 실제로 더 짧을 것입니다 .

Cases[...,x_/;x<#]&

2

Prepend또는 주위에서 작업하여 바이트를 저장할 수 있습니다 PrependTo.

l~Prepend~x
{x}~Join~l
{x,##}&@@l

또는

l~PrependTo~x
l={x}~Join~l
l={x,##}&@@l

불행하게도, 이것은 일반적인에 도움이되지 않는 Append의 짧은 상응하는 것 같다, Array.push()다른 언어입니다.


2

Mathematica 10.2 : BlockMapPartition+Map

이 팁의 제목은 "릴리스 정보를 모두 읽으십시오"입니다. 참고로 여기에 10.2 릴리스 정보오늘 10.3 릴리스 정보가 있습니다.

어쨌든 마이너 릴리스조차도 풍부한 새로운 기능이 포함되어 있으며 10.2의 가장 유용한 기능 중 하나 (골프 용)가 새로운 BlockMap기능입니다. 그것은 본질적으로 Partitionand를 결합 Map하는데, 이것은 골퍼들에게 아주 좋습니다. 왜냐하면 Partition꽤 자주 사용 되기 때문에 정말 성가신 긴 기능 이름입니다. 새로운 함수는 Partition자체적으로 단축되지는 않지만 함수를 파티션에 매핑하려고 할 때마다 (아마도 더 자주 발생하지는 않음) 이제 한두 바이트를 저장할 수 있습니다.

#&/@l~Partition~2
BlockMap[#&,l,2]
#&/@Partition[l,3,1]
BlockMap[#&,l,3,1]

명명되지 않은 함수의 새로운 위치를 사용하면 괄호를 절약 할 수있어 절감 효과가 더욱 커집니다.

#&@@(#&/@Partition[l,3,1])
#&@@BlockMap[#&,l,3,1]

불행히도, 나는 BlockApply그들이 왜 거기에있는 동안 추가하지 않았는지 전혀 모른다 ...

또한 순환 목록을 얻기 위해 BlockMap사용할 수있는 4 번째 매개 변수를 지원하지 않습니다 Partition.

Partition[Range@5, 2, 1, 1]
(* Gives {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 1}} *)
BlockMap[f, Range@5, 2, 1, 1]
(* Nope... *)

2

변수에 함수 및 표현식 저장

답이 동일한 함수 또는 표현식을 여러 번 사용하는 경우 변수에 저장하는 것이 좋습니다.

표현식이 길이 l이고 n시간 을 사용하는 경우 일반적으로 l * n바이트를 사용합니다 .

그러나 길이 1 변수에 저장하면 3 + l + n바이트 (또는 2 + l + n필요하지 CompoundExpression (;)않거나 괄호 가없는 곳에 변수를 할당하면 바이트) 만 걸립니다 .


예를 들어, N보다 작은 트윈 소수를 찾는 간단한 문제를 생각해 봅시다 .

이 54 바이트 솔루션을 작성할 수 있습니다.

Select[Range@#,PrimeQ@#&&(PrimeQ[#+2]||PrimeQ[#-2])&]&

이 예에서는 함수 PrimeQ가 세 번 사용됩니다.

PrimeQ변수 이름 을 지정 하면 바이트 수를 줄일 수 있습니다. 다음은 모두 48 바이트 (54-6 바이트)입니다.

Select[p=PrimeQ;Range@#,p@#&&(p[#+2]||p[#-2])&]&
Select[Range@#,(p=PrimeQ)@#&&(p[#+2]||p[#-2])&]&

2

오름차순 키-값 목록을 얻으려면 Sort대신SortBy

와 같은 목록의 list = {{1, "world"}, {0, "universe"}, {2, "country"}}경우 다음 세 문장은 거의 동일합니다.

SortBy[list,#[[1]]&]
list~SortBy~First
Sort@list

결합 Select하고SortBy

때로는 더 큰 세트에서 항목을 선택하여 최소 / 최대를 찾기 위해 정렬해야 할 때가 있습니다. 경우에 따라 두 가지 작업을 하나로 결합 할 수 있습니다.

예를 들어, 최소한 다음 두 문장은 거의 같습니다.

SortBy[Select[l,SomeFormula==SomeConstant&],SortValue&]
SortBy[l,SortValue+99!(SomeFormula-SomeConstant)^2&]

SortBy[Select[l,SomeFormula!=SomeConstant&],SortValue&]
SortBy[l,SortValue+1/(SomeFormula-SomeConstant)&]

1/0ComplexInfinity모든 실수보다 "큰"입니다.

키-값 목록의 경우 :

{SortValue,#}&/@SortBy[Select[l,SomeFormula==SomeConstant],SortValue&]
Sort[{SortValue+99!(SomeFormula-SomeConstant)^2,#})&/@l]

1

Array와 병합##&

다차원 배열을 사용하여 평면화해야하는 결과 목록을 계산할 ##&때는 네 번째 인수로 사용 하십시오. 이렇게하면 Array의 헤드가 대신 ##&( Sequence)로 바뀌 List므로 최종 결과는 (평평한) Sequence결과가됩니다.

2 차원에서 비교

{Array[f,dims,origin,##&]}
Join@@Array[f,dims,origin]

물론, Join@@Array[f,dims] 여전히 2보다 짧은 바이트입니다 (또는 접두어 표기법을 사용할 수있는 경우 3) {Array[f,dims,1,##&]}.

3 차원 {Array[f,dims,origin,##&]}이상에서 원점이 1 인 경우에도 항상 대안보다 짧습니다.

{Array[f,dims,1,##&]}
f~Array~dims~Flatten~2

1

기본값

기본값 은 누락 된 패턴 인수를 효율적으로 처리합니다. 예를 들어, 우리는 패턴 일치시킬 경우 Exp[c_*x]의 값에 대한 규칙에 c, 순진한

Exp[x] + Exp[2x] /. {Exp[c_*x] -> f[c], Exp[x] -> f[1]}
(*    f[1] + f[2]    *)

c누락 될 때마다 기본값을 사용하는 경우보다 많은 바이트를 사용합니다 .

Exp[x] + Exp[2 x] /. Exp[c_.*x] -> f[c]
(*    f[1] + f[2]    *)

기본값 사용은 패턴 다음에 점으로 표시됩니다 c_..

기본값은 오퍼레이션과 연관되어 있습니다. 위의 예제에서 오퍼레이션은 Timesc_.*x있으며에 대한 결 측값 은 1 c_과 연관된 기본값 (1)에서 가져옵니다.의 경우 기본값 은 0입니다.TimesPlus

Exp[x] + Exp[x + 2] /. Exp[x + c_.] -> f[c]
(*    f[0] + f[2]    *)

들어 Power지수, 기본은 1 :

x + x^2 /. x^n_. -> p[n]
(*    p[1] + p[2]    *)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.