Codice golf: distribuire le palle (I)


12

Sfida

In questo compito hai calcolato il numero di modi in cui possiamo distribuire le sfere A nelle celle B con ogni cella che abbia almeno una palla.

Gli ingressi A e B sono indicati in un'unica riga separata da uno spazio vuoto, gli ingressi sono terminati da EOF.

Potresti voler controllare le tue soluzioni qui .

Ingresso

0 0
1 0
12 4
6 3
18 17
20 19
15 13
18 9
20 20
17 14
9 2
14 13
18 11

Produzione

1
0
14676024
540
54420176498688000
23112569077678080000
28332944640000
38528927611574400
2432902008176640000
21785854970880000
510
566658892800
334942064711654400

vincoli

  • Ogni A e B possono essere distinti.
  • 0 <= A, B <= 20
  • Puoi usare qualsiasi lingua tu scelga
  • Vince la soluzione più breve!

1
Ci sono limiti di tempo?

@Tim Nordenfur: Aggiornato :-)
Quixotic,

Quel link non è valido per me.
mellamokb,

3
@Debanjan Non mi piace l'idea di incollare domande da SPOJ qui. Le persone inviano il loro codice per competere lì e non sarebbe giusto per loro.
fR0DDY,

1
@Debanjan, vedo il tuo riferimento e ti sollevo Mathworld (eqn. 5 dice che S(n,0)è 1se n=0e 0altrimenti). Se vuoi posso trovare un riferimento per l'affermazione più forte che Stirling2 si trova nel sottogruppo associativo del gruppo esponenziale di Riordan.
Peter Taylor,

Risposte:


4

JavaScript (90 93 )

function f(a,b){n=m=r=1;for(i=b;i>0;n*=-1){r+=n*m*Math.pow(i,a);m=m*i/(b-i--+1)}return--r}

http://jsfiddle.net/RDGUn/2/

Ovviamente, qualsiasi linguaggio basato sulla matematica come APL mi batterà a causa della verbosità della sintassi e della mancanza di costrutti matematici incorporati :)

Modifica Inoltre, non ho alcuna funzionalità relativa all'input ad eccezione dei parametri passati nella funzione, non sono sicuro di come utilizzare l'input standard con JavaScript ...

Edit: Sposta i--nella m=m*espressione; spostare n*=-1in for; iniziare r=1a combinare i compiti e rimuoverne uno estraneo al ritorno. (salva 3 caratteri)


Potresti usare la shell spidermonkey - almeno ha readlinee print. Non so cosa usano gli altri qui.
Jesse Millikan,

@Jesse: interessante. Perderò comunque lol.
mellamokb,

prompte alertsono io "standard" di JavaScript, in quanto sono le tipiche chiamate io di blocco, nonostante il fatto che in genere non useresti mai il blocco di io con JavaScript.
zzzzBov

4

Golfscript - 56 50 49 48 41 40 38 37 caratteri

n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/

Nota: gestisce più righe di input, è veloce (1/8 di secondo per eseguire i casi di test) e non si interrompe per alcun input legale.

(La prima versione è stata anche il mio primo programma Golfscript in assoluto; grazie a eBusiness per aver messo in evidenza diversi trucchi che mi mancavano).

Per rendere anche questo utile post educativo, ecco una spiegazione di come funziona. Iniziamo con la ricorrenza f(n, k) = k * (f(n-1, k) + f(n-1, k-1)). Questo può essere inteso in modo combinatorio dicendo che per posizionare nsfere kdistinguibili in secchi distinguibili in modo tale che ogni secchio contenga almeno una pallina, scegli uno dei ksecchi per la prima pallina ( k *) e quindi conterrà almeno un'altra pallina ( f(n-1, k)) o non lo farà ( f(n-1, k-1)).

I valori risultanti da questo formano una griglia; prendendo ncome indice di riga e kcome indice di colonna e indicizzando entrambi da 0 inizia

1   0   0   0    0    0   0 ...
0   1   0   0    0    0   0 ...
0   1   2   0    0    0   0 ...
0   1   6   6    0    0   0 ...
0   1  14  36   24    0   0 ...
0   1  30 150  240  120   0 ...
0   1  62 540 1560 1800 720 ...
.   .   .   .    .    .   . .
.   .   .   .    .    .   .  .
.   .   .   .    .    .   .   .

Quindi, rivolgendosi al programma,

n%{~ <<STUFF>> }/

