Không phải máy làm đậu thường xuyên của bạn


42

Hãy xem xét phiên bản ASCII này của một cơ chế tương tự như máy đậu hoặc trò chơi plinko / pachinko :

    O

    ^
   \ ^
  ^ ^ \
 \ ^ / ^
U U U U U
1 2 3 4 5

Các Olà một quả bóng rơi xuống.

  • Khi nó chạm a ^, có khả năng 50-50 nó sẽ sang trái hoặc phải.
  • Khi nó chạm a /, nó luôn đi bên trái.
  • Khi nó chạm a \, nó luôn luôn đi đúng.

Quả bóng cuối cùng rơi vào một trong những Umáng được đánh số ở phía dưới. Câu hỏi là, xác suất cuối cùng trong mỗi máng là bao nhiêu?

Đối với trường hợp đặc biệt này, các xác suất là 0.0, 0.1875, 0.5625, 0.125, và 0.125, đối với máng từ 1 đến 5 tương ứng.

Dưới đây là một ví dụ khác với 3 máng thay vì 5. Các xác suất 0.5, 0.50.0:

  O

  /
 ^ ^
U U U
1 2 3

Trong thử thách này, chúng tôi sẽ khái quát vấn đề này thành một cơ chế với bất kỳ số lớp nào được thiết lập theo bất kỳ kiểu nào.

Thử thách

Viết chương trình hoặc hàm lấy biểu diễn ASCII của cấu trúc kim tự tháp của cơ chế. (Nhập qua stdin / dòng lệnh / hàm arg.)

Bạn có thể cho rằng nó đi kèm với các không gian đặt nó trong hình dạng phù hợp, ví dụ:

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Hoặc bạn có thể cho rằng nó không có chỗ trống, vd

^
\^
^^\
\^/^

(Nếu muốn, bạn có thể giả sử có một dòng mới và / hoặc một số mẫu không gian theo dõi nhất quán.)

Cấu trúc kim tự tháp đầu vào có thể có bất kỳ số cấp nào (còn gọi là dòng), bao gồm 0. Mỗi cấp độ có thêm một ^, /hoặc \so với trước, và có levels + 1máng ở phía dưới (mà không phải là một phần của đầu vào).

Chương trình / chức năng của bạn phải in / trả về danh sách các xác suất mà quả bóng rơi vào từng máng (theo thứ tự máng ngoài cùng bên trái đến máng ngoài cùng bên phải). Đây phải là các giá trị dấu phẩy động, khi được in, có ít nhất 3 vị trí thập phân (không cần số 0 hoặc dấu thập phân không cần thiết; 1tốt cho 1.000, .5là tốt cho 0.500, v.v.). Nếu bạn đã viết một hàm, bạn có thể in các giá trị hoặc trả về một danh sách / mảng của các float.

Bất kỳ định dạng danh sách in hợp lý là tốt. ví dụ như 0.5 0.5 0.0, [0.5 0.5 0.0], [0.5, 0.5, 0.0], {0.5, 0.5, 0.0}, hoặc 0.5\n0.5\n0.0sẽ tất cả sẽ ổn thôi.

Ví dụ

0 Cấp độ: (sôi xuống một tầm thường U)

Đầu vào: [no input/empty string given]
Đầu ra:1.0

1 cấp độ:

Đầu vào: ^
Đầu ra:0.5 0.5

Đầu vào: /
Đầu ra:1.0 0.0

Đầu vào: \
Đầu ra:0.0 1.0

2 cấp độ: (ví dụ thứ hai ở trên)

Đầu vào:

 /
^ ^

Đầu ra: 0.5 0.5 0.0

3 cấp độ:

Đầu vào:

  ^
 ^ ^
^ ^ ^

Đầu ra: 0.125 0.375 0.375 0.125

Đầu vào:

  \
 / \
/ / \

Đầu ra: 0.0 0.0 0.0 1.0

4 cấp độ: (ví dụ đầu tiên ở trên)

Đầu vào:

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Đầu ra: 0.0 0.1875 0.5625 0.125 0.125

7 cấp độ:

Đầu vào:

      ^
     / ^
    ^ ^ /
   / \ / \
  ^ ^ / ^ \
 ^ \ ^ \ / ^
\ ^ ^ ^ \ ^ /

Đầu ra: 0.0 0.09375 0.28125 0.4375 0.1875 0.0 0.0 0.0

Chấm điểm

Câu trả lời ngắn nhất trong byte thắng. Tiebreaker là bài trước.


