Índices e valores de swap

29

A tarefa

Escreva um programa ou função cuja entrada seja uma lista / matriz X de números inteiros e cuja saída seja uma lista de conjuntos de números inteiros Y , de modo que para cada elemento e em cada conjunto Y [ i ], X [ e ] = i , e de tal modo que o número total de elementos nos conjuntos em Y é igual ao número de elementos em X .

(Esta é basicamente a mesma operação que reverter uma hashtable / dicionário, exceto aplicada a matrizes.)

Exemplos

Esses exemplos assumem a indexação baseada em 1, mas você pode usar a indexação baseada em 0, se preferir.

X             Y
[4]           [{},{},{},{1}]
[1,2,3]       [{1},{2},{3}]
[2,2,2]       [{},{1,2,3}]
[5,5,6,6]     [{},{},{},{},{1,2},{3,4}]
[6,6,5,5]     [{},{},{},{},{3,4},{1,2}]

Esclarecimentos

  • Você pode representar um conjunto como uma lista, se desejar. Se você fizer isso, a ordem de seus elementos não importa, mas você não pode repetir elementos.
  • Você pode usar qualquer formato de E / S inequívoco razoável; por exemplo, você pode separar elementos de um conjunto com espaços e os conjuntos com novas linhas.
  • Y deve ser finitamente longo e pelo menos longo o suficiente para ter todos os elementos de X como índices de matriz. No entanto, pode ser maior que o elemento máximo de X (os elementos extras seriam conjuntos vazios).
  • Os elementos de X serão todos índices de matriz válidos, ou seja, números inteiros não negativos se você usar a indexação com base em 0 ou números inteiros positivos se você usar a indexação com base em 1.

Condição de vitória

Como um desafio do , quanto menor, melhor.

Cyoce
fonte
Relacionado . Na postagem da Sandbox (agora excluída, mas você pode visualizá-la se tiver reputação), decidimos que provavelmente não era uma duplicata, mas fique à vontade para votar para fechar se não concordar.
"A ordem de seus elementos não importa" significa que as saídas [5,5,6,6]e [6,6,5,5]podem ser idênticas?
Freira Furada
11
@LeakyNun A ordem dos elementos dos conjuntos na lista de saída não importa. Portanto, [5,5,6,6]e [6,6,5,5]não pode ter saída idêntica, mas a saída para [5,5,6,6]também poderia ter sido, por exemplo [{},{},{},{},{2,1},{4,3}],.
Ngenisis 10/05
Existe um valor máximo presumível de um índice em X? Os conjuntos vazios também podem ter um 0 em vez de estarem realmente vazios? Por exemplo, seria [{0},{0},{0},{0},{1,2},{3,4}]uma saída válida para [5,5,6,6]?
Skidsdev 10/05
@ Mayube: Não para a primeira resposta (embora se você estiver usando um idioma que tenha um número limitado de números inteiros, você pode escrever o programa como se os números inteiros pudessem ser ilimitadamente grandes, e não se preocupe com isso se alguém lhe der uma inteiro de intervalo como entrada). Com relação à segunda pergunta, essa é uma sintaxe inequívoca (se esquisita) quando você estiver usando a indexação baseada em 1; portanto, nesse caso (obviamente, não, se você estiver usando a indexação baseada em 0, porque o 0 significaria algo) mais.)

Respostas:

9

MATL , 8 bytes

tn:IXQ&D

Entrada é um vetor de coluna, com ;como separador (por exemplo [2;2;2]). Saída é a representação de seqüência de caracteres de uma matriz de células de vetores de linha (por exemplo {[]; [1 2 3]}). Um vetor de linha de um único elemento é igual a um número (portanto, {1; 2; 3}seria a saída em vez de {[1]; [2]; [3]}).

Experimente online! Ou verifique todos os casos de teste .

Explicação