divide l'input in righe e quindi per ogni riga lo valuta, mettendo ne kin pila, e quindi chiama <<STUFF>>, che è il seguente:

),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;

Questo calcola le prime k+1voci della n+1riga di quella griglia. Inizialmente lo stack è n k.
),dà stack di n [0 1 2 ... k]
{!}%dà stack di n [1 0 0 ... 0]dove ci sono k0.
\{ <<MORE STUFF>> }*porta nin cima e lo rende il numero di volte che eseguiamo <<MORE STUFF>>.
Il nostro stack attualmente è una riga della tabella: [f(i,0) f(i,1) ... f(i,k)]
0.@mette un paio di 0 prima di quell'array. Il primo sarà je il secondo sarà f(i,j-1).
{ <<FINAL LOOP>> }/scorre attraverso gli elementi dell'array; per ognuno lo mette in cima allo stack e quindi esegue il corpo del loop.
.@+2$*@)@è noiosa manipolazione dello stack per ottenere ... j f(i,j-1) f(i,j)e cedere ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]pop-over del rimanentek+1 f(i,k)e raccoglie tutto in un array, pronto per il prossimo giro del ciclo.
Alla fine, quando abbiamo generato la nriga della tabella,
)p;prende l'ultimo elemento, lo stampa e scarta il resto della riga.

Per i posteri, tre soluzioni a 38 caratteri su questo principio:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


1
Abbastanza buono per un principiante, ci sono alcune possibili riduzioni su piccola scala, immediatamente trovo [0]-> 1,, lo spazio dopo zip può essere rimosso e l'altro spazio può essere rimosso se si memorizza in un operatore anziché in k. Non ho ancora esaminato il tuo codice, ma sospetto che potresti cavartela semplicemente usando un valore senza metterlo in un array in alcuni punti.
aaaaaaaaaaaa

1
+ 1, non capisco Golfscript ma questo sembra sufficientemente veloce, eppure molto breve.
Chisciotte

@eBusiness e @Peter Taylor: su una nota diversa .. quanto voi ragazzi valutate Golfscript su una scala di facile apprendimento?
Chisciotte

@Debanjan, dipende da quello che già sai. È un linguaggio funzionale basato su stack. Ho già usato un linguaggio funzionale (SML - in più ho scritto codice di stile funzionale in linguaggi OO), e in precedenza ho usato linguaggi basati su stack (bytecode Java assemblato con Jasmin, PostScript), quindi l'unico vero ostacolo Devo imparare quali operatori sono disponibili. Se conosci solo le lingue della famiglia Algol (C, Java, ecc.) Allora avrai tre ostacoli da saltare contemporaneamente.
Peter Taylor,

@Debanjan - È molto più semplice di quanto sembri, puoi iniziare a scrivere il codice quasi immediatamente, ma ovviamente ci vuole del tempo per imparare tutti i piccoli trucchi.
aaaaaaaaaaaa

3

J, 40

4 :'|-/x(^~*y!~])i.1x+y'/&.".;._2(1!:1)3 

Per esempio

4 :'-/((x^~|.@:>:)*y&(!~))i.y'/x:".>{.;:(1!:1)3
15 13
28332944640000

<1 sec per tutti i casi di test.

Le modifiche

  • (52 → 47) Riduci con -/invece di alternare (1 _1)*(idea di JB)
  • (47 → 53) Requisito di input multilinea notato: - /
  • (53 → 48) Sfrutta la simmetria dei binomi.
  • (48 → 48) Fai tacito!
  • (48 → 41)
  • (41 → 40) Incremento compressione + conversione in1x+

1
Hey! Questa è stata la mia idea! O :-)
JB

Ok, lo ruberò 1x+allora, ma questo mi riacquista solo 1 personaggio, mentre tu ne hai presi 5!
JB

3

Lisp comune (83)

(defun b (x y)
  (if (= (* x y) 0)
      (if (= (+ x y) 0) 1 0)
      (* y (+ (b (decf x) y) (b x (1- y)))))))

Sembra che ci dovrebbe essere un modo più breve per testare i casi di base, ma non mi viene in mente nulla di strano.


3

J, da 38 a 42