16
Quincunx đã trả lời tốt hơn điều này.
Sở thích của Calvin

"Một số mô hình nhất quán của các khoảng trống theo dõi" - tôi có thể giả sử rằng các khoảng trắng ở vạch thứ N mã hóa xác suất để quả bóng rơi vào thùng thứ N không?
Random832

4
@ Random832 Số (Bạn có thực sự nghĩ rằng nó sẽ bay không?)
Sở thích của Calvin

Có một lý do tôi đã đăng nó như một bình luận thay vì một câu trả lời. Tôi chỉ nghĩ thật thú vị khi câu đố này được cho phép về đầu vào - hầu hết tôi đã thấy chính tả định dạng của đầu vào và / hoặc đầu ra nghiêm ngặt hơn.
Random832

@ Random832: Đầu vào và đầu ra rất rõ ràng. Các lỗ hổng tiêu chuẩn (như mã hóa câu trả lời trong đầu vào) không cần phải giải quyết trong mọi thử thách.
Alex A.

Câu trả lời:


10

CJam, 50 48 45 44 42 40 byte

1]q{iD%"(+0 0+( (\Y/::+ (d2/_a+"S/=~+}/p

Điều này hy vọng đầu vào sẽ không có không gian và có một dòng mới. Ví dụ:

^
\^
^^\
\^/^

[0 0,1875 0,5625 0,125 0,125]

Thuật toán

Ý tưởng cơ bản là bạn tiếp tục phân tích cú pháp từng ký tự (chỉ có 4 ký tự khác nhau) và thực hiện các hoạt động khác nhau trên phân phối xác suất (ban đầu là một mảng chứa 1 phần tử giá trị 1). Đối với mỗi hàng ký tự đầu vào (bắt đầu bằng ký tự đầu tiên trên hàng đầu tiên), chúng tôi duy trì một mảng xác suất có cùng kích thước. Mỗi nhân vật hành động theo xác suất đầu tiên từ danh sách và đẩy cặp kết quả đến cuối danh sách. Sau mỗi dòng, chúng tôi tổng hợp các cặp từ danh sách để có được số lượng chính xác của các mục làm các mục trên dòng tiếp theo.

Dưới đây là bốn ký tự và các hành động cần thiết tương ứng với mỗi:

  • ^: Khi ký tự này xảy ra, bạn chia xác suất hiện tại thành hai phần. Ví dụ: nếu chúng ta có cái này trên dòng đầu tiên, chúng ta phải chuyển đổi [1]thành[0.5 0.5]
  • /: Khi ký tự này xảy ra, chúng ta phải đặt <current probability> 0thay thế cho xác suất hiện tại trong mảng.
  • \: Khi ký tự này xảy ra, chúng ta phải đặt 0 <current probability>thay thế cho xác suất hiện tại trong mảng.
  • \n: Khi nhân vật này xảy ra, chúng tôi có một dòng mới. Do đó, chúng tôi nhóm tất cả các cặp từ 3 ký tự trên và tổng hợp chúng để có xác suất của từng mục cho dòng tiếp theo. Dành cho người cũ [0 0.5 0.25 0.25]được chuyển đổi thành [0 0.75 0.25]. Lưu ý rằng các mục đầu tiên và cuối cùng có một cặp ẩn (có giá trị 0) trước và sau chúng.

Bây giờ chúng ta chỉ phải xác định đúng nhân vật và thực hiện hành động đúng. Hãy sử dụng các toán học thông thường ở đây để làm điều đó. Các mã ASCII cho ^, \, /\n94, 92, 47, và 10. Sau một vài thử nghiệm, chúng ta có được phương trình đơn giản này để chuyển đổi các số này thành 0, 1, 2 và 3:

"^\/
":ied13f%ed4f%ed

cho:

Stack: [[94 92 47 10]]
Stack: [[3 1 8 10]]
Stack: [[3 1 0 2]]
3102

Trong một mảng có độ dài 4, cái cuối cùng 4f%sẽ được ẩn. Vì vậy, chúng ta chỉ cần làm %13theo mã ASCII của ký tự và chọn hành động đúng từ một loạt các hành động.

Mã giải thích :

1]                                 e# Initial probability array with 1 probability
  q{                          }/   e# Read the whole input and iterate char by char
    iD%                            e# mod the ASCII code of the character with 13
"(+0 0+( (\Y/::+ (d2/_a+"S/        e# This is our actions array in order of [\ / \n ^]
                           =~      e# We pick the correct action and eval it
                             +     e# Evaling each action will leave one number out of the
                                   e# pairs out of the array. So we put it back in
                                p  e# Print the final probability array

