GolfScript 자체가 너무 자주 사용되기 때문에 J에서 골프를 치기위한 편리한 힌트 저장소가 악의 제국과의 싸움에 도움이 될 수 있다고 생각합니다. 이미 간결한 언어를 더 짧게 만들기위한 팁이 있습니까?
J를 배우고 자하는 사람들에게는 jsoftware 사이트, 특히 어휘 , Learning J 안내서 및 J for C 프로그래머 안내서가 시작됩니다.
GolfScript 자체가 너무 자주 사용되기 때문에 J에서 골프를 치기위한 편리한 힌트 저장소가 악의 제국과의 싸움에 도움이 될 수 있다고 생각합니다. 이미 간결한 언어를 더 짧게 만들기위한 팁이 있습니까?
J를 배우고 자하는 사람들에게는 jsoftware 사이트, 특히 어휘 , Learning J 안내서 및 J for C 프로그래머 안내서가 시작됩니다.
답변:
J에서 마지막 몇 글자를 짜내는 데는 미묘한 부분이 많이 있습니다. 다음의 경우, 각 대문자가 원시 동사라고 가정합니다 (즉, 이름을 구분하는 데 필요한 공백을 제거합니다).
당신은 기차가가는 있고, 당신은을 통해 다른 도중에 꼭대기에 함수를 적용해야하는 경우 ([:FLGR)
와 (LF@:GR)
같은 수의 문자를 가지고 있지만, (LF@GR)
하나를 저장합니다. G의 프레임이 F의 모나드 순위보다 크거나 같으면 유효한 변환입니다. 특히, 모든 열차는 무한 순위를 가지고 수행 , ,. ,: ~. /: \: [ ]
하고 대부분 사용 #
하고 |.
.
목록에서 문자열을 선택해야하고 공백이없는 경우을 사용하십시오 >i{ab`cd`ef
. 더럽지 만 단일 문자를 당기지 않고 더 짧게하려면 charlist의 길이가 4가 아닌 한 처리해야 할 각 새 문자열의 문자를 저장합니다. 무슨 일이 일어나고 있는지 정의되지 않은 이름은 동사에 대한 참조로 처리되며 해당 동사의 거론을 취할 때 상자의 문자열이 나타납니다. 명사, 부사 또는 결합 유형으로 이미 정의 된 이름은이 방식으로 사용할 수 없습니다. 이러한 이름은 이전에 `
확인할 수 있기 때문 입니다.
암묵적 동사가 아닌 작업 할 표현이 충분하다면 운 좋게도 변수에 재사용하는 비트, 명사, 동사 또는 부사를 할당하는 것이 좋습니다. Parens는 때때로 당신이 전에 있던 공간에 딱 맞아서 스스로를 갚을 것입니다. 그리고 대부분의 그러한 정의는 그들이 다시 한번 재사용된다면 그만한 가치가 있습니다.
같은 연결 (FGH)^:(u`v`w)
은 다시 쓸 수 있습니다 u`v`w(FGH^:)
. 이 방법은 올바른 길이의 인자를 제거하는 경우에만 저장하지만 아무리 긴 길이의 열차에서도 작동합니다. 이 트릭은 왼쪽 피연산자를 미리로드 할 때만 작동합니다. (무슨 일이 일어 났는지 전혀 몰랐습니까? '속담 부사' 를 찾아 J Dictionary 의 구문 분석 및 실행 섹션을 연구하십시오 .)
사용하지 마십시오 a.&i.
, 사용 u:
! 그러나 길이 {&a.
와 3&u:
동일하며 전자는 연결에 더 유용 할 수 있습니다 (연결에 따라 다름).
상황이 좋아 (2%~F)
하고 (F%2:)
길이가 동일합니다. 때로는 열차의 나머지 모습 @
에 따라 첫 번째 요령으로 작성된 트릭으로 구조를 재구성하여 필사적 인 캐릭터를 구할 수 있기 때문에 유용 합니다. (그리고 물론, 경우 F
입니다 ]
기차가 사용 모나드이다 %&2
대만족, 숯불을 절약 할 수 있습니다.)
가장 왼쪽 동사 가 ]
있거나 같은 고리 모양의 기차 ( [
예 :) (]FGH)
.
]
이기적인 응용 프로그램을 분리하고 올바른 인수 만 사용할 수 있습니다. ( (]FGH)~
적어도 1 자 이상의 페널티 로 왼쪽으로 (FGH)@]
바꾸십시오 .) char를 저장하고 gerunds에 매우 편리합니다![
모나 딕 방식으로 적용된 후크에서 오른쪽의 부작용에 대한 작업을 수행 한 다음 인수를 다시 반환 할 수 있습니다. 가장 일반적인 사용법은 1!:2
형식화 정크와 함께입니다.I / O가 짜증 난다. 할 수있는 모든 것에서 루프를 만들어 프로세스 속도를 높입니다. 1!:1
순위를 가지고 0
, 그리고 모두 1!:2 3
순위를 가지고는 _ 0
, 예를 들어, 그래서 1의 배열을하여이를 활용하고 실행하는 1!:1
그들을 직접. 참고 ".
또한 일반적으로 단지 바로 뒤에 넣을 수 있도록 순위 1을 가지고 1!:1
도, 그리고를 통해 첨부하지 @
또는 순위 헛소리.
이것을 넣을 곳을 찾기는 쉽지 않지만 ::
유용 할 수 있습니다.
::]^:_
예를 들어, 더 이상 할 수 없을 때까지 위험한 일을 할 수있는 특히 강력한 조합입니다. (일반적인 ^:_
-as-a-loop주의 사항 에 따라 다름 )
또한 {
원하는 색인이없는 목록에서 사용할 수 있습니다 . 도메인 색인이 발생하면 도메인 오류가 발생하기 때문입니다. 예를 들어리스트가 존재하는 경우에만리스트의 헤드를 가져 오는 데 유용합니다 ( ::]
빈리스트 ::_1:
를 리턴하거나 오류 코드를 리턴하는 등을 사용하십시오).
]`($:@u)@.v
보통보다 짧은 만들 수 있습니다 u^:v^:_
, 특히의 정의를, u
그리고 v
주변에 재생할 수 있습니다. 비슷한 경우 조건부 등에 보유하고 u^:(1-v)
대 ]`u@.v
. 특히 이름이 많은 동사가 떠 다니는 경우 옵션을 고려하십시오. 또한 좀 더 융통성 $:
이 있지만를 사용 하는 경우 반복하기 쉬운 재귀 깊이가 있음을 기억하십시오 . (보통 1800 회 반복?)
%&2
하면 문자가 절약됩니다." 그리고 -:
다른 것을 저장합니다!
J에서 골프를 할 때 가장 중요한 것은 문제를 이해하는 것뿐만 아니라 문제를 일련의 배열 변환으로 줄이는 것입니다. J 코드로 성공하려면 이러한 사고 방식을 이해해야합니다.
예를 들어, 최근의 문제는 가장 큰 하위 배열 문제 를 해결하도록 요청했습니다 . 이 문제를 해결하기위한 주식 알고리즘은 Kadane의 알고리즘에 다음과 같은 비공식적 인 설명이 있습니다.
배열과 각 위치를 살펴보고 여기에서 끝나는 가장 큰 하위 배열의 합계 (최대 0 또는 현재 색인의 값에 이전 위치에서 끝나는 가장 큰 하위 배열의 합계)를 찾으십시오. 전체 배열에서 가장 큰 하위 배열을 찾으려면 이러한 하위 배열의 최대 값을 계산하십시오.
명령형 코드로의 변환은 간단합니다.
이 알고리즘은 처음에는 축소처럼 보이지 않는 명시 적 루프가 있으므로 J에 대해 한 눈에 복잡해 보입니다. 알고리즘이 수행하는 작업을 알고 있으면 개별 단계를 풀고 실제로 두 가지 간단한 배열 작업을 수행하는 것을 볼 수 있습니다.
이제이 두 단계는 J에서 구현하기가 매우 쉽습니다. 번역은 다음과 같습니다.
(0 >. +)/\. y , 0
–이 단계는 J의 패러다임에 더 잘 맞도록 어레이의 다른 쪽 끝에서 작동합니다. 0 >. +
에 대한 암묵입니다 0 >. x + y
.>./ y
종합하면, 우리는 알고리즘의 매우 간결한 구현을 얻습니다.
>./ (0 >. +)/\. y , 0
알고리즘 구현에 접근하는이 방법을 배우면 솔루션이이 코드만큼 간결 해집니다.
시간이 지남에 따라 축적 한 몇 가지 트릭이 있습니다. 이 목록은 J golfing에 대한 지식이 많아 질수록 확장 될 것입니다.
=
은 처음에는 이상하지만 ASCII 예술 과제에 매우 유용합니다.&
힘있는 연결을 원할 때 암묵적인 맥락에서 2 차원 을 사용하십시오 . 어휘는 u@[&0
나에 대한 암묵적 대안으로 암시합니다 4 : 'u^:x y
.[:
또는 @:
시퀀스를 피할 수 있습니다 . 예를 들어의 결과 중 첫 번째 항목을 삭제하려면 어떤 이유로 든 불가능한 경우 대신 사용하십시오 .u@v
u
v
1}.v
[:}.v
}.@v
] v
이따금 문맥에서 v@]
모나 딕을 사용하려는 경우 보다 종종 짧습니다 v
. 이것은 특히 v
동사가 길 때 유용합니다 .m (n v w) y
대신 대신 쓸 수 있습니다 (n v m&w) y
. 공백과 괄호를 피할 수 있습니다.#\
대신에 >:@i.@#
.u &. v
v
앞면이 있을 때 유용합니다 . 그렇지 않은 경우 [: vinv u & v
또는 u & (v :. vinv)
대신 사용할 수 있습니다 .^:_
플러드 필 또는 시뮬레이션과 같이 수렴에 도달하려는 알고리즘에 매우 유용합니다.=.
및 =:
문구의 어느 곳에 나 포함될 수 있습니다. 암묵적 표기법으로는 충분하지 않은 단일 라이너를 만들려면 이것을 사용하십시오.,
다차원 배열을 줄일 때 다중 축소 대신 모나 딕 을 사용하십시오 .루프 사용에주의하십시오.
J는 구조 (반복했지만 for. do. end.
, while. do. end.
및 변형을), 당신이 그들을 사용하여 자신을 발견 할 경우 알고리즘은 J의 골프 강점과 할 수있는 문자 절감이 있다는 것을 재생되지 않는 가능성이있다.
^:
전원 연결은 당신의 친구입니다. 동사 x
시간 을 실행하려면
verb^:x
목록에서 각 반복의 결과가 필요한 경우 :
verb^:(i.x)
^:
조건부로 동사를 실행하는 데 사용할 수도 있습니다 .
+:^:(3<])"0[ 1 2 3 4 5 6
1 2 3 8 10 12
항목이 3보다 큰 +:
경우 두 배가 됩니다 ( 동사 순위가 변경되어 한 번에 항목이 작동 함).^:
3<]
"0
(i.x)
예 와 같이 작동 f^:(<x)
합니다 f^:(i.x)
. 즉
입력
1!:1[1
Enter 키를 누르면 한 줄의 입력이 종료됩니다.
1!:1[3
여러 줄의 입력이 필요합니다 (Mac의 경우 Ctrl-D, Windows의 경우 Ctrl-C로 끝남).
숫자를 입력하려고하면를 사용 ".
하여 문자열을 평가하고 조작 할 수있는 숫자 목록을 반환합니다. 하나의 숫자를 사용하고 있지만 숫자에 대해 개별적으로 조작 해야하는 경우 ".,.
(Jan Dvorak의 의견 덕분에) "."0
문자열을 별도의 숫자로 나눕니다.
"."0[1!:1[1
12345
1 2 3 4 5
".,.1!:1[1
12345
1 2 3 4 5
문자열을 읽는 경우 별도의 문자열로 된 박스 목록을 얻는 가장 짧은 방법은을 사용하는 것 ;:
입니다. 공백으로 구분 된 문자열에 가장 적합합니다.
;:1!:1[1
hello world
┌─────┬─────┐
│hello│world│
└─────┴─────┘
1!:1[2
(있는 경우) 잘 될까요?
2
유효하지 않은 것처럼 보 입니까? 지금 시도해 볼 J 컴퓨터가 없습니다. 내가 볼 수있는 곳에 2
대한 메모 바로 아래 1!:1
입니다 1!:2
.
".
순위가 1-xx 이므로 ,.
항상 2D 배열을 생성하므로 ".,' ',.
(공간이있는 스티치, 라벨 지정 및 평가, 8 자) 8 문자로만 바꿀 수 있습니다 ".,.
(레이블 항목 및 평가, 4 자).
일반적으로 OEIS 시퀀스 문제를 해결하려면 해당 페이지에 제공된 수식 중 하나를 사용해야합니다. 이들 중 일부는 J에 잘 적응하고 다른 일부는 J에 적합하지 않습니다. 재귀 수식은 간단하지만 반복이 간단하지 않을 수 있습니다. 내가 사용하기 시작한 패턴은
(s(]f)^:[~]) n
] Gets n
s The first value in the sequence
~ Commute the argument order, n is LHS and s is RHS
[ Gets n
^: Nest n times with an initial argument s
(]f) Compute f s
Returns (f^n) s
여기서 s
순서의 첫 번째 값 f
은 이전 항에 지정된 다음 항을 계산하는 동사이며 계산 n
하려는 항의 인덱스 (0부터 시작)입니다. 이 방법은 다이어 드의 힘을 계산할 때 LHS가 다이어 드에 바인딩되어 새로운 모나드를 형성하고 그 모나드가 초기 값에 중첩된다는 사실에 의존합니다. 권력 부사에 주어진 dyad 는 LHS에 대한 (]f)
인덱스 n
와 시퀀스의 항 값 이 주어진 후크 s
입니다. 후크는 모나드로 적용 f
되며 의 결과를 반환하기 위해 s
무시 n
됩니다 f s
.
때로는 J가 표준 라이브러리 에서 동사를 지원한다는 것을 알 수 있습니다 . 예를 들어, 대부분의 비트 단위 정수 연산은 기본 호출을 사용하는 것보다 짧은 이름에 바인딩됩니다.
AND =: (17 b.) NB. it is actually '$:/ :(17 b.)'
날짜 및 시간 내장도 가능합니다.
값 집합이 [a, b, c]
있고와 같은 제품을 기반으로 범위를 형성하려는 [0, 1, 2, ..., a*b*c-1]
경우 일반적인 접근 방식은 제품을 찾은 다음 [:i.*/
6 바이트의 비용이 드는 범위를 형성하는 것 입니다. 더 짧은 방법은 ,@i.
4 바이트입니다. i.
여전히 계산하면서 다차원 배열을 형성 할 수 있으므로 평평하게하면 동등한 범위가 생성됩니다.
값을 인쇄하고 명시적인 루프없이 계속 사용하는 암묵적인 방법 ([echo)
은 모나드 경우입니다. echo
표준 라이브러리의 동사는 그 내용을 stdout
인터프리터에 사용 된 것과 동일한 형식으로 인쇄합니다 . 그런 다음 후크는 왼쪽 [
동사를 사용하여 동일한 입력 값을 전달합니다 .
정수의 기본 10 자리를 얻는 표준 방법은 10#.inv]
8 바이트가 너무 비쌉니다! 다른 방법은 문자열을 문자열로 변환하여 순위 0으로 구문 분석 "."0@":
하여 바이트를 저장하는 것이지만 더 좋은 방법은 ,.&.":
다른 바이트를 저장하여 최종 비용을 8 대신 6 바이트로 만드는 것입니다.
나에게 유용한 몇 가지를 공유하고 있습니다. 기본적으로이 모든 것들은 내가받은 팁이지만, 대부분의 크레딧은 없습니다.
사용하는 대신 +/@:(FGH)
사용 (1#.FGH)
. 이것은베이스 1로 디베이스를 의미하며, 이는 효과적으로 어레이를 합산하는 것을 의미합니다. 의 길이는 길지만 +/
캡이나 컴포지션이 필요하지 않으므로을 사용하는 것보다 훨씬 짧습니다 +/
.
부울 목록이 있고 후행 진실의 수를 세려면를 사용하십시오 #.~
. 여기를 참조하십시오 . APL의 대답 이 어떻게 작동하는지에 대한 좋은 설명을 제공합니다. 물론, 이것은 나에게 두 번만 도움이되었지만 어쨌든 공유 할 것이라고 생각했습니다.
구체적인 속임수가 아니라 일반적인 제안 : 부사 &.
는 아래에서 우아하고 (더 중요한 것은) 짧은 솔루션을 만듭니다. 골프를 칠 때 명심하십시오.
종종 이진 및 기타 기본 변환 문제에 유용합니다 . 예를 들어 숫자에서 가장 중요한 비트를 제거하는이 코드는 }.&.#:
다음과 같습니다. 10 진수로 돌아 가기). 간단한 해결책은 2 바이트 더 #.@}.@#:
있습니다.
Under는을 사용할 수 있으므로 10 진수로 작업해야하는 문제에도 도움이됩니다 u&.":
. 예를 들어, 마일리지를 십진수로 나누는 단거리 마일은 다음에서 사용합니다 ,.&.":
.
마지막 예는 벡터의 크기를 찾는 것 입니다. -square는 순위가 0 이므로 -square를 사용 하여 -square +/&.:*:
에서 모든 결과를 수집해야 합니다.*:
&.:
*:
때때로, 당신은 rank 와 같은 <"0 i.3 3
동사를 적용하고 싶은 코드를 가질 것 입니다. 그러나 명사 ( ) 를 사용하는 경우 공백을 포함해야하는 경우가 종종 있습니다. 이를 피하기 위해, 등가의 다른 동사 를 사용하고 대신 사용할 수 있습니다 . 예를 들어 rank가 있기 때문에 대신 사용할 수 있습니다 .v
r
0
u
u"v
+
0 0 0
<"+
<"0
다음은 모든 동사와 그 순위의 표입니다 (을 사용하여 얻을 수 있음 v b. 0
).
0 0 0 > + * - % ^ | ! ? <. <: >. >: +. +: *. *: %: ^. j. o. q: r.
0 _ _ -. -: E. i: p:
1 0 1 p..
1 0 _ { A.
1 1 0 p.
1 1 1 #.
1 1 _ C.
1 _ _ ;: ". i. I.
2 _ 2 %.
_ 0 0 = < ~. ~: {: }: ?. L.
_ 1 0 #:
_ 1 _ $ # |. |: {. }. ": {::
_ _ _ , ; [ ] _: $. $: ,. ,: /: \: [: e. s: u: x: 0:
이 표를 사용하려면 r
왼쪽 에서 원하는 순위 를 찾은 다음 v
오른쪽에서 적절한 동사를 선택하십시오 . 예를 들어, v
깊이 2 _ 2
에서 동사를 벡터화 해야하는 경우 왼쪽에서 해당 순위를 찾아 %.
오른쪽에서 선택하십시오 . 그런 다음 v"%.
대신 사용 합니다 v"2 _ 2
.
strings
도서관 : 골프 팁문자열 라이브러리는 문자열 조작으로 모든 작업을 수행하는 데 크게 도움이됩니다. 물론, include'strings'
J를 고려하면 비용이 많이 들지만 때로는 이점을 얻을 수 있습니다.
stringreplace
문자열 바꾸기를 사용하여 자신을 찾으십니까? A stringreplace B
와 같은지 확인 하십시오 B rplc A
.
실제로 이것은 다음과 같이 rplc
구현됩니다.
rplc
stringreplace~
cuts
동사 cuts
는 다음을 제공합니다.
x에서 y를 자르십시오 (접합) 문자열 (동사 컷 n) 텍스트 n = _1 (최대 문자열 제외) n = 1 ~ 문자열 포함 n = _2 이후 문자열 제외 n = 2 이후 및 문자열 포함
실제로 문자열을 자릅니다.
코드에서 숫자 사용에 제한이있는 경우 :
0 %_
: 무한대로 나눈 값.
1 #_
: 얼마나 많은 무한대?
2 #_ _
: 두 개의 무한대.
3 verb
: 내장되어 있습니다.
4 dyad
: 다른 내장.
기본 무한대 리터럴 : 11 : _bb
, 26 : _bq
등
x (F G H) y == (x F y) G (x H y)
x (F G) y == x F (G y)
x ([: G H) y == G (x H y) NB. G is called monadically
NB. Verbs are grouped from the right by units of 3.
NB. For the following, think like G, I, K are replaced by the results of (x G y) etc.
NB. and then the sentence is run as usual.
x (F G H I J K) y == x (F (G H (I J K))) y
== x F ((x G y) H ((x I y) J (x K y)))
NB. Using conjunctions for dyadic verb
x F@G y == F (x G y) NB. Atop; Same as x ([: F G) y; Consider as golfing alternatives
x F&G y == (G x) F (G y) NB. Compose; G is applied monadically to both arguments
(F G H) y == (F y) G (H y)
(G H) y == y G (H y) NB. Note that this is different from APL
([: G H) y == G (H y)
(F G H I J K) y == (F (G H (I J K))) y
== y F ((G y) H ((I y) J (K y)))
F@G y == F (G y)
x&F y == x F y
F&y x == x F y
y F~ x == x F y
F~ y == y F y
(F x) G (H y)
암묵적 솔루션 : (G~F)~H
; 실제 동사에 따라 왼쪽 및 오른쪽 인수를 재정렬하여 제거하십시오 ~
.
x ((G~F)~H) y
x (G~F)~ (H y)
(H y) (G~F) x
(H y) G~ (F x)
(F x) G (H y)
>:y == 1+y
<:y == 1-~y or _1+y
+:y == 2*y
-.y == 1-y
-:y == 2%~y
*:y == 2^~y
#.y == 2#.y
#.inv y == 2#.inv y NB. #: doesn't work this way
{.y == 0{y
{:y == _1{y
}.y == 1}.y
+/y == 1#.y
(G~F)~H
순전히 거품이 있습니다!
&
당신의 친구입니까, 현명하게 사용하십시오v
동사이며, n
명사, x
그리고 y
각각 왼쪽과 오른쪽 인수한다.
&
: ~
부사 / 접합 사슬 내부 소개부사 / 결합 체인은 왼쪽부터 평가합니다. 그래서 우리가 원하는 동안 _2&+/\&.>
구문 분석하기 때문에 같은 것이 작동하지 않습니다 . 이 경우, 우측의 왼쪽 / 스와핑 에로, 바이트를 저장할 수 있기 때문에이 일 파싱 등 . 왜 이것이 작동하는지 확인하려면 :(_2&+)/\&.>
_2&(+/\)&.>
+/\
+/\~&_2&.>
((+/\)~)&_2&.>
+/\~&_2 y
is equivalent to
y +/\~ _2
is equivalent to
_2 +/\ y
is equivalent to
_2&(+/\) y
&
: 반복 x
횟수당신은 알고 있었나요 당신은 왼쪽 인자를 줄 경우 x
에 &
함수가 적용 x
에 번y
? 몇 가지 과제는 특정 작업 x
시간 을 요구합니다 . 주로 두 가지 방법으로 달성 할 수 있습니다.
^:
올바른 피연산자없이 전력 연산자 사용연산이 v
이면 v^:
왼쪽 피연산자가 주어지면 모나 브 동사가되는 부사 열차가됩니다. 그래서 v
에 적용 y
, x
배.
x(v^:)y
is equivalent to
(v^:x)y
&
을 가장 바깥 쪽 연결로 사용이를 사용하려면 일정하게 식별해야 n
하고 이항 동사 u
그래서 중 하나, n u y
또는 y u n
동일합니다 v
. 그런 다음 전체 작업을 작성 n&u
하거나 u&n
해결할 수 있습니다 . 이 형식은 상수 선택이 분명 할 때 가장 효과적입니다 3 u:
( 예 : 3 in (문자를 ASCII 값으로 변환)).
또한, u&n
약간 위에 바람직 n&u
의 최 구조 때 u
접속사 또는 부사 (있는 경우 n&u
이어야한다 n&(u)
; 수행 할 수있는 u~&n
대신에).
&
dynamic과 유사한 의미에서 임의의 인수에 대해 임의의 함수를 반복적으로 달성하기 위해 기차의 어느 곳에 나 2 차원을 배치 할 수 있습니다 ^:
.
GolfScript gets its own way far too often
2019