Código de golfe: distribuindo as bolas (I)


12

Desafio

Nesta tarefa, você calculou o número de maneiras pelas quais podemos distribuir as bolas A nas células B, com cada célula tendo pelo menos uma bola.

As entradas A e B são fornecidas em uma única linha separada por um espaço em branco, as entradas são terminadas por EOF.

Você pode verificar suas soluções aqui .

Entrada

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

Resultado

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

Restrições

  • Todos os A e B podem ser distinguidos.
  • 0 <= A, B <= 20
  • Você pode usar qualquer idioma de sua escolha
  • A solução mais curta vence!

1
Existem limites de tempo?

@ Tim Nordenfur: Atualizado :-)
Quixotic

Esse link é inválido para mim.
mellamokb

3
@Debanjan Eu não gosto da idéia de colar perguntas do SPOJ aqui. As pessoas enviam seu código para competir lá e isso seria injusto para elas.
FR0DDY

1
@Debanjan, eu vejo sua referência e te levo a Mathworld (a equação 5 diz que S(n,0)é 1se n=0e 0não). Se você quiser, posso encontrar uma referência para a afirmação mais forte de que Stirling2 está no subgrupo associativo do grupo exponencial de Riordan.
Peter Taylor

Respostas:


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/

Obviamente, qualquer linguagem baseada em matemática, como a APL, me derrotará por causa da verbosidade da sintaxe e da falta de construções matemáticas internas :)

Editar Além disso, não tenho nenhuma funcionalidade relacionada à entrada, exceto os parâmetros passados ​​para a função, não tenho certeza de como usar a entrada padrão com JavaScript ...

Editar: Mover i--para m=m*expressão; mudar n*=-1para for; comece r=1a combinar as tarefas e remova as estranhas no retorno. (economize 3 caracteres)


Você pode usar o shell spidermonkey - pelo menos tem readlinee print. Não sei o que os outros aqui usam.
Jesse Millikan 28/03

@ Jessé: Interessante. Eu vou perder de qualquer maneira lol.
Mellamokb 29/03/11

prompte alertsão o io "padrão" do JavaScript, pois são as chamadas io de bloqueio típicas, apesar de você nunca usar o bloqueio io com JavaScript.
zzzzBov

4

Golfscript - 56 50 49 48 41 40 38 37 caracteres

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

Nota: ele lida com várias linhas de entrada, é rápido (1/8 segundos para executar os casos de teste) e não quebra para nenhuma entrada legal.

(A primeira versão também foi o meu primeiro programa Golfscript; agradeço ao eBusiness por apontar vários truques que perdi).

Para tornar este post educacional útil também, aqui está uma explicação de como ele funciona. Começamos com a recorrência f(n, k) = k * (f(n-1, k) + f(n-1, k-1)). Isso pode ser entendido combinatoricamente como dizer que, para colocar nbolas distinguíveis em kbaldes distinguíveis, de modo que cada balde contenha pelo menos uma bola, você escolhe um dos kbaldes para a primeira bola ( k *) e, em seguida, conterá pelo menos mais uma bola ( f(n-1, k)) ou não vai ( f(n-1, k-1)).

Os valores resultantes disso formam uma grade; tomando ncomo o índice de linha e kcomo o índice da coluna e indexando ambos a partir de 0 começa

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

Então, voltando-se para o programa,

n%{~ <<STUFF>> }/

divide a entrada em linhas e, em seguida, para cada linha a avalia, colocando ne kna pilha e, em seguida <<STUFF>>, chama , da seguinte maneira:

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

Este calcula as primeiras k+1entradas do n+1th linha dessa grade. Inicialmente, a pilha é n k.
),dá pilha de n [0 1 2 ... k]
{!}%dá pilha de n [1 0 0 ... 0]onde há k0s.
\{ <<MORE STUFF>> }*traz a nao topo e faz com que seja o número de vezes que executamos <<MORE STUFF>>.
Nossa pilha atualmente é uma linha da tabela: [f(i,0) f(i,1) ... f(i,k)]
0.@coloca um par de 0s antes dessa matriz. A primeira será je a segunda será f(i,j-1).
{ <<FINAL LOOP>> }/percorre os elementos da matriz; para cada um, coloca-o no topo da pilha e depois executa o corpo do loop.
.@+2$*@)@é chato manipulação pilha para tomar ... j f(i,j-1) f(i,j)e rendimento ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]aparece fora a esquerda ao longok+1 f(i,k)e reúne tudo em uma matriz, pronta para a próxima rodada.
Finalmente, quando geramos a nquinta linha da tabela,
)p;pega o último elemento, o imprime e descarta o restante da linha.

