Zorluklar Dizisi # 2: Yuvalanmış Bir Diziyi Ayırma


36

Not: Bu, bir dizi zorluğundaki # 2'dir . Önceki meydan okuma için, buraya tıklayın .

Yuvalanmış Listeleri Ayırma

Yuvalanmış bir listedeki değerleri ayırmak için, düzleştirin ve ardından her değeri önceki ile aynı iç içe derinlikte olacak şekilde kaydırın.

Yani, bu liste:

[1, [2, 3], [4, 4, [5, 2], 1]]

Olacaktı:

[1, [2], [3], [4], [4], [[5]], [[2]], [1]]

Meydan okuma

Senin görevin iç içe geçmiş pozitif tamsayılar listesini (dilinizin sınırları dahilinde) alan ve bu ayırma işlemini gerçekleştiren bir program yazmaktır.

Listeyi argüman olarak alan bir işlev veya G / Ç gerçekleştiren tam bir program gönderebilirsiniz.

Bu , en kısa teslim (bayt cinsinden) kazanır! *

* Standart golf boşlukları yasaklanmıştır. Matkabı biliyorsun.


Test Kılıfları

Giriş listeleri, yalnızca kendi dilinizin standart tamsayı boyutunda tamsayıları içerecektir. Dillerin rekabet etmelerini engelleyen kısıtlamalardan kaçınmak için, değerler 10'dan fazla derinliklerde yuvalanmayacaktır.

Girişin boş alt listelerine sahip olmayacağını varsayabilirsiniz: örneğin - [[5, []]]verilmeyecek. Ancak, ana liste boş olabilir.

[]            ->  []

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

Bir köşe davası kaçırdıysam yorum yapmaktan çekinmeyin.

Örnek

Örnek olarak hızlı (topraksız) bir Python 3 çözümü attım - repl.it üzerinde test edebilirsiniz .


Dize tabanlı cevaplar için tek haneden büyük rakamlardan oluşan bir test çantası ekleyin.
orlp

@orlp iyi fikir.
FlipTack

2
Belirli bir maksimum derinliği varsayabilir miyiz? 16 yaşında mı?
orlp

@ orlp Evet diyeceğim, maksimum iç içe geçmiş derinlik 10 olacak, çünkü algoritma ve yöntem yürütme dilinizdeki kısıtlamalardan daha fazla ilgileniyorum. İş parçacığını şimdi güncelleştirecek.
FlipTack

Dize olarak çıktı alabilir miyim?
Rohan Jhunjhunwala,

Yanıtlar:


4

Brachylog , 16 bayt

:{##:0&:ga|g}ac|

Çevrimiçi deneyin!

açıklama

Example input: [1:[2:3]]

:{          }a     Apply the predicate below to each element of the list: [[1]:[[2]:[3]]]
              c    Concatenate: Output = [1:[2]:[3]]
               |   Or: Input = Output = []

  ##                 Input is a list: e.g. Input = [2:3]
    :0&              Call recursively the main predicate with this input: [2:3]
       :ga           Group each element in a list: Output = [[2]:[3]]
          |          Or (not a list): e.g. Input = 1
           g         Group into a list: Output = [1]

ZTartışma TIO'da ne yapar ? Bu olmadan Z, bayt sayımında gerekli görünmesini sağlayan doğru / yanlışla sonuçlanır .
FlipTack

@FlipTack Z, Brachylog’ya çıktı değişkeninin bir değişken olduğunu söyler. Bu, elde edilen çıktı ile birleştirilen bu değişkendir. Bunu kaldırdığınızda Brachylog'a çıktının isimsiz bir değişken olduğunu söyler ve bunun yerine ana yüklemin başarılı veya başarısız olup olmadığını yazdırır. Bu, sonucun bir değişkene "koyulması" olduğu Prolog'dakiyle aynıdır.
Aralık’ta

Tamam :) güzel cevap!
FlipTack

19

Mathematica, 24 21 bayt

##&@@List/@#0/@#&/@#&

