Simplificar una matriz

22

Entrada

Una matriz que puede contener matrices o enteros positivos, consecutivos y ascendentes. Las matrices pueden tener cualquier cantidad de matrices dentro de ellas, y así sucesivamente. Ninguna matriz estará vacía.

Salida

Esta matriz simplificada

Cómo simplificar una matriz

Usaremos la matriz, [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]] como nuestro ejemplo.

Primero, verificamos qué tan profundos están anidados los valores. Aquí están las profundidades y los números a esas profundidades:

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

Construimos la matriz de salida tomando los números en la matriz original, agrupándolos por la profundidad en que están anidados, y luego anidando los grupos a profundidades de las profundidades originales de sus elementos. Organice los números en orden ascendente y profundidad ascendente.

Entonces, nuestra salida es [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]]

Ejemplos

[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]]]]]
Daniel
fuente
¿La salida es flexible? Como números en diferentes líneas, donde cada línea es un nivel; u otros delimitadores / separadores de matriz
Luis Mendo
@LuisMendo, sí, es flexible
Daniel
Te falta un par de paréntesis 8en la línea So, our output is...... Sin embargo, lo arregló en el fragmento de ejemplos.
sbisit
2
Algunas respuestas generan una línea vacía para anidar niveles sin elementos. ¿Está bien devolver una matriz vacía en tales casos, por ejemplo, su primer ejemplo como [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[]]]], [[[[[8]]]]]]?
nimi

Respuestas:

1

Jalea , 8 bytes

fFṄḟ@;/ß

La salida es de un nivel por línea, con líneas vacías para niveles sin elementos. Pruébalo en línea!

Cómo 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.
Dennis
fuente
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])):[]

Explicación usando el ejemplo de entrada: ves un método auxiliar que devuelve los arreglos (con parámetro 1) o valores (sin parámetro). Comenzamos con a = [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]], que no es vacío. Filtramos las matrices, dando [1]. Luego, recursivamente, nos llamamos a nosotros mismos en las matrices concatenadas juntas, es decir [2, 3, [4], [[5, 6], 7, [[[8]]]], 9], el resultado es [2, 3, 9, [4, 7], [[5, 6]], [[[[8]]]]]. Nuevamente filtramos las matrices, lo que nos da el segundo término de nuestra salida [2, 3, 9], sin embargo, debemos tener cuidado de no insertar una matriz vacía aquí. Les queda para envolver las matrices [4, 7], [[5, 6]], [[[[8]]]]dentro de las matrices y agregarlas a la salida, lo que resulta en [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]].

Neil
fuente
Es posible que pueda guardar algunos bytes creando un alias filter. Tal vez comience conF=(x,y)=>x.filter(y)
Cyoce
@Cyoce resultó ser 30 al final!
Neil
Definitivamente tienes algo de golf por hacer en esto. Creo que puede reemplazar [].concat(...v(1))con seguridad v(1)para ahorrar 14 bytes. Probablemente hay algunas otras cosas también, pero me está costando mucho seguir los paréntesis anidados en mi cabeza.
Patrick Roberts
1
@PatrickRoberts [].concat(...v(1))es una bestia muy diferente a v(1), de lo contrario no lo haría. Para un ejemplo simple, considere a = [2, [3], [[4]]]entonces v(1) = [[3], [[4]]]pero [].concat(...v(1)) = [3, [4]].
Neil
@Neil oh, wow, realmente debería haber probado mi sugerencia antes de abrir la boca. Sin embargo, creo que debería haber una forma más corta de hacer esto ...
Patrick Roberts
2

05AB1E , 27 26 25 21 bytes

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

Pruébalo en línea! (ligeramente modificado ya que .gaún no está en TIO)

Explicación

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

La estrategia principal es recorrer cada nivel posible de la matriz anidada e imprimir cualquier dígito en una fila, mientras se mantienen los no dígitos (listas) en una lista de un nivel menos anidado.

