这山有多亮?🔥


62

被定义为一组线段,其第一点的坐标为(0,a)其中a > 0其最后一点具有坐标,并且(b,0),在那里b > 0。所有中间点的y坐标(纵坐标)均严格大于0。为您提供了山峰上的点,它们按x坐标(横坐标)的升序排序。请注意,两个点可以具有相同的x坐标,从而产生山的垂直部分。如果为您提供了两个具有相同x坐标的点,则应按照给定的顺序连接它们。此外,山上可能有水平段,无论什么水平,这些水平段都不会点亮。所有坐标均为非负整数。

问题是:假设太阳是位于山的右侧的无限垂直的光平面,那么将被照亮的山的总长度是多少?该数字不需要四舍五入,但是如果四舍五入,请至少包含四个小数位。我包括了一张图片: 山 在这里,加粗的线表示被点亮的线段。请注意,在输入中,P出现在Q之前(PQ是垂直线段),因此前一个点连接到P而不是Q。

您可以采用任何合理格式的输入,例如列表列表,单个列表,字符串等。

测试用例:

(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

它们不亮。光线完全水平,只能平行于它们而不会射中它们。我编辑了问题以澄清这一点。
操纵

Answers:


14

Python 2中 134 131 128 124 120 117个109  107字节

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

在线尝试!

将输入作为元组列表/浮点数的两元素列表。

说明

我们基本上会遍历图中的点对,如果 ,则我们将计算有多少线暴露在光线下。成对迭代通过循环执行以获取下一个点,每次都弹出列表中的第一个元素以检索当前点。y1>y2for(x2,y2)(x1,y1)

数学–线段的哪一部分暴露在光线下?

一座画得不好的山

令为当前点的坐标。令为当前点之后的点的最大高度(当前点之后的局部最大值),而为下一个点的坐标。为了计算暴露在阳光下的长度,我们应该找到,如图所示。自然,如果,则该片段完全不会暴露在光线下。(x1,y1)ymax(x2,y2)Lx3y1ymax

在形成的三角形中,长度为线段平行于长度为的底线,因此所有三个角度都相等。因此,根据相似性基本定理(大小写角度角),我们可以得出。因此,。然后,我们可以应用勾股定理来发现:x3x2x1x3x2x1=y1ymaxy1x3=(y1ymax)(x2x1)y1

L=(y1ymax)2+x32

通过将两个公式结合起来,我们得出以下表达式,这是该方法的核心:

L=

L=(y1ymax)2+((y1ymax)(x2x1)y1)2
L=(y1ymax)2(1+(x2x1)2y12)

代码–如何运作?

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个字节。

  • 通过删除不必要的条件节省了2个字节y>Y,因为如果从中减去当前点后Y坐标的局部最大值y为正,则该条件是多余的。不幸的是,这使FlipTack的高尔夫无效。

  • 稍微改变一下算法即可节省3个字节:我们没有使用计数器变量,而是将其递增并尾随列表,而是在每次迭代时都删除了第一个元素。

  • 由于ovs节省了8个字节;(x,y),(X,Y)用一种list.pop()技术改变循环条件。

  • 保存2个字节由于与Orjan约翰森(优化的式一点点)。


12

JavaScript,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

Python 2中122 120个字节

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]
乔纳森·艾伦,


1

APL(Dyalog Unicode),31字节SBCS

使用Graham公式

以2×n数据矩阵为右参数的匿名前缀函数。第一行包含从右到左的x值,第二行包含相应的y值。

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

在线尝试!

{} 匿名lambda 参数在哪里:

2-/⍵ 增量(成对减成对)

÷⌿ΔX / ΔY(文献纵分割还原)

×⍨ 正方形(照明乘法自拍照)

1+ 一个添加到那个

( 将以下内容乘以:

  2⌷⍵ 参数的第二行(y值)

  ⌈\ 最大行驶距离(直到现在为止达到的最高高度,从右边过去)

  2-/ (照度成对减减)的增量

  ×⍨ 正方形(照明乘法自拍照)

.5*⍨平方根(点亮。将其提高一半)

+/ 和


1

果冻,23 个字节

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

一个二元链接,在左边有一个y值列表,在右边有一个x值列表(如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

25字节的monadic版本,带有[x,y]坐标列表:

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

试试这个。


1
输入可以是两个值列表。我前一阵子问过OP,他们说很好
Xcoder先生17年

我觉得s和s 太多了。
乔纳森·艾伦,

0

科特林,178字节

fun L(h:List<List<Double>>)=with(h.zip(h.drop(1))){mapIndexed{i,(a,b)->val t=a[1]-drop(i).map{(_,y)->y[1]}.max()!!;if(t>0)t*Math.hypot(1.0,(a[0]-b[0])/(a[1]-b[1]))else .0}.sum()}

在线尝试!

测试部分非常打高尔夫球:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.