Combien de sommets dans ma chaîne de montagnes?

27

Une liste d'entiers positifs peut être visualisée comme une chaîne de montagnes quantifiée où chaque entrée de la liste représente la hauteur d'une section verticale des montagnes.

Par exemple, la liste

1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3

peut devenir la gamme

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(Les gens moins poétiques pourraient appeler cela un graphique à barres, mais je m'égare.)

La question dans ce défi est la suivante: combien de pics se trouvent dans la chaîne de montagnes d'une liste arbitraire? Essentiellement, combien de maxima locaux figurent dans la liste?

Un pic est défini comme une section contiguë d'une ou plusieurs colonnes de la chaîne de montagnes qui sont toutes égales en hauteur, où les colonnes immédiatement à gauche et à droite sont plus basses.

Il est facile de dire visuellement que l'exemple a quatre pics à ces emplacements entre parenthèses:

1, 2, 2, 3, (4), 3, (5), 3, 2, 1, 2, (3, 3, 3), 2, 2, 1, (3)

Notez comment la (3, 3, 3)section de plateau compte comme un pic car il s'agit d'un ensemble contigu de colonnes de hauteur égale, plus élevées que ses colonnes voisines.

Le dernier (3)compte également comme un pic car, pour les besoins de ce défi, nous définirons le voisin gauche de la colonne la plus à gauche et le voisin droit de la colonne la plus à droite comme étant à la hauteur zéro.

Cela signifie que la liste avec une seule valeur, par exemple 1, 1, 1, peut être interprété comme 0, 1, 1, 1, 0, et a donc un pic, non pas: 0, (1, 1, 1), 0.

La seule liste avec zéro pics est la liste vide.

Défi

Écrivez une fonction ou un programme qui prend une liste arbitraire d'entiers positifs et imprime ou renvoie le nombre de pics dans la chaîne de montagnes correspondante.

Le code le plus court en octets gagne. Tiebreaker est un post antérieur.

Cas de test

Input List -> Output Peak Count
[empty list] -> 0
1, 1, 1 -> 1
1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3 -> 4
1 -> 1
1, 1 -> 1
2, 2, 2, 2, 2 -> 1
90 -> 1
2, 1, 2 -> 2
5, 2, 5, 2, 5 -> 3
2, 5, 2, 5, 2, 5, 2 -> 3
1, 2, 3, 4 -> 1
1, 2, 3, 4, 1, 2 -> 2
1, 3, 5, 3, 1 -> 1
7, 4, 2, 1, 2, 3, 7 -> 2
7, 4, 2, 1, 2, 1, 2, 3, 7 -> 3
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 -> 10
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 -> 10
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 -> 10
1, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, 3, 3, 3, 1 -> 4
12, 1, 2, 1, 2, 3, 3, 3, 2, 4, 4, 4, 1, 5, 5, 4, 7, 9 -> 6
87, 356, 37673, 3676, 386, 909, 909, 909, 909, 454, 909, 909 -> 3
87, 356, 37673, 3676, 386, 909, 909, 909, 909, 454, 909, 908, 909 -> 4
Loisirs de Calvin
la source
Ainsi, le plateau peut être arbitrairement long?
nicael
@nicael Oui, ça pourrait être
Calvin's Hobbies
Pouvons-nous prendre l'entrée comme un tableau, pas comme une chaîne?
nicael
@nicael Oui, tout ce qui est raisonnable
Calvin's Hobbies

Réponses:

2

Pyth, 18 octets

su_>VGtG2eMr++ZQZ8

Basé sur @ PeterTaylor répété plus que la solution, mais avec une torsion.

++ZQZ: Ajouter des zéros des deux côtés.

eMr ... 8: Supprimer les répétitions.

u ... 2 ...: Appliquer deux fois ce qui suit:

>VGTG: Mappez chaque paire de nombres pour déterminer s'ils sont en ordre décroissant.

_: Et inverser.

Un 1 en sortie correspond à une 1, 0étape précédente, ce qui correspond à a < b > cl'entrée en raison de l'inversion.

s: Somme (et impression)

isaacg
la source
10

CJam ( 32 26 24 21 octets)

0q~0]e`1f=2ew::>2,/,(

L'entrée attendue est des nombres séparés par des espaces.

Démo en ligne ; suite de tests complète (la sortie attendue est un 1cas de test).

Merci à Martin de m'avoir informé que la version actuelle de CJam améliore l'un des opérateurs utilisés, économisant 2 caractères; et pour une nouvelle économie de 3 caractères.

Dissection

Deux phases: dédupliquer, puis identifier les maxima locaux dans chaque ensemble de trois.

0q~0]      e# Put the input in an array wrapped in [0 ... 0]
e`1f=      e# Use run-length encoding to deduplicate
2ew::>     e# Map [a b c ...] to [(a>b) (b>c) ...]
2,/        e# Split on [0 1], which since we've deduplicated occurs when (a<b) (b>c)
,(         e# Count the parts and decrement to give the number of [0 1]s
Peter Taylor
la source
7

JavaScript (ES6), 54 51 octets

m=>m.map(n=>{h=n<p?h&&!++r:n>p||h;p=n},r=h=p=0)|r+h

Explication

Prend un tableau de nombres

m=>
  m.map(n=>{       // for each number n in the mountain range
      h=
        n<p?       // if the number is less than the previous number:
          h&&      // if the previous number was greater than the number before it
          !++r     // increment the number of peaks and set h to 0
        :n>p||h;   // if the number is greater than the previous number, set h to 1
      p=n          // set p to the current number
    },
    r=             // r = number of peaks
    h=             // h = 1 if the previous number was higher than the one before it
    p=0            // p = previous number
  )|r+h            // return the output (+ 1 if the last number was higher)

Tester

user81655
la source
5

Pyth, 25 23 octets

L._M-M.:b2s<R0y-y+Z+QZZ

Explication:

L              y = lambda b:
  ._M -M .:          signs of subsets
           b          of b
           2          of length 2. That is, signs of differences.

s <R              number of elements less than
     0              0 in
     y -            y of ... with zeroes removed
         y +          y of
             Z        the input with zeroes tacked on both sides
             + Q Z
       Z              
lirtosiast
la source
Agréable. Exceptionnellement, un port vers CJam est plus court: 0q~0]{2ew::-:g0-}2*1-,pour 22.
Peter Taylor
4

