Nicht Ihre Routinebohnenmaschine

42

Betrachten Sie diese ASCII-Version eines Mechanismus, der einer Bohnenmaschine oder einem Plinko / Pachinko- Spiel ähnelt :

    O

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

Das Oist ein Ball, der runterfällt.

  • Wenn es auf a trifft ^, besteht eine 50: 50-Chance, dass es nach links oder rechts geht.
  • Wenn es ein trifft /, geht es immer nach links.
  • Wenn es auf ein trifft \, geht es immer richtig.

Der Ball fällt schließlich in einen der nummerierten UTröge am Boden. Die Frage ist, wie hoch die Wahrscheinlichkeit ist, dass es in jedem Trog landet.

Für diesen speziellen Fall sind die Wahrscheinlichkeiten sind 0.0, 0.1875, 0.5625, 0.125, und 0.125, für Tröge 1 bis 5 sind.

Hier ist ein weiteres Beispiel mit 3 Mulden statt 5. Die Wahrscheinlichkeiten sind 0.5, 0.5und 0.0:

  O

  /
 ^ ^
U U U
1 2 3

In dieser Herausforderung werden wir dieses Problem auf einen Mechanismus mit einer beliebigen Anzahl von Ebenen verallgemeinern, die auf eine beliebige Weise eingerichtet sind.

Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die die ASCII-Darstellung der Pyramidenstruktur des Mechanismus übernimmt. (Eingabe über stdin / command line / function arg.)

Sie können entweder davon ausgehen, dass es mit Leerzeichen kommt, die es in die richtige Form bringen, z

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Oder Sie können davon ausgehen, dass es überhaupt keine Leerzeichen enthält, z

^
\^
^^\
\^/^

(Falls gewünscht, können Sie davon ausgehen, dass eine nachgestellte Zeile und / oder ein konsistentes Muster von nachgestellten Leerzeichen vorhanden ist.)

Die Struktur der Eingabepyramide kann eine beliebige Anzahl von Ebenen (auch als Linien bezeichnet) aufweisen, einschließlich Null. Jede Ebene hat ein weiteres ^, /oder \als die letzte, und es gibt levels + 1Mulden am Boden (die nicht Teil des Eingangs sind).

Sie müssen die Liste der Wahrscheinlichkeiten drucken / zurückgeben, mit denen der Ball in jeder der Mulden landet (in der Reihenfolge von der linken zur rechten Mulde). Dies sollten Gleitkommawerte sein, die beim Drucken mindestens 3 Dezimalstellen haben (überflüssige Nullen oder Dezimalstellen sind nicht erforderlich; 1ist in Ordnung für 1.000, .5ist in Ordnung für 0.500usw.). Wenn Sie eine Funktion geschrieben haben, können Sie die Werte drucken oder eine Liste / ein Array der Floats zurückgeben.

Jedes vernünftige gedruckte Listenformat ist in Ordnung. zB 0.5 0.5 0.0, [0.5 0.5 0.0], [0.5, 0.5, 0.0], {0.5, 0.5, 0.0}, oder 0.5\n0.5\n0.0alles wäre in Ordnung.

Beispiele

0 Levels: (auf ein Trivial reduziert U)

Eingabe: [no input/empty string given]
Ausgabe:1.0

1 Stufe:

Eingabe: ^
Ausgabe:0.5 0.5

Eingabe: /
Ausgabe:1.0 0.0

Eingabe: \
Ausgabe:0.0 1.0

2 Ebenen: (zweites Beispiel oben)

Eingang:

 /
^ ^

Ausgabe: 0.5 0.5 0.0

3 Ebenen:

Eingang:

  ^
 ^ ^
^ ^ ^

Ausgabe: 0.125 0.375 0.375 0.125

Eingang:

  \
 / \
/ / \

Ausgabe: 0.0 0.0 0.0 1.0

4 Ebenen: (erstes Beispiel oben)

Eingang:

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Ausgabe: 0.0 0.1875 0.5625 0.125 0.125

7 Stufen:

Eingang:

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

Ausgabe: 0.0 0.09375 0.28125 0.4375 0.1875 0.0 0.0 0.0

Wertung

