Правление Нейсмита

12

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

Учитывая непустой список высоты в точках, равномерно распределенных вдоль пути, и общее расстояние этого пути в метрах, вы должны рассчитать время, необходимое в соответствии с правилом Нейсмита.

Правило Нейсмита заключается в том, что вы должны отводить один час на каждые пять километров плюс дополнительный час на каждые 600 метров восхождения.

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

Например, учитывая:

[100, 200, 400, 200, 700, 400], 5000

Для первых двух элементов у [100, 200]вас есть 100 метров подъема, что составляет 10 минут. У [200, 400]вас есть 200 метров подъема, что составляет 20 минут, [400, 200]не поднимается, поэтому время для этого не добавляется. [200, 700]500 метров подъема, что составляет 50 минут, и, наконец [700, 400], не поднимается. Один дополнительный час добавляется на расстояние в пять километров. Это составляет 140 минут или 2,333 ... часов.

Тестовые случаи

[0, 600] 2500 -> 1.5 OR 90
[100, 200, 300, 0, 100, 200, 300] 10000 -> 2.8333... OR 170
[40, 5, 35] 1000 -> 0.25 OR 15
[604] 5000 -> 1 OR 60
[10, 10, 10] 2000 -> 0.4 OR 24
[10, 25, 55] 1000 -> 0.275 OR 16.5
Okx
источник
Все результаты тестовых случаев имеют результаты в минуту, это намеренно? Являются ли входные данные похожими [10], 5125или [10, 25, 55], 1000действительными и должны ли обрабатываться?
sundar - Восстановить Монику
@sundar Да, они должны.
Okx
[10, 25, 55], 1000 -> 0.275 OR 16.5
Хулдраесет на'Барья

Ответы:

6

R ,  44  43 42 байта

function(A,D)sum(pmax(0,diff(A)),D*.12)/10

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

-1 байт, используя pmaxнесколько других ответов

Принимает входные данные как Aзапах и Distance, и возвращает время в минутах.

function(A,D)                                 # take Ascent and Distance
                        diff(A)               # take successive differences of ascents
                 pmax(0,       )              # get the positive elements of those
                                 D*.12        # multiply distance by 0.12
             sum(               ,     )       # take the sum of all elements
                                       /10    # and divide by 10, returning the result

Giuseppe
источник
Вы можете получить еще 4 байта, используя pryr :: f (сумма (pmax (0, diff (A)), D * .12) / 10) вместо использования функции
Shayne03
@ Shayne03, который технически изменит этот ответ на «R + pryr», который по правилам сайта считается языком, отличным от базового R, поэтому я оставлю это как есть. Спасибо за предложение, хотя!
Джузеппе
Объяснение имеет форму холма
user70585
2

05AB1E , 15 байтов

¥ʒ0›}OT÷s₄;6//+

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

Возвращает время в минутах.

объяснение

              + # sum of ...
¥ʒ0›}OT÷        # the sum of positive deltas of the altitude divided by 10
        s₄;6//  # the distance divided by 83.33333333 (500/6, or the amount of meters per minute) 
Kaldo
источник
Почти именно то, что я имел в виду. Единственное отличие, которое у меня было, было ₄12//вместо ₄;6//. Так очевидно +1 от меня.
Кевин Круйссен
2

Python 2, 62 60 байт

Сохранено 2 байта благодаря ovs.

lambda e,d:sum((a-b)*(a>b)for a,b in zip(e[1:],e))*.1+d*.012

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

Возвращает время в минутах.

# add all increasing slope differences together
sum(
    # multiply the difference by 0 if a<b, else by 1
    (a-b)*(a>b)
                # create a list of pairs by index, like [(1,0), (2,1) ...(n, n-1)]
                # then interate thru the pairs where a is the higher indexed item and b is the lower indexed item
                for a,b in zip(e[1:],e)
    )
    # * 60 minutes / 600 meters == .1 min/m
    *.1 
    # 60 minutes / 5000 meters = .012 min/m
    +d*.012
Triggernometry
источник
60 байт
овс
2

Perl 6 ,45 39 37 байт

6 байтов сохранено благодаря Джо Кингу.

2 байта сохранены благодаря nwellnhof.

(Благодаря им обоим это больше не похоже на мое первоначальное представление :—).)

*.&{sum (.skip Z-$_)Xmax 0}/600+*/5e3

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

Первый аргумент - это список высот, второй аргумент - это длина пути.

Все дело в том, что угодно. Если выражение распознается как таковое, то каждый *является одним аргументом.

Таким образом, *.&{sum (.skip Z-$_)Xmax 0}/600мы берем первый аргумент (первый вхождение *) и используем для него блок с методоподобной конструкцией .&{}. Блок принимает один аргумент (список), который входит в список $_, так же .skipкак и этот список без первого элемента. Мы вычитаем исходный массив, элемент за элементом, из этого, используя Z-. Застежка-молния прекращается, как только сокращается короткий список, и это нормально.

Затем мы используем оператор перекрестного произведения X. list X(op) listсоздает все возможные пары, где первый элемент находится в левом списке, а второй справа, и использует оператор (op)для них. Результат возвращается как Seq (одноразовый список). Тем не менее, правый список имеет только один элемент, 0, так что он просто * max 0, элемент за элементом. Это гарантирует, что мы считаем только восходящие части пути. Затем мы складываем это и делим на 600.