A seconda delle tue preferenze di rigore riguardo alle lingue interattive e alla presentazione dell'output, fai la tua scelta dallo spettro di soluzioni J:

  • 38 interattivo più breve: 4 :'|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    avvia jconsole, immettilo, quindi incolla l'input (termina con Cd). Noterai che l'output è separato dallo spazio (J è un linguaggio vettoriale, esegue il calcolo sull'intero input nel suo insieme e lo restituisce come vettore 1D, la cui presentazione predefinita è su una sola riga). Ritengo che ok, lo spirito di questo problema è il calcolo, non la presentazione. Ma se insisti invece ad avere newline:
  • 39 interattivo più lungo: la 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    sostituzione di Compose ( &) con Under ( &.) restituisce un vettore di stringhe, la cui presentazione finisce su righe separate.
  • 42 modalità batch: 4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    eseguire dalla riga di comando come$ jconsole balls.ijs < balls.in

Se lo hai votato, potresti voler dare credito anche alla soluzione di Eelvex .


È necessario un Under &.affinché funzioni correttamente in modalità interattiva.
Eelvex,

@Eelvex devi avere un'interpretazione diversa di "correttamente". Avvio jconsole, incolla codice, incolla input, Cd e ricevo l'output. Non necessario. Qual è il tuo?
JB

I nostri codici combinati: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3. 39 caratteri.
Eelvex,

Senza eco o Under ottengo l'output in una sola riga (anziché in più righe).
Eelvex,

@Eelvex in effetti, ma non è esplicitamente vietato.
JB

3

GolfScript - 45 38 36 caratteri

Relazione di ricorrenza di implementazione sporca di media forza ( 38 36 caratteri):

n%{~{.2$*{\(.2$f\2$(f+*}{=}if}:f~p}/

La relazione di ricorrenza che ho rubato dalla soluzione di Peter Taylors, va così:

f(x, y) = y * ( f(x-1, y) + f(x-1, y-1) )

Con casi speciali se una delle variabili è 0.

La mia implementazione non riutilizza i risultati precedenti, quindi ogni funzione chiama il ramo per due nuove chiamate, a meno che non sia stato raggiunto uno dei casi zero. Questo dà il caso peggiore di 2 ^ 21-1 chiamate di funzione che impiegano 30 secondi sulla mia macchina.

Soluzione serie Light-force (45 caratteri):

n%{~.),0\{.4$?3$,@[>.,,]{1\{)*}/}//*\-}/p;;}/

2

J, 55 caratteri

(wd@(4 :'(y^x)--/(!&y*^&x)|.i.y')/@".@,&'x');._2(1!:1)3
  • Passa i casi di test correnti. Io penso che ho capito la matematica ...
  • j602, solo console ( wd). Input su stdin, output su stdout.

Script di test Bash:

jconsole disballs.ijs <<END
12 4
6 3
END

Cosa fa quel j6xx wd?
JB

Intendevo davvero j602 ... Suppongo sia anche in j601. È definito come echo, che è definito come 0 0&$@(1!:2&2). Non sono sicuro di cosa significhi, ma fa qualcosa di simile agli oggetti di grado 1 con stampa carina con un'interruzione di riga. (Sto solo notando che utilizza 2 anziché 4 ... Penso che vada ancora stdout in modalità console, almeno.)
Jesse Millikan

Sto riscontrando problemi nell'esecuzione di questo codice. Lo digito semplicemente nella console?
mellamokb,

@mellamokb Sto usando qualcosa come lo script di test sopra, con il programma salvato come disballs.ijs e il percorso corretto per j602 / bin / jconsole.
Jesse Millikan,

@Jesse: sto eseguendo questo su Windows. Mi << was unexpected at this time. dispiace, sono nuovo di input J, l'ho sempre usato in modalità console.
mellamokb,

2

Golfscript - 26 caratteri

Avvertenza: il caso 12 4 richiede molta memoria (sebbene non tanto quanto la risposta di seguito) e impiega un po 'di tempo per funzionare

~:)\?:x,{x+)base(;.&,)=},,

Ovviamente questa risposta ha alcuni problemi, ma la lascerò qui perché i commenti si riferiscono ad essa e la risposta di mellamokb si basa su di essa.

Golfscript - 24 caratteri

Avvertenza: il caso 12 4 richiede molta memoria e richiede un po 'di tempo per funzionare

~:o)\?,{o)base[0]-,o=},,

2
Non riesco a capire come hai inventato quel codice, non solo questo metodo esaurirà la memoria per input di grandi dimensioni, ma non riesco nemmeno a capire a cosa servano gli operatori di incremento. Il fatto che tu abbia effettivamente raggiunto l'obiettivo per 6 3 sembra essere nient'altro che fortuna.
aaaaaaaaaaaa

Non è un pagliaccio, è mia moglie!
Jesse Millikan,

