Rutin Fasulye Makinesi Değil


42

Bir fasulye makinesine veya plinko / pachinko oyununa benzer bir mekanizmanın bu ASCII sürümünü düşünün :

    O

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

OAşağı düşen bir top.

  • Bir vuruş yaptığında ^, sola ya da sağa gitme şansı 50-50 olur.
  • Bire vurduğunda /her zaman sola döner.
  • Bir vuruş yaptığında \, her zaman doğru gider.

Top nihayetinde alttaki numaralı Uoluklardan birine düşer . Asıl soru, her kanalda ortaya çıkma olasılığı nedir?

Bu özel durumda, olasılıklar vardır 0.0, 0.1875, 0.5625, 0.125, ve 0.125, sırası ile 5 arasındaki olukları 1.

İşte 3 olukları yerine 5. olasılıkları vardır ile başka bir örnek 0.5, 0.5ve 0.0:

  O

  /
 ^ ^
U U U
1 2 3

Bu mücadelede, bu problemi, herhangi bir şekilde kurulmuş herhangi bir sayıda katmana sahip bir mekanizmaya yaygınlaştıracağız.

Meydan okuma

Mekanizmanın piramit yapısının ASCII temsilini alan bir program veya işlev yazın. (Stdin / komut satırı / işlev arg. İle giriş)

Ya uygun bir şekilde yerleştiren boşluklarla geldiğini varsayabilirsin, örneğin

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Veya hiç boşluk bırakmadığını, örneğin

^
\^
^^\
\^/^

(İsterseniz, takip eden bir yeni satır ve / veya bazı takip eden boşluk alanlarının olduğunu varsayabilirsiniz.)

Giriş piramidi yapısı sıfır dahil herhangi bir sayıda seviyeye (aka çizgileri) sahip olabilir. Her seviyede bir daha vardır ^, /ya da \son daha ve orada levels + 1(giriş parçası değildir) altındaki olukları.

Programlamanız / işlevin, topun her bir çukura girme olasılıklarının listesini yazdırması / iade etmesi gerekir (en soldan en sağa veya en soldaki sırayla). Bunlar, basıldığında en az 3 ondalık basamağa sahip kayan nokta değerleri olmalıdır (gereksiz sıfırlar ya da ondalık basamağa ihtiyaç duyulmaz; 1bunun için para cezası iyidir 1.000, .5bunun için iyidir 0.500, vb.). Bir işlev yazdıysanız, değerleri yazdırabilir veya yüzenlerin bir listesini / dizisini döndürebilirsiniz.

Herhangi bir makul basılı liste formatı iyidir. örneğin 0.5 0.5 0.0, [0.5 0.5 0.0], [0.5, 0.5, 0.0], {0.5, 0.5, 0.0}, veya 0.5\n0.5\n0.0tüm düzeleceğine.

Örnekler

0 Seviyeler: (önemsiz bir seviyeye kadar kaynar U)

Giriş: [no input/empty string given]
Çıkış:1.0

1 Seviye:

Giriş: ^
Çıkış:0.5 0.5

Giriş: /
Çıkış:1.0 0.0

Giriş: \
Çıkış:0.0 1.0

2 Seviye: (yukarıdaki ikinci örnek)

Giriş:

 /
^ ^

Çıktı: 0.5 0.5 0.0

3 Seviye:

Giriş:

  ^
 ^ ^
^ ^ ^

Çıktı: 0.125 0.375 0.375 0.125

Giriş:

  \
 / \
/ / \

Çıktı: 0.0 0.0 0.0 1.0

4 Seviye: (yukarıdaki ilk örnek)

Giriş:

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Çıktı: 0.0 0.1875 0.5625 0.125 0.125

7 Seviye:

Giriş:

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

Çıktı: 0.0 0.09375 0.28125 0.4375 0.1875 0.0 0.0 0.0

puanlama

Bayt cinsinden en kısa cevap kazanır. Tiebreaker daha önce yayınlandı.


16
Quincunx buna daha iyi cevap vermişti .
Calvin'in Hobileri

"bazı tutarlı takip alanları modeli" - Nth çizgisindeki sondaki boşlukların, topun Nth kovasına inme olasılığını kodladığını varsayabilir miyim?
Random832

4
@ Random832 Hayır. (Bunun gerçekten uçacağını mı düşünüyorsun?)
Calvin'in Hobileri

Cevap yerine yorum olarak göndermemin bir nedeni var. Ben sadece bu bulmacanın girdiyle ilgili olarak ne kadar izin vericinin ilginç olduğunu düşündüm - çoğu kez girdi ve / veya çıktı formatını daha katı bir şekilde dikte ettim.
Random832

@ Random832: Giriş ve çıkış çok açık. Standart boşluklar (girdideki cevabı kodlamak gibi) her zorlukla cevaplanmak zorunda değildir.
Alex A.

Yanıtlar:


10

CJam, 50 48 45 44 42 40 bayt

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

Bu, girdilerin boşluksuz ve izleyen bir yeni satır olmasını bekliyor. Örneğin:

^
\^
^^\
\^/^

[0 0.1875 0.5625 0.125 0.125]

Algoritma

Temel fikir, her bir karakteri ayrıştırmaya devam etmeniz (sadece 4 farklı karakter var) ve olasılık dağılımında farklı işlemler gerçekleştirmeniz (başlangıçta 1 değerinde 1 element içeren bir dizi). Her giriş karakteri satırı için (ilk satırdaki ilk karakterden başlayarak), aynı boyutta bir olasılık dizisini koruyoruz. Her karakter listeden ilk olasılık üzerine etki eder ve elde edilen çifti listenin sonuna kadar iter. Her satırdan sonra, bir sonraki satırdaki öğelerle tam sayıdaki öğeleri almak için listedeki çiftleri toplarız.

İşte dört karakter ve bunlara karşılık gelen gerekli eylemler:

  • ^: Bu karakter gerçekleştiğinde, mevcut olasılığı iki bölüme ayırırsınız. Örneğin, bunu ilk satırda yaparsak, dönüştürmek zorundayız [1].[0.5 0.5]
  • /: Bu karakterler meydana geldiğinde, <current probability> 0dizideki mevcut olasılığı yerine koymak zorundayız .
  • \: Bu karakterler meydana geldiğinde, 0 <current probability>dizideki mevcut olasılığı yerine koymak zorundayız .
  • \n: Bu karakter gerçekleştiğinde, yeni bir satırımız var. Bu yüzden, yukarıdaki 3 karakterden tüm çiftleri bir araya topladık ve bir sonraki satır için her bir öğenin olasılığını almak için bunları topladık. Örneğin [0 0.5 0.25 0.25]dönüştürülür [0 0.75 0.25]. İlk ve son öğelerin önlerinde ve sonrasında örtük bir çiftinin (0 değerinde) olduğunu unutmayın.

Şimdi sadece doğru karakteri tanımlamamız ve doğru işlemi yapmamız gerekiyor. Bunu yapmak için her zamanki matematiği kullanalım. İçin ASCII kodları ^, \, /ve \nvardır 94, 92, 47, ve 10. Birkaç denemeden sonra, bu sayıları 0, 1, 2 ve 3'e dönüştürmek için bu basit denklemi elde ediyoruz:

"^\/
":ied13f%ed4f%ed

verir:

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

Bir dizi 4'te, sonuncusu 4f%örtük olur. Bu yüzden %13karakterin ASCII koduna yapıyoruz ve bir eylem dizisinden doğru işlemi seçiyoruz.

Kod açıklaması :

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

Burada çevrimiçi deneyin


1
0 satırla nasıl test edersiniz?
trichoplax

1
@trichoplax şimdi çalışmalı.
Doktor,

Şimdi boş girişle çalışıyor :)
trichoplax

15

Yakut 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}

Dizeyi girdi olarak alan (bir piramit biçiminde güzel bir şekilde biçimlendirilebilir) ve bir dizi süzgeci döndüren işlev.

Çevrimiçi sınayın: http://ideone.com/kmsZMe

Oldukça basit bir uygulama. İşte asılsız:

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 bayt

Daha iyi bir yakut sürümü varken, bunu yükseltmeye devam etmeyin . İşte sizin için daha fazla püf noktaları.

Bir argümanla adlandırılmamış fonksiyon. Boşluk içermemelidir. İzleyen bir yeni satır içerebilir veya içermeyebilir.

->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}

Elde etmek için 9 bayt 0 levelsboşa harcar (boş dize). Tüm test durumları doğru çalışıyor , ideone'da buraya bakın .


4
Sırf "daha iyi" olması, Ruby cevabının sizin (veya bu konuda başka bir Ruby cevabının) oy kullanmayacağı anlamına gelmez. :)
Alex A.

Bunu kendim daha iyi yaptım çünkü bazı güzel numaralar içeriyordu. splitMesela multiline'nizi seviyorum .
Cristian Lupascu

12

Pyth, 43 42 41 bayt

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

Bu, girişin boşluksuz olmasını bekler. Çevrimiçi deneyin: Pyth Compiler / Executor

Pyth, 40 bayt (sorgulanabilir)

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

@İsaacg'a bir bayt kaydettiğin için teşekkürler. Bu sorunun aslında soru sorulduğunda Pyth versiyonunda çalışmadığına dikkat edin. Derleyicide küçük bir hata vardı. Bu kod Pyth'in hiçbir yeni özelliğini kullanmamasına rağmen (yalnızca Pyth belgelerinde uzun süredir çalışan ve çalışması gereken şeyler), bu geçerli bir cevap olmayabilir. Kendin için karar ver.

Çevrimiçi deneyin: Pyth Compiler / Executor

Açıklama:

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

