Enumerar Desarranjos

17

Dado um número inteiro positivo n gere todos os desarranjos de n objetos.

Detalhes

  • Um desarranjo é uma permutação sem ponto fixo. (Isto significa que em cada número de desarranjo i não podem estar no entrada -ésimo).i
  • A saída deve consistir em desarranjos dos números (ou alternativamente ).(1,2,,n)(0,1,2,,n1)
  • Como alternativa, você sempre pode imprimir alterações de (ou respectivamente), mas é necessário especificar isso.(n,n1,,1)(n1,n2,,1,0)
  • A saída deve ser determinística, ou seja, sempre que o programa for chamado com algum dado como entrada, a saída deve ser a mesma (o que inclui que a ordem dos desarranjos deve permanecer a mesma) e a saída completa deve ser feita dentro de uma quantidade finita de tempo todas as vezes (não é suficiente fazê-lo com probabilidade 1).n
  • Você pode assumir quen2
  • Para um dado você pode gerar todos os desarranjos ou, alternativamente, pegar outro número inteiro que serve como índice e imprimir o -ésimo desarranjo (na ordem que você escolheu).nkk

Exemplos

Observe que a ordem dos desarranjos não precisa ser a mesma listada aqui:

n=2: (2,1)
n=3: (2,3,1),(3,1,2)
n=4: (2,1,4,3),(2,3,4,1),(2,4,1,3), (3,1,4,2),(3,4,1,2),(3,4,2,1), (4,1,2,3),(4,3,1,2),(4,3,2,1)

OEIS A000166 conta o número de desarranjos.

flawr
fonte
Podemos enviar um gerador?
Fatalize 30/04
@ Fatalize Sim, eu acho que isso seria semelhante o suficiente para os outros dois métodos mencionados (ou você acha que há um forte argumento contra isso?).
flawr 30/04
1
@Fatalize Na verdade, parece que retornar um gerador em vez de uma lista é possível por padrão.
flawr

Respostas:

7

Gelatina , 6 bytes

Œ!=ÐṂR

Um link monádico que aceita um número inteiro positivo que produz uma lista de listas de números inteiros.

Experimente online!

Quão?

Œ!=ÐṂR - Link: integer, n
Œ!     - all permutations of (implicit range of [1..n])
     R - range of [1..n]
   ÐṂ  - filter keep those which are minimal by:
  =    -   equals? (vectorises)
       -   ... i.e. keep only those permutations that evaluate as [0,0,0,...,0]
Jonathan Allan
fonte
5

Braquilog , 9 bytes

⟦kpiᶠ≠ᵐhᵐ

Experimente online!

Este é um gerador que gera um desarranjo [0, …, n-1]dado n.

Se o envolvermos em um ᶠ - findallmetapredicado, obteremos todas as gerações possíveis de perturbações pelo gerador.

Explicação

⟦           The range [0, …, Input]
 k          Remove the last element
  p         Take a permutation of the range [0, …, Input - 1]
   iᶠ       Take all pair of Element-index: [[Elem0, 0],…,[ElemN-1, N-1]]
     ≠ᵐ     Each pair must contain different values
       hᵐ   The output is the head of each pair
Fatalizar
fonte
5

JavaScript (V8) , 85 bytes

Uma função recursiva que imprime todos os distúrbios baseados em 0.

f=(n,p=[],i,k=n)=>k--?f(n,p,i,k,k^i&&!p.includes(k)&&f(n,[...p,k],-~i)):i^n||print(p)

Experimente online!

Comentado

f = (                   // f is a recursive function taking:
  n,                    //   n   = input
  p = [],               //   p[] = current permutation
  i,                    //   i   = current position in the permutation
  k = n                 //   k   = next value to try
) =>                    //         (a decrementing counter initialized to n)
  k-- ?                 // decrement k; if it was not equal to 0:
    f(                  //   do a recursive call:
      n, p, i, k,       //     leave all parameters unchanged
      k ^ i &&          //     if k is not equal to the position
      !p.includes(k) && //     and k does not yet appear in p[]:
        f(              //       do another recursive call:
          n,            //         leave n unchanged
          [...p, k],    //         append k to p
          -~i           //         increment i
                        //         implicitly restart with k = n
        )               //       end of inner recursive call
    )                   //   end of outer recursive call
  :                     // else:
    i ^ n ||            //   if the derangement is complete:
      print(p)          //     print it