2
Non capisco Golfscript ma come hai detto e sono d'accordo che il tuo approccio è troppo lento.
Chisciotte

3
@mellamokb, bravo con te per capire come avrebbe dovuto funzionare :) Ci sono voluti solo 2 caratteri extra per correggere quel bug. Ora siamo nell'area oscura in cui il codice più breve può essere corretto ma non pratico. Il code-golf è pieno di risposte follemente inefficienti, ma i microsecondi contro i secondi di solito non contano. Questo è un caso estremo (anche molta memoria). Debanjan ha indicato che le risposte devono essere più veloci, ma questo sito non è SPOJ, questa domanda è taggata code-golf
gnibbler

1
@gnibbler, 0 0dovrebbe produrre 1; 0 kper qualsiasi altro kdovrebbe produrre 0; n 1per n > 0dovrebbe produrre 1.
Peter Taylor,

2

Python 140 Chars

import sys
f=lambda n,k:(n and k and n>=k and k*(f(n-1,k-1)+f(n-1,k)))or(n+k==0 and 1)or 0
for l in sys.stdin:print f(*(map(int,l.split())))

2

dc, 100 caratteri

[0q]s5[1q]s6[l2l3>5l3 0>5l2 0=6l2 1-S2l3dS3 1-S3l1xL3s9l1xL2s9+L3*]s1[?z0=5S3S2l1xL3L2+s9fs9l4x]ds4x

Purtroppo, DC non sembra essere supportato da ideone. Potrebbero esserci ancora un personaggio o due da spremere, ma è ora di andare a letto.

Nota: questo supporta più linee di input, ha una precisione sufficiente per fornire l'output corretto anche per 20 19(maledizione, Perl, per il tempo che ho sprecato nel debug della mia soluzione!) E fornisce l'output corretto per 0 0.

I suggerimenti di Nabb consentono di abbreviare almeno per quanto riguarda

[0q]sZ[1q]sI[?z0=ZSkSn[lnlk>Zlk0>Zln0=Iln1-SnlkdSk1-SklFxLks9lFxLns9+Lk*]dsFxfs9l4x]ds4x

a scapito di lasciare spazzatura negli stack del registro (e quindi esaurire la memoria se calcoliamo miliardi di risposte).


I registri sono sempre caratteri singoli (è possibile utilizzare qualsiasi carattere, il che renderà il codice più leggibile), quindi l11viene analizzato come l1 1(è possibile utilizzare Kcome token a singolo carattere 0se non si modifica comunque la precisione). È possibile modificare il loop di input in ?[...?z1=4]. È possibile incorporare la macro nel registro 1. E probabilmente puoi salvare molti più personaggi in generale, ma aspetterò che sia più breve per comprenderlo.
Nabb,

@Nabb, ah, non ho letto abbastanza attentamente la pagina man. Sto usando solo 8 o 9 registri, quindi non ho incontrato le conseguenze del mio malinteso. Grazie.
Peter Taylor,

1

Golfscript (28 31 37 )

