Quanto è illuminata questa montagna? 🔥


62

Una montagna è definita come un insieme di segmenti di linea il cui primo punto ha coordinate (0,a)dove a > 0, e il cui ultimo punto ha coordinate (b,0), dove b > 0. Tutti i punti intermedi hanno una coordinata y (ordinata) strettamente maggiore di 0. Vengono assegnati i punti sulla montagna ordinati in ordine crescente di coordinata x (ascissa). Nota che due punti possono avere la stessa coordinata x, producendo un segmento verticale della montagna. Se ti vengono dati due punti con la stessa coordinata x, devono essere collegati nell'ordine in cui sono stati assegnati. Inoltre, ci possono essere segmenti orizzontali della montagna. Questi segmenti orizzontali non sono illuminati, qualunque cosa accada. Tutte le coordinate sono numeri interi non negativi.

La domanda: qual è la lunghezza totale della montagna che verrebbe illuminata, supponendo che il sole sia un piano di luce verticale infinito situato alla destra della montagna? Non è necessario arrotondare questo numero, ma se è arrotondato, includere almeno quattro cifre decimali. Ho incluso un'immagine: La montagna qui le linee in grassetto rappresentano i segmenti illuminati. Si noti che nell'input, P appare prima di Q (PQ è un segmento di linea verticale), quindi il punto precedente è collegato a P e non a Q.

Puoi accettare input in qualsiasi formato ragionevole, come un elenco di elenchi, un singolo elenco, una stringa, ecc.

Caso di prova:

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

Output: 6200.0000

Ci sono due segmenti illuminati qui, come mostrato in questa immagine: Test Case Fig il primo ha lunghezza 5000/2 = 2500 e il secondo ha lunghezza 3700.

Questo è , quindi vince la risposta più breve in byte.


1
Suggerimento: quando si trova la lunghezza di un segmento, è necessario considerare tre punti: i due punti finali e il punto che lo "blocca" (nella seconda immagine, sarebbe (9000.3500) che determina la lunghezza del segmento 3-4-5. Lascia che i due punti sul segmento principale siano (x1, y1)e (x2,y2). Il punto che sta "bloccando" è (x3, y3). Supponi y2 <y3 <= y1. Quindi la lunghezza del segmento è ((y1 - y3)/(y1 - y2))*sqrt((x1 - x2)^2 + (y1 - y2)^2). Questa è essenzialmente la formula della distanza, moltiplicata per la frazione del segmento effettivamente utilizzata
truccato il

1
La montagna può essere orizzontale?
user202729

Sì, ci possono essere segmenti orizzontali sulla montagna. Comunque andrà a 0 ad un certo punto.
truccato il

1
Ma dovrebbero essere illuminati?
user202729

Non sono accesi. La luce, essendo perfettamente orizzontale, può solo correre parallela a loro e non colpirli mai. Ho modificato il problema per chiarire questo.
truccato il

Risposte:


14

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

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

Provalo online!

Accetta input come un elenco di tuple / elenchi a due elementi di numeri in virgola mobile.

Spiegazione

Fondamentalmente ripetiamo le coppie di punti nel grafico e, se , calcoliamo la parte della linea esposta alla luce. L'iterazione a coppie viene eseguita con un ciclo per ottenere il punto successivo, ( x 2 , y 2 ) , facendo scattare il primo elemento nell'elenco ogni volta per recuperare il punto corrente, ( x 1 , y 1 ) .y1>y2for(X2,y2)(X1,y1)

Matematica - Quale parte del segmento di linea è esposta alla luce?

Una montagna mal disegnata

(X1,y1)ymun'X(X2,y2)LX3y1ymun'X

X3X2-X1X3X2-X1=y1-ymun'Xy1X3=(y1-ymun'X)(X2-X1)y1