Die kürzeste Antwort in Bytes gewinnt. Tiebreaker ist früherer Beitrag.

Calvins Hobbys
quelle
16
Quincunx sollte das besser beantworten.
Calvins Hobbys
"Ein konsistentes Muster von nachgestellten Leerzeichen" - darf ich annehmen, dass die nachgestellten Leerzeichen in der N-ten Zeile die Wahrscheinlichkeit codieren, dass der Ball im N-ten Eimer landet?
Random832,
4
@ Random832 Nein. (Glaubst du wirklich , dass das fliegen würde?)
Calvins Hobbys
Es gibt einen Grund, warum ich es als Kommentar anstatt als Antwort gepostet habe. Ich fand es nur interessant, wie freizügig dieses Rätsel bei der Eingabe war - die meisten, die ich gesehen habe, haben das Format der Eingabe und / oder Ausgabe strenger vorgegeben.
Random832
@ Random832: Die Eingabe und Ausgabe sind sehr eindeutig. Standardlücken (wie das Kodieren der Antwort in der Eingabe) müssen nicht bei jeder Herausforderung behoben werden.
Alex A.

Antworten:

10

CJam, 50 48 45 44 42 40 Bytes

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

Dies setzt voraus, dass die Eingabe kein Leerzeichen enthält und eine nachgestellte Newline enthält. Zum Beispiel:

^
\^
^^\
\^/^

[0 0.1875 0.5625 0.125 0.125]

Algorithmus

Die Grundidee ist, dass Sie jedes Zeichen weiter analysieren (es gibt nur 4 verschiedene Zeichen) und verschiedene Operationen für die Wahrscheinlichkeitsverteilung ausführen (anfangs ein Array mit 1 Element mit Wert 1). Für jede Zeile von Eingabezeichen (beginnend mit dem ersten Zeichen in der ersten Zeile) wird ein Wahrscheinlichkeitsarray mit derselben Größe verwaltet. Jedes Zeichen wirkt auf die erste Wahrscheinlichkeit aus der Liste und verschiebt das resultierende Paar an das Ende der Liste. Nach jeder Zeile addieren wir Paare aus der Liste, um die genaue Anzahl der Elemente als Elemente in der nächsten Zeile zu erhalten.

Hier sind die vier Zeichen und die jeweils erforderlichen Aktionen:

  • ^: Wenn dieses Zeichen auftritt, teilen Sie die aktuelle Wahrscheinlichkeit in zwei Teile. Zum Beispiel, wenn wir dies in der ersten Zeile haben, müssen wir die konvertieren [1]zu[0.5 0.5]
  • /: Wenn dieses Zeichen auftritt, müssen wir <current probability> 0die aktuelle Wahrscheinlichkeit im Array ersetzen.
  • \: Wenn dieses Zeichen auftritt, müssen wir 0 <current probability>die aktuelle Wahrscheinlichkeit im Array ersetzen.
  • \n: Wenn dieses Zeichen auftritt, haben wir eine neue Zeile. Daher gruppieren wir alle Paare aus den obigen 3 Zeichen und addieren sie, um die Wahrscheinlichkeit jedes Elements für die nächste Zeile zu erhalten. Zum Beispiel. [0 0.5 0.25 0.25]wird konvertiert zu [0 0.75 0.25]. Beachten Sie, dass das erste und das letzte Element vor und nach ihnen ein implizites Paar (Wert 0) haben.

Jetzt müssen wir nur noch den richtigen Charakter identifizieren und die richtige Aktion ausführen. Verwenden wir dazu die üblichen Berechnungen. Der ASCII - Codes für ^, \, /und \nist 94, 92, 47, und 10. Nach einigen Versuchen erhalten wir diese einfache Gleichung, um diese Zahlen in 0, 1, 2 und 3 umzuwandeln:

"^\/
":ied13f%ed4f%ed

gibt:

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

In einem Array der Länge 4 4f%wäre das letzte implizit. Also machen wir einfach %13den ASCII-Code des Zeichens und wählen die richtige Aktion aus einer Reihe von Aktionen aus.

Code Erklärung :

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

Probieren Sie es hier online aus

