Trocas únicas de uma matriz

19

Inspirado por Retirado de uma pergunta no Stack Overflow .

O desafio

Dado um número inteiro n>1, produza todas as matrizes que podem ser obtidas trocando exatamente duas entradas na matriz [1, 2, ..., n].

As matrizes podem ser produzidas em qualquer ordem.

Você pode usar consistentemente [0, 1, ..., n-1](com base em 0) em vez de [1, 2, ..., n](com base em 1).

Regras adicionais

Casos de teste

Entrada 2fornece saída (assumida com base em 1)

2 1

Entrada 3fornece saída (observe que as três matrizes podem estar em qualquer ordem)

1 3 2
2 1 3
3 2 1

Entrada 4dá saída

1 2 4 3
1 3 2 4
1 4 3 2
2 1 3 4
3 2 1 4
4 2 3 1

Entrada 7dá saída

1 2 3 4 5 7 6
1 2 3 4 6 5 7
1 2 3 4 7 6 5
1 2 3 5 4 6 7
1 2 3 6 5 4 7
1 2 3 7 5 6 4
1 2 4 3 5 6 7
1 2 5 4 3 6 7
1 2 6 4 5 3 7
1 2 7 4 5 6 3
1 3 2 4 5 6 7
1 4 3 2 5 6 7
1 5 3 4 2 6 7
1 6 3 4 5 2 7
1 7 3 4 5 6 2
2 1 3 4 5 6 7
3 2 1 4 5 6 7
4 2 3 1 5 6 7
5 2 3 4 1 6 7
6 2 3 4 5 1 7
7 2 3 4 5 6 1
Luis Mendo
fonte
Entradas nos índices fornecidas por oeis.org/A211369 mais uma (ou duas se indexação com 0) em uma lista lexicograficamente classificada de todas as permutações de comprimento n.
Jonathan Allan
5
Agradeço a flexibilidade do [0 ... n-1]vs [1 ... n]! Eu sempre me sinto um pouco irritado quando tenho que usar um 1+porque J zero-indexes.
cole

Respostas:

3

Geléia , 11 8 bytes

ŒcżU$y€R

Experimente online!

Como funciona

ŒcżU$y€R  Main link. Argument: n

Œc        Take all 2-combinations of [1, ..., n].
  żU$     Zip the result with the reversed pairs.
       R  Range; yield [1, ..., n].
     y€   For each [[i, j], [j, i]] in the result to the left, yield the result to
          the right, with i replaced by j and vice versa. 
Dennis
fonte
O que exatamente faz y? Sempre foi um mistério para mim.
caird coinheringaahing
Ele realiza substituições. Por exemplo, [1,2],[4,3]y1,2,3substitui cada 1 em [1, 2, 3] por 4 e cada 2 por 3 .
Dennis
8

R , 54 bytes

function(n)combn(n,2,function(x){z=1:n
z[x]=rev(x)
z})

Experimente online!

Retorna uma matriz em que cada coluna é uma permutação.

combn(n,k)gera todas as combinações de tamanho kda lista nou de 1:nse nfor um único inteiro. Opcionalmente, também é necessária uma função FUNa ser aplicada às combinações resultantes. Então, escrevemos uma função que executa a troca e retorna a lista trocada. Os resultados são todos acumulados em um array, que é neste caso bidimensional e, portanto, uma matriz.

Giuseppe
fonte
6

Haskell , 62 bytes

f n=[[1..x-1]++y:[x+1..y-1]++x:[y+1..n]|x<-[1..n],y<-[x+1..n]]

Experimente online!

Eu só gerar a permutação, dada a xe ypara swap, para cadax,y

H.PWiz
fonte
5

Wolfram Language (Mathematica) , 43 bytes

