Simplifique uma matriz


22

Entrada

Uma matriz que pode conter matrizes ou números inteiros positivos, consecutivos e ascendentes. As matrizes podem ter qualquer número de matrizes dentro delas, e assim por diante. Nenhuma matriz estará vazia.

Saída

Essa matriz simplificada

Como simplificar uma matriz

Usaremos a matriz [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]]como nosso exemplo.

Primeiro, verificamos a profundidade dos valores aninhados. Aqui estão as profundidades e os números nessas profundidades:

0  1
1  2 3 9
2  4 7
3  5 6
5  8

Construímos a matriz de saída pegando os números na matriz original, agrupando-os pela profundidade em que estão aninhados e, em seguida, aninhando os grupos nas profundidades das profundidades originais de seus elementos. Organize os números em ordem crescente e profundidade crescente.

Então, nossa produção é [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]]

Exemplos

[1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]] -> [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]]
[[[1]], [2, [3]], 4, [5, [6, [7, [8], [9, [[10]]]]]]] -> [4, [2, 5], [[1, 3, 6]], [[[7]]], [[[[8, 9]]]], [[[[[[10]]]]]]]
[1] -> [1]
[1, [2], [[3]], [[[4]]], [[[[5]]]]] -> [1, [2], [[3]], [[[4]]], [[[[5]]]]]
[1, [[[[2], 3]]] [[4]]] -> [1, [[4]], [[[3]]], [[[[2]]]]]

A saída é flexível? Como números em linhas diferentes, onde cada linha é um nível; ou outras matrizes delimitadores / separadores
Luis Mendo


@LuisMendo, sim, é flexível
Daniel

Está faltando um par de colchetes 8na linha So, our output is...... No entanto, você o corrigiu no snippet de exemplos.
Sbisit

2
Algumas respostas produzem uma linha vazia para aninhar níveis sem elementos. É bom retornar uma matriz vazia nesses casos, por exemplo, você primeiro exemplo como [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[]]]], [[[[[8]]]]]]?
N /

Respostas:


1

Gelatina , 8 bytes

fFṄḟ@;/ß

A saída é um nível por linha, com linhas vazias para níveis sem elementos. Experimente online!

Como funciona

fFṄḟ@;/ß  Main link. Argument: A (array)

 F        Flat; yield all integers (at any level) in A.
f         Filter; intersect A with the integers, yielding those at level 0.
  Ṅ       Print the filtered array and a linefeed. Yields the filtered array.
     ;/   Reduce by concatenation.
          This decreases the levels of all integers at positive levels by 1.
   ḟ@     Swapped filter-false; remove the integers at level 0 in A from the array
          with decreased levels.
       ß  Recursively call the main link on the result.
          The program stops once A is empty, since ;/ will result in an error.

3

JavaScript (ES6), 139 109 bytes

f=(a,v=b=>a.filter(a=>b^!a[0]))=>a[0]?v().concat((a=f([].concat(...v(1))),b=v())[0]?[b]:[],v(1).map(a=>[a])):[]

Explicação usando a entrada de exemplo: vé um método auxiliar que retorna as matrizes (com parâmetro 1) ou valores (sem parâmetro). Começamos com a = [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]], que não é vazio. Nós filtramos as matrizes, dando [1]. Em seguida, recorremos a nós mesmos às matrizes concatenadas juntas, ou seja [2, 3, [4], [[5, 6], 7, [[[8]]]], 9], o resultado [2, 3, 9, [4, 7], [[5, 6]], [[[[8]]]]]. Mais uma vez filtramos as matrizes, o que nos dá o segundo termo de nossa saída [2, 3, 9], no entanto, temos que ter cuidado para não inserir uma matriz vazia aqui. Ainda resta envolver as matrizes [4, 7], [[5, 6]], [[[[8]]]]dentro das matrizes e anexá-las à saída, resultando em [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]].


Pode salvar alguns bytes criando um alias para filter. Talvez comece comF=(x,y)=>x.filter(y)
Cyoce

@Cyoce Acabou por ser 30 no final!
28416 Neil

Você definitivamente tem algum golfe para fazer sobre isso. Eu acho que você pode substituir [].concat(...v(1))com segurança v(1)para salvar 14 bytes. Provavelmente também existem algumas outras coisas, mas estou tendo dificuldade em acompanhar os parênteses aninhados na minha cabeça.
Patrick Roberts

1
@PatrickRoberts [].concat(...v(1))é uma fera muito diferente v(1), caso contrário eu não faria isso! Para um exemplo simples, considere a = [2, [3], [[4]]]então v(1) = [[3], [[4]]]mas [].concat(...v(1)) = [3, [4]].
Neil

@ Neil oh, uau, eu realmente deveria ter testado minha sugestão antes de abrir minha boca. Eu sinto que deve haver uma maneira mais curta de fazer isso embora ..
Patrick Roberts

2

05AB1E , 27 26 25 21 bytes