Optimierer
quelle
1
Wie testest du es mit 0 Zeilen?
Trichoplax
1
@trichoplax sollte jetzt funktionieren.
Optimierer
Es funktioniert jetzt mit leerer Eingabe :)
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}

Funktion, die als Eingabe die Zeichenfolge verwendet (kann gut als Pyramide formatiert werden) und ein Array von Gleitkommazahlen zurückgibt.

Testen Sie es online: http://ideone.com/kmsZMe

Ziemlich unkomplizierte Implementierung. Hier ist es ungolfed:

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
}
Cristian Lupascu
quelle
13

Ruby, 140 158 Bytes

Stimmen Sie nicht weiter darüber ab, wenn es eine bessere Rubinversion gibt . Hier sind weitere Tricks für dich.

Unbenannte Funktion mit einem Argument. Darf keine Leerzeichen enthalten. Kann eine nachgestellte Zeile enthalten oder nicht.

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

Verschwendet 9 Bytes, um zu behandeln 0 levels(leere Zeichenfolge). Alle Testfälle klappen einwandfrei , siehe hier bei ideone .

blutorange
quelle
4
Nur weil es eine "bessere" Ruby-Antwort gibt, heißt das noch lange nicht, dass Ihre (oder eine andere Ruby-Antwort) keine Stimmen wert ist. :)
Alex A.
Ich habe das selbst hochgestuft, weil es ein paar nette Tricks enthält. Ich mag splitzum Beispiel Ihre Mehrfachleitung .
Cristian Lupascu
12

Pyth, 43 42 41 Bytes

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

Dies setzt voraus, dass die Eingabe keine Leerzeichen enthält. Probieren Sie es online aus: Pyth Compiler / Executor

Pyth, 40 Bytes (fraglich)

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

Vielen Dank an @isaacg für das Speichern eines Bytes. Beachten Sie, dass diese Version in der Version von Pyth nicht funktionierte, als die Frage gestellt wurde. Es gab einen winzigen Fehler im Compiler. Obwohl dieser Code keine neuen Funktionen von Pyth verwendet (nur Dinge, die lange in den Pyth-Dokumenten waren und hätten funktionieren sollen), ist dies möglicherweise keine gültige Antwort. Entscheide dich selbst.

Probieren Sie es online aus: Pyth Compiler / Executor

Erläuterung:

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

Wenn ich zum Beispiel momentan die Eingabewahrscheinlichkeiten G = [0.5, 0.5, 0.0]und die Zeile habe, H = "^/^"passiert Folgendes:

  • Postleitzahl ... [(0.5,"^"), (0.5,"/"), (0.0,"^")]
  • Ausgabewahrscheinlichkeiten erstellen ... [[0.25,0.25], [0.5,0.0], [0.0, 0.0]]
  • 0 + Summe ... [0, 0.25, 0.25, 0.5, 0.0, 0.0, 0.0]
  • hacken ... [0,0.25], [0.25,0.5], [0.0,0.0], [0.0]]
  • Summe ... [0.25, 0.75, 0.0, 0.0]
Jakube
quelle
3
Ich habe versucht, Golf zu spielen, und es hat mich zu einem Fehler im Compiler geführt. Das Golfspiel funktioniert jetzt, da ich den Fehler behoben habe. Das Golfspiel besteht darin, die Liste der Listen mit zwei Werten durch eine Liste zu ersetzen und dann den anderen Wert zu generieren, indem der erste Wert von subtrahiert wird hk. ,K@[ZJhkcJ2)x"\/"ek-JK
isaacg
1
Dies ist wirklich eine feine Linie, wenn Sie einen Fehler beheben, der nicht als neuere Version der Sprache gezählt wird (und daher immer noch für Fragen gültig ist, die vor dem Fix gestellt wurden)
Optimizer
1
@Optimizer Ihr Recht. Der Antwort wurden einige Anmerkungen hinzugefügt, die die Umstände erklären.
Jakube
2
@Optimizer In diesem Fall scheint es wie eine gute Faustregel ist , ob es wirklich eine neuere Version der Sprache oder eine neuere Version der Sprache Implementierung dass behebt ein Fehler, die Umsetzung näher in Einklang mit der Spezifikation zu bringen.
Desty
@Desty Deshalb habe ich erwähnt, dass es eine feine Linie ist;)
Optimierer
8

