私のパスタソースは何ですか?


37

バックグラウンド

フランスでは、おそらく欧州連合の残りの部分では、販売のために利用可能な任意の食品はしなければならないで、そのパッケージに、それを構成する成分をリスト重量パーセントの降順。ただし、以下の場合を除き正確な割合を示す必要はありません。カバーのテキストまたは画像で成分が強調表示されてい。

たとえば、パッケージに大きな赤いトマトと美しいバジルの葉だけが表示されている私のバジルトマトソースには、次の表示があります。

原材料:トマト80%、玉ねぎ、バジル1.4%、海塩、つぶしたニンニク、生の砂糖、エキストラバージンオリーブオイル、黒胡pepper。

食いしん坊に聞こえるかもしれませんが… どのくらいの玉ねぎを食べます正確ますか?

チャレンジ

最終的に不完全な降順の重量パーセントのリストが与えられた場合、レシピで見つかる可能性のある最小および最大重量パーセントの完全なリストを出力します。

  • 関数または完全なプログラムのいずれかを作成できます。
  • 入力は任意の合理的な形態(例えば、数値や文字列のリストの配列)であってもよいです。小数値は、少なくとも小数点以下1桁までサポートする必要があります。重量パーセントの欠落は、一貫性のある明確な方法(0'?'またはnullなど)で表すことができます。あなたは、入力が常に有効なレシピに関連する(されると仮定することができます[70]し、[∅, ∅, 50]例えば、無効です)。
  • 出力は、(例えば、最小及び最大の重量百分率の両方のための1つのアレイ、又は二重の単一のリスト)は、任意の合理的な形態であり得ます。最小と最大のパーセントは、任意の順序であっても(ことができる[min, max][max, min]の両方許容可能です)。正確な重量の割合は、他の割合とは異なる方法で処理する必要はなく、等しい最小値と最大値で表すことができます。

標準ルール適用されます。コードを入力している間、私のパスタ皿は冷めているので、最短の提出が勝ちます。

この問題は一見しただけでは難しいため、ここではいくつかのケースの段階的な解決策を示します。

[40, ∅, ∅]

それぞれxy2つの不足している割合を呼び出しましょう。

  • 最初の成分の後に40%であるxため、40%を超えることはできません。
    [40, [?, 40], [?, ?]]
  • 2つの欠落している割合の合計は常に60%です。その結果:
    • 最大値をx取る場合、最小値を取るため、60%-40%= 20%になります。 y
      [40, [?, 40], [20, ?]]
    • 最小値をx取る場合、最大値を取ります。しかし、より低くすることはできませんyxy、この場合、x= y= 60%/ 2 = 30%です。
      [40, [30, 40], [20, 30]]

[70, ∅, ∅, 5, ∅]

のは、それぞれ呼ぶことにしましょうxyz3つの欠落している割合。

  • の最小および最大パーセンテージはz、必ず0%〜5%です。zしばらく= 0%と仮定しましょう。2つの欠落したパーセンテージの合計は常に25%です。その結果:
    [70, [?, ?], [?, ?], 5, [0, 5]]
    • yその最小限を取る場合値を、5%、次いで、xそのとる最大 5%= 20% -従って25%の値を、。
      [70, [?, 20], [5, ?], 5, [0, 5]]
    • 最大値をy取る場合、最小値を取る。しかし、より低くすることはできませんxxy、ので、この場合、x= y= 25%/ 2 = 12.5%です。
      [70, [12.5, 20], [5, 12.5], 5, [0, 5]]
  • ここでz= 5%と仮定した場合、すべてが正常であることを確認しましょう。欠落している2つの割合の合計は常に20%です。その結果:
    • yその最小限を取る場合5%の値をx最大値をとる 5%= 15% -従って20%の値を、。このケースは、以前に計算された範囲に既に含まれています。
    • 最大値をy取る場合、最小値を取る。しかし、より低くすることはできませんので、この場合、= = 20%/ 2 = 10%です。このケースは、以前に計算された範囲に既に含まれていますが、ではありません。 xxyxyyx
      [70, [10, 20], [5, 12.5], 5, [0, 5]]

テストケース

Input:  [∅]
Output: [100]

Input:  [70, 30]
Output: [70, 30]

Input:  [70, ∅, ∅]
Output: [70, [15, 30], [0, 15]]

Input:  [40, ∅, ∅]
Output: [40, [30, 40], [20, 30]]

Input:  [∅, ∅, 10]
Output: [[45, 80], [10, 45], 10]

Input:  [70, ∅, ∅, ∅]
Output: [70, [10, 30], [0, 15], [0, 10]]

Input:  [70, ∅, ∅, 5, ∅]
Output: [70, [10, 20], [5, 12.5], 5, [0, 5]]

Input:  [30, ∅, ∅, ∅, 10, ∅, ∅, 5, ∅, ∅]
Output: [30, [10, 25], [10, 17.5], [10, 15], 10, [5, 10], [5, 10], 5, [0, 5], [0, 5]]