Затем мы добавляем */5e3, где *происходит второй раз, и, таким образом, это второй аргумент, и делим его на 5000. Сумма - это время в часах. (Это более эффективно, чем время в минутах, так как нам нужно было бы умножить, и это *должно быть отделено пробелом от WhwhatStar *.)

Ramillies
источник
@ JoKing, это хорошее применение X, спасибо!
Рамилли
1
На самом деле, мы можем избежать последнего X/, просто разделив сумму на 10. 39 байт
Джо Кинг,
37 байтов, используя WhwhatCode и .&{}(возвращает часы).
nwellnhof
2

ОК , 21 байт

{y+/0|1_-':x}..1.012*

Попробуйте онлайн! Злоупотребление ошибкой синтаксического анализа, где так .1.012же, как .1 .012.

              .1.012* /a = [0.1 * input[0], 0.012 * input[1]]
{           }.        /function(x=a[0], y=a[1])
      1_-':x          /  a = subtract pairs of elements from x
    0|                /  a = max(a, 0) w/ implicit map
 y+/                  /  y + sum(a)

-1 спасибо Стристер .

к , 23 байта

{.1*(.12*y)++/0|1_-':x}

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

zgrep
источник
{y+/0|1_-':x}..1.012*на 21 байт? начать аккумулятор с y.
Стритстер
В самом деле! Я бы применил подобное улучшение к коду, но, к сожалению, мой интерпретатор к (2016.08.09) не любит, когда я запускаю аккумулятор с чем-то подобным образом. :/
zgrep
1

Pyth , 15 байт

c+*E.12s>#0.+QT

Полная программа, ожидает набор высот в качестве первого аргумента, расстояние в качестве второго. Возвращает время в минутах.

Попробуйте онлайн здесь или проверьте все тестовые случаи сразу здесь .

c+*E.12s>#0.+QT   Implicit: Q=input 1, E=input 2
           .+Q    Take the differences between each height point
        >#0       Filter to remove negative values
       s          Take the sum
  *E.12           Multiply the distance by 0.12
 +                Add the two previous results
c             T   Divide the above by 10, implicit print
Sok
источник
1

APL (Dyalog Unicode) , 21 20 18 байт

.1×.12⊥⎕,-+/0⌊2-/

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

Традиционная функция, принимающая ввод (справа налево) как 1st ⎕= Высота / Глубина, 2nd ⎕= Расстояние.

Спасибо @ngn за то, что он волшебник один три байта.

Как это устроено:

.1×.12⊥⎕,-+/0⌊2-/  Function;
                   Append 0 to the heights vector;
              2-/  ⍝ Pairwise (2) differences (-/);
            0      Minimum between 0 and the vector's elements;
          +/       ⍝ Sum (yields the negated total height);
         -         ⍝ Subtract from;
   .12⊥⎕,          ⍝ Distance × 0.12;
.1×                ⍝ And divide by 10;
Ж. Салле
источник
спасибо за "мастера" :) вам не нужно копировать выражение несколько раз, чтобы проверить его, вместо этого поместите его в tradfn ; ,0не является необходимым, для проблемного теста должно быть ,604, а не604
нгн
Видишь, вот почему ты волшебник. Копирование выражения несколько раз - моя полная ошибка, я просто заменил и в старом коде на и слишком ленив, чтобы поместить заголовок / нижний колонтитул tradfn. ,0Бит , хотя? Золото.
Ж. Салле
0

Java 8, 89 байт

a->n->{int s=0,p=0,i=a.length;for(;i-->0;p=a[i])s+=(p=p-a[i])>0?p:0;return s/10+n/500*6;}

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

Объяснение:

a->n->{                   // Method with integer-array and integer parameter and integer return-type
  int s=0,                //  Sum-integers, starting at 0
      p=0,                //  Previous integer, starting at 0
  i=a.length;for(;i-->0;  //  Loop `i` backwards over the array
                 ;        //    After every iteration:
                  p=a[i]) //     Set `p` to the current value for the next iteration
    s+=(p=p-a[i])>0?      //   If the previous minus current item is larger than 0:
         p                //    Add that difference to the sum `s`
        :                 //   Else:
         0;               //    Leave the sum the same
   return s/10            //  Return the sum integer-divided by 10
          +n/500*6;}      //  Plus the second input divided by 500 and then multiplied by 6
Кевин Круйссен
источник
0

Stax , 17 байт

ü;█y☼òΓ▀ßîP<<╪⌠öß

Запустите и отладьте его на staxlang.xyz!

Принимает все входные данные как плавающие, хотя это сохраняет байт только в распакованной версии. Вероятно, улучшается; только сейчас возвращаюсь к коду в гольф, я немного ржавый.

Распаковывается (20 байт) и объяснение:

0!012*s:-{0>f{A/m|++
0!012*                  Float literal and multiplication for distance
      s                 Swap top two stack values (altitudes to the top)
       :-               List of deltas
         {0>f           Filter: keep only positive changes
             {A_m       Map: divide all ascents by 10
                 |++    Add these times to that for horizontal travel
                        Implicit print

0!012*s:-{0>f{A_:m|++ работает для интегральных входов для 21 байта без упаковки и до сих пор 17 упакованных.

Хулдрасет на'Барья
источник