La regla de Naismith

12

La regla de Naismith ayuda a calcular el tiempo necesario para una caminata o caminata, dada la distancia y el ascenso.

Dada una lista no vacía de la altitud en puntos espaciados uniformemente a lo largo de un camino y la distancia total de ese camino en metros, debe calcular el tiempo necesario de acuerdo con la regla de Naismith.

La regla de Naismith es que debe permitir una hora por cada cinco kilómetros, más una hora adicional por cada 600 metros de ascenso.

La entrada debe tomarse en metros, que se garantiza que consisten en enteros no negativos, y la salida debe ser consistentemente de horas o minutos (pero no de ambos), y debe poder dar números decimales cuando corresponda (las inexactitudes de coma flotante están bien) .

Por ejemplo, dado:

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

Para los dos primeros elementos [100, 200]tiene 100 metros de ascenso, que son 10 minutos. Con [200, 400]usted tiene 200 metros de ascenso que son 20 minutos, [400, 200]no asciende, por lo que no se agrega tiempo para eso. [200, 700]Hay 500 metros de ascenso, que son 50 minutos, y finalmente [700, 400]no asciende. Se agrega una hora adicional para la distancia de cinco kilómetros. Esto suma 140 minutos o 2.333 ... horas.

Casos de prueba

[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
fuente
Todos los resultados de los casos de prueba tienen resultados de minutos completos, ¿es intencional? ¿Las entradas son similares [10], 5125o [10, 25, 55], 1000válidas y deben manejarse?
sundar - Restablece a Monica el
@sundar Sí, deberían.
Okx
[10, 25, 55], 1000 -> 0.275 OR 16.5
Khuldraeseth na'Barya

Respuestas:

6

R ,  44  43 42 bytes

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

Pruébalo en línea!

-1 byte usando pmaxcomo múltiples otras respuestas hacen

Toma entradas como Aaroma e Disancia, y devuelve el tiempo en 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
fuente
Puede obtener 4 bytes más usando pryr :: f (sum (pmax (0, diff (A)), D * .12) / 10) en lugar de usar la función
Shayne03
@ Shayne03 que técnicamente cambiaría esta respuesta a "R + pryr", que según las reglas del sitio cuenta como un lenguaje diferente al de la base R, así que lo mantendré como está. Gracias por la sugerencia, sin embargo!
Giuseppe
La explicación tiene forma de colina
user70585
3

JavaScript (ES6), 50 bytes

Guardado 1 byte gracias a la respuesta de Giuseppe (dividido por 10 al final del proceso)

Toma entrada como ([altitudes])(distance). Devuelve el tiempo en minutos.

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

Pruébalo en línea!

Arnauld
fuente
2

05AB1E , 15 bytes

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

Pruébalo en línea!

Devuelve el tiempo en minutos.

Explicación

              + # 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
fuente
Casi exactamente lo que tenía en mente. La única diferencia que tuve fue en ₄12//lugar de ₄;6//. Tan obvio +1 de mi parte.
Kevin Cruijssen
2

Haskell, 47 46 bytes

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

Devuelve el tiempo en horas.

Pruébalo en línea!

nimi
fuente
2

Python 2, 62 60 bytes

Guardado 2 bytes gracias a los ovs.

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

Pruébalo en línea!

Devuelve el tiempo en 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
Triggernometry
fuente
60 bytes
ovs
2

Perl 6 ,45 39 37 bytes

6 bytes guardados gracias a Jo King.

2 bytes guardados gracias a nwellnhof.

(Gracias a ambos, esto ya no se parece en nada a mi presentación original :—).)

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

Pruébalo en línea!

El primer argumento es la lista con elevaciones, el segundo argumento es la duración de la caminata.

Todo el asunto es un WhateverCode. Si una expresión se reconoce como tal, entonces cada *uno es un argumento.

