課題の配列#2:ネストされた配列を分離する


36

注:これは、一連の課題の第2位です。前のチャレンジについては、ここをクリックしてください

ネストされたリストの分離

ネストされたリスト内の値を分離するには、フラット化してから、各値をラップして、以前と同じネストされた深さになるようにします。

つまり、このリストは次のとおりです。

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

になるでしょう:

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

チャレンジ

あなたの仕事は、(あなたの言語の制限内で)正の整数のネストされたリストを取り、この分離操作を実行するプログラムを書くことです。

リストを引数として受け取る関数、またはI / Oを実行する完全なプログラムを送信できます。

これはであるため、最短の送信(バイト単位)が勝ちです!*

*標準的なゴルフの抜け穴は禁止されています。あなたはドリルを知っています。


テストケース

入力リストには、言語の標準整数サイズの整数のみが含まれます。言語の制約が競合するのを防ぐため、値は10を超える深さでネストされません。

入力に空のサブリストがないと仮定することができます。たとえば- [[5, []]]は与えられません。ただし、メインリストは空の場合があります。

[]            ->  []

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

コーナーケースを逃した場合、コメントを残すことをheしないでください。

簡単な(未使用の)Python 3ソリューションを例としてまとめました。repl.itでテストできます。


文字列ベースの回答用に1桁より大きい数字のテストケースを追加します。
orlp

@orlp良いアイデア。
FlipTack 16

2
特定の最大深度を想定できますか?16歳?
orlp

@orlpはい、私はあなたの言語の制約よりもあなたのアルゴリズムとメソッドの実行に興味があるので、最大のネストされた深さは10になります。今すぐスレッドを更新します。
FlipTack

文字列として出力できますか?
ローハンジュンジュンワラ

回答:


4

Brachylog、16バイト

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

オンラインでお試しください!

説明

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]

ZTIO の議論は何をしますか?これがない場合、これはtrue / falseで出力されるようZであり、バイトカウントで必要であるように見えます。
FlipTack 16

@FlipTack Zは、出力引数が変数であることをBrachylogに伝えます。これは、結果の出力と統合されるこの変数です。削除すると、出力が匿名変数であることがBrachylogに通知され、代わりにメインの述語が成功したか失敗したかが出力されます。これは、結果が変数に「入れられる」プロローグと同じです。
16

OK :)いい答えです!
FlipTack 16

19

Mathematica、24 21バイト

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

または次のいずれか:

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

説明

これが非常に短い理由は、基本的に明示的なベースケースを必要としない再帰であるためです。

ここには多くの構文糖衣がありますので、これをアンゴルフすることから始めましょう。 &は、その左にある名前のない関数を示し、その引数はとして記述され#ます。この関数内で#0は、関数自体を参照します。これにより、名前のない再帰関数を作成できます。しかし、内部関数に名前を付けて抜き出すことから始めましょう。

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

他の重要なシンタックスシュガーであるf/@xため、短いありますMap[f, x]それが呼び出すすなわちfのすべての要素にx。理由f[x_] := ... f /@ xは無限再帰につながらないため、アトムに何かをマッピングすると、実際に関数を呼び出すことなくアトムが変更されないままになるためです。したがって、ベースケース(現在の要素は整数)を明示的にチェックする必要はありません。

そのため、関数はf最初に内の最も深いリストに再帰しx、その時点f/@でノーオペレーションになります。次に##& @@ List /@、その上でuseを呼び出します。Listリストにマッピングすると、各要素が個別のリストにラップされるだけなので、に{1, 2, 3}なり{{1}, {2}, {3}}ます。次に、それを適用 ##&ます。つまり、ヘッド(つまり、外側のリスト)は、##&ため、これはに変わり##&[{1}, {2}, {3}]ます。しかし、##&単純に引数を返しますSequence(これは、ラップされていないリスト、または他の言語の一種の「スプラット」演算子と考えることができます)。

