Comment est allumé cette montagne? 🔥


62

Une montagne est définie comme étant un ensemble de segments de droite dont le premier point a les coordonnées (0,a)a > 0, et dont le dernier point a les coordonnées (b,0), où b > 0. Tous les points intermédiaires ont une coordonnée y (ordonnée) strictement supérieure à 0. Les points de la montagne sont classés dans l'ordre croissant des abscisses (abscisses). Notez que deux points peuvent avoir la même coordonnée x, produisant un segment vertical de la montagne. Si on vous donne deux points avec la même coordonnée x, ils doivent être connectés dans l'ordre dans lequel ils vous sont donnés. De plus, il peut y avoir des segments horizontaux de la montagne. Ces segments horizontaux ne sont pas éclairés, quoi qu'il en soit. Toutes les coordonnées sont des entiers non négatifs.

La question: quelle est la longueur totale de la montagne qui serait éclairée, en supposant que le soleil soit un plan de lumière vertical infini situé à droite de la montagne? Ce nombre n'a pas besoin d'être arrondi, mais s'il l'est, incluez au moins quatre décimales. J'ai inclus une image: La montagne Ici, les lignes en gras représentent les segments allumés. Notez que dans l'entrée, P apparaît avant Q (PQ est un segment de droite), donc le point précédent est connecté à P et non à Q.

Vous pouvez prendre des entrées dans n’importe quel format raisonnable, comme une liste de listes, une liste unique, une chaîne, etc.

Cas de test:

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

Output: 6200.0000

Il y a ici deux segments illuminés, comme le montre cette image: Pic de cas de test le premier a une longueur de 5000/2 = 2500 et le second une longueur de 3700.

C'est du , donc la réponse la plus courte en octets est gagnante.


1
Astuce: Lorsque vous recherchez la longueur d’un segment, vous devez tenir compte de trois points: les deux extrémités et le point qui le "bloque" (dans la deuxième image, ce serait (9 000 300) qui détermine la longueur. du segment 3-4-5. Soit les deux points du segment principal (x1, y1)et et (x2,y2). Le point qui le "bloque" est (x3, y3). Supposons que y2 <y3 <= y1. La longueur du segment est alors ((y1 - y3)/(y1 - y2))*sqrt((x1 - x2)^2 + (y1 - y2)^2): c’est essentiellement le formule de distance, multipliée par la fraction du segment réellement utilisé.
truqué

1
La montagne peut-elle être horizontale?
user202729

Oui, il peut y avoir des segments horizontaux sur la montagne. Cependant, il ira à 0 à un moment donné.
truqué

1
Mais devraient-ils être allumés?
user202729

Ils ne sont pas allumés. La lumière, étant parfaitement horizontale, ne peut leur être parallèle et ne jamais les frapper. J'ai édité le problème pour clarifier ceci.
truqué

Réponses:


14

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

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

Essayez-le en ligne!

Prend l'entrée en tant que liste de tuples / listes à deux éléments de nombres à virgule flottante

Explication

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

Maths - Quelle partie du segment de droite est exposée à la lumière?

Une montagne mal dessinée

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

x3x2x1x3x2x1=y1ymaxy1x3=(y1ymax)(x2x1)y1

L=(y1ymax)2+x32

En joignant les deux formules, nous arrivons à l'expression suivante, qui est au cœur de cette approche:

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

Code - Comment ça marche?

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

  • Optimisé progressivement la formule à des fins de golf.

  • Enregistré 1 octet grâce à FlipTack .

  • Vous avez sauvegardé 2 octets en supprimant la condition inutile y>Y, puisque si le maximum local de la coordonnée Y après le point actuel soustrait yest positif, cette condition est redondante. Cela invalide malheureusement le golf de FlipTack, cependant.

  • Vous avez économisé 3 octets en modifiant légèrement l’algorithme: au lieu d’avoir une variable de compteur, de l’incrémenter et de réduire la liste, vous supprimez le premier élément à chaque itération.

  • Sauvegardé 8 octets grâce à ovs ; changer (x,y),(X,Y)dans la condition de boucle avec une list.pop()technique.

  • 2 octets sauvés grâce à Ørjan Johansen (optimisé un peu la formule).


12

JavaScript, 97 octets

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 octets peuvent être enregistrés si la version inversée de l'entrée est considérée comme valide.)


10

APL + WIN, 48 octets

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

Demande une liste de coordonnées x suivie d'une liste de coordonnées y

Explication

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)

