골프를위한 팁에 Perl 6


16

Perl 6에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 저는 Perl 6에 특정한 코드 골프 문제에 적용될 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.

Perl 6은 Perl 5가 아니므로이 질문은 중복되지 않습니다. Perl 5 골프에 대한 대부분의 팁은 Perl 6에는 적용되지 않습니다.

답변:


9

sub리터럴을 피하십시오 . 대부분의 경우 {}코드 블록에 간단히 사용할 수 있습니다 . 예를 들어 다음 코드를 작성하지 마십시오.

sub ($a){$a*2}

대신 블록 구문을 사용하십시오. 이것은 또한 사용할 수 있습니다 $_, @_그리고 %_당신은 단지 하나의 변수가 필요하면 자리 표시 자 변수. 더 필요한 경우 $^a, $^b변수 등을 사용할 수 있습니다 .

{$_*2}

또한 드문 경우에, 어떤 코드 (특히 간단한 표현식이있는 경우)를 사용할 수도 있습니다. 는 *자리 표시 자 인수를 대체합니다.

* *2

8

Perl 6은 Nd , Nl 및  No 범주의 모든 유니 코드 문자 를 유리수 리터럴로 사용할 수있는 기괴한 기능을 가지고 있습니다 . 이 중 일부는 ASCII로 숫자 값을 쓰는 것보다 짧습니다.

  • ¼(2 바이트)보다 짧 .25거나 1/4(3 바이트).
  • ¾(2 바이트)보다 짧 .75거나 3/4(3 바이트).
  • (3 바이트)는 1/16(4 바이트) 보다 짧습니다 .
  • 𐦼(4 바이트)는 11/12(5 바이트) 보다 짧습니다 .
  • 𒐲(4 바이트)는 216e3(5 바이트) 보다 짧습니다 .
  • 𒐳(4 바이트)는 432e3(5 바이트) 보다 짧습니다 .

이에 대한 후속 조치로, 여러 자릿수 및 / 또는 빼기 say (3² + 4², 2²⁰, 5⁻²)==> 와 함께 유니 코드 지수를 사용할 수도 있습니다 (25 1048576 0.04). 이 같은 학대 할 수 있습니다 유니 코드의 전체 목록은 여기에 있습니다 : docs.perl6.org/language/unicode_texas .
Ramillies

8

입력을 읽는 기능을 배우십시오. Perl 6에는 ARGV 또는 STDIN (ARGV에 아무것도 지정되지 않은 경우)에서 입력을 쉽게 읽을 수있는 많은 흥미로운 기능이 있으며, 올바르게 사용하면 코드가 단축 될 수 있습니다. 파일 핸들 메소드로 호출하면 특정 파일 핸들에서 작동하도록 강제 할 수 있습니다 (예를 들어 from에서 읽지 STDIN만 ARGV에서 인수를 읽어야 하는 경우 유용합니다 ).

get

이 함수는 단일 라인을 가져 와서 자동으로 꽉 들어 오게 할 필요가 없습니다. 한 줄만 읽어야하는 경우에 유용합니다.

lines

이 함수는 파일 또는 STDIN에서 모든 행을 가져옵니다. 게으른 목록이므로와 함께 사용 for하면 필요한 내용 만 읽습니다. 예를 들어.

say "<$_>"for lines

slurp

전체 파일 또는 STDIN을 읽고 결과를 단일 문자열로 리턴합니다.


버그는 수정되었습니다. 언제 알지 못하지만 say "<$_>" for lines지금 작동합니다
cat

5

경고 : 텍스트 벽이 다가오고 있습니다. 시간이 지남에 따라 수집 된 많은 작은 트릭입니다.

익명 블록으로 솔루션 작성

이것은 이미 언급되었지만 반복하고 싶습니다. TIO에서는 my $f =헤더에 코드를 작성하고 블록을 코드로 작성하고 바닥 글을로 시작할 수 ;있습니다. 이것은 작업을 수행하는 가장 짧은 방법 인 것 같습니다 (입력 내용을 신경 쓰지 않아도되므로 인수로 제공됩니다).

또 다른 좋은 방법은 -n또는 -p스위치를 사용하는 것이지만 TIO에서 작동시키는 방법을 찾지 못했습니다.

