配列サンドイッチ


8

2012/2013のACMプログラミングコンテストの最初の予選の問題Cから転載

A 1、A 2、...、A nという名前の配列がいくつかあり、それぞれが昇順でソートされています。配列内のすべてのアイテムは32ビット整数になります。

サンドイッチは、インデックスjの集合である1、J 2、...、J nは、その結果A 1 [J 1 ]≤A 2 [J 2 ]≤....≤A N [j個のN ]。
A i [0]はA iの最初の要素です。

いくつかの配列を指定して、それらの配列から得られるすべての可能なサンドイッチを、改行で区切って出力します。

あなたの言語でこれを行う組み込み関数があるのなら、それを使わないでください。

入力は任意の方法で指定でき、出力は空白で区切る必要がありますが、任意の順序で指定できます。

テストケース:
[[1, 5, 7, 10], [2, 6, 6, 8, 12], [4, 5, 9]]

出力:

0 0 0
0 0 1
0 0 2
0 1 2
0 2 2
0 3 2
1 1 2
1 2 2
1 3 2
2 3 2

テストケース:
[[10, 20, 30], [1, 2, 3]]

出力:

最短のコードが勝ちます。


1
配列にはどのような値を含めることができますか?正の整数のみ?
Ilmari Karonen 2012

@IlmariKaronen:負の整数も含まれます。
beary605 2012

@PeterTaylor:簡単にするために、32ビット整数になります。
beary605 2012

@DavidCarraher:次のテストケースです。もっと明確にすべきです。
beary605 2012

ありがとう。現在、私の現在のソリューションは3つの要素の配列に対してのみ機能することがわかります。それを一般化するには、もう少し作業が必要になります。
DavidC、2012

回答:


2

APL(33)

↑1-⍨B/⍨{(⍳⍴A)∘≡⍋⍵⌷¨A}¨B←,⍳⊃∘⍴¨A←⎕

入力はキーボードから読み込まれますが、APLリストとして指定する必要があります。

(1 5 7 10) (2 6 6 8 12) (4 5 9)