Dùng thử trực tuyến tại đây


1
Làm thế nào để bạn kiểm tra nó với 0 hàng?
trichoplax

1
@trichoplax nên hoạt động ngay.
Tối ưu hóa

Nó hoạt động ngay bây giờ với đầu vào trống :)
trichoplax

15

Ruby 140

->s{r=[1.0]
s.lines.map{|l|n=[i=0.0]*(r.size+1)
l.scan(/\S/).map{|e|a,b=e>?/?e>?]?[0.5]*2:[0,1]:[1,0]
z=r[i]
n[i]+=z*a
n[i+=1]+=z*b}
r=n}
r}

Hàm lấy chuỗi đầu vào (có thể được định dạng độc đáo dưới dạng kim tự tháp) và trả về một mảng số float.

Kiểm tra trực tuyến: http://ideone.com/kmsZMe

Thực hiện khá đơn giản. Đây là vô căn cứ:

F = -> input {
  probabilities = [1.0]

  input.lines.each { |line|

    new_probabilities = [0.0] * (probabilities.size+1)
    elements = line.scan /\S/
    elements.map.with_index{|el, i|
      deltas = el > '/' ? (el > ']' ? [0.5,0.5] : [0,1]) : [1,0]

      d1, d2 = deltas

      new_probabilities[i] += probabilities[i] * d1
      new_probabilities[i + 1] += probabilities[i] * d2
    }
    probabilities = new_probabilities
  }
  return probabilities
}

13

Ruby, 140 158 byte

Đừng tiếp tục phát huy điều này khi có phiên bản ruby ​​tốt hơn . Dưới đây là nhiều thủ thuật cho bạn.

Hàm không tên với một đối số. Không được chứa bất kỳ khoảng trắng. Có thể hoặc không chứa một dòng mới.

->s{Z=(s.split'
')<<[]
K=[]
F=->i,j,f{k=Z[i][j]
K[i]||=0
k==?^?2.times{|m|F[i+1,j+m,f/2]}:!k ?K[j]+=f :F[i+1,j+(k==?/?0:1),f]}
F[0,0,1.0]
K}

Lãng phí 9 byte khi phải xử lý 0 levels(chuỗi trống). Tất cả các trường hợp thử nghiệm hoạt động chính xác, xem ở đây tại ideone .


4
Chỉ vì có câu trả lời Ruby "tốt hơn" không có nghĩa là câu trả lời của bạn (hoặc bất kỳ câu trả lời nào khác của Ruby cho vấn đề đó) không đáng để bình chọn. :)
Alex A.

Tôi ủng hộ điều này vì nó chứa một số thủ thuật hay. Tôi thích multiline của bạn split, ví dụ.
Cristian Lupascu

12

Pyth, 43 42 41 byte

umsdc+0sm@c[ZJhkJZKcJ2K)2x"\/"ekC,GH2.z]1

Điều này hy vọng đầu vào sẽ không có không gian. Dùng thử trực tuyến: Trình biên dịch / thực thi Pyth

Pyth, 40 byte (nghi vấn)

umsdc+0sm,K@[ZJhkcJ2)x"\/"ek-JKC,GH2.z]1

Cảm ơn @isaacg, vì đã lưu một byte. Lưu ý rằng phiên bản này không thực sự hoạt động trong phiên bản Pyth, khi câu hỏi được đặt ra. Có một lỗi nhỏ trong trình biên dịch. Mặc dù mã này không sử dụng các tính năng mới của Pyth (chỉ những thứ có trong tài liệu Pyth trong một thời gian dài và đáng lẽ phải hoạt động), đây có thể không phải là một câu trả lời hợp lệ. Quyết định cho chính mình.

Dùng thử trực tuyến: Trình biên dịch / thực thi Pyth

Giải trình:

umsdc+0sm,K@[ZJhkcJ2)x"\/"ek-JKC,GH2.z]1   
u                                   .z]1  reduce G, starting with G = [1], for H in all_input():
                               C,GH         zip(G,H)
        m                                   map each pair k to:
            [ZJhkcJ2)                         create a list [0, k[0], k[0]/2]
                     x"\/"ek                  index of k[1] in "\/" (-1 for "^")
          K@                                  take the correspondent element of the list and store in K
         ,                  -JK               create a pair (K, k[0]-K)                                                      
     +0s                                    sum and insert 0 at the begin
    c                              2        chop into pairs
 msd                                        sum up each pair
                                            G gets updated with this new list

