ブダペスト


30

課題は簡単です。有限の非負整数が与えられると、ネストされた配列を出力するプログラムまたは関数を作成します。

ルール

  • コードは、整数0 ‌≤ n ‌ <2 31 ごとに一意の有効なネストされた配列を生成する必要があります。
  • 最大16個のオープンブラケットを持つネストされた配列はすべて、この範囲内で出力する必要があります。(これは、コードが16個を超える開き括弧を持つネストされた配列を出力できないことを意味するものではありません。)
  • コードは、実際の配列(コンマの有無にかかわらず)の代わりに、ネストされた配列の文字列表現を出力する場合があります。

1つの可能なマッピング:

0 -> []
1 -> [[]]
2 -> [[[]]]
3 -> [[], []]
4 -> [[[[]]]]
5 -> [[[], []]]
6 -> [[[]], []]
7 -> [[], [[]]]
8 -> [[], [], []]
9 -> [[[[[]]]]]
etc.

得点

これはであるため、バイト単位の最短コードが優先されます。


時間/メモリの制限はありますか?
デニス

@Dennis時間制限として1時間は妥当と思われますか?私は記憶のために合理的であるものの見当がつかない。
-ETHproductions

時間制限がある場合、メモリは大した問題ではありません。1時間は非常に寛大なようです。コードが十分に高速であるかどうかを確認するのに1時間待ちたくありません。
デニス

4
時間制限がないことを希望します。これにより、独創性の範囲が広がります
トンホスペル

2
@TonHospelカンマなしで出力できます。エントリが有効であることを証明できる限り、時間制限は問題ないでしょう。
ETHproductions

回答:


12

パイソン2.7、172の149 124 118バイト

x=input();y="";z=0
for b in bin(x)[2+(x<1):]:y+="[]"[b<"1"];z+=b>"0"or-1;z+=99*(z<0)
print"["+(y,"[]"*(x+16))[z>0]+"]"

説明:

で全単射を定義[1]0。ブラケットの任意の配置は、次いで、例えば、二進数およびその逆のように書くことができる。[][]1010(10)と[[][]]110100(52)。最大15個のオープンブラケット(合計30個のブラケット)のすべての有効な配置は、最大30ビット(先行ゼロは無視)の数字でカバーされます。これは正確には2 31未満の数字です。

最初のforループは、この全単射の逆を行い、数値が括弧の配列に変換され、配列が有効であることを確認します。