説明:

  • B←,⍳⊃∘⍴¨A←⎕:Aは入力として評価され、BはAで指定されたリスト内のすべての可能なインデックスセットです。
  • {(⍳⍴A)∘≡⍋⍵⌷¨A}¨B:インデックスの各セットについて、リストから値を取得し(⍵⌷¨A)、それらがソートされているかどうかを確認します((⍳⍴A)∘=⍋
  • B/⍨:前の式が真であったすべてのインデックスのセットをBから選択します(つまり、すべてのサンドイッチ)
  • 1-⍨:この質問は0ベースの配列とAPL配列がデフォルトで1ベースであると想定しているため、すべてのインデックスから1を減算します。
  • :インデックスのセットのリストを行列として配置します(各セットは独自の行にあります)

3

Mathematicaの120 130

編集する

このバージョンは、さまざまなサイズの配列で動作します。


l = List;
g = Grid@Cases[Outer[l, Sequence @@ MapIndexed[l, #, {2}], 1]~Flatten~(Length[#] - 1), 
x_ /; LessEqual @@ x[[All, 1]] == True :> x[[All, 2, 2]] - 1] &

使用法

g@{{10, 20, 30}, {1, 22, 3}}
g@{{1, 5, 7, 10}, {2, 6, 6, 8, 12}, {4, 5, 9}}
g@{{10, 20, 30}, {1, 2, 3}}
g@{{1, -2, 3}, {-12, -7, 8, 9, 6}, {3, 99, 9}, {100, 10, -23}, {90, 10}}

結果


説明

上記の最初の例を使用して、

a = {{10, 20, 30}, {1, 22, 3}}

MapIndexedすべての要素のインデックスを設定します。注意:Mathematicaは1から数え始めます(後でそれを考慮します)。

MapIndexed[l, a, {2}]

{{{10、{1、1}}、{20、{1、2}}、{30、{1、3}}}、{{1、{2、1}}、{22、{2、 2}}、{3、{2、3}}}}


Outerすべてのリストを生成し、それぞれの候補をサンドイッチ配列として、それらの要素のインデックスを作成します。%以前の出力の結果が含まれています。番号、10および22出力後に強調表示した{10,22}ものは、まだ識別されていないサンドイッチ配列を参照しています。

Outer[l, Sequence @@ %, 1]~Flatten~(Length[a] - 1)

{{{10、{1、1}}、{1、{2、1}}}、{{ 10、{1、1}}、{ 22、{2、2}}}、{{10、{ 1、1}}、{3、{2、3}}}、{{20、{1、2}}、{1、{2、1}}}、{{20、{1、2}}、 {22、{2、2}}}、{{20、{1、2}}、{3、{2、3}}}、{{30、{1、3}}、{1、{2、 1}}}、{{30、{1、3}}、{22、{2、2}}}、{{30、{1、3}}、{3、{2、3}}}}


Cases上記の各要素をテストして、LessEqual(以下)関係が成立するかどうかを判断します。以下に示す結果は、アレイサンドイッチが検出された例です。もう一度、{10,22}出力で強調表示しました。

Cases[%, x_ /; LessEqual @@ x[[All, 1]] == True]

{{{ 10、{1、1}}、{ 22、{2、2}}}、{{20、{1、2}}、{22、{2、2}}}}


%%最後から2番目の結果を指します。:>、[RuleDelayed]は、対象のインスタンスの部分、つまり配列サンドイッチのインデックスを返します。  -1Mathematicaが0ではなく1で配列を開始するという事実を修正します 

Cases[%%, 

バツ_ /; LessEqual @@ x [[All、1]] == True:> x [[All、2、2]]-1]

{{0、1}、{1、1}}


Grid結果をグリッドに表示します。最初の行0 1は、最初のサブリスト(つまり10)の要素0 と2番目のサブリスト(つまり22)の要素1が、見つかった最初のサンドイッチ配列を構成することを意味します。

Grid@%

0 1

1 1


数の配列を修正することで人工的に答えを単純化するので、私はこの答えが嫌いです。
FUZxxl 2012

それが3つの「行」の配列に対してのみ機能するという意味であれば、私はあなたの嫌いを共有します。問題は、LessEqualサイズが不定の配列を処理できるようにすることです。同じ仮定が一般性を妨げる他の例があるかもしれません。機会があれば、アプローチを一般化します。
DavidC、2012

@FUZxxlアプローチを一般化することができました。見てください。
DavidC、2012

3

GolfScript、51文字

~:A{,}%{*}*,{A{,.@.@/\@%}%\;}%{:k,,{.A=\k==}%.$=},`

入力例(標準入力):

[[1 5 7 10] [2 6 6 8 12] [4 5 9]]

出力例(標準出力へ):

[[0 0 0] [0 0 1] [0 0 2] [0 1 2] [1 1 2] [0 2 2] [1 2 2] [0 3 2] [1 3 2] [2 3 2]]

(コンマなしで入力する必要があることに注意してください。そうしないと、プログラムがクラッシュする可能性が高くなります。)


私はこのコードがどのように機能するかについていくつかの説明を追加する必要があると思います:

  • ~:A入力をGolfScriptコードとして評価し、結果(配列の配列)をに割り当てますA。またA、次のステップのためにスタックにコピーを残します。

  • {,}%各サブ配列をその長さに置き換え、{*}*それらの長さを掛け合わせて、可能なサンドイッチ候補の総数を与えます。次に、この数値は、,0から始まる連続した整数の配列に変換されます。

  • {A{,.@.@/\@%}%\;}%各数値を対応するサンドイッチ候補に変換します(つまり、有効なインデックスの配列をの各サブ配列に変換しますA)。たとえば、上記の入力が与えられた場合、0はto [0 0 0]1to [1 0 0]2to [2 0 0]3to [3 0 0]4to [0 1 0]などにマッピングされます。(コードがどのように実行されるかを正確に把握することは、興味のある読者のための演習として残します。)

  • {:k,,{.A=\k==}%.$=},サブアレイの対応する要素にそれらの各々をマッピングすることによってサンドイッチ候補をフィルタリングA(例えば、その結果[0 0 0]生じるであろう[1 2 4][1 0 0]生じるであろう[5 2 4]上記の入力のため、など)結果の配列をソートし、ソートされていないコピーと比較すること、 。それらが等しい場合、配列はすでにソートされているため、候補は確かにサンドイッチです。

  • 最後に、`フィルタリングされたサンドイッチの配列を出力用の文字列に変換します。


スペースで区切る必要があるため、スペースやタブも機能します。
beary605 2012

はい、出力形式を変更しました。
Ilmari Karonen 2012

1

R-89文字

i=do.call(expand.grid,lapply(x,seq_along))
i[apply(diff(t(mapply(`[`,x,i)))>=0,2,all),]-1

どこ

x = list(c(1, 5, 7, 10), c(2, 6, 6, 8, 12), c(4, 5, 9))

または

x = list(c(10, 20, 30), c(1, 2, 3))

1

Python、 149 141 140

import itertools as I;x=input();r=range;print[p for p in I.product(*map(r,map(len,x)))if all(x[i][p[i]]<=x[i+1][p[i+1]]for i in r(len(x)-1))]

Pythonには、順列を生成できる便利なitertoolsライブラリがあります。これは、有効なインデックスの可能なすべての順列を反復処理し、それらが基準を満たしているかどうかをチェックします。

私はこれをより短くすることができると思いますが、まだそれに取り組んでいます。

編集:これで、あなたの読書の(不)便宜のためにすべて1行になりました!


r=range1つの文字を保存します。
beary605 2012

先端をありがとう。ライブラリ関数にエイリアスを付けることができるとは思いもしませんでした。
scleaver 2012

1

Python 120

f=lambda p,k=0:['%i '%j+m for j,v in enumerate(p[0])if v>=k for m in f(p[1:],v)]if p else['']
print'\n'.join(f(input()))

...まだ考えています、「列挙する」は非常に長い言葉です。


1

GolfScript(44文字)

~{.,,]zip}%{{`{+}+1$\/}%\;}*{2%.$=},{(;2%}%`

Ilmariのエントリと同じ入力および出力形式。

デモ

大まかな内訳:

各入力行をペアの配列にマップします [value index]

{.,,]zip}%

デカルト積を行の上に重ねます

{{`{+}+1$\/}%\;}*

0番目、2番目、4番目などのエントリが減少しないものにフィルターをかけます。

{2%.$=},

それぞれを1番目、3番目、5番目などのエントリにマップします。

{(;2%}%

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