Arnauld
fonte
4

Ruby , 55 bytes

->n{[*0...n].permutation.select{|x|x.all?{|i|i!=x[i]}}}

Experimente online!

Gera todos os desarranjos baseados em 0

Kirill L.
fonte
2

05AB1E , 9 bytes

Lœʒāø€Ë_P

Experimente online!

Explicação

L           # push [1 ... input]
 œ          # get all permutations of that list
  ʒ         # filter, keep only lists that satisfy
   āø       # elements zipped with their 1-based index
     €Ë_P   # are all not equal
Emigna
fonte
2

Japonês , 8 bytes

Baseado em 0

o á fÈe¦

Experimente (o rodapé incrementa todos os elementos para facilitar a comparação com os casos de teste)

o á fÈe¦     :Implicit input of integer
o            :Range [0,input)
  á          :Permutations
    f        :Filter
     È       :By passing each through this function
      e      :  Every element of the permutation
       ¦     :  Does not equal its 0-based index
Shaggy
fonte
2

Python 2 , 102 bytes

lambda n:[p for p in permutations(range(n))if all(i-j for i,j in enumerate(p))]
from itertools import*

Experimente online!

Indexação baseada em 0, lista de tuplas.

itertoolsSolução não baseada:

Python 2 , 107 bytes

n=input()
for i in range(n**n):
 t=[];c=1
 for j in range(n):c*=j!=i%n not in t;t+=[i%n];i/=n
 if c:print t

Experimente online!

Indexação baseada em 0, linhas de listas, programa completo.

Nota: Esta solução, mesmo que não importe a itertoolsbiblioteca, não é muito maior que a outra que a importa, porque a maior parte do volume aqui está construindo as permutações. A verificação de perturbação é realmente de cerca de 7 bytes adicionais! O motivo é que a verificação é feita em tempo real como parte do edifício de cada permutação. Isso não é verdade para a outra solução, na qual é necessário verificar se cada permutação retornada pela itertools.permutationsfunção é de fato um distúrbio e, é claro, o próprio mapeamento leva muitos bytes.

Erik, o Outgolfer
fonte
2

MATL , 11 bytes

:tY@tb-!AY)

Isso gera todos os desarranjos em ordem lexicográfica.

Experimente online!

Explicação com exemplo

Considere entrada 3.

:     % Implicit input n. Range [1 2 ... n]
      % STACK: [1 2 3]
t     % Duplicate
      % STACK: [1 2 3], [1 2 3]
Y@    % All permutations, in lexicographical order, as rows of a matrix
      % STACK: [1 2 3], [1 2 3; 1 3 2; ··· ; 3 2 1]
t     % Duplicate
      % STACK: [1 2 3], [1 2 3; 1 3 2; ··· ; 3 2 1], [1 2 3; 1 3 2; ··· ; 3 2 1]
b     % Bubble up: moves third-topmost element in stack to the top
      % STACK: [1 2 3; 1 3 2; ··· ; 3 2 1], [1 2 3; 1 3 2; ··· ; 3 1 2; 3 2 1], [1 2 3]
-     % Subtract, element-wise with broadcast
      % STACK: [1 2 3; 1 3 2; ··· ; 3 2 1], [0 0 0; 0 1 -1; ··· ; 2 -1 -1; 2 0 -2]
!A    % True for rows containining only nonzero elements
      % STACK: [1 2 3; 1 3 2; ··· ; 3 1 2; 3 2 1], [false false ··· true false]
Y)    % Use logical mask as a row index. Implicit display
      % STACK: [2 3 1; 3 1 2]
Luis Mendo
fonte
2

Perl 5 -MList::Util=none -n , 100 89 bytes

