Bu dağ ne kadar aydınlık? 🔥


62

Bir dağ ilk nokta çizgi segmentleri bir dizi olarak tanımlanır koordinatları vardır (0,a)burada a > 0olan, son nokta koordinatları vardır ve (b,0), b > 0. Tüm orta noktalarda kesinlikle 0'dan büyük bir y koordinatı (koordinat) vardır. Dağdaki puanlara, artan x-koordinatı (abscissa) sıralaması verilir. İki noktanın aynı x koordinatına sahip olabileceğini ve dağın dikey bir kesimini oluşturabileceğini unutmayın. Aynı x koordinatına sahip iki nokta verilirse, verildikleri sırayla bağlanmaları gerekir. Ek olarak, dağın yatay kısımları olabilir. Bu yatay kısımlar, ne olursa olsun yanmaz. Tüm koordinatlar negatif olmayan tamsayılardır.

Soru: Güneşin dağın sağında yer alan sonsuz bir dikey ışık düzlemi olduğu varsayılarak aydınlatılacak olan dağın toplam uzunluğu nedir? Bu sayının yuvarlatılması gerekmez, ancak yuvarlanırsa en az dört ondalık basamak içerir. Bir resim Dağ ekledim : Burada koyu çizgiler, yanan kısımları temsil eder. Girişte, P'nin Q'dan önce göründüğüne dikkat edin (PQ dikey bir çizgi kesimidir);

Girdiyi, liste listesi, tek liste, dize vb. Gibi makul bir biçimde alabilirsiniz.

Test durumu:

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

Output: 6200.0000

Bu resimde gösterildiği gibi burada iki tane aydınlatmalı bölüm vardır: Test Durumu Pic İlki 5000/2 = 2500 ve ikincisi 3700 uzunluğa sahiptir.

Bu , yani bayt cinsinden en kısa cevap kazanır.


1
İpucu: Bir parçanın uzunluğunu bulurken, göz önünde bulundurmanız gereken üç nokta vardır : iki uç nokta ve onu "engelleyen" (2. resimde, uzunluğu belirleyen (9000.30000) olan nokta. 3-4-5 segmentinin ana segment üzerindeki iki noktanın (x1, y1)ve (x2,y2)“blok” olan noktanın olmasını bekleyin (x3, y3). y2 <y3 <= y1 olduğunu varsayalım. Sonra segmentin uzunluğu budur ((y1 - y3)/(y1 - y2))*sqrt((x1 - x2)^2 + (y1 - y2)^2). gerçekte kullanılan segmentin
donatıldı

1
Dağ yatay olabilir mi?
user202729

Evet, dağda yatay bölümler olabilir. Ancak bir noktada 0'a gidecektir.
hileli

1
Ama onlar yakılmalı mı?
user202729

Yanmıyorlar. Mükemmel yatay olan ışık, sadece onlara paralel olarak çalışabilir ve asla çarpmaz. Bunu açıklığa kavuşturmak için sorunu düzelttim.
hileli

Yanıtlar:


14

Python 2 ,  134 131 128 124 120 117 109  107 bayt

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

Çevrimiçi deneyin!

Girdileri, kayan nokta sayısının başlık / iki öğe listelerinin bir listesi olarak alır.

açıklama

Grafikteki nokta çiftleri boyunca temelde ve eğer ise ne kadarının ışığa maruz kaldığını hesaplıyoruz. İkili yineleme, bir sonraki noktayı elde etmek için bir döngü ile gerçekleştirilir , geçerli noktayı almak için her seferinde listedeki ilk elemanı , .y1>y2for(x2,y2)(x1,y1)

Matematik - Çizgi bölümünün hangi kısmı ışığa maruz kalıyor?

Kötü çizilmiş bir dağ

Let mevcut noktasının koordinatları olabilir. Let geçerli bir (bu noktadan sonra lokal maksimumlar) ve bir noktadan sonra maksimum yüksekliği aşağıdaki noktasının koordinatları olabilir. Güneşe maruz kalan uzunluğu hesaplamak için , şemada gösterildiği gibi bulmalıyız . Doğal olarak, eğer ise, segment hiç ışığa maruz kalmaz.(x1,y1)ymax(x2,y2)Lx3y1ymax

Oluşan üçgende, uzunluğundaki çizgi parçası, uzunluğundaki tabana paraleldir , bu nedenle üç açı da aynıdır. Bu nedenle, Temel Benzerlik Teoreminden (vaka Açısı Açısı), . Bu nedenle, . Sonra, Pisagor Teoremi'ni bulmak için uygulayabiliriz:x3x2x1x3x2x1=y1ymaxy1x3=(y1ymax)(x2x1)y1

L=(y1ymax)2+x32

İki formüle katılarak, bu yaklaşımın özü olan şu ifadeye ulaşırız:

L=

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

Kod - Nasıl çalışır?

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.

Değişiklikler

  • Formülü golf oynamak için kademeli olarak optimize etti.

  • FlipTack sayesinde 1 byte kaydedildi .

  • Gereksiz koşulun kaldırılmasıyla 2 bayt kurtarıldı y>Y, çünkü Y noktasının yerel maksimumu çıkarıldıktan sonraki akım noktasının ypozitif olması durumunda, bu koşul fazlalık olur. Bu ne yazık ki, FlipTack'in golfünü geçersiz kılıyor.

  • Algoritmayı biraz değiştirerek 3 bayt kurtarıldı: bir sayaç değişkenine sahip olmak yerine, onu artırarak ve listeyi tıklamak yerine, her bir yinelemede ilk elemanı kaldırırız.

  • Ovs sayesinde 8 bayt kurtarıldı ; Değişen (x,y),(X,Y)bir ile döngü durumunda list.pop()tekniği.

  • Ørjan Johansen sayesinde 2 bayt kurtarıldı (formülü biraz optimize etti).


12

JavaScript, 97 bayt

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

(Girişin tersine çevrilmesi geçerliyse, 5 bayt kaydedilebilir.)


10

APL + WIN, 48 bayt

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

Bir x koordinatı listesi ve ardından y koordinatı listesi için bilgi istemi

açıklama

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)

