Насколько горит эта гора? 🔥


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

Здесь есть два подсвеченных сегмента, как показано на этом изображении: Test Case Pic первый имеет длину 5000/2 = 2500, а второй имеет длину 3700.

Это , поэтому выигрывает самый короткий ответ в байтах.


1
Подсказка: при нахождении длины сегмента необходимо учитывать три точки: две конечные точки и точку, которая «блокирует» ее (на 2-м рисунке это будет (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

Они не горят. Свет, будучи совершенно горизонтальным, может идти только параллельно им и никогда не попадать на них. Я отредактировал проблему, чтобы прояснить это.
сфальсифицировано

Ответы:


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

Попробуйте онлайн!

Принимает ввод как список кортежей / двухэлементных списков чисел с плавающей точкой.

объяснение

Мы в основном перебираем пары точек на графике, и если , то мы вычисляем, сколько линии подвергается воздействию света. Попарная итерация выполняется с циклом, чтобы получить следующую точку , каждый раз выталкивая первый элемент в списке для извлечения текущей точки . ( x 2 , y 2 ) ( x 1 , y 1 )Y1>Y2for(Икс2,Y2)(Икс1,Y1)

Математика. Какая часть отрезка подвергается воздействию света?

Плохо нарисованная гора

Пусть - координаты текущей точки. Пусть - максимальная высота точки после текущей (локальные максимумы после текущей точки), а - координаты следующей точки. Чтобы вычислить длину, выставленную на солнце, , мы должны найти , как показано на диаграмме. Естественно, если , сегмент вообще не подвергается воздействию света.y m a x ( x 2 , y 2 ) L x 3 y 1y m a x(Икс1,Y1)YмaИкс(Икс2,Y2)LИкс3Y1YмaИкс

В сформированном треугольнике отрезок длиной параллелен основанию длиной , поэтому все три угла совпадают. Следовательно, из основной теоремы подобия (случай Угол-угол) мы можем вывести, что . Следовательно, . Затем мы можем применить теорему Пифагора и найти:Икс3Икс2-Икс1Икс3Икс2-Икс1знак равноY1-YмaИксY1Икс3знак равно(Y1-YмaИкс)(Икс2-Икс1)Y1

Lзнак равно(Y1-YмaИкс)2+Икс32

Соединяя две формулы, мы получаем следующее выражение, которое является ядром этого подхода:

Lзнак равно(Y1-YмaИкс)2+((Y1-YмaИкс)(Икс2-Икс1)Y1)2
Lзнак равно(Y1-YмaИкс)2(1+(Икс2-Икс1)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.

Изменения

  • Постепенно оптимизирована формула для игры в гольф.

  • Сохранено 1 байт благодаря FlipTack .

  • Сохранены 2 байта путем удаления ненужного условия y>Y, поскольку, если локальные максимумы Y- координаты после текущей точки, вычтенной из y, положительны, то это условие является избыточным. Это, к сожалению, делает гольф FlipTack недействительным.

  • Сэкономили 3 байта, немного изменив алгоритм: вместо того, чтобы иметь переменную счетчика, увеличивать ее и составлять список, мы удаляем первый элемент на каждой итерации.

  • Сохранено 8 байтов благодаря ovs ; изменение (x,y),(X,Y)в состоянии цикла с помощью list.pop()техники.

  • Сохранено 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

Запрашивает список координат х, а затем список координат у

объяснение

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 quack Удалось попробовать его в старой версии Dyalog Unicode (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

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].
Джонатан Аллан

3

Python 2 , 89 байт

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

Попробуйте онлайн!

Принимает в список пар поплавков. На основании решения ovs .


Подумайте, что мы можем взять обратный список (нам разрешено принимать x и y как отдельные списки), поэтому вы можете отбросить [::-1].
Джонатан Аллан

1

APL (Dyalog Unicode) , 31 байт SBCS

Использует формулу Грэма .

Функция анонимного префикса, принимающая 2 × n матрицу данных в качестве правильного аргумента. Первая строка содержит значения x справа налево, а вторая строка - соответствующие значения y.

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

Попробуйте онлайн!

{... } анонимная лямбда, где аргумент:

2-/⍵ дельты (букв. попарно минус-сокращения)

÷⌿ΔxΔy (букв. Уменьшение вертикального деления)

×⍨ квадрат (лит. умножение селфи)

1+ один добавил к этому

(...  умножьте на это следующее:

  2⌷⍵ вторая строка аргумента (значения у)

  ⌈\ максимальный пробег (самая высокая высота, достигнутая до сих пор, идущая справа)

  2-/ дельты от (лит. попарно минус-сокращение)

  ×⍨ квадрат (лит. умножение селфи)

.5*⍨квадратный корень (лит. поднять это до степени половины)

+/ сумма


1

Желе , 23 байта

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

Диадическая ссылка, содержащая список значений y слева и список соответствующих значений x справа (как явно разрешено ФП в комментариях)

Попробуйте онлайн!

Как?

Часть освещенного (наклонного) участка - это та же доля, которая была бы освещена, если бы это была вертикальная капля. Обратите внимание, что, поскольку для оценки длины склона происходит возведение в квадрат, рассчитанные высоты вдоль пути могут быть отрицательными (также в приведенных ниже длинах трасс освещенных склонов рассчитываются как отрицательные, деленные на отрицательные).

ṀÐƤḊ_⁸«©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-байтовая монадическая версия со списком [x,y]координат:

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

Попробуй это.


1
На входе может быть два списка значений. Я спросил у ОП некоторое время назад, и они сказали, что все в порядке .
г-н Xcoder

Я чувствую, что есть слишком много с и с.
Джонатан Аллан

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.