마른 콩 기계


26

사람들에게 이산 확률 분포의 개념을 소개하는 전형적인 예는 빈 머신입니다 . 이 기계는 상단의 좁은 통로에서 많은 양의 구슬이 떨어지고 인터레이스 핀의 줄을 쳤습니다. 각 핀에서 구슬이 핀의 왼쪽 또는 오른쪽으로 떨어질 수 있습니다. 마지막으로 핀은 기계 하단의 수직 통에 수집됩니다. 이 기계의 간단한 다이어그램은 다음과 같습니다.

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |
|_|_|_|_|_|_|

이 다이어그램에서 O기호는 구슬이 떨어진 위치를 나타냅니다. 각각 ^의 핀은 구슬이 50 % 확률로 핀의 왼쪽이나 오른쪽으로 사각형으로 이동할 수있는 핀입니다. 그런 다음 구슬은 장치 하단의 통에 모이고 충분한 수의 구슬에 대해 통에있는 구슬 더미의 높이는 불연속 이항 분포와 비슷합니다.

도전

이 문제를 해결하려면 위와 같은 다이어그램을 기반으로 빈 머신의 결과 확률 분포를 계산합니다. 다이어그램은 측면의 필드 또는 현재 필드 아래의 필드쪽으로 구슬이 통과하는 2 차원 '프로그램'으로 해석됩니다. 구슬이 기계의 바닥에 도달하면 확률 분포를 계산합니다. 흥미를 유지하기 위해이 다이어그램에는 단순한 소스 및 핀보다 몇 가지 필드가 더 포함됩니다. 예제 다이어그램은 다음과 같습니다.

|     O     |
|     ^     |
|    ^ /    |
|   ^ | ^   |
|  <^- =  v |
| ^ ^ ^ ^ ^ |

또한, 이제는 구슬이 각각 회전 방향을 갖습니다. 이 방향은 일부 필드에 의해 설정되며 대리석이 다음 필드로 이동하여 다른 여러 필드에서 결정됩니다.

다음과 같은 필드가 정의됩니다.

  • O: 출처. 바로 아래에 대리석이 나타납니다. 이 구슬의 방향은 50 % 왼쪽, 50 % 오른쪽입니다. 각 소스는 같은 양의 구슬을 생산합니다.
  • U싱크대 이 필드에 들어가는 모든 구슬은 콩 기계에서 제거됩니다.
  • : 빈 공간. 이 필드에 대리석이 도착하면 아래 필드로 이동합니다.
  • -: 층. 구슬이이 필드에 도달하면 현재 방향에 따라 왼쪽의 필드 또는 오른쪽의 필드로 이동합니다.
  • ^스플리터. 이 필드에 대리석이 도착하면 스플리터의 오른쪽 또는 왼쪽으로 필드로 이동하는 비율이 50 %입니다. 이것은 또한 대리석의 방향을 결정합니다.
  • v: 가입하십시오. 이 필드에 대리석이 도착하면 아래 필드로 이동합니다.
  • /: 경사 패드. 구슬이이 필드에 도착하면 패드의 왼쪽에있는 필드로 이동하여 구슬의 방향을 설정합니다.
  • \: 이전과 동일하지만 오른쪽에 있습니다.
  • |: 리플렉터. 이 필드에 대리석이 도착하면 대리석 방향을 반대로하고이 반대 방향을 기준으로 대리석을 오른쪽 또는 왼쪽으로 이동합니다.
  • =대포. 대리석이 필드에 도착하면, 그것은 대리석이 아닌 필드를 만날 때까지, 현재의 방향으로 왼쪽 또는 오른쪽으로 이동합니다 , -또는 O.
  • <: 이전과 동일하지만 항상 방향을 설정하고 왼쪽으로 이동합니다.
  • >: 이전과 동일하지만 오른쪽에 있습니다.

다이어그램과 관련하여 다음과 같은 보증이 제공됩니다.

  • 각 입력 행의 길이는 필드에서 정확히 동일합니다.
  • 각 행의 가장 왼쪽과 가장 오른쪽 필드는 항상 |입니다.
  • 다이어그램에는 \/또는 과 같은 불확정 한 반복 횟수 동안 구슬이 기계에 붙어있는 가능한 경로가 포함되어 있지 않습니다 ^^.
  • 다이어그램에는 위에서 언급 한 필드 만 포함됩니다.
  • 하나 이상의 소스가 있습니다

결과

당신의 임무는 구슬이 그래프의 아래쪽을 빠져 나가는 확률 분포의 16 줄 키 ASCII 막대 그래프를 생성하는 것입니다. 따라서 다음 문제의 경우 :

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |

프로그램은 다음과 같은 솔루션을 생성해야합니다 (측면의 파이프를 포함하여 입력 프로그램과 너비가 같아야합니다).

     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
 # # # # # #
 # # # # # # 

다음은 모든 다른 필드 유형의 기능을 테스트해야하는 예입니다.