D˜gFvyydi„ÿ ?}}¶?.gG«

Experimente online! (ligeiramente modificado porque .gainda não está no TIO)

Explicação

D˜gF                    # flattened input length times do
    vy                  # for each y current level of list
      ydi„ÿ ?}          # if y is a digit, print with space
              }         # end v-loop
               ¶?       # print newline
                 .g     # calculate length of stack (this should be .g but I can't test)
                   G«   # length stack times, concatenate items on stack

A estratégia principal é fazer um loop sobre cada nível possível da matriz aninhada e imprimir qualquer dígito em uma linha, mantendo os não dígitos (listas) em uma lista um nível menos aninhado.


2

Perl, 52 bytes

Apenas uma sub-rotina recursiva. (incomum para uma resposta Perl, eu sei ..)

sub f{say"@{[grep!ref,@_]}";@_&&f(map/A/?@$_:(),@_)}

Chame assim:

$ perl -E 'sub f{say"@{[grep!ref,@_]}";@_&&f(map/A/?@$_:(),@_)}f(1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9])'
1
2 3 9
4 7
5 6

8

Cada linha da saída corresponde a um nível de profundidade da matriz (daí a linha vazia no exemplo acima).

Ele pode ser transformado em um programa completo por apenas mais alguns bytes: adicione -nflag e um eval(dentro @{ }para transformar a entrada em uma matriz e não uma matrizref) para transformar a entrada em uma matriz Perl:

perl -nE 'sub f{say"@{[grep!ref,@_]}";@_&&f(map/A/?@$_:(),@_)}f(@{+eval})' <<< "[1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]]"

Minha abordagem anterior era um pouco mais longa (65 bytes), mas ainda interessante, então deixarei aqui:

perl -nE '/\d/?push@{$;[$d-1]},$_:/]/?$d--:$d++for/\[|]|\d+/g;say"@$_"for@' <<< "[1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]]"

2

JavaScript (ES6) 121 144 152

Editar Muito revisado, 1 byte salvou thx Patrick Roberts e 21 mais apenas revisando o código

Função recursiva trabalhando em matrizes de entrada e saída. Não fazer, como o pedido de ter elementos em profundidade 1 como elementos individuais na matriz de saída (enquanto que os níveis maiores são agrupadas como um elemento): [l1,l1, [l2...], [[l3...]] ]. Enquanto isso seria mais direto:[ [l1...], [[l2...]], [[[l3...]]] ]

f=(l,d=0,r=[])=>l.map(v=>v[0]?f(v,d+1,r):r[d]=[...r[d]||[],v])
r.reduce((r,v,d)=>d?[...r,(n=d=>d-->1?[n(d)]:v)(d)]:v,[])

Nova linha adicionada para facilitar a leitura.

Algumas notas: a linha 2 é avaliada repetidamente a cada chamada recursiva, mas apenas a última iteração no final da recursão é útil.
O manuseio especial quando d==0na linha 2 cuida da anomalia para elementos de nível 1.
A nfunção recursiva lida com a matriz aninhada na saída

Teste

f=(l,d=0,r=[])=>l.map(v=>v[0]?f(v,d+1,r):r[d]=[...r[d]||[],v])
&&r.reduce((r,v,d)=>d?[...r,(n=d=>d-->1?[n(d)]:v)(d)]:v,[])

console.log=x=>O.textContent+=x+'\n'

test=[
 [ 
   [1, [2,3], 4], /* -> */ [1, 4, [2,3]]
 ]
,[
   [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]], 
   // ->
   [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]]
 ]
,[
  [[[1]], [2, [3]], 4, [5, [6, [7, [8], [9, [[10]]]]]]],
  // ->
  [4, [2, 5], [[1, 3, 6]], [[[7]]], [[[[8, 9]]]], [[[[[[10]]]]]]] 
 ]
,[  
  [1], /* -> */ [1]
 ]
,[  
  [1, [2], [[3]], [[[4]]], [[[[5]]]]],
  // ->
  [1, [2], [[3]], [[[4]]], [[[[5]]]]]
 ]
,[  
  [1, [[[[2], 3]]], [[4]]],
  [1, [[4]], [[[3]]], [[[[2]]]]]
]]

test.forEach(t=>{
  var i=t[0], k=t[1], r=f(i),
      si=JSON.stringify(i),
      sr=JSON.stringify(r),
      sk=JSON.stringify(k)
  
  console.log((sr==sk?'OK ':'KO ')+si + " => " + sr)
})
<pre id=O></pre>


1
Dado que existem apenas matrizes aninhadas e números inteiros positivos e é especificado que nenhuma das matrizes na entrada está vazia, seria um teste mais fácil para o seu operador ternário em v[0]vez de v.map. Economiza 1 byte.
Patrick Roberts

@PatrickRoberts cool thanks
edc65 #

1

JavaScript (ES6) 168 bytes