Emigna
fuente
2

Perl, 52 bytes

Solo una subrutina recursiva. (Inusual para una respuesta de Perl, lo sé ...)

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

Llámalo así:

$ 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 línea de la salida corresponde a un nivel de profundidad de la matriz (de ahí la línea vacía en el ejemplo anterior).

Se puede convertir en un programa completo por solo unos pocos bytes más: agregue un -nindicador y un eval(dentro @{ }para transformar la entrada en una matriz y no una matrizref) para transformar la entrada en una matriz Perl:

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

Mi enfoque anterior fue un poco más largo (65 bytes), pero aún interesante, así que lo dejaré aquí:

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

JavaScript (ES6) 121 144 152

Editar Revisado mucho, 1 byte guardado gracias a Patrick Roberts y 21 más solo revisando el código

Función recursiva que trabaja en matrices de entrada y salida. No me gusta la petición de tener elementos en profundidad 1 como elementos individuales en matriz de salida (mientras que mayores niveles se agrupan como un elemento): [l1,l1, [l2...], [[l3...]] ]. Si bien esto sería más directo:[ [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,[])

Nueva línea agregada para facilitar la lectura.

Algunas notas: la línea 2 se evalúa una y otra vez en cada llamada recursiva, pero solo es útil la última iteración al final de la recursividad.
El manejo especial d==0en la línea 2 se ocupa de la anomalía de los elementos de nivel 1.
La nfunción recursiva maneja la matriz de anidamiento en la salida

Prueba

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>

edc65
fuente
1
Dado que solo hay matrices anidadas y enteros positivos, y se especifica que ninguna de las matrices en la entrada está vacía, una prueba más fácil para su operador ternario sería en v[0]lugar de v.map. Ahorra 1 byte.
Patrick Roberts
@PatrickRoberts genial gracias
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``+']')

Manifestación

sbisit
fuente
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]));

Descompostura

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
Jörg Hülsermann
fuente
1

Pyth 19 16 bytes

W=Qsf!&sITp+TdQk

Pruébalo en línea. Banco de pruebas.

Tenga en cuenta el espacio inicial. Produce niveles en filas como la respuesta de Perl.

Explicación

  • Entrada implícita en Q .
  • fartículos ilter T de Q:
    • Compruebe si sum esI dentición T.
    • Si era (era un número), print Tmás un espacio+ ... d.
    • Si no lo fue (era una matriz), guárdelo.
  • sum los artículos. Esto elimina una capa de matrices de cada elemento. Si no queda ninguno, rinde0 .
  • Asignar =el resultado aQ .
  • WMientras el resultado no sea vacío, imprima la cadena vacía ky una nueva línea.
PurkkaKoodari
fuente
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 no admite listas mixtas (enteros y lista de enteros) de forma predeterminada, defino un tipo de lista personalizada L. Ejemplo 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: lleva un tiempo ejecutarlo, porque recorre todos los Ints positivos (32 o 64 bits) para buscar un nivel de nido tan profundo. Además: el tipo de lista personalizada no se puede imprimir de forma predeterminada, por lo que si desea ver el resultado como en el ejemplo anterior, debe agregarlo deriving Showa la datadeclaración (->data L=I Int|R[L] deriving Show ). Como no es necesario para devolver una lista L de una función, no cuento los bytes.

Cómo 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 @BlackCap guardó un byte al cambiar de >>= a donotación. ¡Gracias!

nimi
fuente
Do notación ahorra un byteh l=R$do d<-[1..];[i|(e,i)<-0#l,d==e]!d
Blackcap
0

JavaScript (ES6), 127 137 134 bytes

Toma una matriz como entrada y devuelve una cadena.

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 prueba

Arnauld
fuente
@ Shebang Gracias por notarlo. Esto debería ser arreglado.
Arnauld
¡Creo que eso se ve bien ahora! :)
Kade