Non la tua macchina per fagioli ordinaria


42

Considera questa versione ASCII di un meccanismo simile a una macchina bean o a un gioco plinko / pachinko :

    O

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

La Oè una palla che cade.

  • Quando colpisce un ^, c'è una probabilità del 50-50 che andrà a sinistra o a destra.
  • Quando colpisce a /, va sempre a sinistra.
  • Quando colpisce a \, va sempre bene.

La palla alla fine cade in uno dei Utrogoli numerati in basso. La domanda è: qual è la probabilità che finisca in ogni depressione?

Per questo caso particolare, le probabilità sono 0.0, 0.1875, 0.5625, 0.125, e 0.125, per trogoli 1 a 5, rispettivamente.

Ecco un altro esempio con 3 vasche invece di 5. Le probabilità sono 0.5, 0.5, e 0.0:

  O

  /
 ^ ^
U U U
1 2 3

In questa sfida generalizzeremo questo problema a un meccanismo con un numero qualsiasi di livelli impostati in qualsiasi modo.

Sfida

Scrivi un programma o una funzione che includa la rappresentazione ASCII della struttura piramidale del meccanismo. (Input tramite stdin / riga di comando / arg funzione).

Puoi anche supporre che arrivi con spazi che lo mettano nella forma corretta, ad es

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Oppure puoi supporre che arrivi senza spazi, ad es

^
\^
^^\
\^/^

(Se lo si desidera, è possibile supporre che vi sia una nuova riga finale e / o un modello coerente di spazi finali).

La struttura della piramide di input può avere un numero qualsiasi di livelli (ovvero linee), incluso lo zero. Ogni livello ne ha uno in più ^, /o \rispetto all'ultimo, e ci sono levels + 1trogoli in fondo (che non fanno parte dell'input).

Il programma / funzione deve stampare / restituire l'elenco delle probabilità che la pallina atterra in ciascuno dei trogoli (nell'ordine più a sinistra a quello più a destra). Questi dovrebbero essere valori in virgola mobile che, quando stampati, hanno almeno 3 cifre decimali (non sono necessari zeri superflui o punti decimali; 1va bene per 1.000, .5va bene per 0.500, ecc.). Se hai scritto una funzione, puoi stampare i valori o restituire un elenco / matrice dei float.

Qualsiasi ragionevole formato di elenco stampato va bene. ad esempio 0.5 0.5 0.0, [0.5 0.5 0.0], [0.5, 0.5, 0.0], {0.5, 0.5, 0.0}, o 0.5\n0.5\n0.0sarebbe stato tutto a posto.

Esempi

0 livelli: (si riduce a una banale U)

Ingresso: [no input/empty string given]
Uscita:1.0

1 livello:

Ingresso: ^
Uscita:0.5 0.5

Ingresso: /
Uscita:1.0 0.0

Ingresso: \
Uscita:0.0 1.0

2 livelli: (secondo esempio sopra)

Ingresso:

 /
^ ^

Produzione: 0.5 0.5 0.0

3 livelli:

Ingresso:

  ^
 ^ ^
^ ^ ^

Produzione: 0.125 0.375 0.375 0.125

Ingresso:

  \
 / \
/ / \

Produzione: 0.0 0.0 0.0 1.0

4 livelli: (primo esempio sopra)

Ingresso:

   ^
  \ ^
 ^ ^ \
\ ^ / ^

Produzione: 0.0 0.1875 0.5625 0.125 0.125

7 livelli:

Ingresso:

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

Produzione: 0.0 0.09375 0.28125 0.4375 0.1875 0.0 0.0 0.0

punteggio

Vince la risposta più breve in byte. Tiebreaker è post precedente.


16
Quinconce era meglio rispondere a questa.
Calvin's Hobbies,

"qualche modello coerente di spazi finali" - posso supporre che gli spazi finali dell'ennesima linea codifichino la probabilità che la palla finisca nell'ennesimo secchio?
Casuale 832,

4
@ Random832 No. (Credi davvero che volerebbe ?)
Calvin's Hobbies

C'è un motivo per cui l'ho pubblicato come commento anziché come risposta. Ho solo pensato che fosse interessante quanto fosse permissivo questo enigma sull'input - la maggior parte che ho visto dettare il formato dell'input e / o dell'output in modo più rigoroso.
Casuale 832,

