f=lambda n,k=1:k/n or n*f(n,k+1)+k*f(n-1,k)
Provalo online!
Un approccio diverso
Da quando ho pubblicato questa sfida, ho cercato di trovare una soluzione ricorsiva a questo problema. Anche se non sono riuscito a utilizzare nient'altro che carta e penna, sono riuscito a trasformare la formula in golf in un problema pratico - almeno per alcune definizioni di pratica - che ha reso più facile l'analisi.
Immagina un game show con k + m candidati che funzioni come segue.
Nel round 1, tutti i candidati devono svolgere un determinato compito il più velocemente possibile. I k candidati che completano il compito vincono più velocemente 1 k $ (un kilodollar) ciascuno e avanzano al round 3.
Nel turno 2, le m rimanenti candidati ottiene una seconda possibilità di unirsi agli altri k . Ad ogni candidato viene posta una domanda. Se rispondono correttamente alla domanda, vincono 1 k $ e passano al round 3. Tuttavia, se non rispondono alla domanda, vengono eliminati dal gioco. Questo significa che il round 3 avrà tra k e k + m candidati, a seconda di quanti possono rispondere alle loro domande.
Round 3 è costituito da m più concorsi che sono simili a turno 1. In ogni concorso, i partecipanti devono svolgere un certo compito. A differenza del round 1, solo un candidato riceve un premio, ma tutti i candidati possono partecipare al prossimo concorso. Ogni contest paga il doppio rispetto al contest precedente; il primo paga 2 k $ e l'ultimo 2 m k $ .
Nota che, poiché tutti i premi sono poteri di due, sapere quanti premi in denaro guadagnati da un candidato significa che sappiamo se sono passati al terzo round e quali dei concorsi del terzo round hanno vinto.
Supponiamo che tu stia guardando il game show e il round 1 sia già finito, quindi sai quali k candidati hanno già raggiunto il round 3 e quali m candidati sono ancora bloccati nel round 2. In quanti modi è possibile distribuire il montepremi residuo?
Una volta che sappiamo che del secondo turno di m candidati hanno avanzato al turno 3, è facile calcolare i possibili risultati di questo scenario specifico. Se j candidati avanzano, ci sono k + j candidati totali al turno 3, e quindi k + j possibili risultati per ogni gara. Con m contest individuali nel round 3, questo fa (k + j) m risultati per tutti i contest m .
Ora, j può assumere qualsiasi valore compreso tra 0 e m , a seconda di quali candidati rispondono correttamente al round 2. Per ogni valore fisso di j , ci sono m C j diverse combinazioni di j candidati che potrebbero essere avanzate al round 3. Se chiamiamo il numero totale di risultati possibili per k round 3 candidati e m round 2 candidati g (m, k) , otteniamo la seguente formula.
Se risolviamo k = 1 , otteniamo il seguente caso speciale, che costituisce il nostro nuovo approccio per risolvere il problema originale.
Una formula ricorsiva
Ora, supponi che ti sei addormentato durante gli spot dopo il primo round e ti sei svegliato giusto in tempo per vedere chi ha vinto l'ultimo concorso del terzo round e quindi il primo premio di 2 milioni di $ . Non hai altre informazioni, nemmeno quanti premi in denaro quel candidato ha vinto in totale. In quanti modi è possibile distribuire il montepremi residuo?
Se il vincitore era uno dei m candidati del round 2, già ora dobbiamo aver superato il round 3 . Quindi, abbiamo effettivamente k + 1 candidati nel round 3, ma solo m - 1 candidati nel round 2. Dato che conosciamo il vincitore dell'ultimo contest, ci sono solo m - 1 contest con esiti incerti, quindi ci sono g (m - 1, k + 1) possibili esiti.
Se il vincitore è uno dei k candidati che hanno saltato il round 2, il calcolo diventa leggermente più complicato. Come in precedenza, sono rimasti solo m - 1 round, ma ora abbiamo ancora k candidati nel round 3 e m candidati nel round 2. Poiché il numero di candidati del round 2 e il numero di concorsi del round 3 sono diversi, i possibili risultati non possono essere calcolato con una semplice invocazione di g . Tuttavia, dopo che il candidato del primo turno 2 ha risposto - giustamente o erroneamente - il numero di candidati del turno 2 corrisponde ancora una volta alle gare m - 1 turno 3. Se il candidato avanza, ci sono k + 1 round 3 candidati e quindi g (m - 1, k + 1)possibili esiti; se il candidato viene eliminato, il numero di candidati del round 3 rimane a k e ci sono g (m - 1, k) possibili esiti. Poiché il candidato avanza o meno, ci sono g (m - 1, k + 1) + g (m - 1, k) possibili esiti che combinano questi due casi.
Ora, se aggiungiamo i risultati potenziali per tutti i candidati k + m che avrebbero potuto vincere il primo premio, il risultato deve corrispondere a g (m, k) . Ci sono m round 2 concorrenti che portano a g (m - 1, k + 1) risultati potenziali ciascuno e k round 3 concorrenti che portano a g (m - 1, k + 1) + g (m - 1, k) quelli. Riassumendo, otteniamo la seguente identità.
Insieme al case base
queste due formule caratterizzano completamente la funzione g .
Un'implementazione golfistica
Mentre
g=lambda m,k=1:0**m or(m+k)*g(m-1,k+1)+k*g(m-1,k)
(49 byte, 0**m
produce 1 volta che m scende a 0 ) o anche
g=lambda m,k=1:m<1 or(m+k)*g(m-1,k+1)+k*g(m-1,k)
(48 byte, restituisce True anziché 1 ) sarebbero soluzioni valide, ci sono ancora byte da salvare.
Se definiamo una funzione f che prende il numero n di candidati del turno 1 anziché il numero m di candidati del turno 2 come primo argomento, cioè
otteniamo la formula ricorsiva
con custodia di base
Finalmente abbiamo
così l'implementazione di Python
f=lambda n,k=1:k/n or n*f(n,k+1)+k*f(n-1,k)
( k/n
restituisce 1 volta n = k ) risolve l'attività attuale con l'indicizzazione basata su 1.