3
物事をより明確にするために[40, ∅, ∅]、入力から出力への段階的な説明を追加し[70, ∅, ∅, 5, ∅]ます。テストケースを見ずに課題を明確にする必要がありますが、現在はそうではありません。私がそれを正しく理解している場合[40, ∅, ∅]:100%に60以上が必要で、これら2つに分けられます。最初の値は30以上でなければなりません(そうでない場合、2番目の値はそれより上になりますが、順番が揃っていれば不可能です)。さらに、それはを超えることはできない40ので、最初[30,40]になり、2番目はになり[(100-40-40=)20, (100-40-30=)30]ます。
ケビンクルーッセン

一貫して[min,max]/ [max,min]または混合が許可されていますか?
-l4m2

@ l4m2ミキシング[min,max][max,min]境界線は許容できますが、あいまいな結果につながることはないので、大丈夫だと思います。
ブラックホール

たぶん私は何かを逃していますが、なぜ[70, 12, 11, 5, 2]あなたの2番目の例ではうまくいかないのですか?動作する場合、の最小値はx未満です12.5
DLosc

回答:


11

JavaScript(ES6)、252バイト

0パーセンテージの欠落が予想されます。すべてのエントリの最小値と最大値のペアを返します。

a=>(g=a=>(h=(M,I,J=I^1)=>a.some((x,i)=>a.map((y,j)=>s-=j-i?M(j,i)-i?y[I]:M(w=y[I],z=x[J])-z||w==z?w:++k&&z:y[J],s=100,k=1,X=x)&&(I?-s:s)<0)?X[J]=M(X[I],X[J]+s/k):0)(Math.max,0)+h(Math.min,1)?g(a):a)(a.map((n,i)=>[n?p=n:a.find(n=>i--<0&&n)||0,p],p=100))

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

どうやって?

初期化

まず、入力配列a []の各値を可能な最大範囲に置き換えます。

a.map((n, i) =>       // for each value n at position i in a[]:
  [                   //   generate a [min, max] array:
    n ?               //     if n is not 0:
      p = n           //       use n as the minimum and save it in p
    :                 //     else:
      a.find(n =>     //       find the first value n
        i-- < 0 &&    //         which is beyond the current value
        n             //         and is not equal to 0
      ) || 0,         //       or use 0 as a default value
    p                 //     use p as the maximum
  ],                  //   end of array declaration
  p = 100             //   start with p = 100
)                     // end of map()

例:

[ 0 ] --> [ [ 0, 100 ] ]
[ 30, 0, 5, 0 ] --> [ [ 30, 30 ], [ 5, 30 ], [ 5, 5 ], [ 0, 5 ] ]

主な機能

主な関数はh()です。最小化または最大化しようとすると、矛盾しているように見える最初のエントリを探します。見つかった場合は、他の範囲を考慮して、少なくとも一時的に許容できる値に更新します。

入力としてM = Math.max / I = 0またはM = Math.min / I = 1取りJI XOR 1として定義します。

ので、H()は最小化及び最大化するパスの両方をサポートするように書かれたコードは、コメントに少し厄介です。そのため、M = Math.maxI = 0およびJ = 1の最大化パスのみに注目します。これらのパラメーターを使用すると、コードは次のようになります。

a.some((x, i) =>              // for each range x at position i in a[] (tested range):
  a.map((y, j) =>             //   for each range y at position j in a[] (reference range):
    s -=                      //     update s:
      j - i ?                 //       if i is not equal to j:
        Math.max(j, i) - i ?  //         if j > i:
          y[0]                //           the reference range is beyond the tested range
                              //           so we just use the minimum value of the y range
        :                     //         else:
          Math.max(           //           take the maximum of:
            w = y[0],         //             w = minimum value of the y range
            z = x[1]          //             z = maximum value of the x range
          ) - z ||            //           if it's not equal to z
          w == z ?            //           or they are equal (i.e. if w <= z):
            w                 //             use w
          :                   //           else:
            ++k && z          //             increment the counter k and use z
      :                       //       else:
        y[1],                 //         use the maximum value of the y range
    s = 100,                  //     start with s = 100
    k = 1,                    //     start with k = 1
    X = x                     //     save the range x in X
  ) &&                        //   end of map()
  (0 ? -s : s) < 0            //   abort if s < 0 (i.e. if we've subtracted more than 100)
) ?                           // end of some(); if truthy:
  X[1] = Math.max(            //   update the maximum value of the faulty range to:
    X[0],                     //     either the minimum value
    X[1] + s / k              //     or the maximum value, less the correction
  )                           //   whichever is greater
:                             // else:
  0                           //   do nothing

再帰

再帰関数g()は、最小化または最大化のいずれのパスでも新しい修正が行われないまでh ()を呼び出し続け、最終的に最終結果を返します。

g = a => h(Math.max, 0) + h(Math.min, 1) ? g(a) : a

うまくできました:-)!
ブラックホール

4
@Blackholeありがとう!ところで、私自身のパスタソースは読み取ります[38,0,10,0,0,0,0,0,0,0]
アーナウルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.