이 산은 얼마나 밝습니까? 🔥


62

산이 제 포인트 선분의 집합으로 정의된다 좌표를 갖는 (0,a)위치를 a > 0가진 마지막 점의 좌표를 가지고 있으며 (b,0), b > 0. 모든 중간 점은 y보다 큰 y 좌표 (좌표)를 갖습니다. 산 위의 점은 x 좌표 (가로)의 오름차순으로 정렬됩니다. 두 점은 동일한 x 좌표를 가질 수 있으며 산의 수직 선분을 생성합니다. 동일한 x 좌표로 두 점이 주어지면 주어진 순서대로 연결되어야합니다. 또한, 산의 수평 선분이있을 수 있습니다.이 수평 선분은 무엇이든 불이 켜지지 않습니다. 모든 좌표는 음이 아닌 정수입니다.

문제는 태양이 산의 오른쪽에 위치한 무한한 수직의 수직면이라고 가정 할 때, 조명을받을 산의 전체 길이는 얼마입니까? 이 숫자는 반올림 할 필요는 없지만 반올림 할 경우 소수점 이하 네 자리 이상을 포함하십시오 . 그림을 포함 시켰습니다. 산 여기서 굵게 표시된 선은 점등 된 선분을 나타냅니다. 입력에서 P는 Q 앞에 나타나고 (PQ는 수직선 세그먼트) 이전 점은 Q가 아닌 P에 연결됩니다.

리스트리스트, 단일리스트, 문자열 등과 같은 합리적인 형식으로 입력 할 수 있습니다.

테스트 사례 :

(0,3000)
(500, 3500)
(2500, 1000)
(5000,5000)
(9000,2000)
(9000,3500)
(10200,0)

Output: 6200.0000

이 이미지에 표시된 것처럼 여기에 두 개의 점등 세그먼트가 있습니다 테스트 케이스 그림 . 첫 번째 세그먼트의 길이는 5000/2 = 2500이고 두 번째 세그먼트의 길이는 3700입니다.

이것은 이므로 바이트 단위의 최단 답변이 이깁니다.


1
힌트 : 세그먼트의 길이를 찾을 때 고려해야 할 세 가지 점이 있습니다. 두 개의 끝점과이를 "차단"하는 점 (두 번째 그림에서 길이를 결정하는 (9000,3500)) 3-4-5 세그멘트. 주요 부분의 두 지점하자 (x1, y1)(x2,y2). 그것이 "차단"되어있는 점 (x3, y3). Y2 가정 <Y3 <= Y1은. 세그먼트에서의 길이가된다 ((y1 - y3)/(y1 - y2))*sqrt((x1 - x2)^2 + (y1 - y2)^2). 이것은 본질적이고 화학식 거리가 실제로 사용되는 부분의 비율을 곱한.
조작 된

1
산이 수 평일 수 있습니까?
user202729

그렇습니다. 산에는 수평 부분이있을 수 있습니다. 그러나 어느 시점에서 0으로 이동합니다.
리깅

1
그러나 그들은 불을 켜야 하는가?
user202729

불이 들어오지 않습니다. 완벽하게 수평 인 빛은 그들과 평행을 이룰 수 있고 절대로 닿지 않습니다. 이것을 명확히하기 위해 문제를 편집했습니다.
리깅

답변:


14

파이썬 2 ,  134131128124120117109107  바이트

p=input();s=0
for X,Y in p[1:]:x,y=p.pop(0);n=y-max(zip(*p)[1]);s+=n*(1+((X-x)/(y-Y))**2)**.5*(n>0)
print s

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

입력을 튜플 목록 / 소수점 부동 소수점 목록으로 가져옵니다.

설명

기본적으로 그래프의 한 쌍의 점을 반복하고 인 경우 빛에 얼마나 많은 선이 노출되는지 계산합니다. 페어 단위 반복은 루프로 수행되어 다음 포인트 ( x 2 , y 2 ) 를 가져 와서 현재 포인트 ( x 1 , y 1 ) 를 검색 할 때마다 목록의 첫 번째 요소를 팝합니다 .와이1>와이2for(엑스2,와이2)(엑스1,와이1)

수학 – 선분의 어떤 부분이 빛에 노출됩니까?

잘못 그려진 산

(엑스1,와이1)와이에이엑스(엑스2,와이2)엑스와이1와이에이엑스

엑스엑스2엑스1엑스엑스2엑스1=와이1와이에이엑스와이1엑스=(와이1와이에이엑스)(엑스2엑스1)와이1

=(와이1와이에이엑스)2+엑스2

두 공식을 합치면 다음과 같은 표현에 도달 할 수 있습니다.

=(와이1와이에이엑스)2+((와이1와이에이엑스)(엑스2엑스1)와이1)2
=(와이1와이에이엑스)2(1+(엑스2엑스1)2와이12)

코드 – 어떻게 작동합니까?