$"=',';@b=1..$_;map{%k=$q=0;say if none{++$q==$_||$k{$_}++}/\d+/g}glob join$",("{@b}")x@b

Experimente online!

Xcali
fonte
1

Gaia , 10 bytes

┅f⟨:ċ=†ỵ⟩⁇

Experimente online!

┅		| push [1 2 ... n]
 f		| push permutations
  ⟨	⟩⁇	| filter where result of following is truthy
   :ċ		| dup, push [1 2 ... n]
     =†ỵ	| there is no fixed point
Giuseppe
fonte
1

J , 26 bytes

i.(]#~0~:*/@(-|:))i.@!A.i.

Experimente online!

i. (] #~ 0 ~: */@(- |:)) i.@! A. i.
i. (                   )            NB. 0..input
   (                   ) i.@! A. i. NB. x A. y returns the
                                    NB. x-th perm of y
                                    NB. i.@! returns 
                                    NB. 0..input!. Combined
                                    NB. it produces all perms
                                    NB. of y
    ] #~ 0 ~: */@(- |:)             NB. those 2 are passed as
                                    NB. left and right args
                                    NB. to this
    ] #~                            NB. filter the right arg ]
                                    NB. (all perms) by:
         0 ~:                       NB. where 0 is not equal to...
              */@                   NB. the product of the 
                                    NB. rows of...
                 (- |:)             NB. the left arg minus
                                    NB. the transpose of
                                    NB. the right arg, which
                                    NB. will only contain 0
                                    NB. for perms that have
                                    NB. a fixed point
Jonah
fonte
1

R , 81 80 bytes

function(n)unique(Filter(function(x)all(1:n%in%x&1:n-x),combn(rep(1:n,n),n,,F)))

Experimente online!

Retorna um listcontendo todos os desarranjos. Altamente ineficiente, pois gera(n2n)valores possíveis como ncombinações de tamanho de tempos [1..n]repetidos ne filtros para permutações 1:n%in%xe desarranjos 1:n-x,.

Ferramentas R + , 62 bytes

function(n,y=gtools::permutations(n,n))y[!colSums(t(y)==1:n),]

Experimente online!

Muito mais eficiente, retorna um em matrixque cada linha é um distúrbio.

Giuseppe
fonte
1

C ++ (gcc) , 207 196 bytes

-5 bytes por ceilingcat -6 bytes por Roman Odaisky

#include<regex>
#define v std::vector
auto p(int n){v<v<int>>r;v<int>m(n);int i=n;for(;m[i]=--i;);w:for(;std::next_permutation(&m[0],&m[n]);r.push_back(m))for(i=n;i--;)if(m[i]==i)goto w;return r;}

Experimente online!

movatica
fonte
Você pode fazer muito melhor se usar um parâmetro de saída, especialmente se for um std :: array, de modo que seja pré-dimensionado - 145 bytes
Roman Odaisky
@RomanOdaisky: boa ideia, mas como eu entendo as regras do código de golfe, você terá que levar o código de pré-localização para a contagem de bytes.
movatica
@movatica Uma área cinza, acho que o código é mais provável válido do que inválido. Felizmente, ele grava os resultados corretos em algum lugar, e é responsabilidade do chamador ler a saída. Observe que algoritmos STL, como da std::copymesma forma, confiam ao chamador o fornecimento de espaço adequado para a saída.
Roman Odaisky
@RomanOdaisky: O comportamento da STL é realmente um argumento válido.
movatica
0

C ++ (gcc) , 133 bytes

Eu acho que isso se tornou diferente o suficiente da outra submissão para merecer uma resposta separada. Finalmente, um uso para index[array]sintaxe de dentro para fora!

#include<regex>
[](int n,auto&r){int i=n;for(;i[*r]=--i;);for(;std::next_permutation(*r,*r+n);)for(i=n;i--?(r[1][i]=i[*r])-i:!++r;);}

Experimente online!

Roman Odaisky
fonte
0

Haskell, 76 bytes

