Có gì trong nước sốt mì ống của tôi?


37

Lý lịch

Ở Pháp, và có lẽ trong phần còn lại của Liên minh châu Âu, bất kỳ thực phẩm nào được bán phải liệt kê các thành phần cấu thành nó trên bao bì của nó, theo thứ tự tỷ lệ phần trăm giảm dần . Tuy nhiên, tỷ lệ chính xác không cần phải được chỉ định, trừ khi thành phần được tô sáng bằng văn bản hoặc hình ảnh trên trang bìa.

Ví dụ, sốt cà chua húng quế của tôi, chỉ hiển thị một số cà chua lớn màu đỏ và lá húng quế đẹp trên bao bì của nó, có các chỉ dẫn sau:

Thành phần: Cà chua 80%, hành tây thái miếng, húng quế 1,4%, muối biển, tỏi nghiền, đường mía thô, dầu ô liu nguyên chất, hạt tiêu đen.

Nghe có vẻ ngon, nhưng chính xác thì tôi sẽ ăn bao nhiêu hành tây ?

Thử thách

Đưa ra một danh sách tỷ lệ phần trăm trọng lượng theo thứ tự giảm dần, cuối cùng không đầy đủ, đưa ra một danh sách đầy đủ các tỷ lệ phần trăm tối thiểutối đa có thể tìm thấy trong công thức.

  • Bạn có thể viết một hàm hoặc một chương trình đầy đủ.
  • Đầu vào có thể ở bất kỳ dạng hợp lý nào (ví dụ, mảng số hoặc danh sách các chuỗi). Các giá trị phân số phải được hỗ trợ ít nhất đến một vị trí thập phân. Một tỷ lệ phần trăm thiếu có thể được biểu diễn theo bất kỳ cách nhất quán và rõ ràng nào ( ví dụ 0, '?'hoặc null, chẳng hạn). Bạn có thể giả định rằng đầu vào sẽ luôn được liên kết với một công thức hợp lệ ( chẳng hạn, [70][∅, ∅, 50]không hợp lệ).
  • Đầu ra có thể ở bất kỳ dạng hợp lý nào (ví dụ, một mảng cho cả hai tỷ lệ phần trăm trọng lượng tối thiểu và tối đa, hoặc một danh sách các bộ đôi, chẳng hạn). Tỷ lệ tối thiểu và tối đa có thể theo bất kỳ thứ tự nào ( [min, max][max, min]cả hai đều được chấp nhận). Tỷ lệ phần trăm chính xác không cần phải được xử lý khác với tỷ lệ phần trăm khác và có thể được biểu thị bằng các giá trị tối thiểu và tối đa bằng nhau.

Áp dụng quy tắc chuẩn cho : trong khi bạn đang nhập mã của mình, món mì ống của tôi đang nguội dần, vì vậy bài nộp ngắn nhất sẽ thắng.

Ví dụ

Vì vấn đề này khó hơn so với cái nhìn đầu tiên, đây là cách giải quyết từng bước của một vài trường hợp.

[40, ∅, ∅]

Hãy gọi tương ứng xyhai phần trăm bị thiếu.

  • Bởi vì nó xuất hiện sau thành phần đầu tiên ở mức 40%, xkhông thể cao hơn 40%.
    [40, [?, 40], [?, ?]]
  • Tổng của hai tỷ lệ phần trăm còn thiếu luôn là 60%. Hậu quả là :
    • Nếu xlấy giá trị tối đa của nó , thì ylấy giá trị tối thiểu của nó , do đó là 60% - 40% = 20%.
      [40, [?, 40], [20, ?]]
    • Nếu xlấy giá trị tối thiểu của nó , thì ylấy giá trị tối đa của nó . Nhưng xkhông thể thấp hơn y, vì vậy trong trường hợp này, x= y= 60% / 2 = 30%.
      [40, [30, 40], [20, 30]]

[70, ∅, ∅, 5, ∅]

