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

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)


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

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


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              

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)).


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.


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


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 *)

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

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

2

Mathematica, 55 39 36 35 octets

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

Fonctionne maintenant sur tous les cas de test!


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


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])
)


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

@ 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)


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


@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!


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


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.


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.