Yanan dikey mesafeler = h ve yanan yatay mesafeler (3) * (1) / (2). Gerisi Pisagor'dur.


Çalışır +/.5*⍨(h*2)+×⍨((h←-2-/⌈\m)÷-2-/m←⌽⎕)×⌽-2-/⎕mı?
Kritixi Lithos,

Maalesef eski APL + WIN sürümüm operatöre sahip değil, söyleyemem
Graham

@Cows quack Dyalog Unicode (v13) 'un eski bir versiyonunda denemeyi başardı ve öneriniz işe yaramıyor
Graham

6

Swift , 190 bayt

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

Çevrimiçi deneyin!

açıklama

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 bayt

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

Çevrimiçi deneyin!


İki giriş olarak bir x değeri listesi ve bir de y değeri listesi alabileceğimiz için, bir koordinat listesini tersine çevirerek ihtiyacımızı ortadan kaldırabiliriz [::-1].
Jonathan Allan,

2

Python 2 , 89 bayt

M=t=0
for x,y in input()[::-1]:
 if y>M:t+=(y-M)*abs((x-X)/(y-Y)+1j);M=y
 X,Y=x,y
print t

Çevrimiçi deneyin!

Yüzen çiftlerin bir listesini alır. Kapalı Tabanlı Ovs çözümü .


Tersine bir liste alabileceğimizi düşünelim (x ve y'yi ayrı listeler olarak alabiliriz), böylece listeyi bırakabilirsiniz [::-1].
Jonathan Allan,

1

APL (Dyalog Unicode) , 31 bayt SBCS

Graham'ın formülünü kullanır .

2 × n veri matrisini doğru argüman olarak alarak adsız önek işlevi. İlk satır sağdan sola doğru x değerlerini, ikincisi de karşılık gelen y değerlerini içerir.

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

Çevrimiçi deneyin!

{} İsimsiz lambda argüman nerede :

2-/⍵ deltalar (lit. çift eksi azaltma)

÷⌿ΔxΔy (lit. dikey bölme azaltma)

×⍨ kare (lit. çarpma selfie)

1+ buna bir tane eklendi

( Şununla çarpın:

  2⌷⍵ argümanın ikinci satırı (y değerleri)

  ⌈\ maksimum çalışma (en yüksek yükseklik şimdiye kadar bir araya geldi, sağdan sağa)

  2-/ deltaları (lit. çift eksi azaltma)

  ×⍨ kare (lit. çarpma selfie)

.5*⍨karekök (yanar, bunu bir buçuk gücüne yükselt)

+/ toplam


1

Jöle , 23 bayt

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

Soldaki y değerlerinin bir listesini ve sağdaki ilgili x değerlerinin bir listesini alan bir dyadik bağlantı (yorumlarda OP'nin açıkça izin verdiği şekilde)

Çevrimiçi deneyin!

Nasıl?

Yanan bir (eğimli) bölümün kesri, düşey bir damla olsaydı yanan aynı kesirdir. Eğim uzunluklarını değerlendirmek için kareler oluştuğundan, yol boyunca hesaplanan yüksekliklerin negatif olabileceğine dikkat edin (ayrıca aşağıda ışıklı eğimlerin çalışma uzunlukları negatif olarak bölünmüş olarak hesaplanır).

ṀÐƤḊ_⁸«©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

Koordinatların bir listesini alarak 25 byte monadik versiyonu [x,y]:

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

Bunu dene.


1
Giriş iki değer listesi olabilir. OP'ye bir süre önce sordum ve sorun olmadığını söylediler .
Bay Xcoder,

Ben çok fazla var gibi hissediyorum ler ve s.
Jonathan Allan,

0

Kotlin , 178 bayt

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

Çevrimiçi deneyin!

Test bölümü çok golf değil :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.