n&x=[x++[i]|i<-[1..n],notElem i x,i/=length x+1]
d n=iterate(>>=(n&))[[]]!!n
Michael Klein
fonte
0

Python 2 , 82 bytes

f=lambda n,i=0:i/n*[[]]or[[x]+l for l in f(n,i+1)for x in range(n)if~-(x in[i]+l)]

Experimente online!

88 bytes como programa:

M=[],
r=range(input())
for i in r:M=[l+[x]for l in M for x in r if~-(x in[i]+l)]
print M

Experimente online!

93 bytes usando itertools:

from itertools import*
r=range(input())
print[p for p in permutations(r)if all(map(cmp,p,r))]

Experimente online!

xnor
fonte
0

Perl 6 , 49 37 bytes

Edit: Depois de algumas idas e vindas com Phil H, reduzimos para apenas 37 bytes:

(^*).permutations.grep:{all @_ Z-^@_}

Experimente online!

Usando o Whateverno início, podemos evitar os colchetes (salva 2 caracteres). Em seguida, use um Zmetaoperador com- qual cada elemento de uma permutação (por exemplo, 2,3,1) e subtrai 0,1,2 em ordem. Se algum deles for 0 (falso), a junção all falhará.


A solução original foi ( Experimente on-line! )

{permutations($_).grep:{none (for $_ {$++==$_})}}
user0721090601
fonte
1
Bom começo, você pode tornar o filtro mais curto com Z ativado
Phil H
@ Philh Eu sabia que tinha que haver uma maneira de integrar o operador zip, mas não conseguia entender direito. Nice
user0721090601
PhilH usando essa estratégia, ainda pode derrubar outros 3 matando parênteses: tio.run/##K0gtyjH7n1upoJamYKvwv7ogtSi3tCSxJDM/…
user0721090601
PhilH que último não funciona. Para todos, exceto n = 2, mais de um elemento será rejeitado
user0721090601
Claro, esqueci o requisito ... removido
Phil H
0

Carvão , 44 28 bytes

riscado 44 ainda é regular 44

NθIΦEXθθEθ﹪÷ιXθλθ⬤ι‹⁼μλ⁼¹№ιλ

Experimente online! Link é a versão detalhada do código. Basicamente baseado na resposta não-itertools do @ EricTheOutgolfer. Explicação:

Nθ                              Input `n`
     Xθθ                        `n` raised to power `n`
    E                           Mapped over implicit range
         θ                      `n`
        E                       Mapped over implicit range
            ι                   Outer loop index
           ÷                    Integer divided by
             Xθ                 `n` raised to power
               λ                Inner loop index
          ﹪     θ               Modulo `n`
   Φ                            Filtered where
                  ι             Current base conversion result
                 ⬤              All digits satisfy
                         №ιλ    Count of that digit
                       ⁼¹       Equals literal 1
                   ‹            And not
                    ⁼μλ         Digit equals its position
  I                             Cast to string
                                Implicitly print
Neil
fonte
0

C (gcc) , 187 180 bytes

*D,E;r(a,n,g,e){e=g=0;if(!a--){for(;e|=D[g]==g,g<E;g++)for(n=g;n--;)e|=D[n]==D[g];for(g*=e;g<E;)printf("%d ",D[g++]);e||puts("");}for(;g<E;r(a))D[a]=g++;}y(_){int M[E=_];D=M;r(_);}

Experimente online!

Jonathan Frech
fonte
@ceilingcat Obrigado.
Jonathan Frech 15/09
0

Pitão , 12 bytes

f*F.e-bkT.PU

Experimente online!

           UQ # [implicit Q=input] range(0,Q)
         .P  Q# [implicit Q=input] all permutations of length Q
f             # filter that on lambda T:
   .e   T     #   enumerated map over T: lambda b (=element), k (=index):
     -bk      #     b-k
 *F           # multiply all together

O filtro funciona assim: se algum elemento estiver em seu local original, (elemento-índice) será 0 e todo o produto será 0 e, portanto, falsey.

ar4093
fonte