Entonces, en *.&{sum (.skip Z-$_)Xmax 0}/600, tomamos el primer argumento (la primera aparición de *) y usamos un bloque con una construcción similar a un método .&{}. El bloque toma un argumento (la lista), que entra $_, así .skipes esa lista sin el primer elemento. Restamos la matriz original, elemento por elemento, de eso, usando Z-. La compresión se detiene tan pronto como se agota la lista más corta, lo cual está bien.

Luego usamos el operador de productos cruzados X. list X(op) listcrea todos los pares posibles donde el primer elemento es de la lista izquierda y el segundo de la derecha, y utiliza el operador (op)en ellos. El resultado se devuelve como Seq (una lista de una sola vez). Sin embargo, la lista de la derecha tiene solo un elemento, 0, por lo que simplemente lo hace * max 0, elemento por elemento. Eso asegura que solo contamos las partes ascendentes de la caminata. Luego lo sumamos y dividimos por 600.

Luego agregamos */5e3, donde *ocurre por segunda vez, y entonces es el segundo argumento, y lo dividimos entre 5000. La suma es el tiempo en horas. (Esto es más eficiente que el tiempo en minutos, ya que tendríamos que multiplicar, y *tendría que estar separado por un espacio del WhateverStar *).

Ramillies
fuente
1
42 bytes usandoX
Jo King
@JoKing, es un buen uso de X¡gracias!
Ramillies
1
En realidad, podemos evitar el último X/simplemente dividiendo la suma por 10. 39 bytes
Jo King
37 bytes usando CualquieraCódigo y .&{}(devuelve horas).
nwellnhof
2

ok , 21 bytes

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

Pruébalo en línea! Abusar de un error de análisis donde .1.012es lo mismo 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 gracias a streester .

k , 23 bytes

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

Pruébalo en línea!

zgrep
fuente
{y+/0|1_-':x}..1.012*por 21 bytes? iniciar acumulador con y.
Callejero
¡En efecto! Aplicaría una mejora similar al código k, pero desafortunadamente al intérprete k que tengo (2016.08.09) no le gusta que inicie el acumulador con nada de esa manera. :/
zgrep
1

Pyth , 15 bytes

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

Programa completo, espera el conjunto de alturas como primer argumento, la distancia como segundo. Devuelve el tiempo en minutos.

Pruébelo en línea aquí , o verifique todos los casos de prueba a la vez aquí .

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

APL (Dyalog Unicode) , 21 20 18 bytes

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

Pruébalo en línea!

Función tradicional tomando entrada (de derecha a izquierda) como 1st ⎕= Alturas / Profundidades, 2nd ⎕= Distancia.

Gracias a @ngn para ser un mago uno de tres bytes.

Cómo 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é
fuente
gracias por "wizard" :) no tienes que copiar la expresión varias veces para probarla, ponla en un tradfn ; ,0es innecesario, la prueba problemática debería ser ,604, no604
ngn
Mira, por eso eres un mago. La copia de la expresión varias veces es totalmente mi culpa, simplemente reemplacé el y en el código anterior con y era demasiado vago para poner el encabezado / pie de página tradfn. El ,0bit de embargo? Oro.
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;}

Pruébalo en línea.

Explicación:

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
fuente
0

Japt , 39 bytes

0oUl)x@W=UgXÄ -UgX)g ¥É?0:W/#ɘ} +V/(#Ǵ0

Pruébalo en línea!

Probablemente se puede jugar al golf un poco más.

Bejofo
fuente
0

Stax , 17 bytes

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

¡Ejecútelo y depúrelo en staxlang.xyz!

Toma todas las entradas como flotantes, aunque esto guarda un byte solo en la versión desempaquetada. Probablemente mejorable; justo ahora volviendo al golf de código, estoy algo oxidado.

Desempaquetado (20 bytes) y explicación:

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|++ funciona para entradas integrales para 21 bytes sin empaquetar y aún con 17 paquetes.

Khuldraeseth na'Barya
fuente