t     % Implicit input, say x. Duplicate
n     % Number of elements, say N
:     % Range: [1 2 ... N]
IXQ   % accumarray(x, [1 2 ... N], [], @(x){sort(x).'})
&D    % String representation

A maior parte do trabalho é realizada pela função de ordem superior do Matlab accumarray, que agrupa elementos na segunda entrada de acordo com os valores correspondentes na primeira e aplica uma função especificada a cada grupo. A função nesse caso é @(x){sort(x).'}, que gera os elementos classificados em cada grupo e faz com que os resultados de todos os grupos sejam compactados em uma matriz de células.

Luis Mendo
fonte
7

Python, 69 bytes

lambda s:[[j for j,x in enumerate(s)if x==i]for i in range(max(s)+1)]

Usa indexação baseada em 0.

Uriel
fonte
7

Geléia , 7 5 bytes

=þṀT€

Experimente online!

Como funciona

=þṀT€  Main link. Argument: A (array)

  Ṁ    Yield m, the maximum of A.
=þ     Equals table; for each t in [1, ..., m], compare all elemnts of A with t,
       yielding a 2D Boolean array.
   T€  Truth each; for each Boolean array, yield all indices of 1.
Dennis
fonte
5

Gelatina , 8 bytes

Jẋ"Ṭ€;"/

Experimente online!

Como funciona

Jẋ"Ṭ€;"/  argument: z           eg. [6,6,4,4]
J         [1 .. len(z)]             [1,2,3,4]
   Ṭ€     untruth each of z         [[0,0,0,0,0,1],
                                     [0,0,0,0,0,1],
                                     [0,0,0,1],
                                     [0,0,0,1]]
 ẋ"       repeat each of ^^         [[[],[],[],[],[],[1]],
          as many times as           [[],[],[],[],[],[2]],
          each of ^                  [[],[],[],[3]],
                                     [[],[],[],[4]]]
       /  reduce by...
     ;"   vectorized concatenation  [[],[],[],[3,4],[],[1,2]]
Freira Furada
fonte
4

Mathematica, 36 bytes

Join@@@#~Position~n~Table~{n,Max@#}&

Explicação

insira a descrição da imagem aqui

Para cada nin {1, 2, ..., Max@#}, onde Max@#é o maior número inteiro na lista de entrada, calcula os Positions onde naparece na lista de entrada #. Como Position[{6,6,5,5},5](por exemplo) retorna {{3},{4}}, passamos Apply Joina todos os elementos no nível {1}do resultado.

ngenisis
fonte
3

Haskell , 45 bytes

spega uma lista de números inteiros e retorna uma lista de listas. Indexado em 1 para manter as entradas do caso de teste não modificadas (embora a saída obtenha algumas listas vazias extras).

s l=[[i|(i,y)<-zip[1..]l,y==x]|x<-[1..sum l]]

Experimente online!

Essas são compreensões de lista aninhadas bastante simples. O único pequeno ajuste é aproveitar a opção de fazer uma lista mais longa usando em sumvez de maximum.

Ørjan Johansen
fonte
3

PHP, 55 bytes

<?while($i<=max($_GET))print_r(array_keys($_GET,$i++));

Indexado a 0.

user63956
fonte
3

R, 68 49 47 bytes

lapply(1:max(x<-scan()),function(y)which(y==x)) 

Surpreendentemente, muito mais direto do que as soluções mais longas. Pega um vetor xde STDIN, cria um vetor de 1para max(x), gera implicitamente uma lista de comprimento max(x)e verifica quais índices xcorrespondem aos da nova lista. Imprime implicitamente a saída.

Versão antiga:

o=vector('list',max(x<-scan()));for(i in x)o[[i]]=c(o[[i]],F<-F+1);o

Abordagem ligeiramente diferente da outra resposta R. Leva um vetor para STDIN, cria uma lista com comprimento igual ao valor máximo na entrada. Faz um loop na entrada e adiciona o índice no lugar certo.

Usa indexação baseada em 1.

JAD
fonte
2

Python 2 , 91 86 85 bytes

Estou programando no meu telefone, mas gostei muito desse desafio. Definitivamente, ainda posso jogar golfe.

def f(a):
 r=[[]for i in range(max(a)+1)]
 for i,j in enumerate(a):r[j]+=[i]
 print r

Experimente online!

totalmente humano
fonte
Jogou fora novamente por uma compreensão de lista aninhada. : D
totallyhuman
2

Geléia , 9 bytes

Ṭ+\ịĠȧ@"Ṭ

Conjuntos vazios indexados em 1 representados como 0, conjuntos de um item representado como Nconjuntos de vários itens representados como[M,N,...]

Experimente online!

Quão?

Ṭ+\ịĠȧ@"Ṭ - Main link: list a        e.g. [6,6,4,4]
Ṭ         - untruth a                     [0,0,0,1,0,1]
  \       - cumulative reduce with:
 +        -   addition                    [0,0,0,1,1,2]
    Ġ     - group indices of a by value   [[3,4],[1,2]]
   ị      - index into                    [[1,2],[1,2],[1,2],[3,4],[3,4],[1,2]]
        Ṭ - untruth a                     [0,0,0,1,0,1]
       "  - zip with:
     ȧ@   -   and with reversed @rguments [0,0,0,[3,4],0,[1,2]]
Jonathan Allan
fonte
2

JavaScript (ES6), 64 62 bytes

Guardado 2 bytes graças a @SteveBennett


Recebe entrada indexada em 0. Retorna uma lista de conjuntos separados por vírgula.

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&`{${o.join`},{`}}`

Casos de teste


Versão alternativa, 53 bytes

Se uma saída simplificada como '||||3,2|1,0'é aceitável, podemos apenas fazer:

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&o.join`|`
Arnauld
fonte
Uau. Estou tão confuso como `{${o.join`},{`}}`é legal o ES2015.
9788 Steve Bennett #
@SteveBennett, é um modelo literal . Nas versões mais antigas do JS seria "{" + o.join("},{") + "}", se isso tornar mais claro.
Shaggy
Não, eu sei sobre isso - é a citação após a palavra junção que me confunde. Isso é fechar a string (nesse caso, wtf) ou é assim que você escapa de uma chave estreita?
Steve Bennett
Hmm, ok, então neste contexto join`é equivalente a join('. Não tinha ideia de que você poderia fazer isso.
Steve Bennett
Ah, agora eu vejo. É um literal de modelo marcado. Que você pode abusar para salvar um par de personagens sempre chamando uma função que leva um argumento string (e ignora outros): array.join` `. Super confusa aqui porque você está incorporando isso em uma sequência de modelo, e ainda mais confusa, a sequência de junção é },{, que coincidentemente parecia parte da sequência de modelo ... e é estranha e feia de qualquer maneira. :)
Steve Bennett
1

Bash , 109 bytes

Pena que não há built-in para o valor máximo da matriz.

a=($@)
for((x=m=1;x<=m;x++)){ for((y=0;y<$#;)){((m<a[y]))&&((m=a[y]));((a[y++]==x))&&printf "%d " $y;};echo;}

Experimente online!

Maxim Mikhaylov
fonte
1

Mathematica 62 bytes

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&

Eu vou executá-lo para você

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&[{4,5,2,3,3,8,6,3}]

{{}, {3}, {4, 5, 8}, {1}, {2}, {7}, {}, {6}}

Experimente online (basta colar o código com ctrl-v e pressione Shift + Enter)
não se esqueça de colar a lista de entradas no final, como no exemplo acima

J42161217
fonte
Bem-vindo ao PPCG! Você pode salvar um byte usando a notação infix para AppendTo. Além disso, {j,1,Length[#1]}poderia ser apenas {j,Length@#}, ou até mais curto {j,Tr[1^#]},. Tr[1^#]é um truque bastante comum para economizar um byte Length.
Ngenisis
1

Perl 6 ,  36 32  29 bytes

->\a{map {a.grep(*==$_):k},1..a.max}

Tente

{map {.grep(*==$^a):k},1.. .max}

Tente

{map {.grep($^a):k},1.. .max}

Tente


Expandido:

{  # bare block lambda with implicit parameter 「$_」

  map

    {  # bare block lambda with placeholder parameter 「$a」

      .grep(  # grep for the values in 「$_」
        $^a   # that are equal to the currently tested value (and declare param)
      ) :k    # return the key (index) rather than the value
    },

    1 .. .max # Range from 1 to the maximum value in 「$_」

}

Retorna índices baseados em zero, para obter 1 uso cruzado entre operadores ( X) combinado com +op . (33 bytes)

{1 X+.grep($^a):k}

Para fazê-lo retornar Set s basta adicionarset lá (total de 37 bytes)

{set 1 X+.grep($^a):k}
Brad Gilbert b2gills
fonte
1

R, 80 bytes 72

1 indexado, leva Xde stdin. Retorna uma lista de vetores dos índices, com NULLo conjunto vazio.

X=scan();Y=vector('list',max(X));Y[X]=lapply(X,function(x)which(X==x));Y

Experimente online!

versão antiga:

X=scan();Y=vector('list',max(X));for(i in 1:length(X))Y[[X[i]]]=c(Y[[X[i]]],i);Y

Experimente online!

Giuseppe
fonte
Eu acho que isso Y=list();funciona tão bem
rturnbull
Conseguiu raspar fewbytes na minha resposta :) codegolf.stackexchange.com/a/120024/59530
JAD
0

Röda , 51 bytes

f s{seq(1,max(s))|[[s()|enum|[_2+1]if[_1=i]]]for i}

É um porto da resposta em Python de Uriel .

Outra versão (88 bytes):

f a{I=indexOf;seq(1,max(a))|{|i|b=a[:]c=[]x=1{c+=x+I(i,b)b-=i;x++}until[I(i,b)<0];[c]}_}

Experimente online!

Ambos um 1-indexado.

fergusq
fonte
0

PowerShell, 81 bytes

$args[0]|%{if($_-gt($c=$r.count)){$r+=@($t)*($_-$c)}$r[--$_]+=,++$i};$r|%{"{$_}"}

Experimente online!

1 indexado.

Andrei Odegov
fonte
0

GNU Make , 214 213 208 204 bytes

X=$(MAKECMDGOALS)
M=0
P=$(eval N=$(word $1,$X))$(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),$(eval M=$N),)$(eval A$N+=$1$(call $0,$(shell expr $1 + 1))),)
$(call P,1)$(foreach K,$(shell seq $M),$(info $(A$K)))

E / S: matriz de entrada via argumentos, saída para stdout, uma por linha, separada por espaços.

$ make -f swap.mk 2 2 2

3 2 1
make: *** No rule to make target `2'.  Stop.

Explicação

X=$(MAKECMDGOALS)     # Input array
M=0                   # Max value encountered in X
P=$(eval
    N=$(word $1,$X))  # Get next word from X
  $(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),
    $(eval M=$N),)    # Update M
    $(eval A$N+=$1    # Append index to a variable named after value
      $(call $0,      # Recurse (call returns empty string)
        $(shell expr $1 + 1))),)
$(call P,1)           # Initial call to P. 1 is the first index
$(foreach K,          # Print all values of A* variables
  $(shell seq $M),
  $(info $(A$K)))     # Uninitialized ones default to empty strings

A ordem dos índices em conjuntos é revertida porque P chama recursivamente antes da atualização A$2(chamada executada na avaliação do lado direito).

eush77
fonte
Tem makealguma maneira de fazer aritmética em si? Chamar programas externos para fazer isso parece um pouco de trapaça, porque você provavelmente poderia colocar muito mais do algoritmo nesses programas e acabar com um programa mais curto.
@ ais523 Não tem. Versão anterior usada bce grep. Eu também poderia usar teste $?. dctem uma sintaxe terser, mas francamente todos parecem iguais.
Eush77
0

Lisp comum, 91 bytes

(lambda(x &aux(l(make-list(eval`(max,@x))))(i 0))(dolist(y x l)(push(incf i)(nth(1- y)l))))

Indexação baseada em 1, retorna os conjuntos como listas.

Experimente online!

Renzo
fonte
0

k , 13 bytes

{(=x)@!1+|/x}

Este é o índice 0.

Experimente online!

{           } /function(x)
 (=x)         /make a map/dictionary of values to their indices
         |/x  /get maximum value in x
      !1+     /make a range from 0 to the value, inclusive
     @        /get map value at each of the values in the range
              /    0N is given where there is no result
zgrep
fonte