Para a posteridade, três soluções de 38 caracteres sobre esse princípio:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


1
Muito bom para iniciantes, existem algumas possíveis reduções em pequena escala, imediatamente acho [0]-> 1,, o espaço após o zip pode ser removido e o outro espaço pode ser removido se você apenas armazenar em um operador em vez de k. Ainda não percorri seu código, mas suspeito que você possa se safar apenas de usar um valor sem colocá-lo em uma matriz em alguns pontos.
aaaaaaaaaaaa 30/03

1
+ 1, eu não entendo o Golfscript, mas isso parece suficientemente rápido e, no entanto, muito curto.
Quixotic

@eBusiness e @ Peter Taylor: Em outra nota .. quanto vocês avaliam o Golfscript na escala de fácil aprendizado?
Quixotic

@Debanjan, depende do que você já sabe. É uma linguagem funcional baseada em pilha. Eu já usei linguagens funcionais antes (SML - mais já escrevi código de estilo funcional em linguagens OO), e usei linguagens baseadas em pilha antes (Java bytecode montado com Jasmin, PostScript), portanto, o único obstáculo real Enfrento é aprender quais operadores estão disponíveis. Se você conhece apenas idiomas da família Algol (C, Java, etc), terá três obstáculos para saltar ao mesmo tempo.
Peter Taylor

@Debanjan - É muito mais fácil do que parece, você pode começar a escrever código quase imediatamente, mas é claro que leva algum tempo para aprender todos os pequenos truques.
Aaaaaaaaaaaa

3

J, 40

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

Por exemplo

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

<1 segundo para todos os casos de teste.

Editar% s

  • (52 → 47) Reduza com em -/vez de alternar (1 _1)*(ideia de JB)
  • (47 → 53) Requisito de entrada multilinha observado: - /
  • (53 → 48) Explorar simetria de binômios.
  • (48 → 48) Torne tácito!
  • (48 → 41)
  • (41 → 40) Aperte incremento + conversão em1x+

1
Ei! Essa foi a minha ideia! O :-)
JB

Ok, eu vou roubar isso 1x+então, mas isso só me devolve 1 personagem, enquanto você levou 5!
JB

3

Lisp comum (83)

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

Parece que deveria haver uma maneira mais curta de testar os casos básicos, mas nada me ocorre de imediato.


3

J, 38 a 42

Dependendo das suas preferências de rigor sobre idiomas interativos e apresentação de saída, faça a sua escolha no espectro J de soluções:

  • 38 menor interativo: 4 :'|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    Inicie o jconsole, insira-o e cole a entrada (termine com Cd). Você notará que a saída é separada por espaço (J é uma linguagem vetorial, ele executa a computação em toda a entrada como um todo e a retorna como um vetor 1D, cuja apresentação padrão é em uma única linha). Considero que ok, o espírito deste problema é computação, não apresentação. Mas se você insistir em ter novas linhas:
  • 39 mais interativo: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    Substituir Compose ( &) por Under ( &.) retorna um vetor de strings, cuja apresentação termina em linhas separadas.
  • 42 modo em lote: 4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    execute a partir da linha de comandos como$ jconsole balls.ijs < balls.in

Se você votou isso, você pode querer ir dar solução do Eelvex algum crédito também.


Você precisa de um Under &.para que ele funcione corretamente em modo interativo.
Eelvex

@ Eelvex, você deve ter uma interpretação diferente de "corretamente". Inicio o jconsole, colo o código, colo a entrada, Cd e recebo a saída. Não é necessário. O que é seu?
JB

Nossos códigos combinado: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3. 39 caracteres.
Eelvex 30/03

