Mesin kacang yang ramping dan rata

26

Contoh klasik untuk memperkenalkan orang kepada konsep distribusi probabilitas diskrit adalah mesin kacang . Mesin ini memiliki sejumlah besar kelereng jatuh dari lorong sempit di atas, setelah itu mereka menabrak deretan pin interlaced, di mana pada setiap pin yang terkena marmer mungkin jatuh ke kiri atau kanan pin. Akhirnya, pin dikumpulkan dalam tempat sampah vertikal di bagian bawah mesin. Diagram sederhana dari mesin ini terlihat seperti ini:

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

Dalam diagram ini, Omenandakan lokasi dari mana kelereng jatuh. Masing ^- masing adalah pin di mana marmer memiliki peluang 50% untuk bergerak ke alun-alun baik ke kiri atau ke kanan pin. Kelereng kemudian berkumpul di tempat sampah di bagian bawah perangkat, dan untuk jumlah kelereng yang cukup besar, ketinggian tumpukan marmer di tempat sampah akan menyerupai distribusi binomial diskrit.

Tantangan

Untuk tantangan ini, Anda akan menghitung distribusi probabilitas yang dihasilkan dari mesin kacang berdasarkan diagram seperti di atas. Diagram ditafsirkan sebagai 'program' dua dimensi yang dilewati kelereng, baik terhadap bidang di samping atau bidang di bawah bidang saat ini. Ketika kelereng mencapai bagian bawah mesin, mereka dihitung untuk distribusi probabilitas. Agar tetap menarik, diagram ini akan berisi beberapa bidang lebih dari sekadar sumber dan pin sederhana. Diagram contoh adalah:

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

Selanjutnya, kelereng sekarang masing-masing memiliki arah putaran. Arah ini diatur oleh beberapa bidang dan menentukan bidang mana selanjutnya yang bergerak marmer di beberapa bidang lainnya.

Bidang-bidang berikut didefinisikan:

  • O: Sumber. Menumbuhkan kelereng langsung di bawahnya. Arah kelereng ini adalah 50% kiri, 50% kanan. Setiap sumber menghasilkan jumlah kelereng yang sama.
  • U: Tenggelam. Setiap kelereng yang memasuki bidang ini dihapus dari mesin kacang.
  • : Ruang kosong. Jika sebuah marmer tiba di bidang ini, ia akan pindah ke bidang di bawah ini.
  • -: Lantai. Jika sebuah marmer tiba di bidang ini, ia akan bergerak ke bidang ke kiri atau bidang di sebelah kanan, tergantung pada arahnya saat ini.
  • ^: Splitter. Jika sebuah marmer tiba di bidang ini, ia memiliki 50% bergerak ke bidang di sebelah kanan atau bidang di sebelah kiri pembagi. Ini juga menentukan arah marmer.
  • v: Bergabunglah. Jika sebuah marmer tiba di bidang ini, ia akan pindah ke bidang di bawah ini.
  • /: Bantalan miring. Jika sebuah marmer tiba di bidang ini, ia akan bergerak ke bidang di sebelah kiri pad, mengatur arah marmer.
  • \: Sama seperti sebelumnya, tetapi ke kanan.
  • |: Reflektor. Jika sebuah marmer tiba di bidang ini, itu akan membalikkan arah marmer, dan memindahkan marmer ke lapangan ke kanan atau ke kiri, berdasarkan pada arah terbalik ini.
  • =: Meriam. Jika kelereng tiba di bidang ini, ia akan bergerak ke kanan atau kiri di arah arus, sampai marmer bertemu bidang yang tidak , -atau O.
  • <: Sama seperti sebelumnya, tetapi akan selalu mengatur arah dan bergerak ke kiri.
  • >: Sama seperti sebelumnya, tetapi ke kanan.

Jaminan berikut diberikan sehubungan dengan diagram.

  • Setiap baris input akan memiliki panjang yang sama persis di bidang.
  • Bidang paling kiri dan paling kanan dari setiap baris akan selalu a |.
  • Diagram tidak akan berisi jalur yang memungkinkan kelereng dapat tersangkut di mesin untuk jumlah iterasi yang tidak pasti, seperti \/atau ^^.
  • Diagram hanya akan berisi bidang yang disebutkan di atas.
  • Ada satu atau lebih sumber

Hasil

Tugas Anda adalah membuat grafik bar ASCII 16-line tinggi dari distribusi probabilitas di mana kelereng keluar dari sisi bawah grafik, diskalakan sehingga probabilitas terbesar mencakup semua 16 karakter. Jadi untuk masalah berikut:

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