~):$\.($\?:@;?,{@+}%{$base$,\-[0]=},,

Modifica alla gnibblersoluzione GolfScript. Penso che questa sia una soluzione funzionante, testata con [3,2], [4,2], [6,3] e [9,2] con risposte corrette. (Ho usato $e @per le variabili per restringere lo spazio attorno alla baseparola chiave).

Ci sono due problemi con gnibblerla soluzione attuale.

  1. Il controllo della lunghezza dopo aver rimosso [0] non garantisce una soluzione, poiché [1,1,1,1] sarebbe valido per l'input [4,2], anche se tutte e 4 le sfere sono nella stessa cella (1). Quindi ho modificato per verificare anche che vengano utilizzate tutte le cifre, ovvero l'array contiene 1-2, quindi ogni cella contiene almeno una pallina.
  2. Nel caso dell'input [4,2], il formato base-3 dei numeri 0-27 è inferiore a 4 cifre e gli 0 più a sinistra non sono inclusi. Ciò significa che [1,1] è incluso come soluzione valida, anche se tecnicamente in realtà [0,0,1,1], il che significa che le prime due sfere non sono posizionate da nessuna parte. Risolvo aggiungendo 3 ^ 3 a ogni voce (genericamente k ^ n-1 alla matrice di k ^ n voci) in modo che le prime voci siano spostate verso l'alto per avere almeno n-cifre nel formato base-k, e l'ultima le voci saranno automaticamente non valide comunque e non influenzeranno la soluzione (perché la seconda cifra sarà sempre 0).

modificare

~:@\?:$,{$+}%{@base(;@,\-,0=},,

`~:@\?:$,{$+@base(;@,\-,0=},,`

Soluzione ancora migliore! Non è necessario incrementare, basta aggiungere a tutti i numeri in modo che inizino con [1] e non mancheranno cifre (inclusa la spaziatura di sinistra di 0) una volta deconata quella prima cifra. Questa soluzione dovrebbe funzionare ed è stata testata con le stesse voci sopra. È anche molto più veloce perché non stiamo incrementando prima di assumere l'esponente per generare l'array (ma soffre ancora dello stesso problema di prestazioni / memoria per input più grandi).

Modifica : usa l gnibbler'idea di spostare l' aggiunta $all'interno del filtro anziché come passaggio aggiuntivo. (salva 3 caratteri).


Interruzioni sull'input 0 0.
Peter Taylor,

Sembra anche gestire solo una riga di input.
Peter Taylor,

E si interrompe n 1per qualsiasi n, fa sì che si blocchi. hmm ..
mellamokb

1
convertire i numeri in base 1 lo farà :)
gnibbler

@gnibbler: hai qualche suggerimento? Avrò solo bisogno di inserire alcune dichiarazioni if ​​all'inizio per catturare quei casi? Sembra che perderò un sacco di terreno in quel modo.
mellamokb,

0

05AB1E , 19 byte

#D`ULX.Œʒ€gßĀ}gs_P+

NOTA: è estremamente lento e già in timeout 12 4. Funziona come previsto, però. Vedrò se riesco a trovare un metodo alternativo che funziona per tutti i casi di test in un tempo ragionevole. Vedi sotto per una versione molto più veloce che esegue tutti i casi di test in meno di un secondo.

Provalo online o verifica alcuni altri casi di test (di dimensioni minori) .

Spiegazione:

#               # Split the (implicit) input-string by spaces
 D              # Duplicate it
  `             # Push both values to the stack
   U            # Pop and store the second value in variable `X`
    L           # Create a list in the range [1,n] for the first value
     X        # Create a list of all possible ways to divide this list into `X` partitions
                # (including empty sublists, so we'll have to filter them out:)
        ʒ       # Filter this list of lists of partition-lists by:
         g     #  Get the length of each partition-list
           ß    #  Get the minimum length
            Ā   #  Truthify; 0 remains 0 (falsey); anything else becomes 1 (truthy)
             }g # After the filter, take the length to get the amount left
 s              # Swap so the duplicated input-list is at the top of the stack again
  _             # Check for each value if they're equal to 0 (1 if truthy; 0 if falsey)
   P            # Take the product of the two to check if both input-values are 0
    +           # And add it to the earlier calculated product (edge case for [0,0] = 1)
                # (After which the result is output implicitly)

05AB1E , 29 byte

Ecco una versione molto più veloce che funziona su tutti i casi di test in circa 0,5 secondi su TIO:

Î#R`V©LRvyYmX*NÈ·<*+Xy*®y->÷U

Porta della risposta JavaScript di @mellamokb , quindi assicurati di votarlo!

Provalo online o verifica tutti i casi di test .

Spiegazione:

Î                    # Push (result=) 0 and the input
 #                   # Split the input by spaces
  R`                 # Push the values to the stack reversed
    V                # Pop and store the first value in variable `Y`
     ©               # Store the second value in variable `®` (without popping)
      LRv            # Loop `y` in the range [`®`,1], with index `N` in the range [0,`®`):
         yYm         #  Calculate `y` to the power `Y`
            X*       #  Multiply it by `X`
                     #  (Note: `X` is 1 before setting it to another value initially)
              NÈ     #  Check if index `N` is even (1 if truthy; 0 if falsey)
                ·<   #  Double it; and decrease it by 1 (1 if truthy; -1 if falseY0
                  *  #  Multiply it to the earlier number
                   + #  And add it to the result
         Xy*         #  Push `X` multiplied by `y`
         ®y->        #  Push `®` - `y` + 1
             ÷       #  Integer divide them
              U      #  Pop and store it as new variable `X`
                     # (output the result at the top of the stack implicitly after the loop)

NOTA: 0 0in questo caso funziona per Edge Case (a differenza della risposta JavaScript da cui ho effettuato il porting di questo metodo), poiché il file Lincorporato creerà un elenco [0,1].

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.