답변:
아래 팁은 가장 경제적이거나 가장 많이 사용되는 팁에 따라 다릅니다.
가능한 경우 Mathematica의 고급 명령을 사용하십시오.
MorphologicalComponents
: 코드 골프 : 카운트 제도
이미지 조작 기능 : 예 : 오늘 (9 월 24 일)은 혼다 생일입니다
Subsets
IntegerPartitions
거리 및 유사성 측정 : 예를 들어 EuclideanDistance
바이트 보호기가 될 수 있습니다. 그것을 작성하는 것이 짧다, 그러나주의 Total@Abs[a-b]
대신 a~ManhattanDistance~b
하고 Max@Abs[a-b]
대신 a~ChessboardDistance~b
.
Graphics and
Text
아스키 아트에 사용 : 예 : 스타 프로그래밍!
및 아날로그 시계를 구축
전용 기호 :
긴 형식 이름 대신 논리 및 집합 연산 기호 : ⋂, ⋃, ∧, ∨
Map
과 Apply
: /@
, //@
. @@
,@@@
접두사 및 접두사 표기법 :
Print@"hello"
대신에 Print["hello"]
a~f~b
대신에 f[a,b]
함수가 한 번만 사용되면 순수한 함수는 문자를 절약 할 수 있습니다.
목록에서 문자열 조인 ""<>{"a","b","c"}
대신에StringJoin@{"a","b","c"}
나열 가능한 기능을 악용하십시오. 목록이 길수록 좋습니다.
{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}}
이름이 긴 일부 내장 함수는 더 짧은 표현식으로 대체 할 수 있습니다.
예를 들면 다음과 같습니다.
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]
경우n
0
1
Complex@z
=> {1,I}.z
여기서 z
양식의 목록은{x,y}
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}}]
Fold
대한 귀하의 트릭은를 FromDigits
제외한 다른 모든 기지에서도 작동 한다고 생각합니다 10
. 예를 들어 FromDigits[n,5]
-> Fold[4#+##&,n]
(베이스에 대한 여분의 바이트를 저장하는 보너스 100
와 1000
).
U+F3C7
입니다.
Echo
인쇄하기 때문에 옵션 이라고 생각하지 않습니다 >>
.
Complex[x,y] => {1,I}.{x,y}
생각 x+y*I
합니까?
이것은 다음과 같이 작동하는 일반적인 벡터입니다.
{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
1^{,,,}
보다 1 바이트 작습니다 0{,,,}+1
.
{,,}^0
. 글을 수정하겠습니다.
골프 코드를 만들 때 종종 간단한 &
구문으로 익명의 (순수한) 함수를 사용하는 기능적 접근 방식을 사용 합니다. 이러한 함수의 인수에 액세스하는 방법에는 여러 가지가 있으며 가능성을 잘 이해하여 몇 바이트를 줄일 수 있습니다.
이전에 순수한 기능을 사용한 적이 있다면 아마 이것을 알 것입니다. N은 번째 인수라고 #n
하며 #
별명 역할 #1
. 예를 들어, 다른 함수와 인수를 매개 변수로 사용하는 함수를 작성하려면 (그 인수를 해당 함수에 전달하기 위해)
#@#2&
음수 에서는 작동 하지 않습니다 (예 : 목록에 액세스 할 때 사용할 수 있음).
Mathematica 10의 주요 새로운 언어 기능 중 하나는 Association
s입니다. 기본적으로 다음과 같이 작성된 임의의 키 유형이있는 키-값 맵입니다.
<| 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
이 트릭은 이 팁 에서 바이트를 절약하기 위해 사용되었습니다. Times
juxtaposition은 기술적으로 연산자 일뿐입니다.
1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6
Unequal
단일 문자 값이나 변수가 인수에없는 경우 바이트를 저장하는 데 사용할 수도 있습니다 ( N
99 %의 경우 작동 할 수 있음).
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
이것들을 계속 실험 해보고, 유용하거나 특히 흥미로운 다른 응용 프로그램을 찾으면 알려주십시오!
Sqrt@2
또는 2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=> Join@@a
(때로는)
Function[x,x^2]
=> xx^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
〚
하고 〛
3 바이트를 사용합니다 (UTF8 가정)
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로 인코딩 된 파일을 사용하려면 $CharacterEncoding
Windows 기본값과 같은 호환 가능한 값으로 설정해야합니다 WindowsANSI
. 일부 시스템에서는 기본적으로 UTF-8
단일 바이트에서 이러한 코드 포인트를 읽을 수 없습니다.
순진 접근 방식 사이에서 선택을 y
하고 z
있는지 여부에 따라 x
입니다 0
또는 1
이다
If[x<1,y,z]
그러나 더 짧은 방법이 있습니다.
y[z][[x]]
이 경우에는 표현식을 [[0]]
제공 하기 때문에 작동 하지만 첫 번째 요소 (이 경우 첫 번째 인수) 만 제공하기 때문 입니다.Head
y
[[1]]
z
이것을 사용하여 둘 이상의 값 중에서 선택할 수도 있습니다.
u[v,w][[x]]
u
실제로 무언가로 평가되는 함수 인 경우에는 작동하지 않습니다 . Mathematica를 그대로 유지 u[v,w]
하는 것이 중요합니다 . 그러나 이것은 u
is가 숫자, 문자열 또는 목록 인 경우를 포함하여 대부분의 경우 작동 합니다.
이 속임수에 대한 크레딧은 alephalpha로 이동합니다-나는 그의 대답 중 하나에서 이것을 발견했습니다.
경우 x
이다 제로, 단지 사용하는 대신 1 기반
{y,z}[[x]]
또는
{u,v,w}[[x]]
드문 경우이지만 곱셈이 일부 값에 대해 평가되지 않는다는 사실을 활용할 수도 있습니다.
{"abc","def"}[[x]]
("abc""def")[[x]]
참고 티카 실제로 인수 순서를,이 평가되지 않은 남아있는 경우 곱셈의, 위에서 인 것입니다 그래서하지만 동일 로
("def""abc")[[x]]
Length
이것은 LegionMammal978과 Misha Lavrov의 제안으로 완전히 다시 작성되었습니다. 둘 다 감사합니다.
대부분의 Length
경우을 사용하여 조금 단축 할 수 있습니다 Tr
. 기본 아이디어는 입력을 1
s 목록으로 바꾸어 목록의 Tr
길이와 같은 것을 합산하는 것입니다.
이를 수행하는 가장 일반적인 방법은 1^x
(list x
) 를 사용 하는 것 입니다. 때문에 작품 Power
입니다 Listable
및 1^n
대부분의 원자 값을 n
그냥 1
(모든 숫자, 문자열 및 기호 포함). 그래서 우리는 이미 이것으로 1 바이트를 저장할 수 있습니다 :
Length@x
Tr[1^x]
물론 이것은 이것이 x
보다 우선 순위가 높은 표현식 이라고 가정합니다 ^
.
s와 s x
만 포함하는 경우 다음을 사용하여 다른 바이트를 저장할 수 있습니다 ( 우선 순위가 ).0
1
Factorial
x
!
Length@x
Tr[x!]
드문 경우 이지만 곱셈보다 우선 x
순위가 낮을 수 ^
있지만 여전히 우선 순위가 높습니다. 이 경우 우선 순위가 우선 순위가 낮 @
으므로 실제로 비교해야합니다 Length[x]
. 이러한 연산자의 예는 .
입니다. 이 경우에도 다음 형식으로 바이트를 저장할 수 있습니다.
Length[x.y]
Tr[0x.y+1]
마지막으로, 어떤 종류의 목록에서 작동하는지에 대한 설명이 있습니다.
맨 위에서 언급했듯이 이것은 숫자, 문자열 및 기호 만 포함 된 플랫 목록에서 작동합니다. 그러나 실제로는 약간 다른 것을 계산하지만 더 깊은 목록에서도 작동합니다. 들어 N -D 직사각형 배열 사용은 Tr
당신에게 제공 최단 (제 반대) 사이즈. 가장 바깥 쪽 치수가 가장 짧거나 치수가 모두 같다는 것을 알고 있다면 Tr
-식은 여전히와 같습니다 Length
.
Length@x == Tr[1^x]
. 대부분의 목록에서 작동합니다.
Tr[x!]
대신 사용 하는 것을 발견 했습니다. Tr[1^x]
x
재귀 솔루션 탐색-Mathematica 는 다중 패러다임이지만 기능적 접근 방식이 가장 경제적 인 경우가 많습니다. NestWhile
검색 문제에 매우 컴팩트 한 솔루션이 될 수 있습니다 NestWhileList
그리고 FoldList
당신은 반환 또는 중간 반복의 결과를 처리해야 할 때 강력하다. Map (/@)
, Apply (@@, @@@)
, MapThread
볼프람의에, 정말 모든 기능 프로그래밍 문서 페이지는 강력한 물건입니다.
증가 / 감소를 위해 양식을 단축 - 예를 들어, 대신 While[i<1,*code*;i++]
당신이 할 수있는While[i++<1,*code*]
미리 증분 / 감소 할 수 있다는 것을 잊지 마십시오 . 예를 들어 --i
대신 i--
. 이렇게하면 준비 작업을 제거하여 주변 코드에서 몇 바이트를 절약 할 수 있습니다.
David Carraher의 # 5에 대한 결론 : 동일한 기능이 여러 번 사용될 때 심볼을 할당하면 바이트를 절약 할 수 있습니다. 예를 들어, ToExpression
솔루션에서 4 번 t=ToExpression
사용하는 경우 t@*expression*
이후 에 사용할 수 있습니다 . 그러나이 작업을 수행하기 전에 동일한 기능을 반복적으로 적용하면보다 경제적 인 재귀 적 접근 방법이 있는지 여부를 고려해야합니다.
{}
경우 사용하지 마십시오 @@@
.경우에 따라 다음과 같은 표현이 나타날 수 있습니다.
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}
합니다.
연산자 양식
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]
%
자유 변수를 얻는 데 사용이 팁은 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=
됩니다.
이것은 본질적 으로이 팁 의 추론 이지만 이것은 자체 답변이 필요하다고 생각되는 충분히 일반적인 작업입니다.
목록이 올바른지 확인하는 순진한 방법은
OrderedQ@a
우리는 1 바이트 더 잘 할 수 있습니다
Sort@a==a
그러나 변수를 체크인하고 싶은 것이 없다면 작동하지 않습니다. (우리 Sort[a=...]==a
는 불필요하게 긴 것과 같은 것이 필요합니다.) 그러나 다른 옵션이 있습니다.
#<=##&@@a
가장 좋은 점은 입력이 동일한 바이트 수에 대해 역 정렬되었는지 여부를 확인하는 데 사용할 수 있다는 것입니다.
#>=##&@@a
a) 목록 요소가 서로 다르다는 것을 알고 b) 0과 9 사이의 하한 (포함 또는 역 정렬 순서의 상한)을 알고 있으면 한 바이트를 더 저장할 수 있습니다.
0<##&@@a
5>##&@@a
이것이 왜 작동하는지 보려면 상단에 링크 된 팁에서 "인수 순서"를 확인하십시오.
##>0&@@a
합니다. 정렬 된 상한과 유사합니다.
대신에 StringRepeat[str,n]
사용 (0Range[n]+str)<>""
. 또는 str
슬롯 인수에 의존하지 않는 경우이 팁에 Array[str&,n]<>""
따라 더 좋습니다 .
StringRepeat[s,n+1]
사용 Array[s&,n]<>s
(당신이 이미 가지고있는 경우에도 n+1
변수에 너무).
Table[str,n]<>""
반대로 정렬 된 숫자 목록이 필요한 경우 사용하지 마십시오
Reverse@Sort@x
그러나
-Sort@-x
6 바이트를 절약 할 수 있습니다. 음수 값으로 정렬하면 SortBy
시나리오에 유용합니다 .
Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]
-Sort@-x
?
Break
하나 또는 두 개의 문자를 저장할 수 있는 표현식을 붙일 수 있습니다 . 예 ( 명확하게하기 위해 다른 세부 정보가 제공되지 않음 ) :
result = False;
Break[]
로 변할 수있다
Break[result = False]
하나의 문자를 저장합니다. 해당 표현식이 함수 애플리케이션보다 우선 순위가 낮 으면 다른 문자를 저장할 수도 있습니다.
Print@x;
Break[]
로 변할 수있다
Break@Print@x
문서화되지 않았지만에 대한 인수 Break
는 주변 루프에 의해 반환되는 것으로 보이며 이로 인해 더 많은 비용을 절약 할 수 있습니다.
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]
정기적으로 사용하는 누군가가 ...
때로는 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
.
다음은 많은 작업을 단축 할 수있는 많은 연산자 입력 양식이있는 목록입니다 . 이 중 일부는 다른 게시물에서 언급되었지만 목록이 길고 항상 새로운 몇 가지를 발견 한 것에 놀랐습니다.
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] :> ...
)
코드 골프의 경우 순수 Function
인수는 Slot
s를 사용하여 가장 일반적으로 참조됩니다 . 예 #
를 들어 첫 번째 인수, #2
두 번째 인수 등 ( 자세한 내용 은 이 답변 참조).
대부분의 경우을 중첩하고 싶을 것 Function
입니다. 예를 들어, 1##&@@#&
는 Function
첫 번째 인수로 목록을 가져와 해당 요소의 곱을 출력합니다. 그 기능은 다음과 같습니다 TreeForm
.
최상위 수준으로 전달 된 인수는 최상위 수준에 Function
있는 Slot
s 및 SlotSequence
s 만 채울 수 있으며,이 경우 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
(이름이없는 Slot
s 와 반대로) 명명 된 인수를 나타내는 기호 또는 기호 목록 인 두 개의 인수 형식 을 갖는 사실을 사용 하는 것 입니다. 이 경우이 경우 3 바이트가 절약됩니다.
xArray[Mod[#^2,x]&,...]
U+F4A1
이진 접두사 연산자를 나타내는 3 바이트 개인용 문자 \[Function]
입니다. Function
다른 형식의 이진 형식을 사용할 수도 있습니다 Function
.
Array[xMod[x^2,#],...]&
이것은 위와 같습니다. 그 이유는 명명 된 인수를 사용하는 경우 Slot
s 및 명명 된 인수를 사용하지 않는 SlotSequences
다음에 속한다고 가정하기 Function
때문입니다.
이제 우리가 Function
s를 이런 식으로 중첩 할 수 있다고해서 항상해야한다는 것을 의미하지는 않습니다. 예를 들어, 입력보다 작은 목록의 요소를 선택하려면 다음과 같은 작업을 수행 할 수 있습니다.
Select[...,xx<#]&
Cases
중첩 된 Function
전체 를 사용할 필요가없고 사용 을 피하는 것이 실제로 더 짧을 것입니다 .
Cases[...,x_/;x<#]&
BlockMap
는 Partition
+Map
이 팁의 제목은 "릴리스 정보를 모두 읽으십시오"입니다. 참고로 여기에 10.2 릴리스 정보 와 오늘 10.3 릴리스 정보가 있습니다.
어쨌든 마이너 릴리스조차도 풍부한 새로운 기능이 포함되어 있으며 10.2의 가장 유용한 기능 중 하나 (골프 용)가 새로운 BlockMap
기능입니다. 그것은 본질적으로 Partition
and를 결합 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... *)
답이 동일한 함수 또는 표현식을 여러 번 사용하는 경우 변수에 저장하는 것이 좋습니다.
표현식이 길이 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])&]&
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/0
는 ComplexInfinity
모든 실수보다 "큰"입니다.
키-값 목록의 경우 :
{SortValue,#}&/@SortBy[Select[l,SomeFormula==SomeConstant],SortValue&]
Sort[{SortValue+99!(SomeFormula-SomeConstant)^2,#})&/@l]
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
기본값 은 누락 된 패턴 인수를 효율적으로 처리합니다. 예를 들어, 우리는 패턴 일치시킬 경우 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_.
.
기본값은 오퍼레이션과 연관되어 있습니다. 위의 예제에서 오퍼레이션은 Times
에 c_.*x
있으며에 대한 결 측값 은 1 c_
과 연관된 기본값 (1)에서 가져옵니다.의 경우 기본값 은 0입니다.Times
Plus
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] *)
(Norm[#-#2]&)
대신EuclideanDistance
.