Chẳng hạn, nếu tôi hiện có xác suất đầu vào G = [0.5, 0.5, 0.0]và hàng H = "^/^"xảy ra như sau:

  • khóa kéo ... [(0.5,"^"), (0.5,"/"), (0.0,"^")]
  • tạo xác suất đầu ra ... [[0.25,0.25], [0.5,0.0], [0.0, 0.0]]
  • 0 + tổng ... [0, 0.25, 0.25, 0.5, 0.0, 0.0, 0.0]
  • chặt ... [0,0.25], [0.25,0.5], [0.0,0.0], [0.0]]
  • tổng ... [0.25, 0.75, 0.0, 0.0]

3
Tôi đã cố gắng để chơi golf này, và nó đã dẫn tôi đến một lỗi trong trình biên dịch. Golf hoạt động, bây giờ tôi đã sửa lỗi. Golf là để thay thế danh sách các danh sách 2 giá trị bằng một danh sách, sau đó tạo ra giá trị khác bằng cách trừ đi giá trị đầu tiên từ đó hk. ,K@[ZJhkcJ2)x"\/"ek-JK
isaacg

1
Đây thực sự là một dòng tốt khi bạn sửa lỗi không được tính là phiên bản mới hơn của ngôn ngữ (và do đó vẫn hợp lệ cho các câu hỏi được hỏi trước khi sửa)
Trình tối ưu hóa

1
@Optimizer Quyền của bạn. Đã thêm một số ghi chú cho câu trả lời, điều đó giải thích các trường hợp.
Jakube

2
@Optimizer Trong trường hợp này, có vẻ như một quy tắc tốt là liệu đó thực sự là phiên bản mới hơn của ngôn ngữ hay phiên bản mới hơn của việc triển khai ngôn ngữ để sửa lỗi, đưa việc triển khai gần với thông số kỹ thuật hơn.
Desty

@Desty Đó là lý do tại sao tôi đã đề cập rằng đó là một dòng tốt;)
Trình tối ưu hóa

8

C #, 274 247 byte

Không có gì lạ mắt, chương trình hoàn chỉnh có thể đọc các dòng (có hoặc không có khoảng trắng, nó chỉ tách chúng ra) từ STDIN và in kết quả được phân tách không gian thành STDOUT.

using Q=System.Console;class P{static void Main(){decimal[]k={1},t;string L;for(int l=0,i;(L=Q.ReadLine())!=null;k=t)for(L=L.Replace(" ",""),t=new decimal[++l+1],i=0;i<l;)t[i]+=k[i]-(t[i+1]=(8-L[i]%8)/2*k[i++]/2);Q.WriteLine(string.Join(" ",k));}}

Mã Tidier với ý kiến:

using Q=System.Console;

class P
{
    // / 47
    // \ 92
    // ^ 94

    static void Main()
    {
        decimal[]k={1},t; // k is old array, t is new array

        string L; // L is the current line, R is the current result (1 if no rows)
        for(int l=0,i; // l is length of old array, i is index in old array
            (L=Q.ReadLine())!=null; // for each line of input
            k=t) // swap array over
            for(L=L.Replace(" ",""), // remove spaces
                t=new decimal[++l+1], // create a new array
                i=0;

                i<l;) // for each position

                t[i]+=k[i]-( // add to left position (for last time)
                        t[i+1]=(8-L[i]%8)/2*k[i++]/2 // assign right position (k is decimal)
                    );

        Q.WriteLine(string.Join(" ",k)); // print result
    }
}

7

Trăn 3, 113

P=[1]
for C in input().split():
 l,*Q=0,
 for p,c in zip(P,C):r=p*"\^/".find(c)/2;Q+=l+r,;l=p-r
 P=Q+[l]
print(P)

Liên tục cập nhật vectơ xác suất Pđể đáp ứng với từng dòng. Vectơ xác suất mới Qnày được tạo ra một mục nhập tại một thời điểm. Lặp lại qua các vị trí mới và tính toán đóng góp từ chốt bên phải r, đồng thời tính toán phần đóng góp còn lại cho vị trí sắp tới p-r.

Yêu cầu mỗi dòng kết thúc trong ít nhất một khoảng trắng để tránh sự cố trong đó các dòng kết thúc bằng dấu gạch chéo ngược.


Đầu vào sẽ có nhiều dòng vì vậy tôi không nghĩ một dòng nào input()có thể xử lý được.
ngẫu nhiên

một dòng mới không được yêu cầu cho mỗi dòng của đầu vào.
Brian Minton