Sem eco ou Abaixo , recebo a saída em apenas uma linha (em vez de várias linhas).
Eelvex 30/03

@ Eelvex, de fato, mas isso não é explicitamente proibido.
JB

3

GolfScript - 45 38 36 caracteres

Relação de recorrência de implementação suja de força média ( 38 36 caracteres):

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

A relação de recorrência que roubei da solução de Peter Taylors, é assim:

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

Com casos especiais, se qualquer variável for 0.

Minha implementação não reutiliza resultados anteriores, portanto, cada chamada de função ramifica para duas novas chamadas, a menos que um dos zero casos tenha sido alcançado. Isso dá o pior caso de chamadas de função 2 ^ 21-1, que levam 30 segundos na minha máquina.

Solução em série de força leve (45 caracteres):

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

2

J, 55 caracteres

(wd@(4 :'(y^x)--/(!&y*^&x)|.i.y')/@".@,&'x');._2(1!:1)3
  • Passa nos casos de teste atuais. Eu acho que entendo a matemática ...
  • j602, somente console ( wd). Entrada em stdin, saída em stdout.

Script de teste do Bash:

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

O que esses j6xx wdfazem?
JB

Eu realmente quis dizer j602 ... Acho que também está no j601. É definido como echo, que é definido como 0 0&$@(1!:2&2). Não sei ao certo o que isso significa, mas faz algo como itens de classificação 1 de impressão bonita com uma quebra de linha. (Só agora estou percebendo que usa 2 em vez de 4 ... acho que ainda vai para stdout no modo console, pelo menos.)
Jesse Millikan

Estou tendo problemas para executar este código. Eu apenas digito no console?
mellamokb

@mellamokb Estou usando algo como o script de teste acima, com o programa salvo como disballs.ijs e o caminho correto para o j602 / bin / jconsole.
precisa

@ Jessie: Eu estou executando isso no Windows. Sinto muito por ser << was unexpected at this time. novo na entrada J, sempre o usei no modo console.
mellamokb

2

Golfscript - 26 caracteres

Aviso: O gabinete do 12 4 precisa de muita memória (embora não tanto quanto a resposta abaixo) e demora um pouco para ser executado

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

Obviamente, esta resposta tem alguns problemas, mas vou deixar aqui porque os comentários se referem a ela e a resposta de mellamokb se baseia nela.

Golfscript - 24 caracteres

Aviso: O gabinete 12 4 precisa de muita memória e demora um pouco para ser executado

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

2
Não consigo entender como você criou esse código, não apenas esse método ficará sem memória para entradas grandes, como também não consigo entender para que servem os operadores de incremento. O fato de você atingir o alvo por 6 3 parece não ser mais que sorte.
Aaaaaaaaaaaa 29/03

Isso não é palhaço, essa é minha esposa!
precisa

2
Eu não entendo o Golfscript, mas como você disse e eu concordo que sua abordagem é muito lenta.
Quixotic

3
@ mellamokb, bom em você por descobrir como deveria funcionar :) Foram necessários apenas 2 caracteres extras para corrigir esse bug. Agora estamos na área obscura, onde o código mais curto pode estar correto, mas não prático. O código-golfe é repleto de respostas insanamente ineficientes, mas microssegundos vs segundos geralmente não importam. Este é um caso extremo ( muita memória também). Debanjan indicou que as respostas precisam ser mais rápido, mas este site não é SPOJ, esta questão é marcado código-golf
gnibbler

1
@gnibbler, 0 0deve produzir 1; 0 kpara qualquer outro kdeve produzir 0; n 1para n > 0deve produzir 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 caracteres

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

Infelizmente, o dc não parece ser apoiado por ideona. Ainda pode haver um ou dois personagens, mas é hora de dormir.

Nota: isso suporta várias linhas de entrada, tem precisão suficiente para fornecer a saída correta mesmo para 20 19(maldição, Perl, pelo tempo que perdi depurando minha solução!) E fornece a saída correta para 0 0.

As sugestões da Nabb permitem encurtar pelo menos até

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

ao custo de deixar lixo nas pilhas de registradores (e, assim, ficar sem memória se calcularmos bilhões de respostas).


