코드 골프 : 공 분배 (I)


12

도전

이 작업에서는 적어도 하나의 공을 갖는 모든 셀과 함께 A 공을 B 셀에 분배 할 수있는 방법의 수를 계산했습니다.

입력 A와 B는 공백으로 구분 된 단일 행으로 제공되며 입력은 EOF로 종료됩니다.

여기서 솔루션을 확인하고 싶을 수도 있습니다 .

입력

0 0
1 0
12 4
6 3
18 17
20 19
15 13
18 9
20 20
17 14
9 2
14 13
18 11

산출

1
0
14676024
540
54420176498688000
23112569077678080000
28332944640000
38528927611574400
2432902008176640000
21785854970880000
510
566658892800
334942064711654400

제약

  • 모든 A와 B를 구별 할 수 있습니다.
  • 0 <= A, B <= 20
  • 원하는 언어를 사용할 수 있습니다
  • 최단 솔루션이 승리합니다!

1
시간 제한이 있습니까?

@Tim Nordenfur : 업데이트 :-)
Quixotic

그 링크는 나에게 유효하지 않습니다.
mellamokb

3
@Debanjan SPOJ의 질문을 여기에 붙여 넣는 아이디어가 마음에 들지 않습니다. 사람들은 그곳에서 경쟁하기 위해 자신의 코드를 제출하면 불공평 할 것입니다.
fR0DDY

1
@Debanjan, 나는 당신의 참조를보고 당신에게 인상 매스 월드 (는 식입니다. (5) 그 말씀 S(n,0)1경우 n=00그렇지 않은 경우). 원하는 경우 Stirling2가 지수 Riordan 그룹의 연관 하위 그룹에 있다는 더 강력한 진술에 대한 참조를 찾을 수 있습니다.
피터 테일러

답변:


4

자바 스크립트 (90 93 )

function f(a,b){n=m=r=1;for(i=b;i>0;n*=-1){r+=n*m*Math.pow(i,a);m=m*i/(b-i--+1)}return--r}

http://jsfiddle.net/RDGUn/2/

분명히 APL과 같은 수학 기반 언어는 구문의 상세 성과 내장 수학 구조의 부족으로 인해 나를 이길 것입니다 :)

편집 또한 JavaScript로 표준 입력을 사용하는 방법을 모르는 함수에 전달 된 매개 변수를 제외한 입력 관련 기능이 없습니다 ...

편집 : 이동 i--으로 m=m*표현; 이동 n*=-1for; 시작 r=1할당을 결합하고 반환에 관계없는 하나를 제거 할 수 있습니다. (3 문자 절약)


spidermonkey 쉘을 사용할 수 있습니다 -적어도 readlineand가 print있습니다. 나는 여기에 다른 사람들이 무엇을 사용하는지 모른다.
Jesse Millikan

@Jesse : 흥미 롭습니다. 어쨌든 롤을 잃을거야.
mellamokb

prompt하고 alert있는 자바 스크립트의 "표준"IO, 그들은 당신이 일반적으로 자바 스크립트 입출력을 차단하고 사용하지 않을 거라고 사실에도 불구하고 통화 IO 전형적인 차단,있는 한.
zzzzBov

4

골프 스크립트 -56 50 49 48 41 40 38 37 자

n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/

참고 : 이것은 여러 줄의 입력을 처리하고 빠르며 (테스트 케이스를 수행하는 데 1/8 초) 법적 입력을 위반하지 않습니다.

(첫 번째 버전은 나의 최초의 Golfscript 프로그램이기도했습니다. 제가 놓친 몇 가지 트릭을 지적한 eBusiness 덕분에).

이 글을 유용한 교육용 게시물로 만들기 위해 어떻게 작동하는지에 대한 설명이 있습니다. 우리는 재발로 시작합니다 f(n, k) = k * (f(n-1, k) + f(n-1, k-1)). 이것은 배치하는 것을 말 combinatorically 이해 될 수 n에서 구별 공을 k각 버킷은 적어도 하나 개의 공을 포함하도록 구별 버킷, 당신이 중 하나를 선택 k처음 볼 (버킷을 k *() 다음 중 하나가 적어도 한 번 더 공을 포함합니다 f(n-1, k)) 또는 ( f(n-1, k-1)) 이 아닙니다 .

