この山の明るさは?🔥


62

山は、最初の点の座標有する線分の集合として定義され、そして最後の点の座標を有します、。すべての中間ポイントには、y座標(座標)が厳密に0より大きい値があります。x座標(横座標)の昇順でソートされた山上のポイントが与えられます。2つのポイントが同じx座標を持つことができ、山の垂直セグメントを生成できることに注意してください。同じx座標を持つ2つのポイントが指定されている場合、それらは指定された順序で接続する必要があります。さらに、山の水平セグメントが存在する場合があります。これらの水平セグメントは、何があっても点灯しません。すべての座標は非負の整数です。(0,a)a > 0(b,0)b > 0

質問:太陽が山の右側にある無限の垂直な光の平面であると仮定すると、照らされる山の全長はいくらですか?この数値を丸める必要はありませんが、丸める場合は、小数点以下4桁以上を含めてください写真を含めました。 山 ここで、太字の線は点灯しているセグメントを表しています。入力では、PはQの前に表示されることに注意してください(PQは垂直線分です)。したがって、前の点はQではなくPに接続されます。

リストのリスト、単一のリスト、文字列など、合理的な形式で入力を取得できます。

テストケース:

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

Output: 6200.0000

この画像に示すように、ここには2つのライトアップセグメントがありますテストケース写真 。最初のセグメントの長さは5000/2 = 2500で、2番目のセグメントの長さは3700です。

これはであるため、バイト単位の最短回答が優先されます。


1
ヒント:セグメントの長さを見つけるとき、考慮する必要がある3つのポイントがあります:2つのエンドポイント、およびそれを「ブロック」するポイント(2番目の図では、長さを決定する(9000,3500)になります) 3-4-5セグメントの主セグメント上の2つの点があるとする(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 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

オンラインでお試しください!

入力をタプルのリスト/浮動小数点数の2要素リストとして受け取ります。

説明

y1>y2for(x2,y2)(x1,y1)

数学–ラインセグメントのどの部分が光にさらされていますか?

よく描かれていない山

(x1,y1)ymax(x2,y2)Lx3y1ymax

x3x2x1x3x2x1=y1ymaxy1x3=(y1ymax)(x2x1)y1

L=(y1ymax)2+x32

2つの式を結合することにより、このアプローチの中心である次の式に到達します。

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バイト節約されました

  • から現在のポイントを引いた後のY座標のy>Y極大値が正の場合、その条件は冗長であるため、不要な条件を削除して2バイトを節約しました。ただし、残念ながらFlipTackのゴルフは無効になります。y

  • アルゴリズムを少し変更することで3バイトを節約しました。カウンター変数を持ち、それをインクリメントしてリストをテーリングする代わりに、各反復で最初の要素を削除します。

  • ovsのおかげで8バイト節約されました。(x,y),(X,Y)ループ条件をlist.pop()テクニックで変更する。

  • ØrjanJohansenのおかげで2バイト節約されました(式を少し最適化)。


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版は持っていないので、私が言うことができないオペレータ
グラハム・

@CowsいんちきDyalogユニコード(V13)の古いバージョンでそれを試して管理し、あなたの提案は、仕事をする
グラハム

6

Swift、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



1

APL(Dyalog Unicode)、31バイトSBCS

グラハムの式を使用します。

データの2×n行列を正しい引数としてとる匿名プレフィックス関数。最初の行には右から左へのx値が含まれ、2行目には対応するy値が含まれます。

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

オンラインでお試しください!

{} 匿名ラムダは引数です:

2-/⍵ デルタ(lit. pairwise minus-reductions)

÷⌿ΔX / Δyの(点灯垂直分割減少)

×⍨ 正方形(点灯乗算乗算セルフィー)

1+ それに追加されたもの

( 次をそれに掛けます:

  2⌷⍵ 引数の2行目(y値)

  ⌈\ 最大走行距離

  2-/ デルタ(lit. pairwise minus-reduction)

  ×⍨ 正方形(点灯乗算乗算セルフィー)

.5*⍨平方根(それを半分のべき乗する)

+/ 和


1

ゼリー、23 バイト

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

左側のy値のリストと右側のそれぞれのx値のリストを取得するダイアディックリンク(コメントでOPによって明示的に許可されている)

オンラインでお試しください!

どうやって?

点灯する(傾斜)セクションの割合は、垂直ドロップの場合に点灯する割合と同じです。勾配の長さを評価するために2乗が発生するため、計算された道のりの高さは負になることがあります(また、以下では、照らされた斜面のランレングスは負の値を負の値で除算して計算されます)。

ṀÐƤḊ_⁸«©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
入力には、値の2つのリストを指定できます。私はしばらく前にOPを尋ねましたが、彼らはそれがいいと言いました
ミスターXcoder

私はあまりにも多くあるように感じるsおよびsの。
ジョナサンアラン

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.