Julia, 66 ans

x->(y=diff([0;x;0]);y=y[y.!=0];sum((y[1:end-1].>0)&(y[2:end].<0)))

Pad, différencier: y=diff([0;x;0]).
Ignorer les plateaux: y=y[y.!=0].
Compter +à -passages à zéro: sum((y[1:end-1].>0)&(y[2:end].<0)).

Rainer P.
la source
3

MATLAB, 29 27 octets

@(a)nnz(findpeaks([0 a 0]))

Fonction anonyme qui trouve les pics dans les données et compte le nombre. 0 est ajouté et ajouté aux données pour garantir que les pics aux extrémités sont détectés conformément à la question.

Cela fonctionnera également avec Octave . Vous pouvez essayer en ligne ici . Collez simplement le code ci-dessus dans la ligne de commande, puis exécutez-le avec ans([1,2,1,3,4,5,6,1])(ou toute autre entrée).


Comme les nombres sont toujours + ve, nous pouvons supposer qu'ils sont supérieurs à zéro, donc nous pouvons économiser 2 octets en utilisant nnzau lieu de numel.

Tom Carpenter
la source
3

Python 3, 75 octets

def m(t):
 a=p=d=0
 for n in t+[0]:a+=(n<p)&d;d=((n==p)&d)+(n>p);p=n
 return a