이 결과 값은 격자를 형성합니다. 복용 n행 인덱스로 및 k컬럼 인덱스로 0 내지 모두를 인덱싱 그것은 시작

1   0   0   0    0    0   0 ...
0   1   0   0    0    0   0 ...
0   1   2   0    0    0   0 ...
0   1   6   6    0    0   0 ...
0   1  14  36   24    0   0 ...
0   1  30 150  240  120   0 ...
0   1  62 540 1560 1800 720 ...
.   .   .   .    .    .   . .
.   .   .   .    .    .   .  .
.   .   .   .    .    .   .   .

프로그램으로 돌아가서

n%{~ <<STUFF>> }/

라인으로 입력을 분할 한 후, 각 라인에 대해 평가하여, 퍼팅 nk스택 다음 호출 <<STUFF>>은 다음과 같이 인 :

),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;

그러면 해당 그리드 k+1의 세 n+1번째 행의 첫 번째 항목 이 계산 됩니다. 처음에 스택은 n k입니다.
),스택 은 0 n [0 1 2 ... k]
{!}%n [1 0 0 ... 0]있는 곳에 스택을 제공합니다 k. 를 맨 위로
\{ <<MORE STUFF>> }*가져오고 n실행 횟수를 지정 <<MORE STUFF>>합니다.
우리의 스택은 현재 테이블의 행입니다 [f(i,0) f(i,1) ... f(i,k)]
0.@. 해당 배열 앞에 몇 개의 0을 넣습니다. 첫 번째는 j이고 두 번째는입니다 f(i,j-1).
{ <<FINAL LOOP>> }/배열의 요소를 반복합니다. 각각에 대해 스택 위에 놓은 다음 루프 본문을 실행합니다.
.@+2$*@)@취할 스택 조작을 지루 ... j f(i,j-1) f(i,j)및 수율 ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]떨어져 팝 왼쪽 오버k+1 f(i,k)모든 것을 배열로 모아서 다음 순환을 준비합니다.
마지막으로, n테이블 의 세 번째 행을 생성하면
)p;마지막 요소를 가져 와서 인쇄하고 나머지 행을 버립니다.

후손을 위해이 원칙에 대한 세 가지 38 문자 솔루션 :
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


1
초보자에게는 아주 좋습니다. 작은 축소가 가능합니다. 즉시 [0]-> 1,, zip 뒤에 공백을 제거 할 수 있으며 k 대신 연산자로 저장하면 다른 공간을 제거 할 수 있습니다. 아직 코드를 단계별로 진행하지는 않았지만 일부 지점에 배열에 넣지 않고 값을 사용하면 도망 칠 수 있습니다.
aaaaaaaaaaaa

1
+1, 나는 Golfscript를 이해하지 못하지만 이것은 충분히 빠르지 만 매우 짧습니다.
Quixotic

@eBusiness와 @Peter Taylor : 다른 쪽에서 .. 배우기 쉬운 규모로 Golfscript를 얼마나 평가하십니까?
Quixotic

@Debanjan, 당신이 이미 알고있는 것에 달려 있습니다. 기능적인 스택 기반 언어입니다. 나는 이전에 기능적 언어를 사용했으며 (SML-OO 언어로 기능적 스타일 코드를 작성했습니다), 전에 스택 기반 언어를 사용했습니다 (Jasmin, PostScript로 조립 된 Java 바이트 코드). 나는 어떤 연산자를 사용할 수 있는지 배우고 있습니다. Algol 가족 (C, Java 등)의 언어 만 알고 있다면 한 번에 세 가지 장애물을 겪을 것입니다.
Peter Taylor

@Debanjan-보기보다 훨씬 쉽습니다. 거의 즉시 코드 작성을 시작할 수 있지만 물론 모든 작은 요령을 배우려면 시간이 걸립니다.
aaaaaaaaaaaa

3

J, 40

4 :'|-/x(^~*y!~])i.1x+y'/&.".;._2(1!:1)3 