인수를 전달할 때 콜론 구문을 사용하십시오.

즉, 대신 1 개의 문자를 저장하고 저장할 thing.method(foo,bar)수 있습니다 thing.method:foo,bar. 불행히도, 분명한 이유로 결과에 다른 메소드를 호출 할 수 없으므로 블록의 마지막 메소드에만 사용하는 것이 좋습니다.

$_최대한 많이 사용하십시오

이 때문에 여러 개별 인수보다 단일 목록 인수를 취하는 것이 더 나은 경우도 있습니다. 액세스 할 때 $_, 당신은 점으로 시작하여 메소드를 호출 할 수 있습니다 : 예는 .sort동일합니다 $_.sort.

그러나 각 블록은 자체 $_블록을 가지므로 외부 블록의 매개 변수는 내부 블록으로 전파되지 않습니다. 내부 블록에서 메인 기능의 파라미터에 액세스해야하는 경우 ...

사용할 ^수없는 경우 변수를 사용하십시오.$_

다음 ^과 같이시길과 변수 이름 사이에를 삽입하십시오 $^a. 이들은 블록 안에서만 작동합니다. 컴파일러는 먼저 블록에 몇 개가 있는지 계산하고 사전 식으로 정렬 한 다음 첫 번째 인수를 첫 번째 인수에 지정하고 두 번째 인수를 두 번째 인수에 지정합니다. ^필요성은 가변 최초로 검출에 사용된다. 따라서 {$^a - $^b}2 개의 스칼라를 빼고 뺍니다. 중요한 것은 알파벳 순서뿐이므로 {-$^b + $^a}같은 것입니다.

혹시 뾰족한 블록 구문을 (같이 사용하는 것 같은 느낌 경우 ->$a,$b {$a.map:{$_+$b}}), 당신은 훨씬 더를 사용하여 블록의 시작에 가짜 문을 작성하는 길 이죠 ^(같은 메인 블록에 사용하지 않을거야 각 인수에 대해 {$^b;$^a.map:{$_+$b}}) (주 골프를하는 더 좋은 방법은 {$^a.map(*+$^b)}바로 컨셉을 보여주고 싶었습니다.)

운영자 문서를 주의 깊게 읽으십시오

운영자는 매우 강력하며 종종 작업을 수행하는 가장 짧은 방법입니다. 특히 메타 사업자 (인수로 통신을 사업자) [], [\], X, <</ >>그리고 Z당신의주의의 가치가있다. meta-op이 다른 meta-op을 인수로 사용할 수 있음을 잊지 마십시오 ( 여기 에서 XZ%%내가 사용했던 것처럼 ). 당신이 사용할 수있는 지도보다 훨씬 저렴 될 수있는, 너무 메소드 호출 ( 대신 ,하지만 조심, 그들은 같은 아니에요! ). 마지막으로 바이너리를 사용하기 전에 훨씬 적은 수의 문자로 동일한 작업을 수행 한다는 점을 명심 하십시오.>>@list>>.method@list.map(*.method)<< >>Z

많은 메타 -op를 서로 힙핑하는 경우 대괄호를 사용하여 우선 순위를 지정할 수 있습니다 []. 너무 많은 연산자를 쌓아 컴파일러를 혼란스럽게 할 때 절약 할 수 있습니다. (매우 자주 발생하지는 않습니다.)

마지막으로, BOOL, 지능 또는 str을에 강제 변환 것들에 필요한 방법을 사용하지 않는 경우 .Bool, .Int그리고 .Str, 오히려 사업자 ?, +~. 또는 더 나은 방법으로 산술 표현식에 넣어서 Int 등으로 강제하는 것입니다. 목록의 길이를 얻는 가장 짧은 방법은 +@list입니다. 2를 목록 길이의 거듭 제곱으로 계산하려면 그냥 말하면 2**@list올바른 일을 할 것입니다.

자유 상태 변수 $를 사용 @하고%

