GolfScript에서의 골프 팁


35

이 게시물이 아직 존재하지 않습니까?

물론 GolfScript 는 골프 용 으로 만들어 졌으므로 특별한 팁이 필요 없다고 생각할 수도 있습니다. 그러나 GolfScript의 기능을 최대한 활용하려면 분명하지 않은 요령을 배워야합니다. 이 게시물은 그러한 유용한 팁과 요령을 수집하기위한 것입니다.

우선 공식 GolfScript 참조 페이지가 있습니다. 먼저 다음 사항에 익숙해 져야합니다.

특히,이 순서대로 페이지를 읽는 것이 좋습니다. 빠른 참조는 이미 내장 기능에 합리적으로 익숙해 질 때까지는 거의 쓸모가 없으며 자습서에는 다른 페이지에서 설명하지 않은 중요한 세부 정보가 포함되어 있습니다. .


추신. 영감과 개인적인 관심을 끌기 위해 다음 과 같이 멋진 답변을보고 싶은 몇 가지 질문 이 있습니다.

  • GolfScript에서 음역을 제한하는 방법은 무엇입니까? 모든 입력이 (또는 마지막 요소에 매핑되는 것을 신경 쓰지 않는 경우) 확인할 수 있지만 {FROM?TO=}%작동 하지 않는 값을 변경하지 않은 채로 보았던 모든 방법은 다소 복잡합니다.FROMTO

  • 문자열을 ASCII 코드 배열로 변환하는 방법은 무엇입니까? 어떤 작업이 부작용으로 발생합니까? ~배열 의 문자와 같이 문자열의 문자를 스택에 덤프하는 가장 좋은 방법은 무엇입니까 ?


또 다른 질문 : 변환 할 수있는 좋은 방법이 ... x에가 ... [x]? 내가 볼 수있는 최고는 [.;]입니다.
피터 테일러

@Peter : x숫자 인 경우 []+작동하며 한 문자 더 짧습니다. 그리고 물론, x스택에 유일한 것이 있다면 ]그렇게 할 것입니다.
Ilmari Karonen 2016 년

최소, 최대 및 절대 값을 수행하는 가장 좋은 방법을 묻고 싶습니다. 내 모든 솔루션은 필요한 것보다 더 많은 캐릭터를 사용하는 것 같습니다.
Claudiu

주어진 인덱스에서 배열을 수정하는 가장 좋은 방법은 무엇입니까?
user1502040

@ user1502040 : 아래에서 답변했습니다. (누군가 더 나은 방법을 알고 있다면 공유하십시오!)
Ilmari Karonen

답변:


29

합리적 / 부동 / 복합

GolfScript에는 정수만 가지고 있기 때문에 여러 번 읽었습니다. 사실이 아닙니다.

2-1? # Raise 2 to the power of -1. Result: 0.5
4-1? # Raise 4 to the power of -1. Result: 0.25
+    # Add. Result: 0.75

출력은

3/4

표준 GolfScript 인터프리터와

0.75

웹 GolfScript .

비슷한 해킹을 통해 Rational, Float 또는 Complex로 캐스팅 할 수 있습니다.

