Makarna sosumda ne var?


37

Arka fon

Fransa'da, ve muhtemelen Avrupa Birliği, satılmaya hazır herhangi gıda geri kalanında gerekir yılında, ambalajının üzerinde bu oluştururlar maddeler listesinde ağırlık yüzdesi azalan sırayla . Bununla birlikte, kesin yüzdesi , belirtilen olmak zorunda değildir sürece bileşen kaplama üzerinde bir metin ya da görüntü ile vurgulanır.

Örneğin, fesleğen domates sosu, sadece büyük kırmızı domatesler ve güzel fesleğen yaprakları ambalajında ​​gösteren, aşağıdaki belirtilere sahiptir:

İçindekiler: Domates% 80, adet soğan, fesleğen% 1.4, deniz tuzu, sarımsak püresi, çiğ şeker kamışı, sızma zeytinyağı, karabiber.

Kulağa lezzetli geliyor, ama… tam olarak ne kadar soğan yiyeceğim ?

Meydan okuma

Azalan sıradaki ağırlık yüzdelerinin bir listesi göz önüne alındığında, nihayetinde eksik, tarifte bulunabilecek asgari ve azami ağırlık yüzdelerinin tam bir listesini çıkar .

  • Bir işlev veya tam bir program yazabilirsiniz.
  • Giriş herhangi bir makul biçimde (örneğin, sayı veya karakter dizileri listesinin dizisi) olabilir. Kesirli değerler en az bir ondalık basamağa desteklenmelidir. Eksik bir ağırlık yüzdesi (bir tutarlı ve kesin bir şekilde temsil edilebilir 0, '?'ya da nullörneğin,). Sen girdi daima geçerli bir reçeteye ilişkilendirilir (varsayabiliriz [70]ve [∅, ∅, 50]örneğin geçersiz edilir).
  • Çıkış herhangi bir makul biçimde (örneğin, minimal ve maksimal ağırlık yüzdeleri ya da çifti tek bir liste her ikisi için bir dizi) olabilir. Minimum ve maksimum yüzdeler herhangi bir sırada olabilir ( [min, max]ve [max, min]her ikisi de kabul edilebilir). Tam ağırlık yüzdelerinin, diğer yüzdelere göre farklı şekilde işlenmesi gerekmez ve eşit minimum ve maksimum değerlerle temsil edilebilir.

için standart kurallar geçerlidir: kodunuzu yazarken, makarna tabağım soğuyor, bu yüzden en kısa sürede gönderim kazanıyor.

Örnekler

Bu problem ilk bakışta göründüğünden daha zor olduğu için, işte birkaç vakanın adım adım çözümü.

[40, ∅, ∅]

Sırasıyla xve yiki eksik yüzdeyi arayalım .

  • Çünkü% 40'taki ilk bileşenden sonra geliyor,% x40'tan fazla olamaz.
    [40, [?, 40], [?, ?]]
  • İki eksik yüzeyin toplamı her zaman% 60'tır. Sonuç olarak:
    • Eğer xkendi alan maksimum değer, ardından yda alır az = 20% 40% - bu nedenle% 60 değeri.
      [40, [?, 40], [20, ?]]
    • Eğer xonun alır minimum değer, ardından yda alır maksimal değer. Fakat xbundan daha düşük olamaz y, bu durumda, x= y=% 60/2 =% 30.
      [40, [30, 40], [20, 30]]

[70, ∅, ∅, 5, ∅]

