La règle de Naismith

12

La règle de Naismith aide à déterminer la durée nécessaire pour une marche ou une randonnée, compte tenu de la distance et de l'ascension.

Étant donné une liste non vide de l'altitude à des points régulièrement espacés le long d'un chemin et la distance totale de ce chemin en mètres, vous devez calculer le temps nécessaire selon la règle de Naismith.

La règle de Naismith est que vous devez prévoir une heure pour tous les cinq kilomètres, plus une heure supplémentaire pour chaque 600 mètres de montée.

L'entrée doit être prise en mètres, ce qui est garanti d'être composé d'entiers non négatifs, et la sortie doit toujours être en heures ou en minutes (mais pas les deux), et doit pouvoir donner des nombres décimaux le cas échéant (les inexactitudes en virgule flottante sont OK) .

Par exemple, étant donné:

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

Pour les deux premiers éléments, [100, 200]vous avez 100 mètres de montée soit 10 minutes. Avec [200, 400]200 mètres de dénivelé soit 20 minutes, [400, 200]pas de montée donc pas de temps ajouté pour ça. [200, 700]est de 500 mètres de montée qui est de 50 minutes, et enfin [700, 400]n'est pas ascendant. Une heure supplémentaire est ajoutée pour la distance de cinq kilomètres. Cela totalise 140 minutes ou 2,333 ... heures.

Cas de test

[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
la source
Les sorties des cas de test ont toutes des résultats d'une minute entière, est-ce intentionnel? Les entrées sont-elles similaires [10], 5125ou [10, 25, 55], 1000valides et doivent-elles être traitées?
sundar
@sundar Oui, ils devraient.
Okx
[10, 25, 55], 1000 -> 0.275 OR 16.5
Khuldraeseth na'Barya

Réponses:

6

R ,  44  43 42 octets

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

Essayez-le en ligne!

-1 octet en utilisant pmaxcomme le font plusieurs autres réponses

Prend les entrées comme Aparfum et Ddistance, et renvoie le temps en minutes.

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
la source
Vous pouvez obtenir 4 octets supplémentaires en utilisant pryr :: f (sum (pmax (0, diff (A)), D * .12) / 10) au lieu d'utiliser la fonction
Shayne03
@ Shayne03 qui changerait techniquement cette réponse en "R + pryr" qui, selon les règles du site, compte comme un langage différent de la base R, donc je vais garder cela tel quel. Merci pour la suggestion!
Giuseppe
L'explication a la forme d'une colline
user70585
3

JavaScript (ES6), 50 octets

1 octet enregistré grâce à la réponse de Giuseppe (division par 10 à la fin du processus)

Prend l'entrée comme ([altitudes])(distance). Renvoie le temps en minutes.

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

Essayez-le en ligne!

Arnauld
la source
2

05AB1E , 15 octets

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

Essayez-le en ligne!

Renvoie le temps en minutes.

Explication

              + # 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
la source
Presque exactement ce que j'avais en tête. La seule différence que j'avais était ₄12//au lieu de ₄;6//. +1 si évident de ma part.
Kevin Cruijssen
2

Haskell, 47 46 octets

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

Renvoie l'heure en heures.

Essayez-le en ligne!

nimi
la source
2

Python 2, 62 60 octets

Enregistré 2 octets grâce aux ovs.

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

Essayez-le en ligne!

Renvoie le temps en minutes.

# 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
Triggernométrie
la source
60 octets
ovs
2

Perl 6 ,45 39 37 octets

6 octets économisés grâce à Jo King.

2 octets économisés grâce à nwellnhof.

(Merci à tous les deux, cela ne ressemble plus à ma soumission originale :—).)

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

Essayez-le en ligne!

Le premier argument est la liste des élévations, le deuxième argument est la longueur du trek.

Le tout est un WwhatCode. Si une expression est reconnue comme telle, alors chacun *est un argument.

