คำนวณความสูงของชามกอง


19

ชามกองสูง

เป้าหมายของปริศนานี้คือการคำนวณความสูงของชามที่ซ้อนกัน

กองชาม

ชามถูกกำหนดให้เป็นอุปกรณ์ที่มีความสมมาตรเรดิอเรย์โดยไม่มีความหนา รูปร่างเงาของมันคือพหุนามแม้ สแต็กถูกอธิบายโดยรายการรัศมีซึ่งแต่ละอันเกี่ยวข้องกับพหุนามแบบคู่ให้เป็นอินพุตเป็นรายการของสัมประสิทธิ์ (เช่นรายการ3.1 4.2แทนพหุนาม3.1x2+4.2x4 )

พหุนามอาจมีระดับโดยพลการ สำหรับความเรียบง่ายความสูงของกองถูกกำหนดให้เป็นระดับความสูงของศูนย์กลางของชามบนสุด (ดูพล็อตของตัวอย่างที่ 3 สำหรับภาพประกอบ)

กรณีทดสอบอยู่ในรูปแบบradius:coeff1 coeff2 ...: แต่ละบรรทัดเริ่มต้นด้วยเลขทศนิยมแทนรัศมีของชามตามด้วยเครื่องหมายโคลอนและรายการที่คั่นด้วยช่องว่างที่มีค่าสัมประสิทธิ์สำหรับกำลังคู่เริ่มต้นด้วยพลังงาน 2 (โดยนัยคงที่ส่วนศูนย์) . ยกตัวอย่างเช่นเส้น2.3:3.1 4.2อธิบายชามรัศมีและรูปร่างพหุนาม2.33.1 * x^2 + 4.2 * x^4

ตัวอย่างที่ 1

42:3.141

อธิบายถึงกองที่มีความสูงเป็นศูนย์เนื่องจากชามเดี่ยวไม่มีความสูง

ตัวอย่างที่ 2

1:1 2
1.2:5
1:3

อธิบายความสูง2.0(ดูรูปประกอบ)

พล็อตของกองสามชาม

ตัวอย่างที่ 3

1:1.0
0.6:0.2
0.6:0.4
1.4:0.2
0.4:0 10

อธิบายความสูง 0.8 (ดูที่ลูกศรสีเขียวในพล็อต)

พล็อตของกองสามชาม

นี่คือรหัสกอล์ฟดังนั้นรหัสที่สั้นที่สุดชนะ

ฉันมีรหัสอ้างอิง

แก้ไข:

การประยุกต์ใช้การอ้างอิงอาศัยไลบรารีเพื่อคำนวณรากของพหุนาม คุณสามารถทำเช่นนั้นได้ แต่ไม่จำเป็นต้องทำ เนื่องจากการดำเนินการอ้างอิงเป็นเพียงการประมาณเชิงตัวเลข (ค่อนข้างดี) ฉันจะยอมรับรหัสใด ๆ ที่สร้างผลลัพธ์ที่ถูกต้องภายในความคลาดเคลื่อนจุดลอยตัวทั่วไป

<ε ε

อีกตัวแปรหนึ่งของปริศนานี้คือการลดความสูงโดยการเรียงลำดับโบวล์ ฉันไม่แน่ใจว่ามีวิธีแก้ปัญหาที่รวดเร็วหรือไม่ หากใครมีความคิดที่ดีกว่า (หรือสามารถพิสูจน์ความสมบูรณ์แบบของ NP) ได้โปรดบอกฉัน!


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Mego

ในรหัสอ้างอิงของคุณผมเชื่อว่าร่างกายของที่ควรจะเป็นเช่นis_maximum return evaluate(differentiate(shape_0), root) > 0.0ขณะนี้มันประเมินการใช้รูทdd(อนุพันธ์ของความแตกต่างระหว่างรูปร่าง) ซึ่งควรส่งคืน 0 เสมอ (สำหรับรูท) เนื่องจากข้อผิดพลาดของคะแนนลอยบางครั้งผลลัพธ์จึงเป็นค่าบวกใกล้กับ 0 ซึ่งเป็นสาเหตุที่รหัสส่งออกผลลัพธ์ที่ถูกต้องหรือแม่นยำกว่าในบางครั้ง ตรวจสอบอินพุต1:0.2, 1:0.1 0.2ที่ควรเอาต์พุต0.0125
ความซ้ำซ้อน