예 :

4 :'-/((x^~|.@:>:)*y&(!~))i.y'/x:".>{.;:(1!:1)3
15 13
28332944640000

모든 테스트 사례에서 1 초 미만

편집

  • (52 → 47)-/ 교대하지 않고 축소 (1 _1)*(JB의 아이디어)
  • (47 → 53) 알려진 여러 줄 입력 요구 사항 :-/
  • (53 → 48) 이항 대칭을 악용하십시오.
  • (48 → 48) 암묵적으로 행동하십시오!
  • (48 → 41)
  • (41 → 40) 스퀴즈 증가 + 변환1x+

1
야! 그게 생각 이었다 ! O :-)
JB

좋아, 나는 그것을 훔칠 것이다 1x+. 그러나 그것은 단지 1 개의 문자를 되 찾는다. 반면에 당신은 5를 가져 갔다!
JB

3

커먼 리스프 (83)

(defun b (x y)
  (if (= (* x y) 0)
      (if (= (+ x y) 0) 1 0)
      (* y (+ (b (decf x) y) (b x (1- y)))))))

기본 사례를 테스트하는 더 짧은 방법이 있어야하는 것처럼 보이지만 나에게 아무런 영향이 없습니다.


3

J, 38 ~ 42

대화식 언어 및 출력 프리젠 테이션에 대한 엄격 성 환경 설정에 따라 J 스펙터 솔루션 중에서 선택하십시오.

  • 38 최단 대화식 : 4 :'|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    jconsole을 시작하고 입력 한 다음 입력을 붙여 넣습니다 (Cd로 끝남). 출력이 공백으로 구분되어 있음을 알 수 있습니다 (J는 벡터 언어이며 전체 입력에 대한 전체 계산을 수행하고 기본 프레젠테이션이 한 줄에있는 1D 벡터로 반환 함). 나는이 문제의 정신은 표현이 아니라 계산이라고 생각합니다. 그러나 대신 줄 바꿈을 요구하는 경우 :
  • 39 이상 대화 형 : 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    교체 작성 ( &과) 에서을 ( &.) 그의 프리젠 테이션 별도의 라인에 끝나는 문자열의 벡터를 반환합니다.
  • 42 배치 모드 : 4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    명령 줄로에서 실행$ jconsole balls.ijs < balls.in

당신이 이것을 투표했다면, 당신은 Eelvex의 솔루션에 약간의 신용도를 줄 수 있습니다.


&.대화식 모드에서 제대로 작동하려면 Under가 필요 합니다.
Eelvex

@Eelvex는 "적절하게"다른 해석을해야합니다. jconsole을 시작하고 코드 붙여 넣기, 입력 붙여 넣기, CD를 붙여서 출력을받습니다. 필요하지 않습니다. 무엇 당신이야?
JB

우리의 코드는 다음과 같이 결합되었습니다 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3. 39
Eelvex

echo 또는 Under가 없으면 출력이 여러 줄이 아닌 한 줄로만 표시됩니다.
Eelvex

@Eelvex는 실제로는 명시 적으로 금지되어 있지 않습니다.
JB

3

GolfScript- 45 38 36 자

중간 수준의 더티 구현 재발 관계 ( 38 36 자) :

