ซอสพาสต้าของฉันคืออะไร


37

พื้นหลัง

ในประเทศฝรั่งเศสและอาจจะอยู่ในส่วนที่เหลือของสหภาพยุโรปอาหารใดมีไว้เพื่อขายต้องแสดงรายการส่วนผสมที่เขียนไว้บนบรรจุภัณฑ์ของตนในน้ำหนักร้อยละหลั่น อย่างไรก็ตามไม่จำเป็นต้องระบุเปอร์เซ็นต์ที่แน่นอนยกเว้นว่ามีการเน้นส่วนประกอบโดยข้อความหรือรูปภาพบนหน้าปก

ตัวอย่างเช่นซอสมะเขือเทศใบโหระพาของฉันที่แสดงเพียงมะเขือเทศสีแดงขนาดใหญ่และใบโหระพาที่สวยงามบนบรรจุภัณฑ์มีข้อบ่งชี้ดังนี้:

ส่วนผสม:มะเขือเทศ 80%, หัวหอมเป็นชิ้น, ใบโหระพา 1.4%, เกลือทะเล, กระเทียมบด, น้ำตาลทรายดิบ, น้ำมันมะกอกบริสุทธิ์พิเศษ, พริกไทยดำ

ฟังดูน่าอร่อย แต่ ... ฉันจะกินหัวหอมมากขนาดไหนกันแน่?

ท้าทาย

เมื่อกำหนดรายการเปอร์เซ็นต์น้ำหนักตามลำดับจากมากไปหาน้อยในที่สุดก็ไม่สมบูรณ์ส่งออกรายการที่สมบูรณ์ของเปอร์เซ็นต์น้ำหนักขั้นต่ำและสูงสุดที่สามารถพบได้ในสูตร

  • คุณสามารถเขียนฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบ
  • การป้อนข้อมูลจะมีรูปแบบที่เหมาะสมใด ๆ (อาร์เรย์ของตัวเลขหรือรายการของสตริงเป็นต้น) ค่าเศษส่วนควรได้รับการสนับสนุนอย่างน้อยหนึ่งตำแหน่งทศนิยม ร้อยละของน้ำหนักที่หายไปสามารถแสดงในลักษณะที่สอดคล้องและโปร่งใสใด ๆ ( 0, '?'หรือnullเป็นต้น) คุณสามารถสันนิษฐานได้ว่าการป้อนข้อมูลจะเชื่อมโยงกับสูตรที่ถูกต้องเสมอ ( [70]และ[∅, ∅, 50]ไม่ถูกต้องเป็นต้น)
  • การส่งออกจะมีรูปแบบที่เหมาะสมใด ๆ (หนึ่งอาร์เรย์สำหรับทั้งสองน้อยที่สุดและมากสุดร้อยละน้ำหนักหรือรายการเดียวของ doublets เป็นต้น) เปอร์เซ็นต์ขั้นต่ำและสูงสุดสามารถอยู่ในลำดับใดก็ได้ ( [min, max]และ[max, min]ยอมรับได้ทั้งคู่) เปอร์เซ็นต์น้ำหนักที่แน่นอนไม่จำเป็นต้องประมวลผลแตกต่างจากเปอร์เซ็นต์อื่น ๆ และอาจแสดงด้วยค่าน้อยที่สุดและสูงสุดเท่ากัน

ใช้กฎมาตรฐานสำหรับการเขียน : ขณะที่คุณพิมพ์รหัสจานพาสต้าของฉันเย็นลงดังนั้นการส่งที่สั้นที่สุดจะเป็นผู้ชนะ

ตัวอย่าง

เนื่องจากปัญหานี้ยากเกินกว่าที่จะเห็นได้อย่างรวดเร็วในครั้งแรกนี่เป็นวิธีแก้ปัญหาแบบทีละขั้นตอนของบางกรณี

[40, ∅, ∅]

ลองโทรตามลำดับxและyเปอร์เซ็นต์ที่หายไปสองอัน

  • เพราะมันมาจากส่วนผสมแรกที่ 40% xจึงไม่สามารถสูงกว่า 40% ได้
    [40, [?, 40], [?, ?]]
  • ผลรวมของเปอร์เซ็นต์ที่ขาดหายไปสองรายการนั้นจะเท่ากับ 60% เสมอ ดังนั้น:
    • หากxใช้ค่าสูงสุดมันก็yจะใช้ค่าน้อยที่สุดซึ่งเป็น 60% - 40% = 20%
      [40, [?, 40], [20, ?]]
    • หากxใช้ค่าน้อยที่สุดyจะรับค่าสูงสุด แต่xต้องไม่ต่ำกว่าyดังนั้นในกรณีนี้x= y= 60% / 2 = 30%
      [40, [30, 40], [20, 30]]