L=(y1-ymun'X)2+X32

Unendo le due formule, arriviamo alla seguente espressione, che è il nucleo di questo approccio:

L=(y1-ymun'X)2+((y1-ymun'X)(X2-X1)y1)2
L=(y1-ymun'X)2(1+(X2-X1)2y12)

Codice - Come funziona?

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.

changelog

  • A poco a poco ottimizzato la formula per scopi di golf.

  • Salvato 1 byte grazie a FlipTack .

  • Salvato 2 byte rimuovendo la condizione non necessaria che y>Y, poiché se i massimi locali di Y coordinati dopo il punto corrente sottratto yè positivo, tale condizione è ridondante. Questo purtroppo invalida il golf di FlipTack, comunque.

  • Ho salvato 3 byte modificando un po 'l'algoritmo: invece di avere una variabile contatore, incrementarla e adeguare l'elenco, rimuoviamo il primo elemento ad ogni iterazione.

  • 8 byte salvati grazie agli ovs ; cambiando (x,y),(X,Y)nella condizione di loop con una list.pop()tecnica.

  • Salvato 2 byte grazie a Ørjan Johansen (ottimizzato un po 'la formula).


12

JavaScript, 97 byte

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 byte possono essere salvati, se si considera valida la versione inversa dell'input.)


10

APL + WIN, 48 byte

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

Richiede un elenco di coordinate x seguito da un elenco di coordinate y

Spiegazione

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)

Le distanze verticali illuminate = he le distanze orizzontali illuminate sono (3) * (1) / (2). Il resto è Pitagora.


Funzionerebbe +/.5*⍨(h*2)+×⍨((h←-2-/⌈\m)÷-2-/m←⌽⎕)×⌽-2-/⎕?
Kritixi Lithos,

Sfortunatamente la mia vecchia versione APL + WIN non ha l' operatore, quindi non posso dire
Graham il

@Cows quack Gestito per provarlo in una vecchia versione di Dyalog Unicode (v13) e il tuo suggerimento funziona
Graham

6

Rapido , 190 byte

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

Provalo online!

Spiegazione

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 byte

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

Provalo online!


Dato che ci è permesso di prendere un elenco di valori x e un elenco di valori y come due input, sono abbastanza sicuro che potremmo prendere un elenco di coordinate al contrario, eliminando la necessità di [::-1].
Jonathan Allan il

3

Python 2 , 89 byte

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

Provalo online!

Comprende un elenco di coppie di float. Basato sulla soluzione di ovs .


Pensa che possiamo prendere un elenco inverso (ci è consentito prendere xey come elenchi separati), in modo da poter eliminare [::-1].
Jonathan Allan,

1

APL (Dyalog Unicode) , 31 byte SBCS

Usa la formula di Graham .

Funzione di prefisso anonima che accetta una matrice di dati 2 × n come argomento corretto. La prima riga contiene i valori x da destra a sinistra e la seconda riga i valori y corrispondenti.

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

Provalo online!

{... } lambda anonimo dov'è l'argomento:

2-/⍵ delta (lett. meno riduzioni a coppie)

÷⌿ΔxΔy (lit. riduzione divisione verticale)

×⍨ quadrato (lit. selfie moltiplicazione)

1+ uno aggiunto a quello

(...  moltiplica quanto segue per quello:

  2⌷⍵ seconda riga dell'argomento (i valori y)

  ⌈\ corsa massima (altezza massima raggiunta fino ad ora, andando da destra)

  2-/ delta di (lett. riduzione negativa a coppie)

  ×⍨ quadrato (lit. selfie moltiplicazione)

.5*⍨radice quadrata (lett. elevalo alla potenza di metà)

+/ somma


1

Gelatina , 23 byte

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

Un collegamento diadico che prende un elenco di valori y a sinistra e un elenco dei rispettivi valori x a destra (come esplicitamente consentito dall'OP nei commenti)

Provalo online!

Come?

La frazione di una sezione (inclinata) che è illuminata è la stessa frazione che si accenderebbe se fosse una caduta verticale. Si noti che poiché si verifica la quadratura per valutare le lunghezze delle pendenze, le altezze calcolate lungo il percorso possono essere negative (anche in basso le lunghezze delle pendenze illuminate sono calcolate come negative divise per negative).

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

Versione monadica da 25 byte che prende un elenco di [x,y]coordinate:

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

Prova questo.


1
L'input può essere due elenchi di valori. Ho chiesto all'OP un po 'di tempo fa e mi hanno detto che va bene .
Mr. Xcoder il

Mi sento come se ci sono troppe s e s.
Jonathan Allan,

0

Kotlin , 178 byte

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

Provalo online!

La parte di test non è molto giocata a golf :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.