n%{~{.2$*{\(.2$f\2$(f+*}{=}if}:f~p}/

Peter Taylors 솔루션에서 훔친 반복 관계는 다음과 같습니다.

f(x, y) = y * ( f(x-1, y) + f(x-1, y-1) )

특별한 경우에는 두 변수 중 하나가 0입니다.

내 구현은 이전 결과를 재사용하지 않으므로 0의 경우 중 하나에 도달하지 않으면 각 함수 호출은 두 개의 새로운 호출로 분기됩니다. 이것은 내 컴퓨터에서 30 초가 걸리는 최악의 2 ^ 21-1 함수 호출을 제공합니다.

경량 시리즈 솔루션 (45 자) :

n%{~.),0\{.4$?3$,@[>.,,]{1\{)*}/}//*\-}/p;;}/

2

J, 55 자

(wd@(4 :'(y^x)--/(!&y*^&x)|.i.y')/@".@,&'x');._2(1!:1)3
  • 현재 테스트 사례를 통과합니다. 나는 수학을 이해하는 것 같아요 ...
  • j602, 콘솔 만 ( wd). stdin에 입력하고 stdout에 출력

배쉬 테스트 스크립트 :

jconsole disballs.ijs <<END
12 4
6 3
END

그 j6xx는 무엇을 wd합니까?
JB

나는 정말로 j602를 의미했다. 나는 그것이 j601에도 있다고 추측하고있다. 과 같이 정의 것 echo으로 정의된다, 0 0&$@(1!:2&2). 그게 무슨 뜻인지 잘 모르겠지만, 줄 바꿈으로 1 번 항목을 예쁘게 인쇄하는 것과 같습니다. (지금 막 4가 아닌 2를 사용한다는 사실에 주목하고 있습니다. 적어도 콘솔 모드에서는 여전히 stdout에
빠질 것 같습니다

이 코드를 실행하는 데 문제가 있습니다. 그냥 콘솔에 입력합니까?
mellamokb

@mellamokb 위의 테스트 스크립트와 같이 프로그램을 disballs.ijs로 저장하고 j602 / bin / jconsole의 올바른 경로를 사용했습니다.
Jesse Millikan

@Jesse : 나는 이것을 Windows에서 실행하고 있습니다. 내가 얻을 << was unexpected at this time. 미안 J 입력에 새로운 해요, 난 항상 콘솔 모드로 사용했다.
mellamokb

2

골프 스크립트-26 자

경고 : 12 4 경우에는 많은 메모리가 필요하지만 (아래 답변 만큼은 아니지만) 실행하는 데 시간이 오래 걸립니다

~:)\?:x,{x+)base(;.&,)=},,

분명히이 답변에는 몇 가지 문제가 있지만 주석은 그것을 참조하고 mellamokb의 답변은 그것을 기반으로하기 때문에 여기에 남겨 두겠습니다.

골프 스크립트-24 자

경고 : 12 4 케이스에는 많은 메모리가 필요하며 실행하는 데 시간이 오래 걸립니다

~:o)\?,{o)base[0]-,o=},,

2
이 코드를 어떻게 만들 었는지 알 수 없습니다.이 방법에는 큰 입력에 대한 메모리가 부족할뿐만 아니라 증분 연산자가 무엇인지 알 수 없습니다. 당신이 실제로 6 3 목표를 명중하는 것은 운이 아닌 것 같습니다.
aaaaaaaaaaaa

저 광대 아니에요 내 아내 야!
Jesse Millikan

2
나는 Golfscript를 이해하지 못하지만 당신이 말했듯이 당신의 접근 방식이 너무 느리다는 것에 동의합니다.
Quixotic

3
@mellamokb, 작동 방식에 대해 잘 알고 있습니다. :) 버그를 수정하는 데 2 ​​문자가 더 필요했습니다. 이제 우리는 가장 짧은 코드가 정확하지만 실용적이지 않은 어두운 영역에 있습니다. 코드 골프는 비효율적 인 답변으로 가득 차 있지만 마이크로 초 대 초는 중요하지 않습니다. 이것은 극단적 인 경우입니다 ( 많은 메모리도). Debanjan은 답변이 더 빨라야한다고 지적했지만이 사이트 SPOJ 가 아닙니다 .이 질문 에는 code-golf
gnibbler

1
@gnibbler 0 0는 생산해야합니다 1; 0 k다른 어떤 것도 k생산해야한다 0. n 1대한 n > 0생산한다 1.
Peter Taylor

2

파이썬 140 문자

import sys
f=lambda n,k:(n and k and n>=k and k*(f(n-1,k-1)+f(n-1,k)))or(n+k==0 and 1)or 0
for l in sys.stdin:print f(*(map(int,l.split())))

2

dc, 100 자

[0q]s5[1q]s6[l2l3>5l3 0>5l2 0=6l2 1-S2l3dS3 1-S3l1xL3s9l1xL2s9+L3*]s1[?z0=5S3S2l1xL3L2+s9fs9l4x]ds4x