p=input();s=0                             # Assign p and s to the input and 0 respectively.
for X,Y in p[1:]:                         # For each point (X, Y) in p with the first
                                          # element removed, do:
    x,y=p.pop(0)                          # Assign (x, y) to the first element of p and
                                          # remove them from the list. This basically
                                          # gets the coordinates of the previous point.
    n=y-max(zip(*p)[1])                   # Assign n to the maximum height after the
                                          # current one, subtracted from y.
    s+=n*(1+((X-x)/(y-Y))**2)**.5         # Add the result of the formula above to s.
                                 *(n>0)   # But make it null if n < 0 (if y is not the
                                          # local maxima of this part of the graph).
print s                                   # Output the result, s.

변경 로그

  • 골프 목적을 위해 공식을 점차적으로 최적화했습니다.

  • FlipTack 덕분에 1 바이트가 절약되었습니다 .

  • 현재 포인트를 뺀 후 Y 좌표 y>Y의 로컬 최대 값 이 양수이면 해당 조건이 중복되므로 불필요한 조건을 제거하여 2 바이트를 절약했습니다 . 불행히도 FlipTack의 골프는 무효화됩니다.y

  • 알고리즘을 약간 변경하여 3 바이트를 절약했습니다. 카운터 변수를 사용하고 증가시키고 목록을 마무리하는 대신 각 반복에서 첫 번째 요소를 제거합니다.

  • ovs 덕분에 8 바이트가 절약되었습니다 . 기술로 (x,y),(X,Y)루프 조건을 변경 합니다 list.pop().

  • Ørjan Johansen 덕분에 2 바이트가 절약되었습니다 (수식을 약간 최적화 함).


12

자바 스크립트, 97 바이트

a=>a.reduceRight(([p,q,l=0,t=0],[x,y])=>[x,y,y>t?(y-t)/(s=y-q)*Math.hypot(x-p,s)+l:l,y>t?y:t])[2]

f=a=>a.reduceRight(([p,q,l=0,t=0],[x,y])=>[x,y,y>t?(y-t)/(s=y-q)*Math.hypot(x-p,s)+l:l,y>t?y:t])[2];
t=[[0, 3000], [500, 3500], [2500, 1000], [5000, 5000], [9000, 2000], [9000, 3500], [10200, 0]];
console.log(f(t));

(반전 버전의 입력을받는 것이 유효한 것으로 간주되면 5 바이트가 저장 될 수 있습니다.)


10

APL + WIN, 48 바이트

+/((h*2)+(((h←-2-/⌈\m)÷-2-/m←⌽⎕)×(⌽-2-/⎕))*2)*.5

x 좌표리스트와 y 좌표리스트를 묻는 프롬프트

설명

h←-2-/⌈\m difference between successive vertical maxima viewed from the right (1)

-2-/m←⌽⎕ vertical difference between points (2)

⌽-2-/⎕ horizontal difference between points (3)

점등 된 수직 거리 = h이고 점등 된 수평 거리는 (3) * (1) / (2)입니다. 나머지는 피타고라스입니다.


시겠습니까 +/.5*⍨(h*2)+×⍨((h←-2-/⌈\m)÷-2-/m←⌽⎕)×⌽-2-/⎕일?
Kritixi Lithos

불행히도 내 이전 APL + WIN 버전에는 연산자가 없으므로 말할 수 없습니다.
Graham

@Cows quack 이전 버전의 Dyalog Unicode (v13)에서 사용해보고 제안 사항이 적용됩니다.
Graham

6

빠른 , 190 바이트

import Foundation
func f(a:[(Double,Double)]){var t=0.0,h=t,l=(t,t)
a.reversed().map{n in if l.0>=n.0&&n.1>l.1{t+=max((n.1-h)/(n.1-l.1)*hypot(n.0-l.0,n.1-l.1),0)
h=max(n.1,h)}
l=n}
print(t)}

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

설명

import Foundation                  // Import hypot() function
func f(a:[(Double,Double)]){       // Main function
  var t=0.0,h=0.0,l=(0.0,0.0)      // Initialize variables
  a.reversed().map{n in            // For every vertex in the list (from right to left):
    if l.0>=n.0&&n.1>l.1{          //   If the line from the last vertex goes uphill:
      t+=max((n.1-h)/(n.1-l.1)     //     Add the fraction of the line that's above the
        *hypot(n.0-l.0,n.1-l.1),0) //     highest seen point times the length of the line
                                   //     to the total
      h=max(n.1,h)}                //     Update the highest seen point
    l=n}                           //   Update the last seen point
  print(t)}                        // Print the total

5

파이썬 2 , 122120 바이트

k=input()[::-1]
m=r=0
for(a,b),(c,d)in zip(k,k[1:]):
 if d>m:r+=(b>=m or(m-b)/(d-b))*((a-c)**2+(b-d)**2)**.5;m=d
print r

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