[70, ∅, ∅, 5, ∅]

ขอเรียกตามลำดับx, yและzสามเปอร์เซ็นต์ที่ขาดหายไป

  • เปอร์เซ็นต์น้อยที่สุดและสูงสุดสำหรับzจำเป็นต้องอยู่ระหว่าง 0% ถึง 5% สมมติว่าz= 0% สักครู่ ผลรวมของเปอร์เซ็นต์ที่ขาดหายไปสองรายการนั้นเป็น 25% เสมอ ดังนั้น:
    [70, [?, ?], [?, ?], 5, [0, 5]]
    • หากyใช้ค่าต่ำสุด 5% ก็xจะใช้ค่าสูงสุดซึ่งก็คือ 25% - 5% = 20%
      [70, [?, 20], [5, ?], 5, [0, 5]]
    • หากyใช้ค่าสูงสุดxมันจะใช้ค่าน้อยที่สุด แต่xต้องไม่ต่ำกว่าyดังนั้นในกรณีนี้x= y= 25% / 2 = 12.5%
      [70, [12.5, 20], [5, 12.5], 5, [0, 5]]
  • เรามาตรวจสอบว่าทุกอย่างเรียบร้อยดีถ้าเราสมมติว่านั่นz= 5% ผลรวมของเปอร์เซ็นต์ที่ขาดหายไปสองรายการนั้นมีค่า 20% เสมอ ดังนั้น:
    • หากyใช้ค่าต่ำสุด 5% ก็xจะใช้ค่าสูงสุดซึ่งเป็น 20% - 5% = 15% กรณีนี้รวมอยู่ในช่วงการคำนวณก่อนหน้านี้แล้ว
    • หากyใช้ค่าสูงสุดxมันจะใช้ค่าน้อยที่สุด แต่xต้องไม่ต่ำกว่าyดังนั้นในกรณีนี้x= y= 20% / 2 = 10% กรณีนี้จะรวมอยู่แล้วในช่วงก่อนหน้านี้สำหรับการคำนวณแต่ไม่ได้สำหรับ yx
      [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, ∅, ∅]: 60 จำเป็นสำหรับอีก 100% หารด้วยสองคนนี้ รายการแรกจะต้องมี 30 หรือสูงกว่า (ไม่เช่นนั้นรายการที่สองจะอยู่เหนือซึ่งไม่น่าจะเป็นไปได้เมื่ออยู่ในลำดับ) นอกจากนี้ยังไม่สามารถจะอยู่เหนือ40ดังนั้นคนแรกที่กลายเป็นและที่สองกลายเป็น[30,40] [(100-40-40=)20, (100-40-30=)30]
Kevin Cruijssen

อนุญาตอย่างสม่ำเสมอ[min,max]/ [max,min]หรือผสมกัน?
l4m2

@ l4m2 การผสม[min,max]และ[max,min]ยอมรับได้ในแนวเขต แต่เนื่องจากมันไม่สามารถนำไปสู่ผลลัพธ์ที่คลุมเครือได้ฉันจึงบอกว่าไม่เป็นไร
Blackhole

บางทีฉันอาจพลาดบางอย่าง แต่ทำไม[70, 12, 11, 5, 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 () ดูเหมือนว่ารายการแรกที่ดูเหมือนจะไม่สอดคล้องกันเมื่อเราพยายามย่อหรือขยายให้ใหญ่สุด หากพบหนึ่งรายการจะอัปเดตเป็นค่าที่ยอมรับอย่างน้อยเป็นการชั่วคราวโดยกำหนดช่วงอื่น ๆ

มันต้องใช้เวลาเป็น input ทั้งM = Math.max / i = 0หรือM = Math.min / i = 1และกำหนดJเป็นผมแฮคเกอร์ 1

เนื่องจากh ()ถูกเขียนขึ้นเพื่อรองรับทั้งการย่อขนาดและการย่อขนาดสูงสุดรหัสจึงค่อนข้างยุ่งยากในการแสดงความคิดเห็น นั่นเป็นเหตุผลที่เราจะมุ่งเน้นไปที่การเพิ่มผ่านเท่านั้นที่เรามีM = Math.max , i = 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

recursion

ฟังก์ชั่นวนซ้ำg ()ยังคงเรียกh ()ต่อไปจนกระทั่งไม่มีการย่อขนาดหรือการขยายให้ใหญ่สุดจะนำไปสู่การแก้ไขใหม่และในที่สุดก็ส่งกลับผลลัพธ์สุดท้าย

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

ทำได้ดีมาก :-)!
Blackhole

4
@Blackhole ขอบคุณ! และ BTW: [38,0,10,0,0,0,0,0,0,0]ซอสพาสต้าของตัวเองอ่าน
Arnauld
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.