보울 파일의 높이 계산


19

그릇 더미 높이

이 퍼즐의 목표는 그릇 더미의 높이를 계산하는 것입니다.

그릇의 스택

보울은 두께가없는 방사상 대칭 장치로 정의됩니다. 실루엣 모양은 다항식입니다. 스택은 계수 목록으로 입력으로 주어진 각각의 짝수 다항식과 관련된 반지름 목록으로 설명됩니다 (예 : 목록 3.1 4.2은 다항식 3.1엑스2+4.2엑스4 나타냄).

다항식은 임의의 정도를 가질 수 있습니다. 간단하게 말해서, 파일의 높이는 가장 높은 그릇의 중심의 고도로 정의됩니다 (그림은 예제 3의 도표 참조).

테스트 사례는 다음과 같은 형식으로되어 있습니다 radius:coeff1 coeff2 .... 각 라인은 보울의 반경을 나타내는 플로트 번호로 시작하고 콜론과 짝수 전력에 대한 계수를 포함하는 공백으로 구분 된 목록으로 시작합니다. . 예를 들어, 선 2.3:3.1 4.2은 반지름 2.3과 모양-다항식을 나타 3.1 * x^2 + 4.2 * x^4냅니다.

실시 예 1

42:3.141

단일 그릇에 높이가 없으므로 높이가 0 인 더미를 나타냅니다.

실시 예 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 하드라고 생각합니다). 누구든지 더 나은 아이디어를 가지고 있거나 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
중복성

@redundancy 어쨌든 실제로 중복됩니다. 최대 y 값이 선택되고 0은 항상 비교 값에 있습니다.
닉 케네디

2
예 3에서 최종 높이는이어야합니다 0.801. 마지막 두 그릇은 반경에 닿습니다 0.1.
attinat

예, 같은 결과를 얻었습니다.
Joel

답변:


6

젤리 , 54 53 바이트

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

온라인으로 사용해보십시오!

형식으로 볼 목록을 위에서 아래로 인수로 가져와 [[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

파이썬 참조

마지막으로 @pasbi가 주요 문제에 포함시킨 Python 참조의 TIO 버전이 있습니다. 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

@Joel이 수정되었습니다. 모든 원래 테스트 사례는에서 만졌습니다 min(r1, r2). 이제 @attinat의 추가 과제를 해결합니다
Nick Kennedy

1
시간이 있다면 골프 언어에 대해 잘 모르는 사람들을 위해 주석이 달린 코드 버전을 보는 것이 좋을 것입니다.
Joel

@Joel은 시간이되면 할 것입니다
Nick Kennedy

2

파이썬 3 + NumPy와 + scipy, 248 240 바이트

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

온라인으로 사용해보십시오!

@xnor 덕분에 -8 바이트

이 함수는 [radius, polynomial]쌍 목록을 입력으로 받아서 파일 높이를 반환합니다.

이 솔루션은 파생 코드를 사용하여 최대 값을 계산하지 않는다는 점을 제외하고는 참조 코드와 거의 동일한 알고리즘을 사용합니다. 한편,이 사용하여 작성 내장에서 numpyscipy파이썬 함수. ungolfed 버전은 다음과 같습니다. 이는 짧은 버전의 아이디어를 빠르게 포착하기를 원하는 사람들을위한 대체 버전의 참조 코드 역할을합니다.

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

온라인으로 사용해보십시오!


공백을 절약하기 위해 전체 for 루프를 콜론 다음 줄에 놓고 i=0선택적 인수로 사용할 수 있습니다.
xnor

@xnor 아, 감사합니다. 200 + 바이트 솔루션에 몇 바이트를 저장해도 크게 바뀌지 않기 때문에 이것을 골프에 너무 많은 노력을 기울이지 않았습니다. 그리고 계산을 크게 단순화 할 수있는 더 좋은 알고리즘이없는 것 같습니다.
Joel

기술적으로 이것은 기본 Python3 설치의 일부가 아니기 때문에 헤더에서 Python3 + numpy + sympy로 설명해야합니다.
Nick Kennedy

@NickKennedy 감사합니다. 설명이 업데이트되었습니다.
조엘

1

Wolfram Language (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}엑스

기호 출력 대신 십진수의 경우 대신 사용하십시오 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은 다항식의 근을 찾을 수있는 기능이 없기 때문에에서 찾은 방법을 사용하여 구현됩니다 polynom::solve.polynomial.

파일의 상단에서 하단으로 숫자 형 벡터 목록을 취하는 함수입니다.

15 바이트를 골라내는 @RobinRyder에게 감사드립니다!


나는 여기에서 일어나는 모든 것을 이해하지 못하지만 (설명은 좋을 것입니다!) 그러나 여기에는 436 바이트 버전이 있습니다.
로빈 라이더
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.