だから、##& @@ List /@リストターン{1, 2, 3}{1}, {2}, {3}(最後のものは、実際に頭に包まれていることを、一種のSequence、しかしすぐにその消滅は、我々は、値のどこかを使用して)。

なぜfそれ自体が課題の解決策ではないのかという疑問が残ります。問題は、最も外側のリストを異なる方法で処理する必要があることです。入力があれば、{{1, 2}, {3, 4}}欲しいものでは{{1}, {2}, {3}, {4}}ありません {{1}}, {{2}}, {{3}}, {{4}}。私の元のソリューションは、リストのJoin外部レベルを復元する引数のリストとして最終結果を渡すことでこれを修正しましたが、これはリストを使用して外部レベルをスキップするだけですf は出力のマップでそれ自体ことします。したがってf、最も外側のリストの個々の要素にのみ適用され、そのリストに触れることはありません。

他の3つの解決策に関しては、最初の解決策は単純にその外側で再帰を適用し、f同様に機能します。他の2つのソリューションはMap、最初に2つの関数を構成してから結果を1回だけマッピングすることにより、繰り返しの操作を回避します。


8

J19 18バイト

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

これは、ボックス化された配列を取得して返す匿名の動詞です。ボックス化された配列は、ネストされた配列のJ(かなり扱いにくい)バージョンです。 すべてのテストケースに合格することを確認してください。

説明

これは、ボックス化された配列を操作するややエキゾチックな操作{::map)とS:spread)を使用します。 {::各リーフをそのリーフへのボックス化されたパスに置き換えます。 S:指定された動詞を指定されたネストの深さに適用し、結果を配列にスプラットします。

(<@]/@,~>)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バイト

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})}

この質問は大変でした。Rのリストは少し奇妙で、サブリストのすべての要素をループするのは絶対に簡単ではありません。そのリストの深さを決定することも簡単ではありません。次に、すべての要素を分離してリストを再作成することが課題になるため、特定の深さのリストを適応的に作成する方法も必要です。

ソリューションは2つの大きな部分で構成されています。すべてのリストをループして深さを記録する再帰関数:

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

vectorのすべてのエントリの深unlist(l)さがdに格納されている場合、を介して暗黙的にリストを作成lapplyし、次の関数を使用してリストを埋めます。

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

この適用呼び出しではq、リスト内のエントリの値を使用してオブジェクトを作成し、その深さをチェックして、それがゼロでないかどうかを確認します。ゼロの場合は、数値のままにしておくことができます。ゼロ以外の場合は、その量のリストにネストする必要があります。したがって、forループを呼び出してd、繰り返し呼び出しますq=list(q)

lapply次に、これらすべての値をqリストに入れて、目的の出力を作成します。

適切な間隔などを備えた完全なプログラム:

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)
}

いいですね、これはテストケースのために最初のPythonソリューションで使用した方法です:)
FlipTack

is.list(y)代わりにclass(y)=='list'?それが実際に機能することを確認できません。
ジュゼッペ



2

C(gcc)、147バイト

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);}

入力例:

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

出力例:

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

2

積み重ね、非競合、25バイト

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

これは、スタックの最上位メンバーを変更するという機能です。あなたは真正の機能を使用する場合は、単に追加[し、]最初と最後に。ここで試してみてください!

読みやすいバージョンは次のとおりです。

{ 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

テストケース:

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

改行なしの出力:

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

ある*コードブロックの引数のような?
ダウンゴート16

この場合、@ Downgoatは引数d-1時間をラップします。$func操作可能な関数です。
コナーオブライエン

2

PHP、101 94バイト

@Christophのおかげで1バイト節約し、それに触発されてさらに6バイト節約しました。

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

再帰関数、かなり簡単

壊す

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
}

結果はどこで初期化されますか?
ニール

@Neil:PHPは明示的な初期化を必要としません。どちらかの$rループの要素を取得または関数が空の配列を返します。通知が生成される場合がありますが、それらはデフォルトの構成では出力されません。
タイタス

それはあなたが一度だけそれを呼び出すことができるだろうということを意味しませんか?
ニール