우리는 x 값의 목록과 y 값의 목록을 두 개의 입력으로 사용할 수 있기 때문에 좌표 목록을 거꾸로 가져갈 필요가 있다고 확신합니다 [::-1].
Jonathan Allan


1

APL (Dyalog Unicode) , 31 바이트 SBCS

용도 그레이엄의 공식을 .

2xn 행렬의 데이터를 올바른 인수로 취하는 익명의 접두사 함수. 첫 번째 행에는 오른쪽에서 왼쪽으로 x 값이 있고 두 번째 행에는 해당 y 값이 있습니다.

{+/.5*⍨(×⍨2-/⌈\2⌷⍵)×1+×⍨÷⌿2-/⍵}

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

{} 익명 람다 인수입니다 :

2-/⍵ 델타 (쌍별 마이너스 감소)

÷⌿ΔxΔy (lit 수직 분할 감소)

×⍨ 정사각형 (lit. 곱셈 셀카)

1+ 하나는 그것에 추가

( 다음을 곱하십시오.

  2⌷⍵ 인수의 두 번째 행 (y 값)

  ⌈\ 최대 실행 (오른쪽에서 시작하여 지금까지 가장 높은 높이)

  2-/ 델타 (쌍별 마이너스 감소)

  ×⍨ 정사각형 (lit. 곱셈 셀카)

.5*⍨제곱근 (점등을 반으로 제곱)

+/ 합집합


1

젤리 , 23 바이트

ṀÐƤḊ_⁸«©0×⁹I¤÷⁸I¤,®²S½S

왼쪽의 y 값 목록과 오른쪽의 각 x 값 목록을 가져 오는 2 진 링크 (댓글에서 OP가 명시 적으로 허용 한대로)

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

어떻게?

불이 켜진 (경사) 섹션의 비율은 수직 드롭 인 경우 불이 켜지는 비율과 동일합니다. 기울기 길이를 평가하기 위해 제곱이 발생하기 때문에 길을 따라 계산 된 높이는 음수 일 수 있습니다 (아래에서 조명 된 기울기의 길이는 음수를 음수로 나눈 값으로 계산 됨).

ṀÐƤḊ_⁸«©0×⁹I¤÷⁸I¤,®²S½S - Link:list, yValues; list, xValues
 ÐƤ                     - for suffixes of the yValues:       e.g. [ 3000, 3500, 1000, 5000, 2000, 3500,    0]
Ṁ                       -   maximum                               [ 5000, 5000, 5000, 5000, 3500, 3500,    0]
   Ḋ                    - dequeue                                 [ 5000, 5000, 5000, 3500, 3500,    0]
     ⁸                  - chain's left argument, yValues          [ 3000, 3500, 1000, 5000, 2000, 3500,    0]
    _                   - subtract                                [ 2000, 1500, 4000,-1500, 1500,-3500,    0]
        0               - literal zero
      «                 - minimum (vectorises)                    [    0,    0,    0,-1500,    0,-3500,    0]
       ©                - copy to the register for later
            ¤           - nilad followed by link(s) as a nilad:
          ⁹             -   chain's right argument, xValues  e.g. [    0,  500, 2500, 5000, 9000, 9000, 10200]
           I            -   incremental differences               [  500, 2000, 2500, 4000,    0, 1200]
         ×              - multiply (vectorises)                   [    0,    0,    0,-6000000, 0,-4200000, 0]
                ¤       - nilad followed by link(s) as a nilad:
              ⁸         -   chain's left argument, yValues        [ 3000, 3500, 1000, 5000, 2000, 3500,    0]
               I        -   incremental differences               [  500,-2500, 4000,-3000, 1500,-3500]
             ÷          - divide (vectorises)                     [    0,    0,    0, 2000,    0, 1200,    0]
                  ®     - recall from the register                [    0,    0,    0,-1500,    0,-3500,    0]
                 ,      - pair (i.e. lit slope [runs, rises])     [[0, 0, 0,    2000, 0,    1200, 0], [0, 0, 0,   -1500, 0,    -3500, 0]]
                   ²    - square (vectorises)                     [[0, 0, 0, 4000000, 0, 1440000, 0], [0, 0, 0, 2250000, 0, 12250000, 0]]            
                    S   - sum (vectorises)                        [  0,   0,   0, 6250000,   0, 13690000,   0]
                     ½  - square root (vectorises)                [0.0, 0.0, 0.0,  2500.0, 0.0,   3700.0, 0.0]
                      S - sum                                     6200.0

[x,y]좌표 목록을 취하는 25 바이트 모나 딕 버전 :

ṀÐƤḊ_«0
Z©Ṫµ®FI×Ç÷I,DzS½S

이거 한번 해봐.


1
입력 값은 두 개의 값 목록이 될 수 있습니다. 나는 얼마 전 OP에 물었고 그들은 괜찮다고 말했다 .
Mr. Xcoder

나는 너무 많은 거기 같은 느낌 의 및 의.
Jonathan Allan

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.