Tính chiều cao của cọc Pile


19

Chiều cao cọc bát

Mục tiêu của câu đố này là tính chiều cao của một chồng bát.

Một chồng bát

Một cái bát được định nghĩa là một thiết bị đối xứng hoàn toàn không có độ dày. Hình dạng bóng của nó là một đa thức thậm chí. Ngăn xếp được mô tả bởi một danh sách bán kính, mỗi liên kết với một đa thức chẵn, được đưa ra làm đầu vào dưới dạng danh sách các hệ số (ví dụ: danh sách 3.1 4.2đại diện cho đa thức 3,1x2+4.2x4 ).

Đa thức có thể có mức độ tùy ý. Để đơn giản, chiều cao của cọc được định nghĩa là độ cao của tâm của bát trên cùng (xem sơ đồ của ví dụ 3 để minh họa).

Các trường hợp thử nghiệm có định dạng radius:coeff1 coeff2 ...: mỗi dòng bắt đầu bằng một số float biểu thị bán kính của bát, theo sau là một dấu hai chấm và một danh sách được phân tách bằng dấu cách chứa các hệ số cho các lũy thừa, bắt đầu bằng lũy ​​thừa 2 (ngụ ý phần không đổi) . Ví dụ, dòng 2.3:3.1 4.2mô tả một bát bán kính 2.3và đa thức hình dạng 3.1 * x^2 + 4.2 * x^4.

ví dụ 1

42:3.141

mô tả một đống chiều cao bằng không vì một cái bát không có chiều cao.

Ví dụ 2

1:1 2
1.2:5
1:3

mô tả một đống chiều cao 2.0(xem cốt truyện).

Âm mưu của một chồng ba bát

Ví dụ 3

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

mô tả một đống chiều cao 0,8 (xem mũi tên màu xanh lá cây trong lô).

Âm mưu của một chồng ba bát

Đây là mã golf, vì vậy mã ngắn nhất sẽ thắng.

Tôi có mã tham chiếu .

Chỉnh sửa:

Việc thực hiện tham chiếu dựa trên một thư viện để tính toán gốc của đa thức. Bạn cũng có thể làm điều đó nhưng bạn không cần phải làm vậy. Vì việc triển khai tham chiếu chỉ là một xấp xỉ bằng số (khá tốt), tôi sẽ chấp nhận bất kỳ mã nào tạo ra kết quả chính xác trong dung sai điểm nổi phổ biến.

<ε

Một biến thể khác của câu đố này là giảm thiểu chiều cao bằng cách sắp xếp lại các bát. Tôi không chắc có giải pháp nhanh không (tôi đoán đó là NP-hard). Nếu bất cứ ai có ý tưởng tốt hơn (hoặc có thể chứng minh tính đầy đủ NP), xin vui lòng cho tôi biết!


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Mego

Trong mã tham chiếu của bạn, tôi tin rằng cơ thể is_maximumnên là ví dụ return evaluate(differentiate(shape_0), root) > 0.0. Hiện tại, nó đánh giá gốc bằng cách sử dụng dd(đạo hàm của sự khác biệt giữa các hình dạng), sẽ luôn trả về 0 (đối với gốc). Do lỗi dấu phẩy động, đôi khi kết quả là giá trị dương gần bằng 0, đó là lý do tại sao mã xuất ra kết quả chính xác hoặc chính xác hơn trong một số thời gian. Kiểm tra đầu vào 1:0.2, 1:0.1 0.2sẽ xuất0.0125
dự phòng

@redundancy dù sao nó cũng thực sự dư thừa. Giá trị max y được chọn và 0 sẽ luôn nằm trong các giá trị so sánh.
Nick Kennedy

2
Trong ví dụ 3, chiều cao cuối cùng phải là 0.801. Hai bát cuối cùng chạm vào bán kính 0.1.
attinat

Vâng, tôi đã nhận được kết quả tương tự.
Joel

Câu trả lời:


6

Thạch , 54 53 byte

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

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

Một liên kết đơn âm lấy đối số của nó là danh sách các bát từ trên xuống dưới theo định dạng [[b1_radius, b1_coef1, ...], [b2_radius, b2_coef1, ...]] và trả về vị trí y của đáy bát trên cùng.

Bây giờ xử lý chính xác các bát gặp nhau ở những nơi khác ngoài bán kính tối thiểu.

