Os números subfatoriais ou rencontros ( A000166 ) são uma sequência de números semelhante aos números fatoriais que aparecem na combinatória de permutações. Em particular, o n º subfactorial ! N dá o número de desarranjos de um conjunto de n elementos. Um desarranjo é uma permutação na qual nenhum elemento permanece na mesma posição. O subfatorial pode ser definido através da seguinte relação de recorrência:
!n = (n-1) (!(n-1) + !(n-2))
De fato, a mesma relação de recorrência vale para o fatorial, mas para o subfatorial partimos de:
!0 = 1
!1 = 0
(Para o fatorial, teríamos, é claro, 1! = 1. )
Sua tarefa é calcular ! N , dado n .
Regras
Como o fatorial, o subfatorial cresce muito rapidamente. Não há problema se o seu programa puder lidar apenas com entradas n , de forma que ! N possa ser representado pelo tipo de número nativo do seu idioma. Entretanto, em teoria , seu algoritmo deve trabalhar para n arbitrário . Isso significa que você pode assumir que os resultados integrais e o valor intermediário podem ser representados exatamente pelo seu idioma. Observe que isso exclui a constante e se ela é armazenada ou calculada com precisão finita.
O resultado precisa ser um número inteiro exato (em particular, você não pode aproximar o resultado com notação científica).
Você pode escrever um programa ou uma função e usar qualquer um dos métodos padrão de recebimento de entrada e saída.
Você pode usar qualquer linguagem de programação , mas observe que essas brechas são proibidas por padrão.
Isso é código-golfe , então a resposta mais curta e válida - medida em bytes - vence.
Casos de teste
n !n
0 1
1 0
2 1
3 2
4 9
5 44
6 265
10 1334961
12 176214841
13 2290792932
14 32071101049
20 895014631192902121
21 18795307255050944540
100 34332795984163804765195977526776142032365783805375784983543400282685180793327632432791396429850988990237345920155783984828001486412574060553756854137069878601
fonte
Respostas:
Função , 336 bytes
A contagem de bytes assume a codificação UTF-16 com a BOM.
Isso define uma função
f
que pega um número inteiro e gera outro número inteiro a uma volta de 90 graus para a esquerda. Funciona para entradas arbitrariamente grandes.Experimente online!
Considerando que este é o Funciton, é até razoavelmente rápido (n = 20 leva cerca de 14 segundos no TIO). A principal desaceleração vem da dupla recursão, pois não acho que o interpretador do Funciton memorize automaticamente as funções.
Infelizmente, algumas fontes monoespaçadas não monoespaçam corretamente as
♭
e / ou inserem pequenas lacunas entre as linhas. Aqui está uma captura de tela do código do TIO em toda a sua beleza:Eu acho que pode ser possível jogar isso um pouco mais, por exemplo, alterando a condição de
>0
para<1
e trocando os ramos do condicional, para que eu possa reutilizar o número literal, ou talvez usando uma fórmula completamente diferente, mas estou bem feliz com o quão compacto já é.Explicação
Isso basicamente implementa a recursão dada no desafio, embora use o caso base ! (- 1) =! 0 = 1 . n-1 e n-2 são calculados com a função predecessora
♭
e o resultado intermediário n-1 é reutilizado em três locais. Não há muito mais, então vou passar rapidamente pelo fluxo de controle:Este é o cabeçalho da função que emite da função de entrada n longo da linha ligada. Isso atinge imediatamente a junção em T, que simplesmente duplica o valor.
A
0
caixa é apenas um literal numérico. Uma junção de quatro direções calcula duas funções: o caminho que sai da base calcula 0 <n , que usaremos para determinar o caso base. O caminho que sai à esquerda calcula 0 << n (um deslocamento para a esquerda), mas descartamos esse valor com a construção Starkov .Conduzimos isso para a condicional de três vias
?
. Se o valor for falso, retornamos o resultado constante1
. A extremidade solta à direita do?
é a saída da função. Estou girando em torno de 180 graus aqui, para que a orientação relativa de entrada e saída def
seja mais conveniente no restante do programa.Se a condição for verdadeira, o outro valor será usado. Vejamos o caminho que leva a esse ramo. (Observe que a avaliação do Funciton é realmente preguiçosa, de modo que esse ramo nunca será avaliado se não for necessário, o que possibilita a recursão em primeiro lugar.)
No outro ramo, primeiro calculamos n-1 e depois dividimos o caminho duas vezes para obter três cópias do valor (uma para o coeficiente de recorrência, uma para o primeiro subfatorial e a última para n-2 ).
Como eu disse, decrementamos uma cópia novamente com outra
♭
, depois alimentamos n-1 e n-2 recursivamentef
e finalmente adicionamos os dois resultados no+
.Tudo o que resta é multiplicar n-1 por ! (N-1) +! (N-2) .
fonte
Oásis , 5 bytes
Usa a fórmula dada por Martin. Código:
Versão dissecada:
com
a(0) = 1
ea(1) = 0
.Explicação
a(n) =
:Experimente online!
fonte
X
:-) BTW, você já implementou isso ? Um destes dias, não será capaz de fugir com apenas mudando os valores iniciaisHaskell , 25 bytes
Experimente online! Usa a outra recorrência da página OEIS .
fonte
Geléia , 7 bytes
Essa abordagem constrói os desarranjos, por isso é bastante lenta.
Experimente online!
Como funciona
fonte
Braquilog (2), 11 bytes
Experimente online!
Explicação
Isso é basicamente apenas uma tradução direta da especificação do inglês para o Brachylog (e, portanto, tem a vantagem de poder ser facilmente modificada para lidar com pequenas alterações na especificação, como encontrar o número de perturbações de uma lista específica).
fonte
Idiomas com soluções integradas
Seguindo a sugestão do xnor, esta é uma resposta CW na qual soluções triviais baseadas em um único built-in para calcular o subfatorial ou gerar todos os desarranjos devem ser editadas.
Mathematica, 12 bytes
fonte
Python 3 ,
3532 bytesIsso usa a relação de recorrência ! N = n! (N-1) + (-1) n da resposta Haskell de @ Laikoni , com caso base ! 0 = 1 .
Experimente online!
fonte
f=lambda n:n<1or n*f(n-1)+(-1)**n
.n=-1
, não importa em qual valor você usar. Isso pode ser útil para alguns idiomas (por exemplo, no Mathematica, você pode deixá-lo indefinido se salvar algum bytes).M , 9 bytes
Como você pode ver removendo o
Ḟ
, M usa matemática simbólica, portanto não haverá problemas de precisão.Experimente online! Não é a solução mais curta que foi publicada, mas é rápida .
Como funciona
fonte
MATL ,
98 bytesDa mesma forma que a resposta do @Dennis 'Jelly , isso realmente constrói as permutações e conta quantas delas são perturbações; então é lento.
Experimente online!
fonte
Matemática , 21 bytes
Sou muito novo nisso e não tenho ideia do que estou fazendo ...
Experimente online!
fonte
Round[(#/. 0->2)!/E]&
e±0=1;±n_:=Round[n!/E]
(embora eu não saiba se o Mathics suporta codificações de byte único para arquivos de origem, como o Mathematica).±
no segundo. Funcionaria comf
, mas ao custo de dois bytes.Round[#!/E]+1-Sign@#&
. Valores iniciais irritantes ...!Ruby, 27 bytes
~0**n
é mais curto que(-1)**n
!fonte
CJam (10 bytes)
Demonstração online .
Isso usa a recorrência
!n = n !(n-1) + (-1)^n
, da qual derivamosn! / e
e descobri que já estava no OEIS.Dissecação
O loop calcula
(-1)^n !n
, então precisamos pegar o valor absoluto no final:fonte
05AB1E , 8 bytes
Experimente online!
Explicação
fonte
MATLAB, 33 bytes
Função Anonympus que usa a fórmula na Seção 3 de Desarranjos e aplicações de Mehdi Hassani.
Exemplo de uso:
fonte
JavaScript (ES6), 26 bytes
Usa a relação de recorrência da resposta de @ Laikoni. No ES7, você pode salvar um byte usando em
+(-1)**n
vez de-(~n%2|1)
.fonte
PostScript,
817669 bytesAqui estão implementações de ambas as fórmulas.
n * f (n-1) + (- 1) ^ n
/ f {dup 0 eq {pop 1} {dup dup 1 sub f mul exch 2 mod 2 mul 1 sub sub} ifelse} defEssa versão gera um float. Se for necessário gerar um número inteiro:
que pesa 73 bytes.
A outra fórmula é um pouco mais longa: 81 bytes.
(n-1) * (f (n-1) + f (n-2))
Essas funções obtêm seus argumentos da pilha e deixam o resultado na pilha.
Você pode testar as funções, em um arquivo ou em um prompt PostScript interativo (por exemplo, GhostScript) com
saída
Aqui está um arquivo PostScript completo que renderiza a saída na tela ou na página da impressora. (Os comentários no PostScript começam com
%
).fonte
-1 3 2 roll exp
é um pouco mais curto queexch 2 mod 2 mul 1 sub
.exp
: oops: No entanto, ele retorna um float e acho que preciso gerar um número inteiro para estar em conformidade com a pergunta.cvi
e economizar. (Nota: não testado, mas ao ler o documento, acho que deve funcionar).cvi
funciona, e ainda é mais curto que a minha versão anterior.PHP, 69 bytes
use desta maneira
a(n) = n*a(n-1) + (-1)^n
fonte
PHP,
5044Correr com
echo <n> | php -nR '<code>
A beleza de
a(n) = n*a(n-1) + (-1)^n
é que depende apenas do valor anterior. Isso permite que ele seja implementado iterativamente em vez de recursivamente. Isso salva uma declaração de função longa.-6 bytes por @Titus. Obrigado !
fonte
$i++<$argv[1]
. -2 bytes:for(;$i++<$argv[1];)$n=++$n*$i-$i%2*2;echo$n+1;
. (-3 bytes com-R
e$argn
.)-R
e$argn
?Mathematica, 40 bytes
Que vem em 31 bytes sob a codificação ISO 8859-1 padrão.
fonte
C, 34 bytes
Explicação:
fonte
R, 47 bytes
Usa a mesma fórmula da resposta do Mego .
Método alternativo, 52 bytes usando a
PerMallows
bibliotecafonte
Na verdade , 18 bytes
Experimente online!
Explicação:
Uma versão de 12 bytes que funcionaria se realmente tivesse mais precisão:
Experimente online!
Ao contrário de todas as outras respostas (no momento da postagem), esta solução não usa a fórmula recursiva nem a fórmula de soma. Em vez disso, ele usa a seguinte fórmula:
Essa fórmula é relativamente fácil de implementar em Na verdade:
Agora, o único problema é que a fórmula vale apenas para o positivo
n
. Se você tentar usarn = 0
, a fórmula gera incorretamente0
. Isso é facilmente corrigido, no entanto: aplicando negação booleana à entrada e adicionando isso à saída da fórmula, a saída correta é fornecida para todos os não negativosn
. Assim, o programa com essa correção é:fonte
n = 100
),(-1)**n/n!
não pode ser representado com flutuadores IEEE 754 de precisão dupla. Isso é aceitável de acordo com o desafio.n=4
...Empilhados , 30 bytes
Experimente online!
Função recursiva simples. Usa o fato de que
!n = not n
paran < 2
. Ligar comon f
.fonte
Alice ,
2018 bytesExperimente online!
Explicação
Isto usa a recursividade de Laikoni de resposta , ! N = n! (N-1) + (-1) n . Semelhante à resposta do Funciton, estou usando o caso base ! (- 1) = 1 . Colocamos 1 na pilha com
1.
. Então isso...... é apenas a estrutura de E / S decimal usual. O código principal é realmente
Quebrado:
fonte