각 블록에서 $(또는 @또는 %) 의 모든 발생은 반짝이는 새 스칼라 (또는 배열 또는 해시) 상태 변수 (값이 블록에 대한 호출에서 지속되는 변수)를 나타냅니다. 소스 코드에서 한 번만 참조해야하는 상태 변수가 필요한 경우이 세 가지가 큰 친구입니다. (대부분 $.) 예를 들어, 역 수학 사이클 챌린지에서는으로 인덱스 된 배열에서 주기적으로 연산자를 선택하는 데 사용할 수 있습니다 $++%6.

의 하위 양식 사용 map, grep외.

의미 : 대신 할 map {my block},list보다 list.map({my block}). 를 사용하더라도 list.map:{my block}이러한 두 가지 접근 방식은 동일한 바이트 수로 나타납니다. 그리고 종종 메소드를 호출 할 때 목록을 괄호로 묶어야하지만 서브를 호출 할 때는 그렇지 않습니다. 따라서 하위 접근 방식은 항상 방법 방법과 동일하거나 적어도 동일합니다.

여기에서 유일한 예외는 mapped, grepped 등 의 오브젝트 가에있는 경우 $_입니다. 그럼 .map:{}분명히 이겼다 map {},$_.

사용 접합 ( &|) 대신 &&하고 ||.

분명히, 그들은 1 바이트 더 짧습니다. 반면에 부울 컨텍스트로 강제로 축소해야합니다. 이것은 항상으로 수행 할 수 있습니다 ?. 여기서 당신은 !opbool 컨텍스트를 강제 op하고 결과를 사용 하고 부정 하는 meta-op에 대해 알고 있어야합니다 .

당신은 목록을 가지고 있고 사용하지 않는, 접합으로 바꿀하려는 경우 [&][|]. 대신 .any및을 사용하십시오 .all. 또한이 .none그렇게 쉽게 접합 작전에 의해 모방 할 수없는.


1
나는 생각 &&하고 ||여전히 단락에 유용합니까?
ASCII 전용

@ASCII 전용 : 예, 물론입니다.
Ramillies

4

변수에 사용되는 공간을 줄입니다

여기에는 몇 가지 부분이 있습니다.

공백 제거

사용하여 선언 된 변수는 my일반적으로 my변수 이름 사이에 공백없이 선언 될 수 있습니다 . my @a와 같습니다 my@a.

시길리스 변수 사용

다음과 같이 백 슬래시를 사용하여 변수를 선언하여 변수 이름 앞의시길을 제거 할 수 있습니다.

my \a=1;

(불행히도 공백을 제거 할 수 없습니다 :()

나중에 나중에 변수 이름으로 참조 할 수 있으므로 유용합니다.

 a=5;
 a.say

기본적으로 코드의 다른 곳에서 변수를 두 번 이상 사용하면 바이트가 절약됩니다. 단점은 변수를 초기화해야한다는 것입니다.

사용 $!$/

이러한 사전 선언 된 변수는 일반적으로 예외 및 정규식 일치에 각각 사용되지만을 사용하여 정의 할 필요는 없습니다 my.

$!=1;
$/=5;

$/배열로 사용하고 바로 가기 $와 숫자를 사용하여 $/배열의 해당 요소에 액세스하는 것이 특히 유용합니다 .

$/=100..200;
say $5;  #105
say $99; #199

2

...대신 사용first

일반적으로 어떤 조건과 일치하는 첫 번째 숫자를 찾으려면 &f다음과 같이 나타낼 수 있습니다.

first &f,1..*

그러나 대신 ...연산자를 사용할 수 있습니다 .

+(1...&f)

에서 시작 0해야하는 경우 -1이후에 대신 사용할 수 있습니다 +.

@acondition이 있는 목록에서 첫 번째 요소의 색인을 원하면 &f일반적으로 다음을 수행하십시오.

first &f,@a,:k

대신 :

(@a...&f)-1

(또는 색인이 0 인 경우 그 반대). 같은 방식으로 모든 요소를 ​​조건을 통과 한 첫 번째 요소까지 가져올 수 있습니다.

이것의 단점은 목록 어떤 시점에서 조건을 통과해야한다는 ...것입니다. 그렇지 않으면 연산자는 목록의 끝을 외삽하여 오류를 던질 것입니다. 왼쪽의 Whatever 코드는 시퀀스의 일부로 해석되므로 사용할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.