Semplifica un array


22

Ingresso

Un array che può contenere array o numeri interi positivi, consecutivi, ascendenti. Le matrici possono avere un numero qualsiasi di matrici al loro interno, e così via e così via. Nessun array sarà vuoto.

Produzione

Questo array è stato semplificato

Come semplificare un array

Useremo l'array, [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]] come il nostro esempio.

Innanzitutto, controlliamo quanto in profondità sono nidificati i valori. Ecco le profondità e i numeri a quelle profondità:

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

Costruiamo l'array di output prendendo i numeri nell'array originale, raggruppandoli in base alla profondità con cui sono nidificati e quindi annidando i gruppi in profondità nelle profondità originali dei loro elementi. Disporre i numeri in ordine crescente e in profondità crescente.

Quindi, il nostro output è [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]]

Esempi

[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]]]]]

L'output è flessibile? Come numeri in diverse linee, in cui ogni riga è di un livello; o altri delimitatori / separatori di array
Luis Mendo,


@ LuisMendo, sì, è flessibile
Daniel,

Manca una coppia di parentesi attorno 8alla linea So, our output is...... Tuttavia, l'hai corretto nello snippet di esempio.
sbisit,

2
Alcune risposte generano una riga vuota per i livelli di annidamento senza elementi. Va bene restituire un array vuoto in questi casi, ad esempio il tuo primo esempio come [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[]]]], [[[[[8]]]]]]?
nimi,

Risposte:


1

Gelatina , 8 byte

fFṄḟ@;/ß

L'output è di un livello per riga, con righe vuote per livelli senza elementi. Provalo online!

Come funziona

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 byte

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])):[]

Spiegazione usando l'input di esempio: vè un metodo helper che restituisce le matrici (con parametro 1) o i valori (senza parametro). Iniziamo con a = [1, [2, 3], [[4]], [[[5, 6], 7, [[[8]]]], 9]], che è vuoto. Filtriamo gli array, dando [1]. Quindi ci chiamiamo in modo ricorsivo sugli array concatenati insieme, ovvero [2, 3, [4], [[5, 6], 7, [[[8]]]], 9]il risultato [2, 3, 9, [4, 7], [[5, 6]], [[[[8]]]]]. Ancora una volta filtriamo gli array, il che ci dà il secondo termine del nostro output [2, 3, 9], tuttavia dobbiamo stare attenti a non inserire un array vuoto qui. Resta da avvolgere le matrici [4, 7], [[5, 6]], [[[[8]]]]all'interno delle matrici e aggiungerle all'output, risultando [1, [2, 3, 9], [[4, 7]], [[[5, 6]]], [[[[[8]]]]]].


Potrebbe essere in grado di salvare alcuni byte creando un alias per filter. Forse inizia conF=(x,y)=>x.filter(y)
Cyoce,

@Cyoce Alla fine si è rivelato 30!
Neil,

Hai sicuramente ancora del golf da fare al riguardo. Penso che puoi tranquillamente sostituirlo [].concat(...v(1))con v(1)per salvare 14 byte. Probabilmente ci sono anche alcune altre cose, ma faccio fatica a tenere traccia delle parentesi annidate nella mia testa.
Patrick Roberts,

1
@PatrickRoberts [].concat(...v(1))è una bestia molto diversa v(1), altrimenti non lo farei! Per un semplice esempio, considera a = [2, [3], [[4]]]allora v(1) = [[3], [[4]]]ma [].concat(...v(1)) = [3, [4]].
Neil,

@Neil oh, wow avrei dovuto testare il mio suggerimento prima di aprire la bocca. Sento che dovrebbe esserci un modo più breve di farlo però ...
Patrick Roberts,

2

05AB1E , 27 26 25 21 byte

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

Provalo online! (leggermente modificato in quanto .gnon è ancora su TIO)

Spiegazione

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 strategia principale è quella di eseguire il ciclo su ogni possibile livello dell'array nidificato e stampare le cifre su una riga, mantenendo le non cifre (elenchi) in un elenco di un livello meno nidificato.