@ ความซ้ำซ้อนมันซ้ำซ้อนจริง ๆ อยู่แล้ว ค่าสูงสุดของ y ถูกเลือกและ 0 จะอยู่ในค่าเปรียบเทียบเสมอ
Nick Kennedy

2
ในตัวอย่าง 3 0.801ความสูงสุดท้ายที่ควรจะเป็น 0.1สุดท้ายทั้งสองชามสัมผัสที่รัศมี
attinat

ใช่ฉันได้รับผลลัพธ์เดียวกัน
โจเอล

คำตอบ:


6

เจลลี่ , 54 53 ไบต์

J×$ÆrAƑƇ«⁹;⁹*€J{ḋ⁸ŻṀ
Œcz€0ḢṂç@I0;ⱮFƲƲ€ṚṁL’R€Ɗ;+Ṁ¥¥ƒ0Ṁ

ลองออนไลน์!

ลิงก์ monadic ที่รับอาร์กิวเมนต์เป็นรายการโบลิ่งจากบนลงล่างในรูปแบบ[[b1_radius, b1_coef1, ...], [b2_radius, b2_coef1, ...]]และส่งคืนตำแหน่ง y ของด้านล่างของชามด้านบน

ตอนนี้จัดการกับโบลิ่งได้อย่างถูกต้องที่พบในสถานที่อื่นนอกเหนือจากรัศมีน้อยที่สุด

คำอธิบาย

ตัวช่วยลิงก์: ใช้อาร์กิวเมนต์ซ้ายlเป็นความแตกต่างของสัมประสิทธิ์ของพหุนามที่แสดงถึงโบลิ่งตั้งแต่ 1 ขึ้นไปและอาร์กิวเมนต์ที่ถูกต้องrคือรัศมีต่ำสุด ส่งคืนค่า y สูงสุดที่ทั้งสองโบลว์พบ

  $                   | Following as a monad:
J                     | - Sequence from 1..<len(l)>
 ×                    | - Multiply (by l)
   Ær                 | Roots of polynomial
     AƑƇ              | Keep only those invariant when passed through absolute function (excludes negative, imaginary and complex numbers)
        «⁹            | Min of these filtered roots and r
          ;⁹          | Concatenate r to the list
            *€        | Each root/radius to the power of:
              J{      | - Sequence from 1..<len(l)>
                ḋ⁸    | Dot product with l
                  Ż   | Prepend zero
                   Ṁ  | Maximum

ลิงก์หลักใช้เสาเข็มเป็นอาร์กิวเมนต์และส่งคืนค่า y ของฐานของชามด้านบน

Œc                               | Combinations length 2
  z€0                            | Transpose each using 0 as a filler
               Ʋ€                | For each one, do the following as a monad:
     Ḣ                           | - Take the head (the radii)     
      Ṃ                          | - Minimum
       ç@     Ʋ                  | - Call the helper link with this (min radius) as right argument and the following as left argument:
         I                       |   - Increments (difference between second and first polynomial for each coefficient)
          0;Ɱ                    |   - Prepend each with a zero (odd coefficients are all zero)
             F                   |   - Flatten
                 Ṛ               | Reverse
                  ṁ    Ɗ         | Mould to the following as a monad:
                   L             | Length
                    ’            | Decrease by 1
                     R€          | Range of each (e.g. [1],[1,2],[1,2,3],[1,2,3,4]
                            ¥ƒ0  | Reduce using the following as a dyad and starting with 0
                        ;  ¥     | - Concatenate the following as a dyad
                         +       |   - Add
                          Ṁ      |   - Take the maximum
                               Ṁ | Finally take the overall maximum

Python อ้างอิง

ในที่สุดนี่คือเวอร์ชัน PIO ของการอ้างอิง Python ที่ @pasbi รวมไว้สำหรับปัญหาหลัก มันอ่านจาก stdin


1
ฉันไม่เข้าใจภาษาเลย จากคำอธิบายดูเหมือนว่าคุณจะเปรียบเทียบแต่ละคู่ของชาม(r1, p1)และ(r2, p2)ที่จุดเท่านั้นmin(r1, r2)หรือไม่ ถ้าเป็นเช่นนั้นที่จะเป็นทางออกที่ผิดเพราะสองชามสามารถสัมผัสระหว่างและ0 min(r1, r2))คุณต้องไปหาmax(p1(x)-p2(x), 0)ในช่วงทั้งสำหรับ[0, min(r1, r2)] xนั่นคือเหตุผลที่โซลูชั่นการอ้างอิงของ @ pasbi คำนวณอนุพันธ์สำหรับการค้นหาสูงสุดในท้องถิ่น
โจเอล

@Joel แก้ไขแล้ว min(r1, r2)ทั้งหมดของกรณีทดสอบเดิมสัมผัส ตอนนี้สามารถแก้ไขความท้าทายเพิ่มเติมของ @ attinat ได้
Nick Kennedy

1
มันจะเป็นการดีถ้าได้เห็นโค้ดแสดงความคิดเห็นสำหรับผู้ที่ไม่มีความรู้ภาษากอล์ฟถ้าคุณมีเวลา
โจเอล

@Joel จะทำอย่างไรเมื่อฉันมีเวลา
นิคเคนเนดี

2

Python 3 + numpy + scipy, 248 240 bytes

from scipy.optimize import*
from numpy import*
def f(b,i=0):
 for r,c in b:p=zeros(2*len(c)+1);p[-3::-2]=c;p[-1]=h=max([0,*(-fminbound(lambda x:polyval(polysub(p,d),x),0,min(s,r),full_output=1)[1]for s,d in b[:i])]);b[i][1]=p;i+=1
 return h

ลองออนไลน์!

-8 ไบต์ขอบคุณ @xnor

ฟังก์ชั่นใช้รายการ[radius, polynomial]คู่เป็นอินพุตและส่งคืนความสูงของเสาเข็ม

โซลูชันนี้ใช้อัลกอริทึมเดียวกันมากกว่าหรือน้อยกว่าในรหัสอ้างอิงยกเว้นว่าจะไม่คำนวณค่าสูงสุดโดยใช้อนุพันธ์ ในขณะเดียวกันมันเขียนโดยใช้ในตัวnumpyและscipyฟังก์ชั่นใน Python เวอร์ชั่นที่ไม่ได้แสดงจะแสดงดังต่อไปนี้ สิ่งนี้ทำหน้าที่เป็นรหัสอ้างอิงทางเลือกสำหรับผู้ที่ต้องการรุ่นที่สั้นกว่าเพื่อจับความคิดได้อย่างรวดเร็ว

from scipy.optimize import fminbound
import numpy as np

def compute_pile_height(bowl_data):
    for i, (r, curve) in enumerate(bowl_data):
        distances = [0]  # Initialize the distances array with 0 as the lower bound for max
        # Construct a complete polynominal coefficient array
        curve_poly = np.zeros(2 * len(curve) + 1)
        curve_poly[-3::-2] = curve
        
        # Iterate over all bowls under the current bowl
        for j in range(i):
            b_r, b_curve_poly = bowl_data[j]

            # Calculate the difference polynominal between the current bowl and bowl j
            diff = np.polysub(curve_poly, b_curve_poly)

            # Find the maximum height difference between bowl j and the current bowl in the range [0, min(b_r, r)]
            max_height_diff = -fminbound(lambda x:np.polyval(diff, x), 0, min(b_r, r), full_output=True)[1]
            distances.append(max_height_diff)

        # Compute the maximum distance as the height for the current bowl, 
        # update the polynominal using the height as the constant coefficient
        curve_poly[-1] = height = max(distances)

        # Update stored data for the current bowl
        bowl_data[i][1] = curve_poly
    return height

ลองออนไลน์!


หากต้องการบันทึกในช่องว่างคุณสามารถใส่ทั้งวงในบรรทัดหลังโคลอนและใส่i=0เป็นอาร์กิวเมนต์ตัวเลือก
xnor

@xnor Ah ขอบคุณ ฉันไม่ได้ใช้ความพยายามมากเกินไปในการตีกอล์ฟนี้เพราะการบันทึกสองสามไบต์ในโซลูชัน 200 + ไบต์จะไม่เปลี่ยนแปลงมากนัก และดูเหมือนว่าไม่มีอัลกอริทึมที่ดีกว่าสำหรับอันนี้ที่สามารถทำให้การคำนวณง่ายขึ้นมาก
โจเอล

เทคนิคนี้ควรอธิบายในส่วนหัวเป็น Python3 + numpy + sympy เนื่องจากไม่มีส่วนหนึ่งของการติดตั้ง Python3 พื้นฐาน
Nick Kennedy

@NickKennedy ขอบคุณ อัปเดตคำอธิบายแล้ว
Joel

1

ภาษา Wolfram (Mathematica) , 104 93 ไบต์

FoldPair[{(R=#;F=#2)&@@#2;H=Max[0,{#2-F,0<x<#~Min~R}~MaxValue~x&@@@#],#~Join~{R|H+F}}&,{},#]&

ลองออนไลน์!

{radius, polynomial}x

สำหรับทศนิยมแทนเอาต์พุตสัญลักษณ์ใช้NMaxValueแทน (หรือเพียงแค่เรียกNผลลัพธ์)

(* Step through a list of bowls: *)
(* At each step, calls a function taking {previous-bowls-list},current-bowl *)
(*  which returns {height,{bowls-list}} *)
(* and returns the final height *)
FoldPair[
  (R=#;F=#2)&@@#2;          (*  extract Radius and Function*)
  {
    H=Max[0,                (*  Height - at least zero; the greatest of *)
      MaxValue[{#2-F,       (*   the required heights *)
          0<x<#~Min~R},x]   (*     within the relevant domain *)
      &@@@#]                (*   given all previous bowls *)
  ,
    #~Join~{R|H+F}          (*   append to list of bowls *)
  }&,
  {},                       (* initial list of bowls (empty) *)
  #                         (* list of bowls *)
]&

1

R , 451 436 ไบต์

function(x){x=c(x[1],x);a=rev(pmax(0,c(combn(x,2,function(y,z=sapply(y,"length<-",max(lengths(y)))){z[is.na(z)]=0
b=rep(0,2*(n=nrow(z)-1))
b[2*1:n]=e=z[-1,2]-z[-1,1]
b=b*1:(2*n)
while(!c(b,1)[1])b=b[-1]
b=rev(b)
s=`if`(length(b)>1,eigen(rbind(-(b/b[1])[-1],cbind(diag(length(b)-2),0)))$va,0)
max(outer(c(pmin(abs(s[s==abs(s)]),r<-min(z[1,])),r),2*1:n,`^`)%*%e)}))))
o={}
for(i in seq(a=x[-1])){o=c(o,max(c(0,o)+a[1:i+F]));F=F+i}
max(o)}

ลองออนไลน์!

ลองออนไลน์!

พูดกว้างพอร์ต R ของคำตอบ Jelly ฉันแม้ว่าตั้งแต่ฐาน R polynom::solve.polynomialมีฟังก์ชั่นเพื่อหารากของพหุนามนี้ไม่มีการดำเนินการโดยใช้วิธีการที่พบใน

ฟังก์ชั่นรับรายการของเวกเตอร์ตัวเลขจากบนลงล่างของกอง

ขอบคุณ @RobinRyder สำหรับการเล่นกอล์ฟขนาด 15 ไบต์!


ผมไม่เข้าใจว่าทุกอย่างที่เกิดขึ้นที่นี่ (คำอธิบายจะดี!) แต่ที่นี่เป็นรุ่น 436 ไบต์
Robin Ryder
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.