Program Anda harus menghasilkan solusi berikut (perhatikan bahwa ia harus memiliki lebar yang sama dengan program input, termasuk pipa ke samping:

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

Contohnya

Berikut ini adalah contoh yang harus menguji fungsionalitas semua jenis bidang yang berbeda:

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

Itu harus menghasilkan output berikut:

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

Aturan

Baik fungsi dan program lengkap merupakan jawaban yang valid untuk tantangan ini. Anda akan menerima diagram sebagai string yang dipisahkan baris baru, dan Anda harus mengembalikan grafik output dalam format yang diberikan. Aturan input / output default berlaku. Sementara mengikuti dan memimpin baris baru diizinkan dalam output, setiap baris harus memiliki lebar yang sama persis dengan input.

Untuk memungkinkan lebih banyak solusi kreatif, program Anda hanya perlu menampilkan hasil yang benar lebih dari 90% dari waktu untuk diagram yang sama. Bagaimanapun, ini adalah simulasi probabilitas.

Mencetak gol

Ini adalah , sehingga skor terendah dalam byte menang.

Nama Pengguna yang Disensor
sumber
Jauh lebih sederhana tetapi terkait .
Peter Taylor
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Dennis
jadi v= [space]?
l4m2
@ 14m2 vdan [space]berbeda dalam bagaimana meriam berinteraksi di sekitar mereka.
Pengguna

Jawaban:

8

Python 3 , 431 429 410 byte

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

Cobalah online!

Jawaban ini merupakan upaya kolaborasi antara Wheat Wizard dan CensoredUsername. Sebagai referensi, ini adalah algoritma ungolfed.

-2 byte dari Mr. Xcoder

-19 byte dari CensoredUsername

Hat Wizard
sumber
-2 byte jika Anda beralih ke Python 2 (pernyataan cetak)?
caird coinheringaahing
1
Dari ini dikatakan: but I can confirm it's doable in 519 characters of python 3 code ;) I don't think I can golf mine much more- Nama Pengguna Disensor
Stephen
Aku benar-benar naif ketika mengatakan itu. Yang mengatakan, kompetisi golf memastikan itu cukup lucu. Juga @cairdcoinheringaahing, pernyataan cetak python 2 adalah pernyataan, bukan ekspresi dan karenanya tidak dapat digunakan dalam pemahaman daftar. Ini berarti bahwa oneliner di bagian atas harus dipecah menjadi beberapa garis indentasi yang akan membuat gain 2 byte dari menghapusnya batal.
CensoredUsername
4

Python 2 , 731 byte

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])

Cobalah online!

-17 byte berkat caird coinheringaahing

-12 byte terima kasih kepada Nathan Shiraini

-56 byte dengan beralih ke indentasi campuran (Python 2)

-28 terima kasih kepada CensoredUsername karena probabilitas dinormalisasi pada akhirnya, jadi tidak perlu bahwa probabilitas akhir selalu bertambah hingga 1.

-7 byte terima kasih kepada Calculator Feline dengan menggunakan elifpernyataan akhir yang lebih pendek .

-218 bytes dengan menggabungkan dua fungsi

HyperNeutrino
sumber
1052 byte
caird coinheringaahing
@cairdcoinheringaahing Right, terima kasih.
HyperNeutrino
2
Dalam panggilan ke Rdan Lsuka R(r+1-N,C+N,P,N=N)(panggilan pertama ke R), Anda tidak perlu N=di akhir; itu seharusnya R(r+1-N,C+N,P,N).
Nathan.Eilisha Shiraini
@NathanShiraini Benar, terima kasih.
HyperNeutrino
... kamu lupa beberapa. 2 baris terakhir dari keduanya Ldan R^^ Juga, level lekukan kedua Anda adalah 4 spasi di mana-mana, saya pikir Anda bisa membuatnya 2.
Nathan.Eilisha Shiraini
3

C, 569 568 556 Bytes

Golf

#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));}

Tidak disatukan

//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));
}

Suntingan

Disimpan 12 byte dengan mengubah kasus makro saya.

Catatan

Kode saya menggunakan sistem bilangan bulat basis 3 untuk menentukan ke mana marmer menuju dan akan menuju setelah (untuk meriam dan barang-barang).

Saya mencoba jadi harus mengalahkan solusi python, saya benar-benar melakukannya.

dj0wns
sumber
1
Saya menghitung 568 byte; mungkin Anda menghitung baris tambahan? Dan sialan aku merasa tidak enak; kalah dalam Python oleh C? Astaga ...: P
HyperNeutrino
Anda benar, saya meninggalkan jejak baru di file. Terima kasih!
dj0wns