|     O     O         |
|  O  ^ /  <^\\\      |
|    ^ >            ^ |
|   ^ ^ ^            =|
|  ^ ^ | ^    <^   O  |
| ^ > ^ | ^   O ^> v  |
||  ^U  ^  |  =    ^\ |
|  ^ ^ ^ ^U ^\ ---^   |
| = ^   ^     =    v  |

결과는 다음과 같습니다.

                     # 
                     # 
                     # 
                     # 
                   # # 
                   # # 
                   # # 
       # #         # # 
       # #         # # 
       # #         # # 
       # #         # # 
      ## #         # # 
      ## # #       # # 
   # ### # #       # # 
 # # ### # #       # # 
 # # ### # #       # # 

규칙

기능과 전체 프로그램 모두이 도전에 대한 올바른 답변을 구성합니다. 다이어그램을 줄 바꿈 문자열로 받으면 주어진 형식으로 출력 그래프를 반환해야합니다. 기본 입력 / 출력 규칙이 적용됩니다. 출력에서 후행 및 선행 개행이 허용되지만 각 행은 입력과 정확히 동일한 너비를 가져야합니다.

보다 창의적인 솔루션을 허용하려면 프로그램에서 동일한 다이어그램에 대해 90 % 이상의 정확한 결과를 출력하면됩니다. 결국 확률 시뮬레이션입니다.

채점

이것은 이므로 바이트 단위의 최저 점수가 이깁니다.


훨씬 간단하지만 관련이 있습니다.
피터 테일러

의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
Dennis

그래서 v= [space]?
l4m2

@ l4m2 v[space]대포가 어떻게 상호 작용하는지에 차이가 있습니다.
검열 된 사용자 이름

답변:


8

파이썬 3 , 431 429 410 바이트

def t(a):e=enumerate;p=a.split("\n");o=[0]*len(p[0]);{m(i,j,p,o,1):m(i,j,p,o,-1)for i,r in e(p)for j,c in e(r)if"O"==c};[print("".join(" #"[round(16*r/max(o)+i)>15]for r in o))for i in range(16)]
def m(r,k,p,o,l,x=1):
 while r<len(p):
  c=p[r][k]
  if"^"==c:x/=2;m(r,k-l,p,o,l,x)
  if"U"==c:return
  if c in" vO":r+=1;continue
  l=[1,l,-1,l,-l,1][ord(c)%6];k-=l
  while";"<c<"?"and p[r][k]in" O-":k-=l
 o[k]+=x

온라인으로 사용해보십시오!

이 답변은 Wheat Wizard와 CensoredUsername 간의 공동 노력입니다. 참고로, 이것은 ungolfed 알고리즘입니다.

Mr. Xcoder에서 -2 바이트

CensoredUsername에서 -19 바이트


Python 2 (print statement)로 전환하면 -2 바이트?
caird coinheringaahing

1
이 중은 말했다 : but I can confirm it's doable in 519 characters of python 3 code ;) I don't think I can golf mine much more- CensoredUsername
스티븐

내가 말했을 때 나는 절망적으로 순진했다. 즉, 골프 경쟁을 보장하는 것은 꽤 재미있었습니다. 또한 @cairdcoinheringaahing, python 2의 print 문은 표현식이 아니라 명령문이므로 목록 이해에 사용할 수 없습니다. 이것은 상단의 oneliner가 여러 개의 들여 쓰기 된 줄로 나뉘어 2 바이트 이득을 제거하여 공백을 제거해야 함을 의미합니다.
검열 된 사용자 이름

4

파이썬 2 , 731 바이트

i=raw_input
l=i()
c=[]
while l:c,l=c+[l],i()
p=[[0]*len(l)for l in c]+[[0]*max(map(len,c))]
S=lambda r,C,p:r>=0and C>=0and r<len(p)and C<len(p[r])
def U(r,C,P,D,N=0):
 if S(r,C,p):p[r][C]+=P
 if S(r,C,c):
	K=c[r][C]
	if K in' O':U(r+1-N,C+D*N,P,D,N)
	elif'v'==K:U(r+1,C,P,D)
	elif'-'==K:U(r,C+D,P,D,N)
	elif'^'==K:U(r,C-1,P/2,-1);U(r,C+1,P/2,1)
	elif'/'==K:U(r,C-1,P,-1)
	elif'\\'==K:U(r,C+1,P,1)
	elif'='==K:U(r,C+D,P,D,1)
	elif'>'==K:U(r,C+1,P,1,1)
	elif'<'==K:U(r,C-1,P,-1,1)
	elif'|'==K:U(r,C-D,P,-D)
for r in range(len(c)):
 for C in range(len(c[r])):
	if'O'==c[r][C]:U(r+1,C,1.,1);U(r+1,C,1.,-1)
p=p[-1][::-1]
s=16/max(p)
f=['#'*min(int(n*s),16)+' '*min(int(16-n*s),16)for n in p]
print('\n'.join(map(''.join,zip(*f)))[::-1])

온라인으로 사용해보십시오!

caird coinheringaahing 덕분에 -17 바이트