veya bunlardan biri:

##&@@List/@#&/@#0/@#&
##&@@List@*#0/@#&/@#&
##&@@List/@#&@*#0/@#&

açıklama

Bunun bu kadar kısa olmasının nedeni, temelde açık bir temel dava gerektirmeyen bir tekrarlama olmasıdır.

Burada çok sözdizimsel şeker var, hadi bunu çözerek başlayalım. &argümanı olduğu gibi yazılan, adsız bir işlevi ifade eder #. Bu fonksiyonun #0içinde, kişinin adsız özyinelemeli fonksiyonlar yazmasına izin veren fonksiyonun kendisi ifade edilir. Fakat içsel işleve bir isim vererek ve dışarı çekerek başlayalım:

f[x_] := ##& @@ List /@ f /@ x
f /@ # &

Diğer önemli sözdizimsel şeker, yani her elementi çektiği f/@xiçin kısadır . Bunun nedeni , sonsuz özyinelemeye yol açmaz, bir şey üzerinde bir atomun üzerinde eşlemenin, işlevi gerçekten çağırmadan atomu değiştirmeden bırakmasıdır. Dolayısıyla, temel durumu (akım elemanı bir tamsayıdır) açıkça kontrol etmemize gerek yoktur.Map[f, x]fxf[x_] := ... f /@ x

Böylece işlev fönce içindeki en derin listeye geri çekilir x, bu noktada f/@no-op olmaz. Sonra buna kullanımı diyoruz ##& @@ List /@. Haritalama Listliste üzerinde sadece bu yüzden ayrı bir listedeki her elemanı sarar {1, 2, 3}olur {{1}, {2}, {3}}. Sonra uygulamak ##& yerine alır başını (dış liste yani) anlamına gelen buna ##&içine bu dönüşler yüzden ##&[{1}, {2}, {3}]. Fakat ##&basitçe argümanlarını Sequence(açılmamış bir liste veya diğer dillerde bir tür "uyarıcı" işleci olarak düşünebileceğiniz) olarak döndürür .

Böylece ##& @@ List /@bir listeye {1, 2, 3}dönüşür {1}, {2}, {3}(bu son şey aslında kafanın içine girer Sequence, ancak değeri herhangi bir yerde kullanır kullanmaz yok olur).

Bu, neden fkendisinin zaten mücadelenin çözümü olmadığı sorusunu bırakıyor . Sorun, en dıştaki listenin farklı şekilde ele alınması gerektiğidir. Biz girdi varsa {{1, 2}, {3, 4}}istediğimiz {{1}, {2}, {3}, {4}}ve değil {{1}}, {{2}}, {{3}}, {{4}} . Benim asıl çözüm için bağımsız değişkenler listesindeki olarak nihai sonucu ileterek bu sabit Joinlistelerin dış düzeyini geri hangi fakat bu sadece kullanarak dış düzeyini atlar f kendisini Çıkışta bir harita. Bu nedenle f, yalnızca en dıştaki listenin tek tek öğelerine uygulanır ve asla bu listeye dokunmaz.

Diğer üç çözüm gelince, ilki basitçe dışında fda işe yarar özyinelemede uygulanır . Diğer iki çözüm Map, önce iki işlevi bir araya getirip, ardından sonucu yalnızca bir kez eşleyerek tekrarlanan bir işlemi önler .


8

J , 19 18 bayt