Donc, dans *.&{sum (.skip Z-$_)Xmax 0}/600, nous prenons le premier argument (la première occurrence de *), et utilisons un bloc dessus avec une construction de type méthode .&{}. Le bloc prend un argument (la liste), qui entre $_, tout .skipcomme cette liste sans le premier élément. Nous soustrayons le tableau d'origine, élément par élément, de celui-ci en utilisant Z-. Le zip s'arrête dès que la liste la plus courte est épuisée, ce qui est OK.

Nous utilisons ensuite l'opérateur de produits croisés X. list X(op) listcrée toutes les paires possibles où le premier élément est de la liste de gauche et le second de la droite, et utilise l'opérateur (op)sur elles. Le résultat est renvoyé sous forme de Seq (une liste unique). Cependant, la liste de droite n'a qu'un seul élément, 0, donc c'est le cas * max 0, élément par élément. Cela garantit que nous ne comptons que les parties ascendantes du trek. Ensuite, nous additionnons et divisons par 600.

Ensuite, nous ajoutons */5e3, où le *se produit pour la deuxième fois, et c'est donc le deuxième argument, et le divisons par 5000. La somme est alors le temps en heures. (C'est plus efficace que le temps en minutes car nous aurions besoin de nous multiplier, et le *devrait être séparé par un espace du WwhatStar *.)

Ramillies
la source
@JoKing, c'est une bonne utilisation de X, merci!
Ramillies du
1
En fait, nous pouvons éviter le dernier X/en divisant simplement la somme par 10. 39 octets
Jo King
37 octets en utilisant WwhatCode et .&{}(renvoie des heures).
nwellnhof
2

oK , 21 octets

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

Essayez-le en ligne! Abuser d'un bug d'analyse où .1.012est le même 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 grâce à streester .

k , 23 octets

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

Essayez-le en ligne!

zgrep
la source
{y+/0|1_-':x}..1.012*pour 21 octets? démarrer l'accumulateur avec y.
streetster
En effet! J'appliquerais une amélioration similaire au code k, mais malheureusement l'interpréteur k que j'ai (2016.08.09) n'aime pas que je démarre l'accumulateur avec quoi que ce soit de cette façon. :/
zgrep
1

Gelée , 12 octets

×.12;I}»0÷⁵S

Essayez-le en ligne!

-1 merci à M. Xcoder .

Erik le Outgolfer
la source
1
Ça ne ×.12marche pas ?
M. Xcoder
@ Mr.Xcoder Oui, j'étais pressé.
Erik the Outgolfer
1

Pyth , 15 octets

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

Programme complet, attend l'ensemble des hauteurs comme premier argument, la distance comme second. Renvoie le temps en minutes.

Essayez-le en ligne ici ou vérifiez tous les cas de test en même temps ici .

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
la source
1

APL (Dyalog Unicode) , 21 20 18 octets

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

Essayez-le en ligne!

Fonction traditionnelle prenant l'entrée (de droite à gauche) comme 1st ⎕= Hauteurs / Profondeurs, 2nd ⎕= Distance.

Merci à @ngn d' être un assistant un octet.

Comment ça fonctionne:

.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é
la source
merci pour "wizard" :) vous n'avez pas à copier l'expression plusieurs fois pour la tester, mettez-la à la place dans un tradfn ; ,0n'est pas nécessaire, le test problématique devrait être ,604, non604
ngn
Vous voyez, c'est pourquoi vous êtes un sorcier. La copie de l'expression plusieurs fois est totalement de ma faute, je viens de remplacer le et dans l'ancien code par et j'étais trop paresseux pour mettre l'en-tête / pied de page tradfn. Le ,0bit bien? Or.
J. Sallé
0

Java 8, 89 octets

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

Essayez-le en ligne.

Explication:

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
la source
0

Stax , 17 octets

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

Exécutez-le et déboguez-le sur staxlang.xyz!

Prend toutes les entrées sous forme de flottants, bien que cela n'économise un octet que dans la version décompressée. Probablement améliorable; revenant tout juste au code golf, je suis un peu rouillé.

Déballé (20 octets) et explication:

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|++ fonctionne pour les entrées intégrales pour 21 octets déballés et encore 17 emballés.

Khuldraeseth na'Barya
la source