아아, dc는 ideone에 의해 지원되지 않는 것 같습니다. 짜 내야 할 캐릭터가 여전히있을 수 있지만, 취침 시간입니다.

참고 : 이것은 여러 줄의 입력을 지원하고 (정확한 결과를 제공하기 위해 20 19Perl을 저주 할 때도) 정확한 출력을 제공하기에 충분한 정밀도를 가지며 올바른 출력을 제공합니다 0 0.

Nabb의 제안에 따라 최소한 단축

[0q]sZ[1q]sI[?z0=ZSkSn[lnlk>Zlk0>Zln0=Iln1-SnlkdSk1-SklFxLks9lFxLns9+Lk*]dsFxfs9l4x]ds4x

레지스터 스택에 정크를 남기는 비용으로 (따라서 수십억 개의 답변을 계산하면 메모리가 부족합니다).


레지스터는 항상 단일 문자 (코드를 더 읽기 쉽게 만들 수있는 모든 문자를 사용할 수 있음) l11로 해석되므로 l1 1( 정밀도를 변경하지 않을 경우 K단일 문자 토큰으로 사용할 수 있음) 로 구문 분석됩니다 0. 입력 루프를로 변경할 수 있습니다 ?[...?z1=4]. register에서 매크로를 인라인 할 수 있습니다 1. 그리고 일반적으로 힙을 더 많은 문자를 절약 할 수는 있지만 이해하기 위해 더 짧을 때까지 기다릴 것입니다.
Nabb

@ Nabb, 아, 맨 페이지를 충분히 읽지 못했습니다. 8 개 또는 9 개의 레지스터 만 사용하므로 오해의 결과에 부딪치지 않았습니다. 감사.
피터 테일러

1

골프 스크립트 (28 31 37 )