Chúng ta hãy gọi tương ứng x, yzba phần trăm bị thiếu.

  • Tỷ lệ phần trăm tối thiểu và tối đa cho znhất thiết phải nằm trong khoảng từ 0% đến 5%. Giả sử z= 0% trong giây lát. Tổng của hai tỷ lệ phần trăm còn thiếu luôn là 25%. Hậu quả là :
    [70, [?, ?], [?, ?], 5, [0, 5]]
    • Nếu ylấy giá trị tối thiểu của nó , 5%, sau đó xlấy giá trị tối đa của nó , do đó là 25% - 5% = 20%.
      [70, [?, 20], [5, ?], 5, [0, 5]]
    • Nếu ylấy giá trị tối đa của nó , thì xlấy giá trị tối thiểu của nó . Nhưng xkhông thể thấp hơn y, vì vậy trong trường hợp này, x= y= 25% / 2 = 12,5%.
      [70, [12.5, 20], [5, 12.5], 5, [0, 5]]
  • Hãy xác minh rằng mọi thứ đều ổn nếu chúng ta giả sử bây giờ z= 5%. Tổng của hai phần trăm còn thiếu luôn là 20%. Hậu quả là :
    • Nếu ylấy giá trị tối thiểu của nó , 5%, sau đó xlấy giá trị tối đa của nó , do đó là 20% - 5% = 15%. Trường hợp này đã được bao gồm trong phạm vi tính toán trước đó.
    • Nếu ylấy giá trị tối đa của nó , thì xlấy giá trị tối thiểu của nó . Nhưng xkhông thể thấp hơn y, vì vậy trong trường hợp này, x= y= 20% / 2 = 10%. Trường hợp này đã được bao gồm trong phạm vi tính toán trước đó y, nhưng không phải cho x.
      [70, [10, 20], [5, 12.5], 5, [0, 5]]

Các trường hợp thử nghiệm

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
Tôi sẽ thêm một lời giải thích từng bước về đầu vào-đầu ra cho [40, ∅, ∅][70, ∅, ∅, 5, ∅]để làm cho mọi thứ rõ ràng hơn một chút. Một thách thức nên rõ ràng mà không cần nhìn vào các trường hợp thử nghiệm, đó không phải là trường hợp ngay bây giờ. Nếu tôi hiểu chính xác cho [40, ∅, ∅]: 60 nhiều hơn là cần thiết cho 100%, chia cho hai . Cái đầu tiên phải từ 30 trở lên (nếu không cái thứ hai sẽ ở trên nó, điều này không thể thực hiện được khi chúng theo thứ tự). Ngoài ra, nó không thể ở trên 40, vì vậy cái đầu tiên trở thành [30,40], và cái thứ hai trở thành [(100-40-40=)20, (100-40-30=)30].
Kevin Cruijssen

Liên tục [min,max]/ [max,min]hoặc cho phép hỗn hợp?
l4m2

@ l4m2 Trộn [min,max][max,min]là đường biên chấp nhận được, nhưng vì nó không thể dẫn đến kết quả mơ hồ, tôi nói rằng nó ổn.
Hố đen

Có thể tôi đang thiếu một cái gì đó, nhưng tại sao nó [70, 12, 11, 5, 2]không hoạt động cho ví dụ thứ hai của bạn? Nếu nó hoạt động, tối thiểu cho xsẽ ít hơn 12.5.
DLosc

Câu trả lời:


11

JavaScript (ES6), 252 byte

Mong 0đợi cho tỷ lệ phần trăm bị thiếu. Trả về một cặp giá trị tối thiểu và tối đa cho tất cả các mục.

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

Hãy thử trực tuyến!

Làm sao?

Khởi tạo

Trước tiên chúng tôi thay thế từng giá trị trong mảng đầu vào a [] bằng phạm vi lớn nhất có thể.

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

Ví dụ:

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

Chức năng chính

Hàm chính là h () . Nó tìm kiếm mục đầu tiên dường như không nhất quán khi chúng tôi cố gắng giảm thiểu hoặc tối đa hóa nó. Nếu nó tìm thấy một, nó cập nhật nó thành một giá trị ít nhất là tạm thời chấp nhận được, với các phạm vi khác.

Nó nhận đầu vào là M = Math.max / I = 0 hoặc M = Math.min / I = 1 và định nghĩa JI XOR 1 .

h () được viết để hỗ trợ cả việc truyền tối thiểu hóa và tối đa hóa, nên mã này hơi khó để nhận xét. Đó là lý do tại sao chúng tôi sẽ chỉ tập trung vào đường chuyền tối đa hóa mà chúng tôi có M = Math.max , I = 0J = 1 . Với các tham số này, mã đọc như sau:

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

Đệ quy

Hàm đệ quy g () tiếp tục gọi h () cho đến khi không vượt quá hoặc tối đa hóa vượt qua dẫn đến một sự điều chỉnh mới và cuối cùng trả về kết quả cuối cùng.

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

Hoàn thành tốt :-)!
Hố đen

4
@Blackhole Cảm ơn! Và BTW: nước sốt mì ống của riêng tôi đọc [38,0,10,0,0,0,0,0,0,0].
Arnauld
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.