Giải trình

Liên kết của trình trợ giúp: lấy đối số bên trái lcác khác biệt về hệ số của các đa thức biểu thị các bát từ 1 trở lên và đối số bên phải của nó rbán kính tối thiểu; trả về giá trị y tối đa nơi hai bát gặp nhau

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

Liên kết chính, lấy một đống bát làm đối số của nó và trả về giá trị y của cơ sở của bát trên cùng

Œ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

Tham khảo Python

Cuối cùng, đây là phiên bản TIO của tài liệu tham khảo Python mà @pasbi đưa vào cho vấn đề chính. Nó đọc từ stdin.


1
Tôi không hiểu ngôn ngữ nào cả. Dựa vào lời giải thích, có vẻ như bạn chỉ so sánh từng cặp bát (r1, p1)(r2, p2)ở điểm min(r1, r2)nào? Nếu vậy, đó sẽ là một giải pháp sai lầm vì hai cái bát có thể chạm vào giữa 0min(r1, r2)). Bạn cần tìm max(p1(x)-p2(x), 0)trên toàn bộ phạm vi [0, min(r1, r2)]cho x. Đó là lý do tại sao giải pháp tham chiếu của @ pasbi tính toán các dẫn xuất để tìm mức tối đa cục bộ.
Joel

@Joel đã sửa. Tất cả các trường hợp thử nghiệm ban đầu chạm vào min(r1, r2). Điều này hiện giải quyết được thách thức bổ sung của @ attinat
Nick Kennedy

1
Sẽ thật tuyệt khi thấy một phiên bản nhận xét của mã cho những người không có kiến ​​thức về ngôn ngữ chơi gôn, nếu bạn có thời gian.
Joel

@Joel sẽ làm gì khi tôi có thời gian
Nick Kennedy

2

Python 3 + numpy + scipy, 248 240 byte

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

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

-8 byte nhờ @xnor

Hàm này có một danh sách [radius, polynomial] cặp làm đầu vào và trả về chiều cao cọc.

Giải pháp này sử dụng ít nhiều thuật toán giống như mã tham chiếu ngoại trừ việc nó không tính toán tối đa bằng các đạo hàm. Trong khi đó, nó được viết bằng cách sử dụng tích hợp numpyvà các scipyhàm trong Python. Các phiên bản không được trình bày được hiển thị dưới đây. Điều này phục vụ như một phiên bản thay thế của mã tham chiếu cho những ai muốn một phiên bản ngắn hơn để nắm bắt ý tưởng một cách nhanh chóng.

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

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


Để tiết kiệm khoảng trắng, bạn có thể đặt toàn bộ vòng lặp for trên dòng của nó sau dấu hai chấm và đặt i=0làm đối số tùy chọn.
xnor

@xnor ơi, cảm ơn. Tôi đã không nỗ lực quá nhiều để chơi golf vì việc lưu một vài byte trong giải pháp 200 byte sẽ không thay đổi nhiều. Và dường như không có thuật toán nào tốt hơn cho thuật toán này có thể đơn giản hóa đáng kể việc tính toán.
Joel

Về mặt kỹ thuật, điều này nên được mô tả trong tiêu đề là Python3 + numpy + sympy vì không phải là một phần của cài đặt Python3 cơ bản.
Nick Kennedy

@NickKennedy Cảm ơn. Mô tả cập nhật.
Joel

1

Ngôn ngữ Wolfram (Mathicala) , 104 93 byte

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

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

{radius, polynomial}x

Đối với số thập phân thay vì đầu ra tượng trưng, ​​sử dụng NMaxValuethay thế (hoặc chỉ gọi Nkết quả).

(* 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 byte

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

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

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

Nói rộng ra một cổng R trong câu trả lời Jelly của tôi, mặc dù vì cơ sở R không có chức năng tìm gốc của đa thức nên điều này được thực hiện bằng phương pháp tìm thấy trong polynom::solve.polynomial .

Một hàm lấy danh sách các vectơ số từ trên xuống dưới của cọc.

Cảm ơn @RobinRyder vì đã chơi golf 15 byte!


Tôi không hiểu mọi thứ đang diễn ra ở đây (giải thích sẽ rất hay!), Nhưng đây là phiên bản 436 byte .
Robin Ryder
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.