f=a=>(s=[],b=-1,k=0,a.replace(/\d+|\[|\]/g,a=>a=='['?b++:a==']'?b--:(s[b]=s[b]||[]).push(a)),'['+s.map((a,b)=>k=a&&(k?',':'')+'['.repeat(b)+a+']'.repeat(b)).join``+']')

Demo


1

PHP, 145 bytes

<?function c($r){$n=[];foreach($r as$k=>$v)if(is_array($v)){$n=array_merge($n,$v);unset($r[$k]);}if($n)$r[]=c($n);return$r;}print_r(c($_GET[a]));

Demolir

function c($r){
  #usort($r,function($x,$y){return is_array($x)<=>is_array($y)?:$x<=>$y;}); 
#no need to sort and a simple sort($r); do it sort array after scalar
  $n=[];
  foreach($r as$k=>$v)if(is_array($v)){$n=array_merge($n,$v);unset($r[$k]);} # put arrays on the same depth together
  if($n)$r[]=c($n); # recursive if an array exists
  return$r; #return changes
}
print_r(c($_GET[a])); #Output and Input

1

Pitão, 19 16 bytes

W=Qsf!&sITp+TdQk

Experimente online. Suíte de teste.

Observe o espaço à esquerda. Produz níveis em linhas como a resposta Perl.

Explicação

  • Entrada implícita Q.
  • fitens Tde filtro de Q:
    • Verifique se sum está com Identição ligada T.
    • Se fosse (era um número), print Tmais um espaço +d.
    • Se não fosse (era uma matriz), mantenha-o.
  • shum os itens. Isso remove uma camada de matrizes de cada item. Se não sobrar nenhum, rende 0.
  • Atribua =o resultado a Q.
  • WEnquanto o resultado não estiver vazio, imprima a string vazia ke uma nova linha.

1

Haskell, 124 123 bytes

data L=I Int|R[L]
d#R l=((d+1)#)=<<l
d#i=[(d::Int,i)]
[]!_=[]
l!1=l
l!d=[R$l!(d-1)]
h l=R$do d<-[1..];[i|(e,i)<-0#l,d==e]!d

Como Haskell não suporta listas mistas (números inteiros e lista de números inteiros) por padrão, eu defino um tipo de lista personalizado L. Exemplo de uso:

*Main> h (R[I 1, R[I 2, I 3], R[ R[I 4]], R[ R[ R[I 5, I 6], I 7, R[R[R[I 8]]]], I 9]])
R [I 1,R [I 2,I 3,I 9],R [R [I 4,I 7]],R [R [R [I 5,I 6]]],R [R [R [R [R [I 8]]]]]]

Nota: leva algum tempo para executar, porque percorre todas as Ints positivas (32 ou 64 bits) para procurar um nível de ninho tão profundo. Além disso: o tipo de lista personalizada não pode ser impresso por padrão; portanto, se você quiser ver o resultado como no exemplo acima, precisará adicionar deriving Showà datadeclaração (-> data L=I Int|R[L] deriving Show). Como não é necessário retornar uma lista L de uma função, não conto os bytes.

Como funciona:

data L=I Int|R[L]               -- custom list type L, which is either an Int
                                -- (-> I Int) or a list of some L (-> R [L]) 

d#R l=((d+1)#)=<<l              -- # makes a list of (depth, I-number) pairs from
d#i=[(d::Int,i)]                -- a given L-list, e.g.
                                -- 0 # (R[I 1,R[I 2,I 3],I 4]) -> [(1,I 4),(2,I 2),(2,I 3),(1,I 4)]
                                -- the type annotation ::Int makes sure that all
                                -- depths are bounded. Without it, Haskell
                                -- would use arbitrary large numbers of type
                                -- ::Integer and the program won't finish

[]!_=[]                         -- ! wraps a list of Is with (d-1) additional
l!1=l                           --  R constructors
l!d=[R$l!(d-1)]

h l=                            -- main function, takes a L-list
      do d<-[1..]               -- for each nest level d make
        [i|(e,i)<-0#l,d==e]     -- a list of all I where the depth is d
                           !!d  -- and wrap it again with d-1 Rs         
     R$                         -- wrap with a final R

Editar O @BlackCap salvou um byte alternando >>=para a donotação. Obrigado!


A notação salva um byteh l=R$do d<-[1..];[i|(e,i)<-0#l,d==e]!d
BlackCap 31/10

0

JavaScript (ES6), 127 137 134 bytes

Pega uma matriz como entrada e retorna uma string.

f=(a,l=[],d=0,o='')=>`[${a.map(x=>x[0]?f(x,l,d+1,o+'['):l[d]=(l[d]?l[d]+',':o)+x),l.map((s,d)=>x+s+']'.repeat(d,x=','),x='').join``}]`

Casos de teste


@ Shebang Obrigado por perceber. Isso deve ser corrigido.
Arnauld 28/10

Eu acredito que parece bom agora! :)
Kade
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.