~):$\.($\?:@;?,{@+}%{$base$,\-[0]=},,

gnibbler의 GolfScript 솔루션으로 수정되었습니다 . 나는 이것이 올바른 해결책으로 [3,2], [4,2], [6,3] 및 [9,2]에서 테스트 된 작동 솔루션이라고 생각합니다. ( 키워드 주위의 공간을 강화하기 위해 $@변수를 사용했습니다 base).

gnibbler의 현재 솔루션 에는 두 가지 문제가 있습니다.

  1. 4 개의 모든 볼이 동일한 셀 (1)에 있더라도 [1,1,1,1]이 입력 [4,2]에 유효하므로 [0]을 제거한 후 길이를 확인해도 솔루션이 보장되지 않습니다. 따라서 모든 숫자가 사용되는지 확인합니다. 즉, 배열에 1-2가 포함되어 있으므로 각 셀에 하나 이상의 공이 포함됩니다.
  2. 입력 [4,2]의 경우, 숫자 0-27의 기본 3 형식은 4 자리 미만이며 가장 왼쪽에있는 0은 포함되지 않습니다. 즉, 기술적으로 실제로는 [0,0,1,1]이더라도 [1,1]이 유효한 솔루션으로 포함됨을 의미합니다. 이는 처음 두 개의 공이 어디에도 배치되지 않음을 의미합니다. 모든 항목에 3 ^ 3을 추가하여 (일반적으로 k ^ n-1을 k ^ n 항목 배열에 추가) 수정하여 첫 번째 항목이 기본 k 형식의 최소 n 자리를 갖도록 위로 이동하고 마지막 항목은 입력은 어쨌든 자동으로 유효하지 않으며 솔루션에 영향을 미치지 않습니다 (두 번째 숫자는 항상 0이므로).

편집하다

~:@\?:$,{$+}%{@base(;@,\-,0=},,

`~:@\?:$,{$+@base(;@,\-,0=},,`

아직 더 나은 솔루션! 증분 할 필요없이 모든 숫자에 더하기 만하면 [1]로 시작하며 첫 번째 숫자를 디콘 한 후에는 왼쪽 패딩 (0의 왼쪽 패딩 포함)이 없습니다. 이 솔루션은 작동해야하며 위와 동일한 항목으로 테스트되었습니다. 배열을 생성하기 위해 지수를 취하기 전에 증가하지 않기 때문에 훨씬 빠릅니다 (그러나 더 큰 입력에 대해 동일한 성능 / 메모리 문제가 여전히 발생합니다).

편집 : 추가 단계 대신 필터 내부 gnibbler추가를 이동한다는 아이디어를 사용하십시오 $. (3 자 저장).


입력이 끊어 0 0졌습니다.
피터 테일러

또한 한 줄의 입력 만 처리하는 것으로 보입니다.
피터 테일러

그리고 n 1n을 끊으면 중단됩니다.
mm

1
기본 1로 숫자를 변환하면 해당 :) 할 것
gnibbler

@gnibbler : 당신은 어떤 제안이 있습니까? 이러한 경우를 포착하기 위해 처음에 if 문을 던져야합니까? 그런 식으로 많은 근거를 잃을 것 같습니다.
mellamokb

0

05AB1E , 19 바이트

#D`ULX.Œʒ€gßĀ}gs_P+

참고 : 속도가 너무 느리고 이미 시간이 초과되었습니다 12 4. 그래도 의도 한대로 작동합니다. 합리적인 시간에 모든 테스트 사례에 적합한 대체 방법을 생각해 낼 수 있는지 살펴 보겠습니다. 1 초 이내에 모든 테스트 사례를 실행하는 훨씬 빠른 버전은 아래를 참조하십시오.

온라인으로 시도 하거나 더 작은 테스트 사례를 몇 가지 더 확인하십시오 .

설명:

#               # Split the (implicit) input-string by spaces
 D              # Duplicate it
  `             # Push both values to the stack
   U            # Pop and store the second value in variable `X`
    L           # Create a list in the range [1,n] for the first value
     X        # Create a list of all possible ways to divide this list into `X` partitions
                # (including empty sublists, so we'll have to filter them out:)
        ʒ       # Filter this list of lists of partition-lists by:
         g     #  Get the length of each partition-list
           ß    #  Get the minimum length
            Ā   #  Truthify; 0 remains 0 (falsey); anything else becomes 1 (truthy)
             }g # After the filter, take the length to get the amount left
 s              # Swap so the duplicated input-list is at the top of the stack again
  _             # Check for each value if they're equal to 0 (1 if truthy; 0 if falsey)
   P            # Take the product of the two to check if both input-values are 0
    +           # And add it to the earlier calculated product (edge case for [0,0] = 1)
                # (After which the result is output implicitly)

05AB1E , 29 바이트

다음은 TIO에서 약 0.5 초 안에 모든 테스트 사례에서 작동하는 훨씬 빠른 버전입니다.

Î#R`V©LRvyYmX*NÈ·<*+Xy*®y->÷U

@mellamokb 의 JavaScript 답변 포트이므로 그를 투표 하십시오!

온라인으로 시도 하거나 모든 테스트 사례를 확인하십시오 .

설명:

Î                    # Push (result=) 0 and the input
 #                   # Split the input by spaces
  R`                 # Push the values to the stack reversed
    V                # Pop and store the first value in variable `Y`
     ©               # Store the second value in variable `®` (without popping)
      LRv            # Loop `y` in the range [`®`,1], with index `N` in the range [0,`®`):
         yYm         #  Calculate `y` to the power `Y`
            X*       #  Multiply it by `X`
                     #  (Note: `X` is 1 before setting it to another value initially)
              NÈ     #  Check if index `N` is even (1 if truthy; 0 if falsey)
                ·<   #  Double it; and decrease it by 1 (1 if truthy; -1 if falseY0
                  *  #  Multiply it to the earlier number
                   + #  And add it to the result
         Xy*         #  Push `X` multiplied by `y`
         ®y->        #  Push `®` - `y` + 1
             ÷       #  Integer divide them
              U      #  Pop and store it as new variable `X`
                     # (output the result at the top of the stack implicitly after the loop)

참고 : 내장이 목록을 생성 0 0하기 때문에이 경우 에는이 경우에 적합합니다 (이 방법을 이식 한 JavaScript 답변과 달리) .L[0,1]

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