@randomra Tôi đã viết cái này trong Idle và nó hoạt động tốt khi đưa các đầu vào đa dòng vào dấu nhắc shell.
xnor

6

Python 3, 138 byte

def f(s):
 r=[1];p=t=0
 for e in s:
  if'!'<e:b=p==t*-~t/2;r+=[0]*b;t+=b;v=ord(e)%7+1;a=r[p]/2;r[-1]+=v//3*a;r+=v%3*a,;p+=1
 return r[~t:]

Hoạt động với mọi khoảng trắng vì tất cả chúng đều được lọc (bởi if'!'<e).

Phương pháp:

  • Chúng tôi giữ một danh sách ngày càng mở rộng rvề xác suất đạt được bất kỳ trở ngại và các máng ngầm bên dưới chúng. Chúng tôi bắt đầu từ danh sách [1].
  • Nếu chúng ta ở chướng ngại vật đầu tiên liên tiếp, chúng ta cần thêm một phần bổ sung 0vào danh sách cho máng dẫn đầu. Chúng tôi quyết định nếu đó là trở ngại đầu tiên bằng cách so sánh chỉ số của nó với số ptam giác tiếp theo t*-~t/2.
  • Đối với mọi trở ngại, chúng tôi thêm một phần giá trị danh sách của nó vào phần tử cuối cùng và một phần cho phần tử trailing mới. Chúng tôi chia giá trị danh sách dựa trên ký tự chướng ngại vật ( ^:0.5 0.5; /:1 0; \:0 1). Chúng tôi sử dụng phương pháp sau:
    • Mang v = ord(char) mod 7 + 1lại năng suất^:4 /:6 \:2
    • v div 3 / 2mang lại phần đầu tiên ( ^:0.5 /:1 \:0)
    • v mod 3 / 2mang lại phần thứ hai ( ^:0.5 /:0 \:1)
  • Kết quả là các t + 1yếu tố cuối cùng của danh sách cuối cùng r.

2 byte nhờ lời khuyên trò chuyện của @ Sp3000.


4

Perl, 78

#!perl -p0a
@r=($/=1);$^=.5;@r=map$r-$l+($l=$$_*($r=shift@r)),/./g,$r=$l=0for@F;$_="@r"

Đưa đầu vào không có khoảng trắng.

Hãy thử tôi .


1

TI-BASIC, 73 76

Đưa đầu vào một dòng tại một thời điểm và kết thúc khi một khoảng trắng được nhập vào chính nó, bởi vì không ngắt dòng nào trong chuỗi cũng như chuỗi trống là hợp pháp trong TI-BASIC.

{1→X
Input Str1
While Str1≠"  //one space
.5seq(inString("^/",sub(Str1,I,1)),I,1,dim(Ans
augment(Ans∟X,{0})+augment({0},∟X-∟XAns→X
Input Str1
End
∟X

Tôi khá chắc chắn rằng tôi đã có kích thước đúng (TI-BASIC được mã hóa, do đó, mỗi lệnh mất một hoặc hai byte, se se () mất một, inString () mất hai, dim () mất một, v.v. đếm kích thước bằng tay.)

Mặc dù ký tự dấu gạch chéo ngược có giá trị trong một chuỗi, lưu ý rằng không có cách nào để nhập một từ bên trong chương trình trừ khi bạn đã sửa đổi máy tính của mình.


0

Javascript - 117

Đã thử sử dụng đệ quy, nhưng quá lâu ...

Hat tip cho xnor cho ý tưởng trừ, trong đó loại bỏ một tá hoặc nhiều nhân vật.

w=s=>{a=[1];s.split('\n').map(m=>{for(b=[i=0];z=a[i],f=m[i];b[i++]+=z-b[i])b[i+1]=f>']'?z/2:f<':'?0:z;a=b})
return a}

Ung dung:

// s must not have spaces
w=s=>{
  // a is the current probability array
  a=[1];
  s.split('\n').map(
    // for each row of input...
    m=>{
      b=[0];  // b is the next row's probability array
      for(i=0; i<m.length;){
        z=a[i]; // z = probability
        f=m[i]; // f = letter
                                  // let's assume i == 0
        b[i+1] = (f>']') ? z/2 :  // if f == '^', b[1] = z/2
          (f<':' ? 0 :            // else if f == '/', b[1] = 0 
            z);                   // else b[1] = z
        b[i++]+=z-b[i];           // then add (z-b[1]) to b[0]
      }
      a=z-b    // increment current probability array
    }
  )
  return a;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.