衝突を避けるために、無効な配置はprintステートメント内で長い括弧のシーケンスに置き換えられます。たとえば、11(3)↔ [[は有効ではないため、代わりに3 + 16個のブラケットを連結します。これにより、すべての配置が一意になります。

そのように得られた配列は、ネストされた配列を作るために一対のブラケット内に配置されている1010(10)になる[[][]]110100(52)となります[[[][]]]。余分なオープンブラケットは、16個のオープンブラケットですべてのアレイをカバーしたことを意味します。


次のプログラムを使用して、最大16個の角かっこを持つ特定の配列の数を計算できます。

s=raw_input();o="";
for c in s[1:-1]:
 if c=="[":o+="1"
 if c=="]":o+="0"
print int(o,2)

OPの意図彼は「ユニーク」指定されたときの素敵な虐待
トンHospel

それはただの天才です。よくやった。(およびコンマなしの形式が許可されます。)
ETHproductions

12

Python、153 128バイト

s=l=0;r="";n=input()
for d in bin(n)[2:]*(n>0):c=d<"1";l=[l,s>1][c];r+="]"*c+(1-l*c)*"[";s+=1-c-l*c
print"["+r+"["*l+"]"*(s+l+1)

2進数を左から右に見て、番号nをネストされたリストにマップします。このアルゴリズムは、2 32未満だけでなく、あらゆる数で機能します。

  1. 現在の2進数が1の場合、出力 [
  2. それ以外の場合、これまでに出力したブラケットのシーケンスが単一の閉じブラケットによってバランスが取れている場合、出力 ][
  3. それ以外の場合、これが2進数の最後の0であれば、output ][です。
  4. それ以外の場合は出力します]

最後に、開いているブラケットを閉じます。


5

スプーン、63バイト(501ビット)

000001001001001011001101001010011011111001010001000000101010
101101100110100101101001000101100010001000000100011000010000
000000000000001110111110010000001110110110010100100100100100
000110011010001000000110110000010000001010110011011011011001
000000011010010010010001000000111011011011101001001001000110
110110010100100101011001000100000011010001000000111011011001
010010010010010001101101101001000110110010110001101101101101
100100010001010010001010011011001000000011001101001001010010
000001100101001000111

これは、スプーンに変換された次のBrainfuckプログラムです。

-[+[+<]>>+]<+++.[->+>+<<]>>++>>,[>-[<->-----]+<+++[-<+<<.>>>>-<]>[-<<-[->+<]<<<[-]>>>>[-<+<<<+>>>>]<<.>>+<[>-]>[-<+<<.>>>>]<<>>]<,]<<<<[>.>.<<[-]]>>>+[-<.>]+

stdinでバイナリの整数を読み取り、stdinでネストされたリストを出力します。0を空の文字列(数字なし)として入力する必要があり、8ビットセルのBrainfuckインタープリターが必要です。Pythonの答えと同じアルゴリズム。

読み取り可能なバージョン:

-[+[+<]>>+]<+++.           push open bracket and print it
[->+>+<<]                  dup
>>++                       increment to close bracket

>>,[                       read input loop
    >-[<->-----]+<+++          subtract 48 and set up if/else
    [-                         if c == 1
        <+                         increment s
        <<.>>>                     output open bracket
    >-<]>[-<                   else
        <-[->+<]                   decrement and move s
        <<<[-]                     zero l
        >>>>[-<+<<<+>>>>]          l = s and restore s
        <<.>                       output close bracket
        >+<[>-]>[-                 if s == 0
            <+                         undo s decrement
            <<.                        output open bracket
        >>>>]<<
    >>]<
,]

<<<<[                      if l
    >.>.                   output pair
<<[-]]
>>>+[-<.>]                 output close bracket s+1 times

3
最近、別の回答についてこの議論を行いましたが、63バイトのファイルを処理できる実際の通訳者はいないようです。リファレンス実装はバイト0x30および0x31を使用したため、この回答には501 バイトのファイルが必要です。
デニス


5

Perl、80 79バイト

再びorlpのアルゴリズムを使用しますが、今回は最初にそれが機能するかどうかを確認しました...

+1を含む -p

STDINに入力番号を与える

nest.pl <<< 8

nest.pl

#!/usr/bin/perl -p
($_=sprintf"%b",$_).=2x(s^.^$&or++$n-pos&&/.0/g?++$n%1:$`&&21^eg-$n);y;102;();

Linusのソリューションはperlで64バイトです:

#!/usr/bin/perl -p
$_=sprintf"%b",/.+/g;$_=10x($&&&$&+16)if!/^(1(?1)*0)+$/;y;10;()

Dennisのソリューションは、perlで59バイトです(大きな数値ではますます遅くなります):

#!/usr/bin/perl -p
1while$_-=(sprintf"%b",$n++)=~/^(1(?1)*0)+$/;$_=$&;y;10;()

これを65バイトとしてスコアする必要があると思います(実際には64バイトではありません)。
ライナス

1
@Linusあなたのルールの回避は素晴らしいものであり、そのすべての賛成に値しますが、私はそれをちょっとしたごまかしと考えています。スコアリングのために-p1余分なバイトとしてカウントされる
トンHospel

5

Pythonの3、120の 114バイト

def f(n,k=0):
 while~n:
  k+=1
  try:r=eval(bin(k).translate({48:'],',49:'['})[3:-1])+[];n-=1
  except:0
 print(r)

テストする Ideoneでます。

使い方

定義された関数fは、入力nを受け取り、k0に初期化します。私たちは、インクリメントしておこうKをするまでのn + 1の値をk個の有効な出力に結果。このようなkの値を見つけるたびに、n-1に達するとデクリメントされ、0を~n生成し、kの最後の値に対応するリストrを生成しますされが出力されます。

正の整数からネストされたリストへの部分的なマッピング(つまりk↦r)は全単射でなければなりませんが、他の制約はありません。この回答で使用されているものは次のように動作します。

  1. kをバイナリ文字列表現に変換し、0bで開始しますます。

    たとえば、44↦ "0b101100"です。

  2. 文字列表現のすべての0(コードポイント48)を文字列「]」に置き換え、すべての1(コードポイント49)を[

    たとえば、"0b101100"↦ "]、b []、[[]、]、"のようになります。

  3. 最初の3文字を削除します(「0b」に対応します))と末尾の文字(できればコンマ)をます。

    たとえば、"]、b []、[[]、]、"↦ "[]、[[]、]"です。

  4. 生成されたコードを評価してみてください。これによりエラーが発生した場合、kはどのリストにもマッピングされません。

    たとえば、「[]、[[]、]」↦([]、[[]])など

  5. 結果(ある場合)を空のリストに連結します。これによりエラーが発生した場合、kはどのリストにもマッピングされません。

    たとえば、([]、[[]])+ []エラーは、+がリストとタプルを連結できないためです。


4

Haskell、71バイト

p 1=["[]"]
p n=['[':h++t|k<-[1..n-1],h<-p k,_:t<-p$n-k]
((p=<<[1..])!!)

最後の行のメイン関数は、サイズ(開き括弧の数)でソートされたすべてのネストされた配列のリストにインデックスを付けます。したがって、サイズが最大16のすべての配列が最初にリストされます。

最初に、より良くて短いコードを見てみましょうが、Haskellのタイプチェッカーは受け入れません。

p 1=[[]]
p n=[h:t|k<-[1..n-1],h<-p k,t<-p$n-k]
((p=<<[1..])!!)

p入力の関数nは、ネストされたすべてのサイズの配列のリストn(開き括弧)を提供します。これは再帰的に行われます。そのような各配列は、hサイズの先頭(最初のメンバー)とサイズのk末尾t(他のメンバー)で構成されn-k、両方とも非ゼロです。または、サイズの空の配列ですn==1

この式p=<<[1..]p(1), p(2), ...、サイズでソートされたすべての配列の単一の無限リストにフラット化されます

[ [], [[]], [[],[]], [[[]]], [[],[],[]], [[],[[]]], [[[]],[]], [[[],[]]], ...

そして、メイン関数がそれにインデックスを付けます。

...または、Haskellが「無限の型を構築することについて愚痴を言っていない場合:t〜[t]」。Haskellは、要素が任意にネストされた配列である上記の無限リストを表すことはできません。すべての要素は同じ型でなければなりませんが、型tをtのリストと同じにすることはできません。実際、関数p依存型付けなし自体に一貫性のある型を割り当てることはできませんが、Haskellにはありません。

そのため、代わりに角括弧の文字列で作業し、文字[]文字に作用することで短所操作をシミュレートします。これには、さらに9バイトが必要です。タイプセーフな言語でのゴルフの危険。


3

Haskell、87 82バイト

0#0=[""]
n#m=['[':x|n>0,x<-(n-1)#m]++[']':x|n<m,x<-n#(m-1)]
(([0..]>>= \y->y#y)!!)

配列要素を出力します。使用例:(([0..]>>= \y->y#y)!!) 3-> "[][]"

関数#は、それぞれが何個残っているかを追跡することにより、すべてのネストされた配列をn開きm括弧と閉じ括弧の文字列として構築します。常にで始まりn == mます。main関数はy # yevery y <- [0,1,...]を呼び出し、入力によって指定されたインデックスで要素を選択します。


2

MATL、31バイト

O`@BEqXJYs0&)0>w~hA+tG>~]x92J-c

オンラインでお試しください!または、最初のいくつかのテストケースを確認しますます(数秒かかります)。

生成されるマッピングは次のとおりです。

0 -> []
1 -> [[]]
2 -> [[][]]
3 -> [[[]]]
4 -> [[][][]]
5 -> [[][[]]]
6 -> [[[]][]]
7 -> [[[][]]]
...

説明

コードは、数字とともに、増加する2進数をテストし続けます 0-1;に置き換えてます つまり、1-1を数字として使用します。数字1はを表し'['-1を表し']'ます。

プログラムは、n +1 個の有効な数値が取得されるまでカウントします。次の2つの条件が満たされる場合、数値は有効です。

  1. 桁の合計がゼロです(つまり、等しい数の1とがあります-1
  2. 累積桁数は常に正です(つまり、累積1桁数は常にの桁数を超えます-1)。ただし、末尾(条件1によってゼロになる場合)は例外です。

一度n 1つの有効な数値が得られた、最後の1を変更することで、音訳さ1[し、-1]し、それが表示されます。

コード:

O          % Push 0: initial count of valid numbers
`          % Do...while
  @        %   Push iteretation index k, starting at 1
  B        %   Convert to binary. For example, k=6 gives [1 1 0 0]
  Eq       %   Multiply by 2, subtract 1: transforms [1 1 0 0] into [1 1 -1 -1]
  XJ       %   Copy that to clipboard J, without popping it
  Ys       %   Cumulative sum: gives [1 2 1 0]
  0&)      %   Split array into its final element and the rest. Gives 0, [1 2 1]
  0>       %   Yields 1 for positive entries (condition 2). So in this case it
           %   gives [1 1 1]
  w        %   Swap: moves second-top element in the stack (0 in this case) to top
  ~        %   Negate: yields 1 if input is 0 (condition 1). Gives 1 in this case
  h        %   Concatenate horizontally. Gives [1 1 1 1]
  A        %   All: gives 1 if all elements are 1. Gives 1 in this case, meaning
           %   that this k is valid
  +        %   Add the result (0 or 1) to the count of valid numbers
  t        %   Duplicate
  G        %   Push input n
  >~       %   Loop condition: false (exit loop) if count exceeds input n
]          % End loop. At this point the result is in clipboard J, in 1/-1 format
x          % Delete count
92         % Push 92. Will be used to convert 1, -1 to '[', ']' (ASCII 91, 93)
J          % Push result in 1/-1 format
-          % Subtract: converts 1 to 91, -1 to 93
c          % Convert to char. Implicitly display
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.