C #, 274 247 Bytes

Nichts Besonderes, komplettes Programm, das Zeilen (mit oder ohne Leerzeichen, es entfernt sie nur) aus STDIN einliest und durch Leerzeichen getrennte Ergebnisse an STDOUT ausgibt.

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

Ordentlicher Code mit Kommentaren:

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
    }
}
VisualMelon
quelle
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)

Aktualisiert wiederholt den Wahrscheinlichkeitsvektor P als Antwort auf jede Zeile. Dieser neue Wahrscheinlichkeitsvektor Qwird jeweils ein Eintrag erstellt. Durchläuft die neuen Slots und berechnet den Beitrag von der rechten Seite aus als r, während gleichzeitig der verbleibende Beitrag zum kommenden Slot als berechnet wird p-r.

Erwartet, dass jede Zeile in mindestens einem Leerzeichen endet, um ein Problem zu vermeiden, bei dem Zeilen mit einem Backslash enden.

xnor
quelle
Die Eingabe wird mehrere Zeilen haben, daher glaube ich nicht, dass ein einzelner input()damit umgehen kann.
Randomra
Es ist nicht für jede Zeile der Eingabe eine nachgestellte neue Zeile erforderlich.
Brian Minton
@randomra Ich habe dies in Idle geschrieben und es hat gut funktioniert, wenn ich mehrzeilige Eingaben in die Shell-Eingabeaufforderung eingegeben habe.
Xnor
6

Python 3, 138 Bytes

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

Funktioniert mit allen Leerzeichen, da alle herausgefiltert werden (von if'!'<e .

Methode:

  • Wir führen eine ständig wachsende Liste r der Wahrscheinlichkeiten für das Erreichen von Hindernissen und der impliziten Talsohlen darunter. Wir beginnen mit der Liste [1].
  • Wenn wir das erste Hindernis in einer Reihe sind, müssen wir 0der Liste für den führenden Trog ein Extra hinzufügen . Wir entscheiden, ob es das erste Hindernis ist, indem wir den Index vergleichenp mit der nächsten Dreieckszahl vergleichen t*-~t/2.
  • Für jedes Hindernis fügen wir seinen Listenwert teilweise zum letzten Element und teilweise zu einem neuen nachgestellten Element hinzu. Wir teilen den Listenwert anhand des Hinderniszeichens (^:0.5 0.5; /:1 0; \:0 1 ). Wir verwenden die folgende Methode:
    • nehmen Sie v = ord(char) mod 7 + 1nachgebend^:4 /:6 \:2
    • v div 3 / 2ergibt den ersten Bruch ( ^:0.5 /:1 \:0)
    • v mod 3 / 2ergibt den zweiten Bruch ( ^:0.5 /:0 \:1)
  • Das Ergebnis sind die letzten t + 1Elemente der endgültigen Liste r.

2 Bytes dank Chat-Rat von @ Sp3000.

randomra
quelle
4

Perl, 78

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

Übernimmt Eingaben ohne Leerzeichen.

Versuch es mit mir .

nutki
quelle
1

TI-BASIC, 73 76

Nimmt die Eingabe zeilenweise vor und endet, wenn ein Leerzeichen alleine eingegeben wird, da in TI-BASIC weder Zeilenumbrüche noch leere Zeichenfolgen zulässig sind.

{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

Ich bin mir ziemlich sicher, dass ich die richtige Größe habe (TI-BASIC ist tokenisiert, daher benötigt jeder Befehl ein oder zwei Bytes - seq () benötigt eins, inString () benötigt zwei, dim () benötigt eins und so weiter. I zählte die Größe manuell.)

Obwohl der umgekehrte Schrägstrich in einer Zeichenfolge gültig ist, gibt es keine Möglichkeit, einen Schrägstrich aus dem Programm heraus einzugeben, es sei denn, Sie haben Ihren Taschenrechner geändert.

Lirtosiast
quelle
0

Javascript - 117

Versucht mit Rekursion, aber das war zu lang ...

Hat Tipp an XNOR für die Subtraktion Idee, die ein Dutzend oder mehr Zeichen rasiert.

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;
}
Nicht dieser Charles
quelle