1
クレイジーになるかもしれません:!cos()。すべての配列に対してcos()返さnullれ、すべての正の整数に対してfloat!= 0を返します。つまり、誰が警告を気にしますか?
クリストフ

1
@Christoph:警告が出力されますが、通知は出力されません(デフォルト設定では)。しかし、それは素晴らしいアイデアです!On is_int:条件を反転しても何も保存されません。私は間にスペース必要elseとしますforeach。ただし$b[0]、整数の場合はNULLです。
タイタス

2

Python 2、122 106バイト

かなりひどいスコア、単純な実装です。

16バイトの節約を支援してくれた@Zachary Tに感謝します!

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)

x1つの引数で呼び出して実行します。何らかの理由で、一度だけ実行できます。


あなたは変更することができますa+=[n(l,d)]a+=n(l,d),(末尾のカンマを注意してください)
FlipTack

に割り当てる必要さえありtますか?
ザカリー16

これを複数回呼び出しても機能しますか?
ザカリー16

n関数に移動し、最初の引数を削除することができますl。これは、常にになるためです。
ザカリー16


2

JavaScript(Firefox 30-57)、53バイト

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

私が今までに持っているES6のベストアンサーは76バイトです:

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
両方のコードブロックで、先頭のを省略したと思いますf=
コナーオブライエン

@ ConorO'Brienまだまた...
ニール


1

Perl 6 60の 47バイト

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

オンラインで試してください。

説明:

  1. [... for |$^a]:入力配列を反復処理し、そこから新しい配列を作成します。
  2. $_ ~~ List ?? ... !! ...:各要素について、それ自体が配列であるかどうかを確認します。
  3. |([$_] for .&f):要素が配列の場合、関数を再帰的に適用し、その再帰呼び出しから返された新しい配列の要素を反復処理し、各要素を独自の配列にラップして、外側のリストに入れます。
  4. $_:要素が配列でない場合は、そのまま渡します。

1

Haskell、71バイト

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

繰り返しますが、Haskellのネイティブリストは任意にネストできないため、独自のリストタイプを定義する必要があります。この新しい型Lは関数から返すことができますが、デフォルトでは出力されないため、結果を見るために、次のshowインスタンスを定義しますL

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

これで、REPLでテストを実行できます。

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

仕組み:ネストレベルをCコンストラクターの関数として渡す単純な再帰。アイデンティティ関数idから開始し、リストがある場合(->パターンマッチd#C l=)、リストのすべての要素の再帰呼び出しにC(-> C .pure.d)のレイヤーを追加#します。番号に遭遇した場合、単純に入れ子レベル関数を適用しますdを番号に。


0

APL(ダイアログ)、44バイト*

匿名の暗黙の接頭辞関数。ネストされたAPLリストを引数として取り、ネストされたAPL配列を返します。

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

オンラインでお試しください!

{} 次の明示的な関数を適用します。引数は次のように表されます

⎕JSON⍵ 引数をJSONに変換します

j← 格納する j

'[]'∘.= テーブルどこ jオープン(上行)及びクローズ(下段)ブラケットに等しいです

-⌿ 一番上の行から一番下の行を引いたもの(垂直差の減少)

+\ 累積合計(各文字のネストレベルを示します)

()⊆ パーティション、1の前に1がない場合は常に新しいパーティションを開始…

  j∊⎕D の各文字jは、D igitsのセットのメンバーです

⊃¨ それぞれの最初のものを選択します(これにより、複数桁の数字ごとにネストレベルが得られます)

∊{...  (各入れ子レベルに次の関数を適用するから、対応する要素を使用して、)ε nlisted(左引数として引数(平坦化)を)。

,⍺ 数値をラベル(リスト)します(スカラーを囲むことができないため)

⊂⍣⍵時間を 囲む

 開示(最も内側のリスト自体がエンクロージャーであるため)


*でDyalogクラシックを使用する⎕ML←3代わりに、(多くのシステムでのデフォルト)のためにのためにティオ!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.