@ Random832: input e output sono molto chiari. Le scappatoie standard (come la codifica della risposta nell'input) non devono essere affrontate in ogni sfida.
Alex A.

Risposte:


10

CJam, 50 48 45 44 42 40 byte

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

Questo si aspetta che l'input sia senza spazio e abbia una nuova riga finale. Per esempio:

^
\^
^^\
\^/^

[0 0.1875 0.5625 0.125 0.125]

Algoritmo

L'idea di base è che continui ad analizzare ogni personaggio (ci sono solo 4 caratteri diversi) ed esegui diverse operazioni sulla distribuzione di probabilità (inizialmente un array contenente 1 elemento di valore 1). Per ogni riga di caratteri di input (a partire dal primo carattere della prima riga), manteniamo un array di probabilità della stessa dimensione. Ogni personaggio agisce sulla prima probabilità dalla lista e spinge la coppia risultante alla fine della lista. Dopo ogni riga, riassumiamo le coppie dall'elenco per ottenere il numero esatto di elementi come gli articoli nella riga successiva.

Ecco i quattro personaggi e le azioni richieste corrispondenti a ciascuno:

  • ^: Quando compare questo personaggio, dividi la probabilità attuale in due parti. Ad esempio, se abbiamo questo sulla prima riga, dobbiamo convertire [1]in[0.5 0.5]
  • /: Quando si presentano questi caratteri, dobbiamo mettere <current probability> 0al posto della probabilità corrente nella matrice.
  • \: Quando si presentano questi caratteri, dobbiamo mettere 0 <current probability>al posto della probabilità corrente nella matrice.
  • \n: Quando compare questo personaggio, abbiamo una nuova linea. Quindi raggruppiamo tutte le coppie di sopra di 3 caratteri e le sommiamo per ottenere la probabilità di ogni elemento per la riga successiva. Per es. [0 0.5 0.25 0.25]viene convertito in [0 0.75 0.25]. Si noti che il primo e l'ultimo elemento hanno una coppia implicita (valutata 0) prima e dopo di essi.

Ora dobbiamo solo identificare il personaggio giusto ed eseguire l'azione giusta. Usiamo i soliti calcoli qui per farlo. I codici ASCII per ^, \, /e \nsono 94, 92, 47, e 10. Dopo alcune prove, otteniamo questa semplice equazione per convertire questi numeri in 0, 1, 2 e 3:

"^\/
":ied13f%ed4f%ed

dà:

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

In una matrice di lunghezza 4, l'ultimo 4f%sarebbe implicito. Quindi facciamo semplicemente %13il codice ASCII del personaggio e scegliamo l'azione giusta da una serie di azioni.

Spiegazione del codice :

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

Provalo online qui


1
Come lo provi con 0 righe?
trichoplax,

1
@trichoplax dovrebbe funzionare ora.
Ottimizzatore

Funziona ora con input vuoto :)
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}

Funzione che accetta come input la stringa (può essere formattata come una piramide) e restituisce una matrice di float.

Provalo online: http://ideone.com/kmsZMe

Implementazione piuttosto semplice. Qui è 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
}

13

Rubino, 140 158 byte

Non continuare a votare questo quando c'è una versione rubino migliore . Ecco altri trucchi per te.

Funzione senza nome con un argomento. Non deve contenere spazi. Può contenere o meno una nuova riga finale.

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

Spreca 9 byte per la gestione 0 levels(stringa vuota). Tutti i casi di test funzionano correttamente, vedi qui su ideone .


4
Solo perché c'è una risposta "migliore" a Ruby non significa che la tua (o qualsiasi altra risposta a Ruby per quella materia) non valga la pena di votare. :)
Alex A.

L'ho votato io stesso perché contiene alcuni trucchi interessanti. Mi piace la tua multilinea split, per esempio.
Cristian Lupascu,

12

Pyth, 43 42 41 byte

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

Questo si aspetta che l'input sia senza spazi. Provalo online: Pyth Compiler / Executor

Pyth, 40 byte (discutibile)

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

Grazie a @isaacg, per aver salvato un byte. Si noti che questa versione in realtà non funzionava nella versione di Pyth, quando è stata posta la domanda. C'era un piccolo bug nel compilatore. Nonostante questo codice non usi nuove funzionalità di Pyth (solo cose che erano nei documenti Pyth da molto tempo e avrebbero dovuto funzionare), questa potrebbe non essere una risposta valida. Decidi tu stesso.

Provalo online: Pyth Compiler / Executor

Spiegazione:

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