{-2.?./*}:rational
{2.-1??./*}:float
{-2.-1??./*}:complex

9
OMGWTFHAX o_O !!!
Ilmari Karonen

3
와트! 이것이 인터프리터의 버그라고 확신하지만 와우
Doorknob

3
가장 최근 통역사의 82 행 : Gint.new(@val**b.val). Gint생성자에 int 캐스트가 누락 된 것 같습니다 .
primo

10

숫자 부정하기

GolfScript에 부족한 것은 내장 부정 연산자입니다. 같은 명백한 방법으로, 부정적으로 스택에 숫자를 변환 -1*하거나 0\-, 세 개의 문자가 필요합니다. 그러나 두 가지 방법으로 할 수 있습니다.

~)

이것은 GolfScript가 2의 보수 산술을 사용하므로 ~ x는x −1과 같습니다 .

물론 변형 (~도 작동합니다. 그들 사이에서 선택하는 것은 일반적으로 맛의 문제입니다.


9

배열 섞기

GolfScript에서 배열을 섞는 가장 쉬운 방법은 임의의 정렬 키로 정렬하는 것입니다. 몇 가지 값만 조용히 섞어 야 할 경우 다음 코드가 수행됩니다.

{;9rand}$

짧은 목록의 경우에도 셔플이 그리 좋지는 않습니다. 생일 역설 때문에 합리적으로 균일 한 셔플을 얻으려면 셔플 rand되는 목록 길이의 제곱보다 인수 가 크게 커야합니다.

9위 의 내용을 대체하면 99최대 10 개의 요소 목록에 대해 상당히 좋은 결과를 얻을 수 있지만 더 긴 목록에는 눈에 띄는 편향이 나타납니다.

9 9 = 387,420,489 가능한 값 을 사용하는 다음 코드 는 최대 약 1000 개 정도의 항목에 적합합니다 (최대 약 20,000 개까지 허용).

{;9.?rand}$

정말 긴 목록의 경우 99 99 ≈ 3.7 × 10 197 값에 9를 더 추가하십시오 .

{;99.?rand}$

테스트 :

10,000 개가 넘는 시험에서 샘플링 된 위에 표시된 여러 변형을 사용하여 10 개 요소 목록에서 첫 번째 요소의 분포는 다음과 같습니다.

  • 의 결과는 다음 10,{;9rand}$0=0같이 첫 번째 위치에서 발생할 가능성이 3 배 이상인 매우 명확한 바이어스 를 보여줍니다 1.

    0 16537 #######################################################
    1 5444  ##################
    2 7510  #########################
    3 8840  #############################
    4 9124  ##############################
    5 12875 ##########################################
    6 9534  ###############################
    7 8203  ###########################
    8 7300  ########################
    9 14633 ################################################
    
  • 를 사용 10,{;99rand}$0=하면 대부분의 편견이 사라지지만 여전히 눈에 띄는 양이 남아 있습니다.

    0 10441 ##################################
    1 9670  ################################
    2 9773  ################################
    3 9873  ################################
    4 10134 #################################
    5 10352 ##################################
    6 10076 #################################
    7 9757  ################################
    8 9653  ################################
    9 10271 ##################################
    
  • 을 사용 10,{;9.?rand}$0=하면 출력은 기본적으로 실제 무작위 샘플과 구별 할 수 없습니다.

    0 9907  #################################
    1 9962  #################################
    2 10141 #################################
    3 10192 #################################
    4 9965  #################################
    5 9971  #################################
    6 9957  #################################
    7 9984  #################################
    8 9927  #################################
    9 9994  #################################
    

추신. 내용은 정말 숫자 배열이나 문자열의 나쁜 셔플, 다음 코드는 때때로 수용 될 수있다 :

{rand}$

일반적으로 어리석게 바이어스되지만 입력 배열의 모든 요소 (또는 문자열의 모든 문자 코드)가 1보다 크면 배열의 순열을 생성 할 확률이 0이 아니며 때로는 만족할 수 있습니다 챌린지 요구 사항이 잘못 작성되었습니다.


3
나는 그가 :( 옳았다 내 동생이 그것에 대해 얘기 한 후 한번 회의적 생일 역설의 수학을했던 기억
ajax333221

8

특정 하위 질문을 해결하려면

문자열을 ASCII 코드 배열로 변환하는 방법은 무엇입니까? 어떤 작업이 부작용으로 발생합니까? 배열의 ~와 같이 문자열의 문자를 스택에 덤프하는 가장 좋은 방법은 무엇입니까?

문제를 이해하지 못하는 사람들을 위해 GolfScript의 유형 시스템은 정수, 배열, 문자열, 블록 순서로 유형에 우선 순위를 부여합니다. 이것은 문자열에 적용되는 일반적인 배열 연산은 거의 항상 문자열을 제공한다는 것을 의미합니다. 예 :

'ABC123'{)}%

'BCD234'스택에 남길 것입니다 .

결과적으로 문자열을 ASCII 코드 배열로 변환하는 가장 좋은 방법은 스택에서 문자를 덤프 한 다음 배열로 모으는 것입니다.

문자열의 문자를 스택에 덤프하는 가장 좋은 방법은 무엇입니까? {}/

문자열을 ASCII 코드 배열로 변환하는 가장 좋은 방법은 무엇입니까? [{}/](일반적인주의 사항으로 스택에 다른 것이 없으면을 건너 뛸 수 있습니다 [)

ASCII 코드 배열을 문자열로 변환하는 가장 좋은 방법은 무엇입니까? ''+(이것은 또한 배열을 평탄화하므로 예를 들어 [65 [66 67] [[[49] 50] 51]]''+제공합니다 'ABC123')


단일 ASCII 코드를 문자열로 바꾸는 가장 좋은 방법은 무엇입니까? []+''+?
Justin

@Quincunx, 다소 길지만 더 좋은 방법은 없습니다. 할 일은 ASCII 코드의 출처를보고 이미 배열에 도착할 수 있는지 확인하는 것입니다.
피터 테일러

6

프로그램이 신비하게 깨지는 경우 변수를 확인하십시오

방금 !변수로 사용했던 명백한 올바른 프로그램을 디버깅하는 데 시간을 보냈습니다 (다시 사용하지 않을 이유로). 불행하게도, 난 사용을 if, 그리고의 구현 밝혀 if호출을 !수행 할 지점을 결정.


6

스택의 최상위 항목을 배열로 감싸기

변환 할 수있는 좋은 방법이 있나요 ... x으로는 ... [x]?

완전한 일반성을 위해 가장 좋은 옵션은 4 자입니다. 그러나 특별한 경우에는 이것을 줄일 수 있습니다.

1 자

]x스택에서 유일하게 특별한 경우에 작동합니다 .

3 자

[]+x정수인 특수한 경우에 작동 합니다.

.,/x진실한 배열 또는 문자열 인 특수한 경우에 작동 합니다. 예 "AB".,/를 들어 ["AB"]; 3,.,/제공합니다 [[0 1 2]]. 그러나 "".,/[].,/모두주고 [].

4 자

[.;] 무조건 작동합니다.


6

주어진 인덱스에서 배열을 수정하는 가장 좋은 방법은 무엇입니까? – user1502040

그건 좋은 질문이야. GolfScript에서는 배열 요소에 값을 직접 할당 할 수있는 방법이 없으므로 전체 배열을 다시 작성해야합니다.

배열의 x인덱스 i에 새로운 값을 삽입하는 가장 짧은 일반적인 방법 은 주어진 인덱스에서 배열을 분할하고 x전반을 다시 결합하기 전에 전반부에 추가 하는 것입니다.

  • .i<[x]+\i>+(11 자)- x(0 기반) 인덱스에서 값 을 배열에 삽입i

하려면 대체 인덱스 값을 i함께 x, 우리는 하나 개의 요소에 의해 배열의 두 번째 절반을 단축해야합니다

  • .i<[x]+\i)>+(12 자)-(0부터 시작) 인덱스의 요소를 i값으로 바꿉니다.x

또는 전반부를 단축하는 대신 효과적으로 동일한 작업을 수행하지만 1 기반 인덱싱을 사용하는 경우가 종종 있습니다.

  • .i(<[x]+\i>+(12 자)-(1 기반) 인덱스의 요소를 i값으로 바꿉니다.x

위의 모든 예제 x에서 숫자 인 경우 +어쨌든 배열로 자동 강제 변환되므로 두 개의 문자를 저장하기 위해 대괄호를 생략 할 수 있습니다 .

  • .i<x+\i>+(9 자)- x(0 기반) 인덱스에서 배열에 숫자 를 삽입i
  • .i<x+\i)>+(10 자)-(0부터 시작) 인덱스의 요소를 i숫자로 바꿉니다.x
  • .i(<x+\i>+(10 자)-(1 기반) 색인의 요소를 i숫자로 바꿉니다.x

x입력 "배열"(또는 둘 다)이 실제로 문자열 인 경우 대괄호를 생략 할 수도 있습니다 .이 경우 결과는 문자열로 변환됩니다 (일반 배열 → 문자열 변환 규칙 사용).


추신. 특별한 경우로, 배열에 사이 i에 2 × i요소 가 있다는 것을 알고 있으면 x(0 문자) 색인 ii/[x]*(6 문자)를 사용 하여 새 요소 를 삽입 할 수 있습니다 . 이것이 실제로하는 일은 배열을 i요소의 덩어리로 나누고 x각 덩어리 사이에 삽입하는 것 입니다. 이 경우 대괄호는 x숫자 일지라도 필요 합니다.


추신. 다른 방법은 동적으로 명명 된 변수를 사용하는 것입니다. 예를 들어

 'foo' 42 ':x'\+~

'foo'변수에 값 을 할당하는 x42동안

 42 'x'\+~

그것을 검색합니다.

x접두사 를 생략하고 숫자 리터럴에 직접 할당 하여이를 더욱 최적화 할 수 있습니다. 이것은 GolfScript에서 완벽하게 적용되며 할당 코드에서 하나의 문자를 저장하고 검색 코드를 원하는대로 줄이거 `~나 전혀 줄이지 않습니다. 색인은 일정합니다!). 물론 단점은 숫자 리터럴에 할당하면 코드의 다른 곳에서 해당 리터럴의 값을 무시한다는 것입니다. 그러나 숫자 리터럴의 사용을 피할 수 있거나 (또는 ​​프로그램을 다시 할당하기 전에 최소한 프로그램 시작으로 제한 할 수 있음)이 경우이 트릭이 완벽하게 적용됩니다.


3
주제를 완전히 벗어남 : 10k 축하합니다! :-D
Doorknob

1
배열에 중복 값이없는 경우 인덱스의 값 i을 9 바이트로 바꿀 수 있습니다 ..[i=]/[x]*
Martin Ender

5

최종 출력 조작

기본적으로 프로그램이 종료되면 GolfScript 인터프리터는 프로그램이 다음과 같이 마치 스택의 모든 내용과 최종 개행을 출력합니다.

]puts

문서에서 직접 언급하지 않은 것은 인터프리터가 문자 그대로 내장을 호출 puts하여이 출력을 생성 하고이 내장은 문자 그대로 다음과 같이 정의 된다는 것입니다.

{print n print}:puts;

따라서, 당신은 억제 또는 재정의하여 최종 출력을 조작 할 수 있습니다 puts, print 및 / 또는 n(또는  당신이있는 거 느낌이 정말 꼬인 경우). 여기 몇 가지 예가 있어요.

마지막 줄 바꿈을 억제하십시오.

'':n;

(물론 ;스택의 빈 문자열이 마음에 들지 않으면 생략 할 수 있습니다 .)

최종 출력을 완전히 억제하십시오.

:puts

puts스택 위에있는 모든 내용을 덮어 씁니다 . 그것이 원하지 않는 일이 발생하면 0:puts;대신 예를 들어 사용할 수 있습니다 . p(으로 정의 됨 {`puts}:p;) 도 억제 하지만 print원하는 경우 여전히 출력에 사용할 수 있습니다 .


그리고 nothing당신은 의미 \n합니까?
CalculatorFeline

후행 줄 바꿈이 마음에 들지 않으면 ];최종 출력을 억제 하는 데 사용할 수도 있습니다 .
wastl

5

최소, 최대 및 절대 값을 수행하는 가장 좋은 방법을 묻고 싶습니다. 내 모든 솔루션은 원래보다 더 많은 캐릭터를 사용하는 것 같습니다. – Claudiu

최소 최대

배열에서 가장 작은 / 가장 큰 값을 찾으려면 정렬하고 첫 번째 / 마지막 요소를 가져옵니다.

  • $0= (3 문자)-아 리트의 최소 요소
  • $-1= (4 자)-배열의 최대 요소

배열의 길이를 알고 있고 요소가 10 개 이하인 -1경우 마지막 요소의 색인으로 바꾸어 최대 3 개의 문자를 찾을 수 있습니다 .

스택에 값이 있으면 먼저 배열로 수집하면됩니다. 이를 위해 때때로 유용한 트릭은 [\]스택의 상위 2 개 요소를 배열로 [@]수집하고 상위 3 개는 수집하는 것입니다. 따라서 우리는 다음을 얻습니다.

  • [\]$0= (6 자)-스택에서 최소 2 개의 값
  • [@]$0= (6 자)-스택에서 최소 3 개의 값
  • [\]$1= (6 자)-스택에서 최대 2 개의 값
  • [@]$2= (6 자)-스택에서 최대 3 개의 값

동일한 트릭을 사용하여 세 가지 값 의 중앙값 을 찾을 수도 있습니다 .

  • [@]$1= (6 자)-스택에서 세 값의 중앙값

다음 은 원래 값을 스택에 남겨두고 두 값의 최소 / 최대를 찾는 데 유용한 또 다른 유용한 트릭입니다 .

  • .2$>$ (5 자)-스택에서 최소 두 개의 값을 찾는 동안 원래 값은 그대로 둡니다.
  • .2$<$ (5 자)-스택에서 최대 2 개의 값을 찾는 동안 원래 값은 그대로 유지

그 작동 방식은 즉 .2$클론 역순 스택 (즉, 상위 두 요소 a ba b b a) </ >복사본 복귀 0 또는 1이고, 스칼라 비교 $로 복사 중 어느 하나의 비교 결과에 따라 두 개의 입력 값을.


스택에 음이 아닌 정수가 두 개인 경우 ,\,&,(5 자)를 사용 하여 최소값을 찾고 ,\,|,(5 자)를 사용하여 최대 값을 찾을 수 있습니다. 이 트릭은 범위에서 각각 교집합과 합집합을 사용합니다. ,각 인수를 교환하지 않고 개별적 으로 적용 할 수 있으면 다른 문자를 저장할 수 있습니다 . 이 방법은 각 인수에 대한 범위를 계산하므로 숫자가 클 때는 효율적이지 않지만 입력이 작은 경우에는 매우 유용 할 수 있습니다.

스택에서 음이 아닌 두 정수의 최소값을 찾는 더 짧은 방법은 ,<,(3 자)입니다. 아아,이 트릭은 최대 값을 찾는 데 효과적이지 않습니다.


절대 값

GolfScript 내장 절대 값 연산자abs(3 자)입니다. 이것은 내가 선호하는 것보다 2 자 이상이지만 일반적으로이기는 것은 어렵습니다.

경우에 따라 (예 : 절대 값을 기준으로 정렬) 숫자의 제곱을 절대 값을 적절히 대체 할 수 있습니다. 이것은 2?또는 두 문자 중 하나로 계산할 수 있습니다 .*. 따라서 우리는 다음을 얻습니다.

  • {.*}$0= (7 자)-배열의 절대 값에 의한 최소 요소
  • {.*}$-1= (8 자)-배열의 절대 값에 의한 최대 요소

마찬가지로 숫자의 절대 값이 3 미만 abs 3<(공백 포함 6 자)인지 테스트하는 대신 사각형이 9 미만 .*9<(4 자, 공백 필요 없음) 인지 테스트 할 수 있습니다 .


스택에 음이 아닌 정수가 두 개인 경우 ,\,&,(5 자)를 사용 하여 최소값을 찾고 ,\,|,(5 자)를 사용하여 최대 값을 찾을 수 있습니다. 이 트릭은 범위에서 각각 교집합과 합집합을 사용합니다. ,각 인수를 교환하지 않고 개별적 으로 적용 할 수 있으면 다른 문자를 저장할 수 있습니다 . 이 방법은 각 인수에 대한 범위를 계산하므로 숫자가 클 때는 효율적이지 않지만 입력이 작은 경우에는 매우 유용 할 수 있습니다.
KirarinSnow

@KirarinSnow : 감사합니다! 답변에 추가했습니다.
Ilmari Karonen 2016 년

4

배열에서 중복 제거

집합 연산자 |(연합), &(교차) 및 ^(대칭 차이)는 여러 배열 요소를 하나로 축소합니다. 따라서 배열에서 중복 요소를 제거하는 가장 간단한 방법은 결합 또는 자신과의 교차를 취하는 것입니다.

.|

또는:

.&

이 연산자는 문자열을 문자 배열로 취급하므로 문자열에서 중복 문자를 제거하는 데 사용될 수도 있습니다.


4

음역 제한

특정 하위 질문을 해결하려면 : 문자열이 주어지면 tr? 를 수행하는 가장 좋은 방법은 무엇입니까? 예 :tr/ABC/abc/

문자열의 모든 문자가 영향을받는 경우 매우 쉽습니다 {'ABC'?'abc'=}%(오버 헤드 : 9 자).

그러나 일부 문자가 음역되지 않고을 'ABC'?제공 하면 중단됩니다 -1.

음역이 비순환 인 경우 문자열 분할 및 조인으로 한 번에 한 번의 교체를 수행 할 수 있습니다 'AaBbCc'1/2/{~@@/\*}/(오버 헤드 : 15 자). 이것은 불가능할 수도 있지만, 현재는 더 좋고 순환 음역에 효과적인 대안이 있습니다.

현재 가장 짧은 일반 솔루션의 오버 헤드는 14 자입니다.

  • 한 가지 방법은 이스케이프 문자 :를 포함하며 , 여기서 리터럴은 null 바이트를 나타냅니다. (물론,이 방법은 완전히 일반적인 것은 아닙니다 . 다른 문자를 널 바이트로 매핑 할 수 없습니다.){.'ABC'?'abc0'=\or}%0

  • 또는 {.'ABC'?'abc'@),+=}%동일한 오버 헤드가 있지만 인쇄 가능한 ASCII 문자 만 사용합니다. 이것은 @),+대체 문자열이 항상 입력 문자로 끝나도록하는 복잡한 (그러나 가장 짧은) 방법입니다.


마지막 접근 방식을 사용하여 입력 문자열에 'ABCDEF'대해 결과를 얻지 'abc000'만 올바른 결과는입니다 'abcDEF'. 뭔가 빠졌습니까?
Cristian Lupascu

1
@ w0lf, 0은 이전에 언급 한 이스케이프 문자이기 때문에 굵게 표시됩니다. 즉 바이트 0입니다.
Peter Taylor

4

문자열을 char 배열로 변환

1/뒤에 다음을 입력하여이 작업을 수행 할 수 있습니다 .

예 : "String"1/배열을 쌓기 위해 푸시합니다 ['S''t''r''i''n''g'].

문자열 주위에서 문자를 이동하려고 할 때 편리합니다.


1
이것이 어떻게 유용한 지 예를 들어 줄 수 있습니까? 문자열은 이미 배열처럼 작동하므로 유용하지 않습니다.
Justin

@Quincunx ascii 값이 아닌 문자를 튀어 나오고 싶을 때 편리합니다
user3700847

그리고 언제하고 싶습니까?
Justin

5
@Quincunx : 예를 들어 문자열 회전. "abc"1/(+-> "bca"이지만 "abc"(+-> bc97.
Dennis

4

숫자 리터럴에 할당

종종 1:x변수 를 쓰고 사용한 다음 업데이트하는 대신 직접 x사용하고 업데이트 할 수 1있습니다.

1:^;{^.p.+:^;}5*
{1.p.+:1;}5*       (4 bytes shorter)

물론 이것은 다른 시작 값에서도 작동하지만 해당 값이 코드의 다른 곳에서 발생하면 중단됩니다.

변수 이름으로 문장 부호

이 경우 없이 할 수있는 프로그램을 많이 - 변수를 사용하기 위해서는 코드에없는 문장 부호를 사용하는 것이 현명이기도 &, |, ^, 또는 ?. 예를 들어, 이런 식으로 변수를 입력 한 다음 줄 바꿈을 작성하는 &n대신 작성할 수 있습니다 x n.


3
그러나 일부 과제에는 예기치 않은 부작용이있을 수 있습니다. 특히,에 할당하는 것은 !이 중단되므로, 자주 나쁜 생각 if하고 do(물론 while, until, and, orxor). 마찬가지로, or별칭으로 인터프리터에 의해 정의되는 1$\if재정의, 그래서 1, $\또한 그것을 깰 것입니다. 재정의 `나누기 p.
Ilmari Karonen 2016 년

3

배열 필터링

배열을 필터링하는 가장 일반적인 방법은를 사용하는 것입니다.이 방법은 배열의 { },각 요소에 대한 코드 블록을 평가하고 결과 값이 참인 요소를 선택합니다 (즉 grep, Perl에서 와 같이 작동 함 ).

그러나 배열 빼기 연산자를 사용하는 -것이 더 짧은 경우가 많습니다. 이 연산자는 두 개의 배열을 취하고 두 번째 배열에서 발생하는 모든 요소를 ​​첫 번째 배열에서 제거합니다. 첫 번째 배열의 요소 순서를 변경하거나 중복을 축소 하지 않습니다 . 유용한 비법은 빼기 연산을 두 번 적용하여 축소되지 않는 배열 교차 연산자를 생성하는 것입니다.

  • a b -: 배열 b에서 찾은 모든 요소를 ​​배열 에서 제거a
  • a. b --: 배열 에서 찾을 수 없는 요소 를 배열 b에서 제거a

특히, 이것은 배열에서 요소가 발생하는 횟수계산하는 데 사용할 수 있습니다 .

  • a.[c]--,: c배열에서 요소 가 발생한 횟수를 센다a

일반적으로이 방법은 다음 중 하나 때문에 최적이 아닙니다.

  • a[c]/,(: c배열에서 요소 가 발생한 횟수를 센다a
  • a{c=},,: c배열에서 요소 가 발생한 횟수를 센다a

하나의 문자가 더 짧습니다 (카운트가 하나씩 꺼져도 괜찮다면 a[c]/,한 문자를 더 저장합니다). 그러나 c숫자이고 a일반 배열 (문자열이 아님) 인 특수한 경우 c, -연산자가 인수를 동일한 유형으로 강제 변환 하기 때문에 대괄호를 생략 할 수 있습니다 .

  • a.c--,: c배열에서 숫자 가 나타나는 횟수를 계산합니다 (문자열 아님).a

( a문자열이고 c0에서 9 사이 a.c--의 숫자 인 경우 숫자 c 가에서 발생 하는 횟수를 계산합니다 a.)


비슷한 트릭을 사용 하여 배열에서 가장 일반적인 요소 를 찾을 수 있습니다 .

:a{a\[.]-,}$0=

또한, 입력이 숫자의 배열이면, 전체 [.]시퀀스는 생략 될 수있다. 아아, 이것은 문자열이없는 문자열 에는 작동 하지 않습니다[.] .


계수 발생 (일반적인 경우)의 경우 a[c]/,(a{c=},,짧은 바이트 하나입니다.
Dennis

@ 데니스 : 감사합니다! 나는에있는 것을 수정했습니다.
Ilmari 카로 넨에게

3

STDIN에서 읽기

GolfScript는 stdin에서 읽을 수 있습니다 :

"#{STDIN.read}"

EOF에 도달 할 때까지 STDIN에서 계속 읽습니다. 또는

"#{STDIN.gets}"

또는

"#{STDIN.readline}"

사용 가능한 다른 것들 :

getbyte
getc
gets([sep])
gets(limit)
gets(sep, limit)
inspect # perhaps useful for an underhanded contest
isatty
read([length])
readbyte
readchar
readline([sep])
readline(limit)
readline(sep, limit)
readlines([sep])
readlines(limit)
readlines(sep, limit)
readpartial(maxlen [, outbuf])

이들 각각에 대해 한 번만 사용할 수 있으며 매개 변수가 변경 될 때마다 한 번만 사용할 수 있으며 빈 괄호로 한 번 더 사용할 수도 있습니다. 그 후, 원래 가치는 새로운 가치 대신 얻는 것입니다.


2
{"#{STDIN.readline}"p}2*2 줄을 읽지 않고 문자열을 한 번만 평가 하는 설명을 추가 할 수 있습니다 .
Howard

2
i정수로 초기화 하면 '"#{'i):i';STDIN.gets}"'++~평가 될 때마다 다른 결과가 나타납니다. 백틱도 언급 할 가치가 있습니다. 우리가 리눅스를 가정한다면, `head -1`대신에 대신 사용할 수 있습니다 STDIN.gets.
데니스

@Dennis : stdin에서 줄을 읽고 스택에 밀어 넣는 새로운 GolfScript 연산자정의"#{var'g','gpush Gstring.new(STDIN.gets)'.cc}"; 할 수도 있습니다 . g
Ilmari Karonen

2

16 진수 입력 디코딩

GolfScript에는 16 진 정수 리터럴이 없으므로 16 진수 입력을로 구문 분석 할 수 없습니다 ~. 대신 코드가 16 진수 입력을 가져와야하는 경우 수동으로 구문 분석해야합니다.

문자열에 적용되는이 8 문자 루프는 소문자 16 진수를 숫자로 변환합니다.

{39%9-}%

대문자 16 진수를 받아 들여야하는 경우 가장 쉬운 (그리고 가장 짧은) 솔루션은 먼저 32|11 자로 총 소문자를 사용하는 것입니다 .

{32|39%9-}%

출력은 기술적으로 여전히 문자열 (ASCII 문자 0 – 15로 구성됨)이지만 대부분의 GolfScript 배열 함수도 문자열을 허용합니다. 배열이 절대적으로 필요한 경우 항상 사용할 수 있습니다 [{39%9-}/]( [스택이 비어 있으면 첫 번째 는 선택 사항 임).

위의 코드 출력을 정수로 변환하려면 간단히 16base(6 자) 를 사용할 수 있습니다 . 대신 바이트 배열을 원한다면 16 진수의 각 쌍을 2/{16base}%(11 자) 로 디코딩하는 가장 짧은 해결책을 찾았습니다 . 모두 합쳐서 16 진수 문자열을 바이트 배열로 바꾸는 가장 짧은 코드는 8 + 11 = 19 자입니다.

{39%9-}%2/{16base}%

이 코드의 출력 실제로 문자열이 아니라 배열입니다. 필요한 경우, 예를 들어 ""+또는 끝에 추가 줄 바꿈이없는 경우 연결하여 문자열을 지정할 수 있습니다 n+.


2

새로운 내장 연산자 정의

표준 GolfScript 인터프리터에는 거의 사용되지 않는 기능 이있어 큰 따옴표로 묶인 문자열 리터럴로 보간 된 Ruby 코드를 허용합니다.

이 기능이 더 일반적으로 사용되지 않는 한 가지 이유는, 어색하게 보간 된 코드가 컴파일 타임에 실행 되고 출력이 GolfScript 인터프리터에 의해 캐시되어 동일한 문자열 리터럴이 이후에도 항상 동일한 값을 산출하기 때문입니다 문자열 평가.

그러나이 기능이 유용한 것으로 밝혀진 것은 Ruby 코드로 구현 된 새로운 GolfScript 연산자를 정의하는 것입니다. 예를 들어, 표준 내장 +연산자 처럼 작동하는 새로운 이진 추가 연산자를 정의하는 방법은 다음과 같습니다 .

"#{var'add','gpush a+b'.cc2}";

코드에서 정의를 어디에 두는지는 중요하지 않습니다. 새로운 연산자는 Ruby 코드를 포함하는 큰 따옴표로 묶인 문자열이 구문 분석되는 즉시 정의됩니다. add작업자가 작업 위의 정의 정확히 같은 내장 +연산자와 정확히 같은 방식으로 사용할 수 있습니다 :

1 2 add          # evaluates to 3
"foo" "bar" add  # evaluates to "foobar"

물론 새로운 추가 연산자를 정의하는 것은 내장 +연산자 지우기 와 같은 어리석은 짓을하지 않는 한 쓸모가 없습니다 . 그러나 동일한 트릭을 사용하여 Golfscript가 배열을 균일하게 섞는 것과 같이 기본적으로 할 수없는 일을하는 새로운 연산자를 정의 할 수 있습니다.

"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";

10,shuf          # evaluates to 0,1,2,...,9 in random order

전체 스택의 내용을 인쇄하거나

"#{var'debug','puts Garray.new($stack).ginspect'.cc}";

4,) ["foo" debug  # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched

또는 대화식 입력 :

"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";

]; { "> " print gets ~ ]p 1 } do   # simple GolfScript REPL

또는 웹 액세스 :

"#{
  require 'net/http'
  require 'uri'
  var'get','gpush Gstring.new(Net::HTTP.get_response(URI.parse(a.to_s)).body)'.cc1
}";

"http://example.com" get

물론 후자의 골퍼 구현은 다음과 같습니다.

"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";

특히 골프 자체는 아니지만 기본 제공 명령이 제공하는 것 이상으로 GolfScript의 기능을 확장 할 수 있습니다.


어떻게 작동합니까?

이런 방식으로 새로운 GolfScript 연산자를 정의하는 방법에 대한 권위있는 참고 자료는 물론 통역사소스 코드입니다 . 즉, 몇 가지 간단한 팁이 있습니다.

  • nameRuby 코드를 실행 하는 새 연산자를 정의하려면 다음을 code사용하십시오.

    var'name','code'.cc
  • 코드 내에서 gpop스택에서 값을 읽고 gpush다시 푸시합니다 $stack. 배열을 통해 스택에 직접 액세스 할 수도 있습니다 . 예를 들어 스택 ab스택에 모두 밀어 넣으 려면 $stack<<a<<b보다 골퍼 gpush a;gpush b입니다.

    • [어레이 시작 마커 의 위치는 어레이에 저장됩니다 $lb. 이 gpop기능은 스택이 해당 위치 아래로 축소되는 경우 이러한 마커 조정을 처리하지만 $stack배열을 직접 조작 해도 그렇지 않습니다.
  • .cc문자열에서 Ruby 코드를 GolfScript 연산자로 컴파일 하는 문자열 메소드는 편리한 래퍼 Gblock.new()입니다. 또한 변형을 가지고 .cc1, .cc2그리고 .cc3그 운전자가 자동으로 스택에서 1, 2 또는 3 인수를 팝업 변수에 할당 할 a, b하고 c. 유형 우선 순위 별로 인수를 자동으로 정렬한다는 점을 제외하고 .order는 작동 하는 메소드 도 있습니다 ..cc2

  • GolfScript 스택의 모든 값은 (와!이어야 함) 형식의 개체 Gint, Garray, Gstring또는 Gblock. 필요한 경우 기본 네이티브 정수 또는 배열에 .val메소드 를 통해 액세스 할 수 있습니다 .

    • 그러나 s Gstring.val배열 을 반환합니다 Gint. Gstringa를 네이티브 Ruby 문자열로 바꾸려면 .to_s대신 호출 하십시오 (또는 문자열 보간과 같이 자동으로 수행하는 컨텍스트에서 사용하십시오). .to_gsGS 값을 호출 하면이 Gstring값이로 바뀌므로 모든 GS 값을로 문자열화할 수 있습니다 .to_gs.to_s.
  • gpush함수는 네이티브 Ruby 숫자, 문자열 또는 배열을 해당 GS 유형으로 자동 랩핑하지 않으므로, 명시 적으로 eg를 호출하여 직접 수행해야합니다 Gstring.new(). GS 값 유형 중 하나 이외의 것을 스택에 푸시하면 나중에 해당 코드를 조작하려고 시도하는 코드가 충돌 할 수 있습니다.

  • GS 값 형식 .factory에는 형식의 생성자를 호출 하는 메서드 도 있습니다.이 메서드는 내용을 조작 한 후 배열 / 문자열을 다시 래핑하는 데 유용 할 수 있습니다. 모든 유형은 또한이 .coerce수행하는 것이 방법 강제 형 변환이 : a.coerce(b)포함 된 한 쌍의 반환 ab동일한 유형 강제 변환합니다.

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