Os registros são sempre caracteres únicos (você pode usar qualquer caractere, o que tornará o código mais legível); portanto, l11é analisado como l1 1(você pode usar Kcomo um token de caractere único, 0caso não mude a precisão). Você pode alterar o loop de entrada para ?[...?z1=4]. Você pode alinhar a macro no registro 1. E você provavelmente pode salvar mais personagens em geral, mas esperarei que seja mais curto para compreendê-lo.
Nabb 31/03

@ Nabb, ah, eu não li a página de manual com bastante atenção. Estou usando apenas 8 ou 9 registros, então não tive as consequências do meu mal-entendido. Obrigado.
Peter Taylor

1

Golfe (28 31 37 )

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

Modificação na gnibblersolução GolfScript. Eu acho que essa é uma solução funcional - testada com [3,2], [4,2], [6,3] e [9,2] com respostas corretas. (Eu usei $e @para variáveis ​​para aumentar o espaço em torno da basepalavra - chave).

Existem dois problemas com gnibblera solução atual.

  1. A verificação do comprimento após a remoção de [0] não garante uma solução, pois [1,1,1,1] seria válido para a entrada [4,2], mesmo que todas as 4 bolas estejam na mesma célula (1). Então, modifiquei para verificar também se todos os dígitos são usados, ou seja, a matriz contém 1-2, para que cada célula contenha pelo menos uma bola.
  2. No caso da entrada [4,2], o formato base-3 dos números 0-27 tem menos de 4 dígitos e os 0 mais à esquerda não são incluídos. Isso significa [1,1] é incluído como uma solução válida, mesmo que tecnicamente seja [0,0,1,1], o que significa que as duas primeiras bolas não são colocadas em lugar algum. Corrijo adicionando 3 ^ 3 a cada entrada (genericamente k ^ n-1 à matriz de entradas k ^ n) para que as primeiras entradas sejam deslocadas para cima, tendo pelo menos n dígitos no formato base-k e a última as entradas serão automaticamente inválidas de qualquer maneira e não afetarão a solução (porque o segundo dígito sempre será 0).

Editar

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

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

Melhor solução ainda! Não há necessidade de incrementar, basta adicionar a todos os números para que eles comecem com [1] e nenhum dígito estará faltando (incluindo o preenchimento à esquerda dos zeros) depois que você desconectar o primeiro dígito. Esta solução deve funcionar e foi testada com as mesmas entradas acima. Também é muito mais rápido, porque não estamos incrementando antes de pegar o expoente para gerar a matriz (mas ainda sofre do mesmo problema de desempenho / memória para entradas maiores).

Editar : use gnibblera idéia de mover a adição de $dentro do filtro em vez de uma etapa extra. (economize 3 caracteres).


Quebra na entrada 0 0.
Peter Taylor

Também parece lidar com apenas uma linha de entrada.
Peter Taylor

E interrompe n 1para qualquer n, faz com que ele trave. hmm ..
mellamokb 29/03

1
conversão de números de base 1 vai fazer isso :)
gnibbler

@gnibbler: Você tem alguma sugestão? Precisarei apenas incluir algumas declarações if no início para capturar esses casos? Parece que vou perder muito terreno dessa maneira.
mellamokb

0

05AB1E , 19 bytes

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

NOTA: É extremamente lento e já atinge o tempo limite 12 4. Está funcionando como pretendido, no entanto. Vou ver se consigo criar um método alternativo que funcione para todos os casos de teste em um tempo razoável. Veja abaixo uma versão muito mais rápida que executa todos os casos de teste em menos de um segundo.

Experimente on-line ou verifique mais alguns casos de teste (menores) .

Explicação:

#               # 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 bytes

Aqui está uma versão muito mais rápida, que funciona para todos os casos de teste em cerca de 0,5 segundos no TIO:

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

Porta da resposta JavaScript de @mellamokb , por isso, certifique-se de que o vota!

Experimente online ou verifique todos os casos de teste .

Explicação:

Î                    # 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)

OBSERVAÇÃO: funciona para maiúsculas e minúsculas 0 0nesse caso (diferente da resposta JavaScript da qual portou este método), porque o Lbuilt-in criará uma lista [0,1].

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.