Örneğin, şu anda giriş olasılıklarım G = [0.5, 0.5, 0.0]ve satırım varsa H = "^/^"aşağıdakiler gerçekleşir:

  • zip ... [(0.5,"^"), (0.5,"/"), (0.0,"^")]
  • çıktı olasılıkları yaratın ... [[0.25,0.25], [0.5,0.0], [0.0, 0.0]]
  • 0 + toplam ... [0, 0.25, 0.25, 0.5, 0.0, 0.0, 0.0]
  • doğrayın ... [0,0.25], [0.25,0.5], [0.0,0.0], [0.0]]
  • topla ... [0.25, 0.75, 0.0, 0.0]

3
Bunu golf oynamaya çalışıyordum ve bu beni derleyicide bir hataya götürdü. Golf çalışıyor, şimdi hatayı düzelttim. Golf, 2-değer listelerinin listesini bir listeyle değiştirmek ve daha sonra ilk değeri çıkartarak diğer değeri üretmektir hk. ,K@[ZJhkcJ2)x"\/"ek-JK
isaacg,

1
Bir hatayı düzeltirken dilin daha yeni bir sürümü sayılmazsa bu gerçekten iyi bir çizgidir (ve bu nedenle düzeltmeden önce sorulan sorular için hala geçerlidir)
Doktoru

1
@Optimizer Hakkınız. Cevaba bazı notlar eklendi, koşulları açıkladı.
Jakube

2
@Optimizer Bu durumda, uygulamanın şartnameye daha yakın olmasını sağlayacak bir hatayı düzelten bir dil versiyonunun gerçekten mi, yoksa dil uygulamasının daha yeni bir versiyonunun mu olduğu çok iyi bir kuraldır .
15’te

@Desty Bu yüzden ince çizgiden bahsetmiştim;)
Optimizer

8

C #, 274 247 bayt

Hiçbir şey fantezi, STDIN'den satırları okuyan (boşluklu veya boşluksuz, sadece onları sıyırır) ve boşlukla ayrılmış sonuçları STDOUT'a yazdıran eksiksiz bir program.

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

Yorumlu Tidier kodu:

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

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

PHer satıra yanıt olarak olasılık vektörünü tekrar tekrar günceller . Bu yeni olasılık vektörü Qbir defada bir giriş oluşturulur. Yeni yuvalar boyunca yinelenir rve kalan yuvaya kalan katkıları hesaplarken, mandalın sağa olan katkısını hesaplar p-r.

Satırların ters eğik çizgiyle bittiği bir sorunu önlemek için her çizginin en az bir alanda bitmesini bekler.


Girdide birden çok satır olacaktır, bu yüzden tek bir input()kişinin bunu kaldırabileceğini sanmıyorum .
randomra

Girişin her satırı için izleyen bir yeni satır gerekmemektedir.
Brian Minton

@randomra Boşta bu yazdım ve çok satırlı girişleri kabuk istemine koyarak iyi çalıştı.
xnor

6

Python 3, 138 bayt

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

Tüm boşluklarla (tümü) filtrelenerek çalışır if'!'<e.

Yöntem:

  • rEngellere ve aşağıda belirtilen örtük çukurlara ulaşma olasılıklarının sürekli genişleyen bir listesini tutarız . Listeden başlıyoruz [1].
  • Eğer üst üste ilk engelde olursak 0, lider kanal için listeye fazladan bir rakam eklememiz gerekir . Endeksini bir psonraki üçgen sayı ile karşılaştırarak ilk engel olup olmadığına karar veririz t*-~t/2.
  • Her engel için liste değerini kısmen son öğeye, kısmen de yeni bir takip elemanına ekleriz. Liste değerini engel karakterine ( ^:0.5 0.5; /:1 0; \:0 1) göre böleriz . Aşağıdaki yöntemi kullanıyoruz:
    • al v = ord(char) mod 7 + 1veren^:4 /:6 \:2
    • v div 3 / 2ilk kesriyi verir ( ^:0.5 /:1 \:0)
    • v mod 3 / 2ikinci fraksiyonu ( ^:0.5 /:0 \:1) verir
  • Sonuç, t + 1son listenin son unsurlarıdır r.

@ Sp3000'ün sohbet önerisi sayesinde 2 bayt.


4

Perl, 78

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

Boşluksuz girdi alır.

Deneyin beni .


1

TI-BASIC, 73 76

Her seferinde bir satır girişini alır ve kendi başına bir boşluk girildiğinde biter, çünkü ne dizgelerde kırılır ne de boş dizgiler TI-BASIC'de yasal değildir.

{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

Büyüklüğü doğru aldığımdan eminim (TI-BASIC belirtilmiş, her komut bir ya da iki bayt alıyor - seq () bir tane alır, inString () iki tane alır, dim () bir tane alır, vb. elle boyutta sayılır.)

Ters eğik çizgi karakteri bir dizgede geçerli olsa da, hesap makinenizi değiştirmediyseniz, programın içinden bir giriş yapmanın bir yolu olmadığını unutmayın.


0

Javascript - 117

Özyineleme kullanarak denedim, ama bu çok uzun oldu ...

Şapka , bir düzine veya daha fazla karakterle traş olan çıkarma fikri için kızardı .

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}

Ungolfed:

// 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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.