Regra de Naismith

12

A regra de Naismith ajuda a calcular o tempo necessário para uma caminhada ou caminhada, dada a distância e a subida.

Dada uma lista não vazia da altitude em pontos uniformemente espaçados ao longo de um caminho e a distância total desse caminho em metros, você deve calcular o tempo necessário de acordo com a regra de Naismith.

A regra de Naismith é que você deve permitir uma hora a cada cinco quilômetros, mais uma hora adicional a cada 600 metros de subida.

A entrada deve ser calculada em metros, que é garantido consistir em números inteiros não negativos, e a saída deve consistentemente ser horas ou minutos (mas não os dois) e deve poder fornecer números decimais onde aplicável (as imprecisões de ponto flutuante são aceitáveis) .

Por exemplo, dado:

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

Para os dois primeiros elementos, [100, 200]você tem 100 metros de subida, ou seja, 10 minutos. Com [200, 400]você tem 200 metros de subida, ou seja, 20 minutos, [400, 200]não está subindo, então não há tempo para isso. [200, 700]é de 500 metros de subida, que é de 50 minutos, e finalmente [700, 400]não está subindo. Uma hora extra é adicionada pela distância de cinco quilômetros. Isso totaliza 140 minutos ou 2,333 ... horas.

Casos de teste

[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
fonte
As saídas dos casos de teste têm resultados de um minuto inteiro, isso é intencional? As entradas são iguais [10], 5125ou [10, 25, 55], 1000válidas e precisam ser manuseadas?
Sundar - Restabelece Monica
@ Sundar Sim, eles deveriam.
Okx 07/08/19
[10, 25, 55], 1000 -> 0.275 OR 16.5
Khuldraeseth na'Barya 08/08/19

Respostas:

6

R ,  44  43 42 bytes

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

Experimente online!

-1 byte usando pmaxcomo várias outras respostas

Toma as entradas como Aperfume e Distance e retorna o tempo em minutos.

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
fonte
Você pode obter mais 4 bytes utilizando Pryr :: f (soma (pmax (0, diff (A)), D * .12) / 10) em vez de usar a função
Shayne03
@ Shayne03 que tecnicamente alteraria essa resposta para "R + pryr", que nas regras do site conta como um idioma diferente do que a base R, então continuarei assim. Obrigado pela sugestão, no entanto!
Giuseppe
A explicação tem a forma de uma colina
user70585
3

JavaScript (ES6), 50 bytes

Economizou 1 byte graças à resposta de Giuseppe (dividindo por 10 no final do processo)

Toma entrada como ([altitudes])(distance). Retorna o tempo em minutos.

a=>d=>a.map(p=n=>d-=(x=p-(p=n))<0&&x,d*=.12)&&d/10

Experimente online!

Arnauld
fonte
2

05AB1E , 15 bytes

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

Experimente online!

Retorna o tempo em minutos.

Explicação

              + # 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
fonte
Quase exatamente o que eu tinha em mente. A única diferença que tive foi em ₄12//vez de ₄;6//. Um +1 tão óbvio de mim.
Kevin Cruijssen
2

Haskell, 47 46 bytes

d#l@(_:t)=d/5e3+sum(max 0<$>zipWith(-)t l)/600

Retorna o tempo em horas.

Experimente online!

nimi
fonte
2

Python 2, 62 60 bytes

Economizou 2 bytes graças a ovs.

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

Experimente online!

Retorna o tempo em minutos.

# 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
Triggernometria
fonte
60 bytes
ovs 6/08/08
2

Perl 6 ,45 39. 37 bytes

6 bytes salvos graças a Jo King.

2 bytes salvos graças ao nwellnhof.

(Graças a ambos, isso não se parece mais com o meu envio original: --).)

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

Experimente online!

O primeiro argumento é a lista com elevações, o segundo argumento é a duração da caminhada.

A coisa toda é um WhateverCode. Se uma expressão for reconhecida como tal, cada *um será um argumento.