Ad esempio, se attualmente ho le probabilità di input G = [0.5, 0.5, 0.0]e la riga H = "^/^"accade quanto segue:

  • cerniera lampo ... [(0.5,"^"), (0.5,"/"), (0.0,"^")]
  • creare probabilità di output ... [[0.25,0.25], [0.5,0.0], [0.0, 0.0]]
  • 0 + somma ... [0, 0.25, 0.25, 0.5, 0.0, 0.0, 0.0]
  • tagliare ... [0,0.25], [0.25,0.5], [0.0,0.0], [0.0]]
  • somma ... [0.25, 0.75, 0.0, 0.0]

3
Stavo cercando di giocare a golf, e questo mi ha portato a un bug nel compilatore. Il golf funziona, ora che ho corretto il bug. Il golf consiste nel sostituire l'elenco di elenchi a 2 valori con un elenco, quindi generare l'altro valore sottraendo il primo valore da hk. ,K@[ZJhkcJ2)x"\/"ek-JK
isaacg,

1
Questa è davvero una linea sottile quando la correzione di un bug non viene conteggiata come una versione più recente della lingua (e quindi è ancora valida per le domande poste prima della correzione)
Optimizer

1
@Optimizer Il tuo diritto. Aggiunte alcune note alla risposta, che spiega le circostanze.
Jakube,

2
@Optimizer In questo caso, sembra una buona regola è se è davvero una versione più recente del linguaggio o di una versione più recente del linguaggio di implementazione che corregge un bug, portando l'attuazione più da vicino linea con le specifiche.
Desty,

@Desty Ecco perché ho detto che è una linea sottile;)
Ottimizzatore

8

C #, 274 247 byte

Niente di speciale, programma completo che legge le linee (con o senza spazi, le rimuove semplicemente) da STDIN e stampa i risultati separati da spazio su 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));}}

Codice Tidier con commenti:

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)

Aggiorna ripetutamente il vettore di probabilità Pin risposta a ciascuna riga. Questo nuovo vettore di probabilità Qviene creato una voce alla volta. Scorre i nuovi slot e calcola il contributo dal piolo alla sua destra come r, calcolando anche il contributo rimanente allo slot imminente come p-r.

Si aspetta che ogni riga termini in almeno uno spazio per evitare un problema in cui le righe finiscono in una barra rovesciata.


L'input avrà più righe, quindi non credo che un singolo input()possa gestirlo.
randomra,

non è richiesta una nuova riga finale per ogni riga dell'input.
Brian Minton,

@randomra Ho scritto questo in Idle e ha funzionato bene inserendo input multilinea al prompt della 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:]

Funziona con tutti gli spazi bianchi poiché sono tutti filtrati (da if'!'<e).

Metodo:

  • Manteniamo un elenco in continua espansione rdelle probabilità di raggiungere eventuali ostacoli e le depressioni implicite sottostanti. Partiamo dalla lista [1].
  • Se siamo al primo ostacolo consecutivo, dobbiamo aggiungere un extra 0all'elenco per il canale principale. Decidiamo se è il primo ostacolo confrontando il suo indice pcon il prossimo numero triangolare t*-~t/2.
  • Per ogni ostacolo aggiungiamo il suo valore di elenco in parte all'ultimo elemento e in parte a un nuovo elemento finale. Dividiamo il valore di elenco in base al carattere ostacolo ( ^:0.5 0.5; /:1 0; \:0 1). Utilizziamo il seguente metodo:
    • Prendi la v = ord(char) mod 7 + 1resa^:4 /:6 \:2
    • v div 3 / 2produce la prima frazione ( ^:0.5 /:1 \:0)
    • v mod 3 / 2restituisce la seconda frazione ( ^:0.5 /:0 \:1)
  • Il risultato sono gli ultimi t + 1elementi dell'elenco finale r.

2 byte grazie al consiglio di chat di @ Sp3000.


4

Perl, 78

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

Accetta input senza spazi.

Prova a me .


1

TI-BASIC, 73 76

Accetta input una riga alla volta e termina quando viene inserito uno spazio da solo, poiché né le interruzioni di riga nelle stringhe né le stringhe vuote sono legali in 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

Sono abbastanza sicuro di avere le dimensioni giuste (TI-BASIC è tokenizzato, quindi ogni comando richiede uno o due byte: seq () ne prende uno, inString () ne prende due, dim () ne prende uno e così via. contò la dimensione manualmente.)

Sebbene il carattere barra rovesciata sia valido in una stringa, tenere presente che non è possibile immetterne uno dall'interno del programma se non si è modificata la calcolatrice.


0

Javascript - 117

Ho provato usando la ricorsione, ma è stato troppo lungo ...

Punta del cappello a xnor per l'idea di sottrazione, che ha rasato una dozzina o più personaggi.

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.