(<@]/@,~>)S:0 1{::

Bu, J'nin (oldukça hantal) iç içe dizilerin sürümü olan kutulu dizileri alan ve döndüren adsız bir fiildir. Tüm test durumlarını geçtiğini görün.

açıklama

Bu , kutulu dizilerde çalışan biraz egzotik işlemleri {::( harita ) ve S:( yayılı ) kullanır . {::her bir yaprağı o kutuya giden kutulu yolla değiştirir. S:verilen bir fiili verilen bir yuva derinliğine uygular, ardından sonuçları bir diziye uyarlar.

(<@]/@,~>)S:0 1{::  Input is y.
(        )          Let's look at this verb first.
        >           Open the right argument,
      ,~            append the left argument to it,
    /               then reduce by
 <@]                boxing. This puts the left argument into as many nested boxes
                    as the right argument is long.
                    This verb is applied to y
               {::  and its map
            0 1     at levels 0 and 1.
                    This means that each leaf of y is paired with its path,
                    whose length happens to be the nesting depth of y,
                    and the auxiliary verb is applied to them.
          S:        The results are spread into an array.

3

R, 199 bayt

function(l){y=unlist(l);f=function(x,d=0){lapply(x,function(y){if(class(y)=='list'){f(y,d=d+1)}else{d}})};d=unlist(f(l));lapply(1:length(d),function(w){q=y[w];if(d[w]){for(i in 1:d[w])q=list(q)};q})}

Bu soru HARD'dı. R listeleri biraz garip ve alt listelerin tüm öğelerini dolaşmak kesinlikle kolay değil. Ayrıca o listenin derinliğini belirlemek de kolay değildir. Daha sonra, meydan okuma listeyi tüm unsurlar ayrılmış olarak yeniden yaratır, bu yüzden de belirli bir derinlikte bir liste oluşturarak uyarlanabilir bir yola ihtiyacımız var.

Çözüm iki büyük bölümden oluşuyor. Tüm listelerde dolaşan ve derinliği kaydeden özyinelemeli bir işlev:

  f=function(x,d=0){
    lapply(x,function(y){
      if(class(y)=='list'){
        f(y,d=d+1)
      } else {
        d
      }})
  }

unlist(l)Depolanan vektörün her girişinin derinliklerine sahip olduğumuzda d, içinde gizli olarak bir liste oluşturur lapplyve aşağıdaki işlevle doldururuz:

  lapply(1:length(d),function(w){
    q=y[w]
    if(d[w]){
      for(i in 1:d[w]){
        q=list(q)
      }
    }
    q
  })

Bu başvuru çağrısında, qlistedeki girişin değerine sahip bir nesne yaratır , derinliğini kontrol eder ve sıfır olup olmadığını kontrol ederiz . Eğer sıfırsa, onu sayısal bir değer olarak bırakabiliriz. Sıfır değilse, bu miktarda listeye yerleştirmemiz gerekir. Bu yüzden döngüsel dzamanlar ararız ve tekrar tekrar çağırırız q=list(q).

lapplysonra tüm bu değerleri qbir listeye koyar , istenen çıktıyı yaratır.

Uygun aralıklarla komple program ve benzeri:

function(our.list){
  values <- unlist(our.list)
  f <- function(part.list, depth = 0){
    lapply(part.list, function(y){
      if(class(y)=='list'){
        f(y, depth <- depth + 1)
      } else {
        return(depth)
      }})
  }
  depths <- unlist(f(our.list))
  new.list <- lapply(1:length(depths), function(w){
    q <- values[w]
    if(depths[w] != 0){
      for(i in 1:depths[w]){
        q <- list(q)
      }
    }
    return(q)
  })
  return(new.list)
}

Güzel, bu test
senaryoları

is.list(y)yerine class(y)=='list'? Bunun gerçekten işe yarayacağını doğrulayamıyorum.
Giuseppe



2

C (gcc), 147 bayt

d=0,l,i;
P(n,c){for(;n--;)putchar(c);}
main(c){for(;~(c=getchar());l=i)i=isdigit(c),P((l<i)*d,91),P(i,c),P((l>i)*d,93),P(l>i,32),d+=(92-c)*(c>90);}

Örnek giriş:

1 [23 3] [40 4 [5 2] 1]

Örnek çıktı:

1 [23] [3] [40] [4] [[5]] [[2]] [1]

2

yığılmış , rekabet etmeyen, 25 bayt

{e d:e$wrap d 1-*}cellmap

Bu, yığının en üst üyesini değiştirdiği bir fonksiyondur. Eğer bir bonafide işlevini istiyorsanız, sadece ekleyebilir [ve ]başına ve sonuna. Burada dene!

İşte okunabilir bir sürüm:

{ arr :
  arr { ele depth :
    ele   $wrap depth 1- * (* execute wrap n times, according to the depth *)
  } cellmap (* apply to each cell, then collect the results in an array *)
} @:a2
(1 (2 3) (4 4 (5 2) 1)) a2 out

Test durumu:

(1 (2 3) (4 4 (5 2) 1))    (* arg on TOS *)
{e d:e$wrap d 1-*}cellmap
out                        (* display TOS *)

Yeni satırlar olmadan çıktı:

(1 (2) (3) (4) (4) ((5)) ((2)) (1))

*kod bloğuna argüman gibi?
Downgoat

@Downgoat bu durumda argüman d-1zamanlarını sarar . $funcmanipüle edilebilir bir fonksiyondur.
Conor O'Brien,

2

PHP, 101 94 bayt

@Christoph sayesinde 1 byte kaydedildi, bundan ilham alan 6 tane daha kaydedildi.

function s($a){foreach($a as$b)if($b[0])foreach(s($b)as$c)$r[]=[$c];else$r[]=$b;return$r?:[];}

özyinelemeli işlevi, oldukça yalındır

Yıkmak

function s($a)
{
    foreach($a as$b)                // loop through array
        if($b[0])                       // if element is array
            foreach(s($b)as$c)$r[]=[$c];    // append separated elements to result
        else$r[]=$b;                    // else append element to result
    return$r?:[];                   // return result, empty array for empty input
}

Sonuç nerede başlatılıyor?
Neil

@Neil: PHP açık başlatma gerektirmez. Her iki $rdöngü öğeleri alır veya fonksiyon boş bir dizi döner. Bildirimler verebilir, ancak bunlar varsayılan yapılandırma ile yazdırılmaz.
Titus

Bu, sadece bir kez arayabileceğiniz anlamına gelmez mi?
Neil

1
Sen de delirebilirsin !cos(). her bir dizi için cos()döner nullve her bir pozitif tamsayı için bir kayan! Demek istediğim ... uyarıları kim önemsiyor?
Christoph

1
@Christoph: uyarılar yazdırılır, uyarılar yazılmaz (varsayılan konfigürasyonda). Ama bu harika bir fikir! On is_int: Durumu tersine çevirmek hiçbir şeyi kurtarmaz; Ben arasına boşluk ihtiyaç elseve foreach. AMA: $b[0]bir tamsayı için NULL.
Titus,

2

Python 2, 122 106 bayt

Oldukça korkunç bir skor, sadece basit bir uygulama.

16 bayttan tasarruf etmenize yardımcı olan @ Zachary T'ye teşekkürler!

def x(l,a=[],d=0):
 n=lambda b:b and[n(b-1)]or l
 if'['in`l`:[x(e,a,d+1)for e in l];return a
 else:a+=n(d)

xÇalıştırmak için bir argüman ile arayın . Bazı nedenlerden dolayı sadece bir kez çalıştırılabilir.


Değişebilirsin a+=[n(l,d)]için a+=n(l,d),(sondaki virgül dikkat edin)
FlipTack

Hatta atamana gerek var tmı?
Zacharı

Birden çok kez aradığınızda bu işe yarar mı?
Zacharı

Her zaman nolacağı için işleve geçebilir ve ilk argümanı kaldırabilirsiniz l.
Zacharı


2

JavaScript (Firefox 30-57), 53 bayt

f=a=>[for(e of a)for(d of e.map?f(e):[e])e.map?[d]:d]

Şimdiye kadar sahip olduğum en iyi ES6 cevabı 76 bayt:

f=(a,r=[],d=0)=>a.map(e=>e.map?f(e,r,d+1):r.push((n=d=>d?[n(d-1)]:e)(d)))&&r

2
Her iki kod bloğunda da liderliği atladığını düşünüyorum f=.
Conor O'Brien,

@ ConorO'Brien Yine ...
Neil


1

Perl 6 , 60 47 bayt

sub f{[$_~~List??|([$_] for .&f)!!$_ for |$^a]}

( Çevrimiçi deneyin. )

Açıklama:

  1. [... for |$^a]: Girdi dizisini yineleyin ve bundan yeni bir dizi oluşturun.
  2. $_ ~~ List ?? ... !! ...: Her eleman için kendisinin bir dizi olup olmadığını kontrol edin.
  3. |([$_] for .&f): Eğer eleman bir dizi ise, fonksiyonu tekrarlı bir şekilde uygulayın, bu özyinelemeli çağrıdan döndürülen yeni dizi elemanlarını yineleyin, her elemanı bir dizi dizisine sarın ve dış listeye kaydırın.
  4. $_: Öğe bir dizi değilse, olduğu gibi iletin.

1

Haskell, 71 bayt

data L=N Int|C[L] 
d#C l=((C .pure.d)#)=<<l
d#n=[d n]
f(C l)=C$(id#)=<<l

Yine kendi liste tipimi tanımlamalıyım, çünkü Haskk'in yerlileri listeleri keyfi olarak yerleştirilemiyor. Bu yeni tür Lbir işlevden döndürülebilir ancak varsayılan olarak yazdırılamaz, bu nedenle bir sonuç görmek için bir showörnek tanımlarım L:

instance Show L where
  show (N n)=show n
  show (C l)=show l

Şimdi REPL'de bir test yapabiliriz:

*Main> f $ C[N 1, C[N 2, N 3], C[N 4, N 4, C[N 5, N 2], N 1]]
[1,[2],[3],[4],[4],[[5]],[[2]],[1]]

*Main> f $ C[C[N 6, C[C[N 7]]]]
[[6],[[[7]]]]

Nasıl çalışır: İç içe yerleştirme düzeyini Ckurucuların işlevi olarak geçen basit bir özyineleme . Kimlik işleviyle başlıyoruz idve bir liste (-> desen eşleşmesi d#C l=) olduğunda, listenin tüm elemanlarını özyinelemeli çağrısına başka bir C(-> C .pure.d) katmanı ekliyoruz #. Bir sayı ile karşılaşırsak, iç içe-seviye işlevini dsayıya uygulamanız yeterlidir .


0

APL (Dyalog) , 44 bayt *

Anonim zımni önek işlevi. İç içe APL listesini argüman olarak alır ve iç içe bir APL dizisini döndürür.

∊{⊃⊂⍣⍵,⍺}¨{⊃¨(j∊⎕D)⊆+\-'[]'∘.=j←⎕JSON⍵}

Çevrimiçi deneyin!

{} Argümanın temsil ettiği aşağıdaki açık fonksiyonu uygulayın :

⎕JSON⍵ argümanı JSON'a dönüştür

j← depolamak j

'[]'∘.= masa jüstü açık (üst sıra) ve yakın (alt sıra) parantezlerin olduğu tablo

-⌿ üst sıra eksi alt sıra (dikey fark azaltma)

+\ kümülatif toplam (bu, her karakter için yuvalama düzeyi verir)

()⊆ Bölümleme, 1'den önce 1 olmadığında yeni bir bölümleme ...

  j∊⎕D burada her bir karakter jkümesinin bir üyesi olan D igits

⊃¨ her birinin ilkini seçin (bu, çok basamaklı sayı başına yuvalama düzeyi verir)

∊{...  Her iç içe geçme düzeyine (aşağıdaki işlevi uygulanır karşılık gelen elemanı kullanılarak), £ değerinin nlisted (sol bağımsız değişken olarak bağımsız değişken (düzleştirilmiş) ):

,⍺ Rakamı tara (listele) (çünkü skalarlar eklenemez)

⊂⍣⍵ kapalı zamanlar

 ifşa (çünkü en içteki listenin kendisi bir muhafazadır)


* İle Dyalog Klasik kullanma ⎕ML←3yerine (birçok sistemlerinde varsayılan), için ve için . Tio!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.