Nathan Shiraini 덕분에 -12 바이트

들여 쓰기로 전환하여 -56 바이트 (Python 2)

확률이 결국 정규화되기 때문에 CensoredUsername 덕분에 -28 덕분에 최종 확률이 항상 1을 더할 필요는 없습니다.

더 짧은 결말을 사용하여 Calculator Feline 덕분에 -7 바이트 elif.

두 함수를 병합하여 -218 바이트



@cairdcoinheringaahing 감사합니다.
HyperNeutrino

2
호출에서 RL같은 R(r+1-N,C+N,P,N=N)(에 첫 번째 호출 R), 당신은 필요하지 않습니다 N=끝에; R(r+1-N,C+N,P,N)대신 해야합니다 .
Nathan.Eilisha Shiraini 2016 년

@NathanShiraini 그래, 고마워.
HyperNeutrino 2016 년

... 당신은 몇 가지를 잊었다. 마지막 두 줄 LR^^ 또한 두 번째 들여 쓰기 수준은 사방에 4 칸입니다. 2를 만들 수 있다고 생각합니다.
Nathan.Eilisha Shiraini 2016 년

3

C, 569 568 556 바이트

골프

#define A s[1]
#define c(i,j,k) break;case i:x=j;y=k;
w,S,i,j,d,x,y,z;main(int*a,char**s){w=strchr(&A[1],'|')+2-A;a=calloc(w,4);for(;i++<'~~';j=0){for(;A[j];){if(A[z=j++]==79){d=rand()%2;x=4;y=7;z+=w;for(;z<strlen(A);){z+=x%3-1+(y%3-1)*w;switch(A[z]){case 85:goto e;c(32,x/3*(3+1),y/3*(3+1))c(45,d*2+3,7)c(94,(d=rand()%2)*2+3,7)c(118,4,8)c(47,3,7)d=0;c(92,5,7)d=1;c(124,(d=!d)*2+3,7)c(60,x,y)case 62:d=A[z]/2%2;case 61:x=d*8;y=4;}}a[z%w]++;e:;}}}for(i=-1;++i<w;S=a[i]>S?a[i]:S);for(j=17;j-->1;puts(""))for(i=0;i<w-1;printf("%c",a[i++]*16./S+0.6<j?32:35));}

언 골프

//Variable Definitions
//direction - marbles current direction, 0 -> left, 1-> right
//arrwidth - width of array
//x - change in x of marble in base 3 - 0 -> Left, 1 -> stay, 2-> right
//y - change in y of marble in base 3 - 0 -> Up, 1 -> stay, 2-> Down
//z - position of marble
//i - iterator on runs of program
//j - iterator on string
//k - iterator on outputstring
//argc - array holding all buckets

#define c(i,j,k) break;case i:x=j;y=k;

arrwidth,scale,i,j,direction,x,y,z;

main(int *argc, char**argv){
  arrwidth=strchr(&A[1],'|')+2 - A; //get width
  argc=calloc(arrwidth,4);
  for(;i++<'~~';j=0){
    for(;A[j];){
      if(A[z=j++] == 79){ //if it finds an O, start sim
        direction=rand()%2;
        x=4;
        y=7;
        z+=arrwidth;
        for(;z<strlen(A);){
          z+=x%3-1 + (y%3-1)*arrwidth;
          switch (A[z]){
            case 85://marble dies dont record
              goto e;
            c(32,x/3*(3+1),y/3*(3+1)) //case ' '
            c(45,direction*2+3,7)    //case -
            c(94,(direction=rand()%2)*2+3,7)    //case ^
            c(118,4,8)    //case v
            c(47,3,7)    //case /
              direction=0;
            c(92,5,7)   //case '\'
              direction=1;
            c(124,(direction=!direction)*2+3,7)
            c(60,x,y)    //case <
            case 62:    //case >
              direction=A[z]/2%2;
            case 61:  //case =
              x=direction*8;
              y=4;
          }
        }
        argc[z%arrwidth]++;
        e:;
      }
    }
  }
  //get output answer in terms of '#'
  for(i=-1;++i<arrwidth;scale=argc[i]>scale?argc[i]:scale);
  for(j=17;j-->1;puts(""))
    for(i=0; i < arrwidth-1;printf("%c",argc[i++]*16./scale+0.6<j?32:35));
}

편집

케이스 매크로를 변경하여 12 바이트를 절약했습니다.

노트

내 코드는 기본 3 정수 시스템을 사용하여 대리석이 향하고 어디로 향할 것인지를 결정합니다 (대포 및 물건의 경우).

나는 그렇게 파이썬 솔루션을 이길려고 노력했지만 실제로했다.


1
568 바이트를 셉니다. 아마도 당신은 후행 줄 바꿈을 세었습니까? 그리고 나는 기분이 나쁘다. 파이썬으로 C로 outgolfed? Jeez ... : P
HyperNeutrino

당신은 맞습니다, 나는 파일에 후행 개척을 남겼습니다. 감사!
dj0wns
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.