En sırasıyla diyelim x, yve züç kayıp yüzdeleri.

  • Minimum ve maksimum yüzdeler zmutlaka% 0 ile% 5 arasındadır. zBir an için = 0% varsayalım . İki eksik yüzeyin toplamı her zaman% 25'tir. Sonuç olarak:
    [70, [?, ?], [?, ?], 5, [0, 5]]
    • Eğer ykendi alan en az bir değer,% 5, sonra xda sürer maksimum = 20% 5% - bu nedenle% 25 değeri.
      [70, [?, 20], [5, ?], 5, [0, 5]]
    • Eğer yonun alır maksimal değer, ardından xda alır minimum değerini. Fakat xbundan daha düşük olamaz y, bu durumda, x= y=% 25/2 =% 12,5.
      [70, [12.5, 20], [5, 12.5], 5, [0, 5]]
  • Şimdi z% = 5 olduğunu kabul edersek her şeyin yolunda olduğunu doğrulayalım . İki eksik yüzeyin toplamı her zaman% 20'dir. Sonuç olarak:
    • Eğer ykendi alan en az bir değer,% 5, sonra xda sürer maksimum = 15% 5% - bu nedenle% 20 değeri. Bu dava daha önce hesaplanan aralıklara dahil edilmiştir.
    • Eğer yonun alır maksimal değer, ardından xda alır minimum değerini. Fakat xbundan daha düşük olamaz y, bu durumda, x= y= 20% / 2 = 10%. Bu dava için önceden hesaplanmış olan aralığa zaten dahil edilmiştir y, ancak için değildir x.
      [70, [10, 20], [5, 12.5], 5, [0, 5]]

Test durumları

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
Ben için girdi-çıkış bir adım-adım açıklama eklersiniz [40, ∅, ∅]ve [70, ∅, ∅, 5, ∅]biraz daha net yapmak şeyler. Test davalarına bakmadan, şu anki durum böyle olmayan bir zorluk net olmalı. Bunu doğru bir şekilde anlarsam [40, ∅, ∅]:% 100 için bu daha fazlasına bölünmüş% 60 daha gereklidir . Birincisi 30 veya daha yüksek olmalıdır (aksi halde ikincisi bunun üzerinde olacaktır, bu sırada sırayla mümkün olmamalıdır). Ek olarak, yukarıda olamaz 40, yani ilk olur [30,40]ve ikinci olur [(100-40-40=)20, (100-40-30=)30].
Kevin Cruijssen

Tutarlı [min,max]/ [max,min]veya karışık izin verilir?
l4m2

@ L4m2 Karıştırma [min,max]ve [max,min]sınırda kabul edilebilir, ancak belirsiz sonuçlara yol açamadığından , tamam olduğunu söyleyebilirim.
Karadelik

Belki bir şeyleri özlüyorum, ama neden [70, 12, 11, 5, 2]ikinci örnek için çalışmıyor ? İşe yararsa, asgari xolandan daha az olacaktır 12.5.
DLosc

Yanıtlar:


11

JavaScript (ES6), 252 bayt

Bekliyor 0yüzdeleri eksik. Tüm girişler için bir çift minimum ve maksimum değer döndürür.

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

Çevrimiçi deneyin!

Nasıl?

Başlatma

Öncelikle a [] giriş dizisindeki her bir değeri mümkün olan en geniş aralık ile değiştirdik.

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

Örnekler:

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

Ana işlev

Ana işlev h () 'dir . Küçültmeyi veya büyütmeyi denediğimizde tutarsız görünen ilk girişi arar. Bir tanesini bulursa, diğer aralıkları göz önüne alındığında, en azından geçici olarak kabul edilebilir bir değere günceller.

Girdi olarak M = Math.max / I = 0 veya M = Math.min / I = 1 değerini alır ve J'yi I XOR 1 olarak tanımlar .

Çünkü s () her ikisi de en aza indirmek ve en üst düzeye geçişleri desteklemek için yazılmış kod açıklama biraz zordur. Bu yüzden M = Math.max , I = 0 ve J = 1 değerlerine sahip olduğumuz sadece büyütme geçidine odaklanacağız . Bu parametrelerle kod aşağıdaki gibi okunur:

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

özyineleme

Özyinelemeli g () işlevi , küçültme veya büyütme geçişi yeni bir düzeltmeye yol açmadıkça h () işlevini sürdürür ve sonunda nihai sonucu döndürür.

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

Güzel bitti :-)!
Karadelik

4
@ Blackhole Teşekkürler! BTW: Kendi makarna sosum okuyor [38,0,10,0,0,0,0,0,0,0].
Arnauld
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.