Les distances verticales éclairées = h et les distances horizontales éclairées sont (3) * (1) / (2). Le reste est Pythagore.


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

Malheureusement, mon ancienne version APL + WIN n'a pas d' opérateur, donc je ne peux pas dire
Graham

@Cows Quack Nous avons réussi à l'essayer dans une ancienne version de Dyalog Unicode (v13) et votre suggestion fonctionne
Graham

6

Rapide , 190 octets

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

Essayez-le en ligne!

Explication

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 octets

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

Essayez-le en ligne!


Étant donné que nous sommes autorisés à prendre une liste de valeurs x et une liste de valeurs y en tant que deux entrées, je suis presque certain que nous pourrions utiliser une liste de coordonnées en sens inverse, éliminant ainsi la nécessité de [::-1].
Jonathan Allan

3

Python 2 , 89 octets

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

Essayez-le en ligne!

Prend une liste de paires de flotteurs. Basé sur la solution d'ovs .


Pensez que nous pouvons prendre une liste inversée (nous sommes autorisés à prendre x et y en tant que listes séparées), afin que vous puissiez supprimer le fichier [::-1].
Jonathan Allan

1

APL (Dyalog Unicode) , SBCS sur 31 octets

Utilise la formule de Graham .

Fonction de préfixe anonyme prenant une matrice de données 2 × n comme argument correct. La première ligne contient les valeurs x de droite à gauche et la seconde les valeurs y correspondantes.

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

Essayez-le en ligne!

{} Lambda anonyme où est l'argument:

2-/⍵ deltas (lit. moins les réductions par paire)

÷⌿Ax / Ay (lit. La réduction de la division verticale)

×⍨ square (lit. multiplication selfie)

1+ un ajouté à cela

( Multipliez ce qui suit avec cela:

  2⌷⍵ deuxième ligne de l'argument (les valeurs y)

  ⌈\ course maximale (hauteur la plus haute atteinte jusqu'à maintenant, en partant de la droite)

  2-/ deltas de (lit. moins la réduction par paire)

  ×⍨ square (lit. multiplication selfie)

.5*⍨racine carrée (lit. élevez cela à la puissance d'une moitié)

+/ somme


1

Gelée , 23 octets

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

Un lien dyadique prenant une liste de valeurs y à gauche et une liste des valeurs x respectives à droite (comme explicitement autorisé par le PO dans les commentaires)

Essayez-le en ligne!

Comment?

La fraction d'une section (en pente) qui est allumée est la même fraction qui serait allumée s'il s'agissait d'une chute verticale. Notez que, étant donné que la quadrature est utilisée pour évaluer les longueurs de pente, les hauteurs calculées le long du chemin peuvent être négatives (également dans la partie inférieure, les longueurs des pistes éclairées sont calculées en tant que négatives divisées par négatives).

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

Version monadique à 25 octets en prenant une liste de [x,y]coordonnées:

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

Essaye celui-là.


1
L'entrée peut être deux listes de valeurs. J'ai demandé à l'OP il y a quelque temps et ils m'ont dit que c'était bien .
M. Xcoder

J'ai l'impression qu'il y a trop de s et s.
Jonathan Allan

0

Kotlin , 178 octets

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

Essayez-le en ligne!

La partie test n’est pas vraiment jouée au golf :)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.