r/.{#->#2,#2->#}&@@@Subsets[r=Range@#,{2}]&

Experimente online!

Explicação: Subsets[Range@#,{2}]gera todos os subconjuntos de {1,2,...,n}tamanho 2 e, para cada subconjunto, /.alterna essas duas coisas na lista {1,2,...,n}.

Essa abordagem é decepcionantemente semelhante a muitos outros envios, mas aqui está um que é mais exclusivo do Mathematica, por 3 bytes extras:

r~Permute~Cycles@{#}&/@Subsets[r=Range@#,{2}]&

Experimente online!

Não é uma árvore
fonte
2
Uma solução Mathematica ainda mais idiomática seria ReplaceList[Range@#,{a___,b_,c___,d_,e___}:>{a,d,c,b,e}]&. Gosto da simplicidade (ou da codificação direta do problema), mas infelizmente a sintaxe de correspondência de padrões é tão detalhada que acaba sendo de 57 bytes.
Martin Ender
5

Haskell, 62 bytes

g n|b<-[1..n]=[[last$k:[j|k==i]++[i|k==j]|k<-b]|i<-b,j<-b,j<i]

Experimente online!

i<-b                -- loop 'i' through [1..n]
     j<-b           -- loop 'j' through [1..n]
          j<i       -- consider only cases where j<i 
 [            k<-b] -- make a list by looping 'k' through [1..n] 
  last              -- pick
          [i|k==j]  -- 'i' if k==j
       [j|k==i]     -- 'j' if k==i
     k              -- 'k' else   
nimi
fonte
4

Haskell , 71 bytes

f 0=[]
f x=map(++[x])(f$x-1)++[[1..y-1]++x:[y+1..x-1]++[y]|y<-[1..x-1]]

Experimente online!


Isso adiciona o número atual ao final de todas as permutações de último e calcula todos os swaps que incluem o novo número.

Assistente de Trigo
fonte
4

MATL , 12 bytes

:2XN!"G:@tP(

Experimente online!

            %implicit input, say, 4
:           %range, stack is {[1,2,3,4]}
2           %push 2
XN          %nchoosek, compute all combinations of [1,2,3,4] taken 2 at a time
            %this results in a matrix where each row is a combination, i.e.,
            %[1, 2;
              1, 3;
              1, 4;
              2, 3;
              2, 4;
              3, 4]
!           %transpose, because "for" iterates over columns
"           %begin for loop
G:          %push input and range, stack is now [1,2,3,4]
@t          %push "for" index (the column), say, [1;2], twice
P           %flip array, so stack is now: {[1,2,3,4],[1;2],[2;1]}
(           %assignment index, sets [1,2,3,4]([1;2])=[2;1],
            %resulting in [2,1,3,4]
            %implicit end of loop, implicit end of program, print the stack implicitly.

Giuseppe
fonte
11
2 bytes mais curtos do que o código que usei para gerar os casos de teste e forma mais effcient :-)
Luis Mendo
@LuisMendo Como você gerou os casos de teste? Eu estava preocupado que o meu fosse mais longo, pois o pedido não era o mesmo!
Giuseppe
11
Eu usei :tY@wy=~!s2=Y). A mesma abordagem que a resposta de oitava de rahnema1, eu acho
Luis Mendo
3

C, 93 bytes

i,j,k;f(n){for(i=0;i++<n;)for(j=i;j++<n;puts(""))for(k=0;k++<n;)printf("%d ",k-i?k-j?k:i:j);}

Experimente online!

Steadybox
fonte
3

Oitava, 38 bytes

@(n)(p=perms(k=1:n))(sum(p~=k,2)==2,:)

Experimente online!

Gera todas as permutações de 1: n e seleciona entre elas aquelas que possuem dois elementos diferentes de 1: n.

rahnema1
fonte
2

JavaScript (ES6), 81 bytes

Imprime matrizes indexadas em 0.

n=>(a=[...Array(n).keys()]).map(i=>a.map(j=>i>j&&alert(a.map(k=>k-i?k-j?k:i:j))))

Demo

alert()é substituído por console.log()este trecho para facilitar a utilização.

Arnauld
fonte
2

Limpo , 90 82 bytes

import StdEnv
$n#n=[1..n]
=tl(removeDup[[if(c<>b)if(c<>a)c b a\\c<-n]\\b<-n,a<-n])

Isso pode ser feito em 80 bytes, mas se transforma em uma tradução direta das respostas de Haskell.

Experimente online!

Furioso
fonte
2

05AB1E , 15 9 bytes

LœʒD{αĀO<

Experimente online!

Explicação

L            # push range [1 ... input]
 œ           # get all permutations
  ʒ          # filter, keep only elements that are true when
     α       # absolute value is taken with
   D{        # a sorted copy
      Ā      # each non-zero value in the resulting array is converted to 1
       O     # the array is summed
        <    # and the sum is decremented
Emigna
fonte
2

Casca , 9 bytes

!2§kδ#≠Pḣ

Experimente online!

Explicação

!2§kδ#≠Pḣ  Input is an integer n.
        ḣ  Range: r=[1,2,..,n]
       P   Permutations of r.
   k       Classify by
     #     number of elements
      ≠    that are different from
  § δ      the corresponding element of r.
!2         Take the second class.
Zgarb
fonte
2

Ruby , 55 53 bytes

->n{n.times{|x|x.times{|y|(w=*0...n)[w[x]=y]=x;p w}}}

Experimente online!

Solução baseada em 0

O truque aqui é que o loop interno sempre "ignora" uma iteração: na primeira vez em que não é executado, apenas uma vez na segunda passagem e assim por diante.

Fiquei feliz com 55 bytes até ver que R podia ser reduzido a 54, então tive que chegar a 53.

GB
fonte
Uso muito inteligente de restrições de saída flexíveis.
Unihedron
1

Python 2 , 90 bytes

f=lambda n,r=range:n*[n]and[a+[n]for a in f(n-1)]+[r(1,i)+[n]+r(i+1,n)+[i]for i in r(1,n)]

Experimente online!

ovs
fonte
1

Pitão, 9 bytes

t{.rLQ*=U

Demonstração

A maneira mais fácil de trocar dois valores é usar .r, que é a função de translação rotativa de Pyth. .r<list>[A, B]trocará todas as ocorrências de Ae Bdentro list.

Portanto, aplicando a função de tradução a UQ, a lista de0 para n-1com cada lista de dois elementos de números diferentes na lista, geraremos a saída desejada. Qé a entrada, ne Ué a função de alcance.

A maneira mais fácil de fazer isso seria:

.rLUQ.cUQ2

.cUQ2 gera todas as 2 combinações de elementos distintos no intervalo e .rLUQ mapeia a .rfunção sobre eles e a lista UQ.

No entanto, isso seria 10 bytes.

Em vez de fazer .cUQ2, os pares ordenados distintos, podemos fazer todos os pares *=U. Isso é implicitamente equivalente a *=UQQ. Começa sobrescrevendo Qcom UQ, e depois levando o produto cartesiano deUQ eUQ . Isso fornece todos os pares de números no intervalo, não necessariamente ordenados ou distintos.

.rLQswaps usando cada lista. Lembre-se de que Qagora é igual à lista de 0paran-1 , não n.

Como os pares não foram encomendados, existem duplicatas. {remove duplicatas. Como os pares não eram distintos, a lista inalterada está presente. Essa lista sempre será a primeira após a desduplicação, pois {preserva a ordem da primeira aparição e a lista inalterada é produzida pela rotação por [0,0]. tremove o primeiro elemento, fornecendo a lista desejada de trocas.

isaacg
fonte
1

Pitão, 11 bytes

fq2snVTUQ.p

Experimente online
Não é tão curto quanto a abordagem de isaacg, mas diferente o suficiente para postar.

Explicação

fq2snVTUQ.p
         .pQ  Take the permutations of the (implicit) range [0,...,input].
f     T       Filter to get the permutations...
   snV UQ     ... where the number of differences with [0,...,input]...
 q2           ... is 2.

fonte
1

Java 8, 109 105 bytes

n->{String r="";for(int i=0,j,k;i++<n;)for(j=i;j++<n;r+="\n")for(k=0;k++<n;)r+=k!=i?k!=j?k:i:j;return r;}

Estou enferrujado. Não tenho jogado código em meses. Acabei portando a resposta C do @Steadybox . Provavelmente, posso jogar mais.

Experimente aqui.

Kevin Cruijssen
fonte
1

Ruby , 66 bytes

->n{a=*1..n
a.permutation.select{|b|b.zip(a).count{|c,d|c!=d}==2}}

Experimente online!

Unihedron
fonte
1

Rubi , 80 bytes

-12 bytes graças ao Unihedron.

->n{(r=1..n).map{|x|r.map{|y|r.map{|i|i==x ?y:i==y ?x:i}}}.flatten(1).uniq[1,n]}

Experimente online!

Eu tinha uma abordagem em mente que era melhor traduzida para Ruby por algum motivo, então ... eu realmente nem conheço Ruby ...

totalmente humano
fonte
Eu superei isso: codegolf.stackexchange.com/a/152652/21830 . Desculpe!
Unihedron
Não precisa se desculpar! Acho que falo pela maioria dos usuários de PPCG quando digo que a concorrência é o que torna o PPCG legal.
totallyhuman
11
Quanto ao seu código, 1. você pode atribuir 1..na uma variável one-char e reutilizá-la (instruções separadas com nova linha ou ponto e vírgula), 2. sem colchetes nas instruções termary: i==x ?y:i==y ?x:i(observe onde eu tenho espaços para separar o shebang em potencial ) e 3. em uniq[1,n]vez de uniq[1..-1].
Unihedron