Então, em *.&{sum (.skip Z-$_)Xmax 0}/600, pegamos o primeiro argumento (a primeira ocorrência de *) e usamos um bloco nele com uma construção semelhante a um método .&{}. O bloco aceita um argumento (a lista), que entra $_, assim .skipcomo essa lista sem o primeiro elemento. Subtraímos a matriz original, elemento a elemento, disso, usando Z-. O zíper pára assim que a lista mais curta é esgotada, o que é bom.

Em seguida, usamos o operador de produto cruzado X. list X(op) listcria todos os pares possíveis em que o primeiro elemento é da lista da esquerda e o segundo da direita e usa o operador (op)neles. O resultado é retornado como uma Seq (uma lista única). No entanto, a lista correta possui apenas um elemento, 0, portanto * max 0, elemento a elemento. Isso garante que contemos apenas partes ascendentes da jornada. Depois, somamos e dividimos por 600.

Em seguida, adicionamos */5e3onde *ocorre pela segunda vez e, portanto, é o segundo argumento, e o dividimos por 5000. A soma é então o tempo em horas. (Isso é mais eficiente que o tempo em minutos, já que precisaríamos nos multiplicar e *precisaria ser separado por um espaço do WhateverStar *.)

Ramillies
fonte
1
42 bytes usandoX
Jo King
@ JoKing, é um bom uso X, obrigado!
Ramillies
1
Na verdade, podemos evitar o último X/por apenas dividindo a soma por 10. 39 bytes
Jo rei
37 bytes usando WhateverCode e .&{}(retorna horas).
Nwellnhof 7/08
2

OK , 21 bytes

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

Experimente online! Abusar de um bug de análise onde .1.012é o mesmo que .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 graças a streester .

k , 23 bytes

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

Experimente online!

zgrep
fonte
{y+/0|1_-':x}..1.012*por 21 bytes? inicie o acumulador com y.
Streetster
De fato! Eu aplicaria um aprimoramento semelhante ao código k, mas infelizmente o intérprete k que eu tenho (08.08.2016) não gosta que eu inicie o acumulador com algo dessa maneira. :/
Zgrep 08/08/19
1

Gelatina , 12 bytes

×.12;I}»0÷⁵S

Experimente online!

-1 graças ao Sr. Xcoder .

Erik, o Outgolfer
fonte
1
Não ×.12funciona?
Mr. Xcoder
@ Mr.Xcoder Sim, eu estava com pressa.
Erik the Outgolfer
1

Pitão , 15 bytes

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

Programa completo, espera que o conjunto de alturas seja o primeiro argumento, a distância como o segundo. Retorna o tempo em minutos.

Experimente on-line aqui ou verifique todos os casos de teste de uma vez aqui .

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
fonte
1

APL (Dyalog Unicode) , 21 20 18 bytes

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

Experimente online!

Função tradicional recebendo entrada (da direita para a esquerda) como 1st ⎕= Alturas / profundidades, 2nd ⎕= Distância.

Graças a @ngn para ser um assistente de um de três bytes.

Como funciona:

.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;
J. Sallé
fonte
obrigado por "wizard" :) você não precisa copiar a expressão várias vezes para testá-la, coloque-a em um tradfn ; ,0é desnecessário, o para o teste problemática deve ser ,604, não604
NGN
Veja, é por isso que você é um mago. A cópia da expressão várias vezes parte é totalmente minha culpa, eu apenas substituí o e no código antigo por e fiquei com preguiça de colocar o cabeçalho / rodapé do tradfn. O ,0pouco embora? Ouro.
J. Sallé
0

Java 8, 89 bytes

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

Experimente online.

Explicação:

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
Kevin Cruijssen
fonte
0

Stax , 17 bytes

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

Execute e depure-o em staxlang.xyz!

Toma todas as entradas como flutuantes, embora isso economize um byte apenas na versão descompactada. Provavelmente improvável; Agora, voltando ao código de golfe, estou um pouco enferrujado.

Descompactado (20 bytes) e explicação:

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|++ trabalha para entradas integrais para 21 bytes descompactados e ainda 17 compactados.

Khuldraeseth na'Barya
fonte