2

Perl, 52 byte

Solo una subroutine ricorsiva. (insolito per una risposta Perl, lo so ..)

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

Chiamalo così:

$ 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

Ogni riga dell'output corrisponde a un livello di profondità dell'array (quindi la riga vuota nell'esempio sopra).

Può essere trasformato in un programma completo solo per qualche byte in più: aggiungi -nflag e un eval(interno @{ }per trasformare l'input in un array e non un arrayref) per trasformare l'input in un array Perl:

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

Il mio approccio precedente era leggermente più lungo (65 byte), ma comunque interessante, quindi lo lascerò qui:

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

modificare Revisionato molto, 1 byte salvato grazie a Patrick Roberts e altri 21 solo per la revisione del codice

Funzione ricorsiva che lavora su array in input e output. Non piace la richiesta di avere elementi a profondità 1 come elementi singoli nella matrice di uscita (mentre i livelli più elevati sono raggruppati come un elemento): [l1,l1, [l2...], [[l3...]] ]. Mentre questo sarebbe più diretto:[ [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,[])

Newline aggiunto per leggibilità.

Alcune note: la riga 2 viene valutata più volte ad ogni chiamata ricorsiva, ma è utile solo l'ultima iterazione alla fine della ricorsione.
La gestione speciale d==0nella riga 2 si occupa dell'anomalia per gli elementi di livello 1.
La nfunzione ricorsiva gestisce l'annidamento dell'array nell'output

Test

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
Dato che ci sono gli array solo nidificati e numeri interi positivi, ed è specificato che nessuna delle matrici in ingresso sono vuoti, un test facile per il vostro operatore ternario sarebbe v[0]invece v.map. Salva 1 byte.
Patrick Roberts,

@PatrickRoberts cool thanks
edc65,

1

JavaScript (ES6) 168 byte

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``+']')

dimostrazione


1

PHP, 145 byte

<?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]));

Abbattersi

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

Pyth, 19 16 byte

W=Qsf!&sITp+TdQk

Provalo online. Suite di test.

Nota lo spazio iniziale. Emette livelli su righe come la risposta Perl.

Spiegazione

  • Ingresso implicito in Q.
  • farticoli ILTER Tdi Qsu:
    • Controlla se sum è Iattivo T.
    • Se era (era un numero), print Tpiù uno spazio +d.
    • Se non lo fosse (era un array), tienilo.
  • sum gli articoli. Ciò rimuove uno strato di matrici da ciascun elemento. Se non ne rimane nessuno, i rendimenti0 .
  • Assegna =il risultato a Q.
  • Wmentre il risultato è vuoto, stampa la stringa vuota ke una nuova riga.

1

Haskell, 124 123 byte

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

Poiché Haskell non supporta elenchi misti (numeri interi e elenco di numeri interi) per impostazione predefinita, definisco un tipo di elenco personalizzato L. Esempio di utilizzo:

*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: l'esecuzione del tempo richiede del tempo, poiché scorre tutti gli Ints positivi (32 o 64 bit) per cercare un livello di annidamento così profondo. Inoltre: il tipo di elenco personalizzato non può essere stampato per impostazione predefinita, quindi se si desidera vedere il risultato come nell'esempio sopra, è necessario aggiungere deriving Showalla datadichiarazione (->data L=I Int|R[L] deriving Show ). Poiché non è necessario per restituire un elenco L da una funzione, non conto i byte.

Come funziona:

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

Edit @BlackCap ha salvato un byte passando da >>=una donotazione. Grazie!


La notazione salva un byteh l=R$do d<-[1..];[i|(e,i)<-0#l,d==e]!d
BlackCap

0

JavaScript (ES6), 127 137 134 byte

Prende un array come input e restituisce una stringa.

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``}]`

Casi test


@Shebang Grazie per avermelo notato. Questo dovrebbe essere risolto.
Arnauld,

Credo che ora vada bene! :)
Kade,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.