Ceci est mon premier codegolf donc il peut y avoir des endroits pour le réduire, en particulier la d=((n==p)&d)+(n>p)partie. Cependant, cela fonctionne sur tous les cas de test

Cameron Aavik
la source
N'est-ce pas 78 octets ?
Jonathan Frech
3

Mathematica, 42 36 33 32 octets

Merci à Martin Büttner pour avoir économisé 1 octet.

Tr@PeakDetect[#&@@@Split@#,0,0]&

PeakDetect fait presque tout!

Cas de test:

Total@PeakDetect[#&@@@Split@#,0,0]&@{12,1,2,1,2,3,3,3,2,4,4,4,1,5,5,4,7,9}
(* 6 *)
Total@PeakDetect[#&@@@Split@#,0,0]&@{87,356,37673,3676,386,909,909,909,909,454,909,908,909}
(* 4 *)
njpipeorgan
la source
Je trouve que ma réponse est suffisamment différente de la vôtre pour en publier une autre.
LegionMammal978
@ LegionMammal978 Le résultat de l'entrée {1} est 1, comme prévu.
njpipeorgan
Je veux dire {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978
@ LegionMammal978 C'est délicat. Je n'ai pas trouvé de solution.
njpipeorgan
Ma solution mise à jour aplatit simplement les "plateaux".
LegionMammal978
2

CJam, 27 26 octets

A0q~0A]e`1f=3ew{~@e>>}%1e=

Utilise le codage de longueur d'exécution pour supprimer les doublons. Après cela, nous vérifions pour chaque triplet si celui du milieu est le plus grand nombre.

Essayez-le ici! Réussit la suite de tests de Peter Taylor .

randomra
la source
2

MATL , 22 octets

0ih0hdZS49+c'21*?0'XXn

Utilise la version actuelle du langage / compilateur.

Exemple

>> matl
 > 0ih0hdZS49+c'21*?0'XXn
 >
> [1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3]
4

Explication

0ih0h           % input array. Append and prepend 0
dZS             % sign of difference between consecutive elements. Gives -1, 0, 1
49+c            % convert to a string of '0','1','2' 
'21*?0'XX       % use (lazy) regular expression to detect peaks: '20' or '210' or '2110'...
n               % number of matches. Implicity print
Luis Mendo
la source
2

Mathematica, 55 39 36 35 octets

Length@FindPeaks[#&@@@Split@#,0,0]&

Fonctionne maintenant sur tous les cas de test!

LegionMammal978
la source
Cool! Mais FindPeaks [#, 0,0, -∞] est nécessaire, sinon il échoue pour le dernier cas de test.
njpipeorgan
Last / @ enregistre un octet. Et le dernier ", 0" pourrait être inutile?
njpipeorgan
Même astuce pour vous: Last/@->#&@@@
Martin Ender
2

Rétine , 33 31 octets

Merci à Neil d'avoir économisé 2 octets.

\b(1+)(?<!\1,\1)(,\1)*\b(?!,\1)

Essayez-le en ligne!

Prend la saisie sous forme de liste unaire séparée par des virgules .

Martin Ender
la source
\b(1+)(?<!\1 \1)( \1)*\b(?! \1)semble économiser 2 octets?
Neil
@Neil bien sûr, merci! :)
Martin Ender
1

JavaScript ES6, 96 94 octets

t=>(a=t.filter((x,i)=>x!=t[i-1])).filter((x,i)=>(x>(b=a[i-1])||!b)&&(x>(c=a[i+1])||!c)).length

Principe: réduire les plateaux en pics uniques, trouver les pics définis comme étant supérieurs aux éléments suivants et précédents.

Prend l'entrée comme un tableau.

Démo:

f=t=>
(a=t.filter((x,i)=>x!=t[i-1]))    //collapse every plateau into the pick
    .filter((x,i)=>
       (x>(b=a[i-1])||!b)&&(x>(c=a[i+1])||!c)    //leave only those values which are greater than the succeeding and preceding ones
    ).length

document.write(
  f([])+"<br>"+
  f([1, 1, 1])+"<br>"+
  f([1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3])+"<br>"+
  f([1])+"<br>"+
  f([1, 1])+"<br>"+
  f([2, 2, 2, 2, 2])+"<br>"+
  f([90])+"<br>"+
  f([2, 1, 2])+"<br>"+
  f([5, 2, 5, 2, 5])+"<br>"+
  f([2, 5, 2, 5, 2, 5, 2])+"<br>"+
  f([1, 2, 3, 4])+"<br>"+
  f([1, 2, 3, 4, 1, 2])+"<br>"+
  f([1, 3, 5, 3, 1])+"<br>"+
  f([7, 4, 2, 1, 2, 3, 7])+"<br>"+
  f([7, 4, 2, 1, 2, 1, 2, 3, 7])+"<br>"+
  f([1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2])+"<br>"+
  f([1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1])+"<br>"+
  f([2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2])+"<br>"+
  f([1, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, 3, 3, 3, 1])+"<br>"+
  f([12, 1, 2, 1, 2, 3, 3, 3, 2, 4, 4, 4, 1, 5, 5, 4, 7, 9])+"<br>"+
  f([87, 356, 37673, 3676, 386, 909, 909, 909, 909, 454, 909, 909])+"<br>"+
  f([87, 356, 37673, 3676, 386, 909, 909, 909, 909, 454, 909, 908, 909])
)

nicael
la source
1

ES6, 50 48 octets

m=>m.map(h=>{f=h>p?c+=!f:f&&h==p;p=h},p=c=f=0)|c

Enregistré 2 octets grâce à @ user81655.

Non golfé:

function peaks(mountains) {
    var previous = 0;
    var count = 0;
    var plateau = false;
    for (var height of mountains) {
        if (height > previous) {
            if (!plateau) count++;
            plateau = true;
        } else if (height != previous) {
            plateau = false;
        }
    }
    return count;
}
Neil
la source
@ user81655 Merci d'avoir attiré mon attention sur cette subtilité. (Je ne l'ai jamais utilisé .map()|auparavant.)
Neil
1

MATL, 23

Comme nous devons utiliser des esolangs basés sur des piles pour être compétitifs, j'ai réimplémenté ma solution Julia en MATL.

0i0hhdtg)t5L)0>w6L)0<*s

Appuyez 0, saisissez 0, concaténez deux fois. 0i0hh=>x = [0, input(''), 0]

Différencier. d=>x = diff(x)

Dupliquez t, convertissez l'un en booléen et utilisez-le pour indexer l'autre. tg)=>x=x(x!=0)

Dupliquez à nouveau. t

Premier: [1,G])0>=>y1 = x(1:end-1)>0

Échange. w

Deuxième: [2,0])0<=>y2 = x(2:end)<0

Logique et, comptez les valeurs véridiques. *s=>sum(y1 & y2)

Rainer P.
la source
Ou vous pourriez vous Pyth, un langage de golf procédural / fonctionnel!
isaacg
OK, MATL est MATLAB pour le golf, mais MATLAB bat MATL.
Utilisateur générique
Très agréable! Quelques conseils: [1,G]-> 5Lenregistre 3 octets. [2,0]-> 6Lenregistre 3 octets
Luis Mendo
1
@GenericUser Plus :-) codegolf.stackexchange.com/a/69050/36398
Luis Mendo
@Rainer je pense à supprimer and( &) de MATL (et même pour or). Il peut toujours être remplacé par *o, et souvent par juste *, comme dans ce cas. Qu'est-ce que tu penses? De cette façon, les personnages &et |pourraient être utilisés pour d'autres fonctions à l'avenir.
Luis Mendo
1

Japt, 19 octets

C'était plus facile que je ne le pensais, mais le début est un peu inutile en raison d'un bug.

Uu0;Up0 ä< ä> f_} l

Essayez-le en ligne!

Comment ça marche

Uu0;Up0 ä< ä> f_} l  // Implicit: U = input
Uu0;Up0              // Add 0 to the beginning and end of U. If this isn't done, the algorithm fails on peaks at the end.
        ä<           // Compare each pair of items, returning true if the first is less than the second, false otherwise.
                     // This leaves us with a list e.g. [true, false, false, true, false].
           ä>        // Repeat the above process, but with greater-than instead of less-than.
                     // JS compares true as greater than false, so this returns a list filled with false, with true wherever there is a peak.
              f_} l  // Filter out the falsy items and return the length.

Version non concurrente, 15 octets

Uu0 p0 ä< ä> è_

Plus tôt dans la journée, j'ai ajouté la èfonction, qui est similaire fmais renvoie le nombre de correspondances plutôt que les correspondances elles-mêmes. J'ai également corrigé un bug oùArray.u retournait la longueur du tableau plutôt que le tableau lui-même.

Essayez-le en ligne!

ETHproductions
la source
1

05AB1E , 9 octets

Ô0.ø¥0‹ÔO

Essayez-le en ligne!

Explication:

Ô0.ø¥0‹ÔO      Full program
Ô              Uniquify (= remove plateaus)
 0.ø           Surround with zeros
    ¥          Push deltas
     0‹        Test each element if lower than 0
               --- we now have a list with 0's (= going uphill) and 
                   1's (going downhill). Since we removed plateaus, all
                   we have to do now is to count the number of ramps
                   going downhill
       Ô       Uniquify (reduce ramps to length 1)
        O      Total sum of the list
scottinet
la source
1

Gelée , 27 octets

ṡ2EÐḟFs2ḣ€1S€ṡ3M€Fċ2
0;⁸;0Ç

Essayez-le en ligne!

Zacharý
la source
Gelée sans TIO ??? lol
Christopher
C'était il y a longtemps, avant de savoir comment me connecter à TIO. Je vais le laisser comme ça pour la postérité.
Zacharý
Vis dat je fixe
Christopher
> _ <_> _ <_> _ <_> _ <
Zacharý
0

GolfScript, 35

~0+0\{.@=!},+:a,2-,{a\>3<.$2=?1=},,

Testez en ligne

Supprime essentiellement les doublons, ajoute un 0 aux deux extrémités et vérifie combien de triplets ont un maximum au centre.

Volatilité
la source
0

Java 8, 141 octets

l->{int r=0,i=1,t;for(l.add(0,0),l.add(0);i<l.size()-1;r+=t>l.get(i-1)&t>l.get(++i)?1:0)for(;(t=l.get(i))==l.get(i+1);)l.remove(i);return r;}

Peut probablement être joué au golf en utilisant une approche différente ou un tableau en entrée au lieu de List.

Explication:

Essayez-le ici.

l->{                     // Method with ArrayList<Integer> parameter and int return-type
  int r=0,               //  Result-integer
      i=1,               //  Index-integer
      t;                 //  Temp integer
  for(l.add(0,0),        //  Add a 0 at the start of the list
      l.add(0);          //  Add a 0 at the end of the list
      i<l.size()-1;      //  Loop (1) from index 1 through length-1 (0-indexed)
      r+=                //    After every iteration, raise the result-integer by:
         t>l.get(i-1)    //     If the current item is larger than the previous
         &t>l.get(++i)?  //     and larger than the next:
          1              //      Increase `r` by 1
         :               //     Else:
          0)             //      `r` remains the same
    for(;(t=l.get(i))==l.get(i+1);
                         //   Inner loop (2) as long as there are two adjacent equal items
      l.remove(i)        //    And remove one of those two equal integers
    );                   //   End of inner loop (2)
                         //  End of loop (1) (implicit / single-line body)
  return r;              //  Return the result-integer
}                        // End of method
Kevin Cruijssen
la source