¿Cuántos picos hay en mi cordillera?

27

Se puede visualizar una lista de enteros positivos como una cadena montañosa cuantificada donde cada entrada de la lista representa la altura de una sección vertical de las montañas.

Por ejemplo, la lista

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

puede convertirse en el rango

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(La gente menos poética podría llamar a esto un gráfico de barras, pero estoy divagando).

La pregunta en este desafío es: ¿Cuántos picos hay en la cordillera de alguna lista arbitraria? Básicamente, ¿cuántos máximos locales hay en la lista?

Un pico se define como una sección contigua de una o más columnas de la cordillera que son todas iguales en altura, donde las columnas inmediatamente a la izquierda y a la derecha son más bajas en altura.

Es fácil decir visualmente que el ejemplo tiene cuatro picos en estas ubicaciones entre paréntesis:

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

Observe cómo la (3, 3, 3)sección de meseta cuenta como un pico porque es un conjunto contiguo de columnas de igual altura, más altas que sus columnas vecinas.

El último también (3)cuenta como un pico porque, para los propósitos de este desafío, definiremos el vecino izquierdo de la columna más a la izquierda y el vecino derecho de la columna más a la derecha para que ambos tengan altura cero.

Esto significa que una lista con sólo un valor, por ejemplo 1, 1, 1, se puede interpretar como 0, 1, 1, 1, 0, y por lo tanto tiene un pico, no ninguno: 0, (1, 1, 1), 0.

La única lista con picos cero es la lista vacía.

Reto

Escriba una función o programa que tome una lista arbitraria de enteros positivos e imprima o devuelva el número de picos en la cadena montañosa correspondiente.

El código más corto en bytes gana. Tiebreaker es una publicación anterior.

Casos de prueba

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
Pasatiempos de Calvin
fuente
Entonces, ¿la meseta puede ser arbitrariamente larga?
nicael
@nicael Sí, podría ser
Calvin's Hobbies el
¿Podemos tomar la entrada como una matriz, no como una cadena?
nicael
@nicael Sí, algo razonable
Hobbies de Calvin

Respuestas:

2

Pyth, 18 bytes

su_>VGtG2eMr++ZQZ8

Basado en la solución repetida mayor que @ PeterTaylor, pero con un giro.

++ZQZ: Agregue ceros en ambos lados.

eMr ... 8: Eliminar repeticiones.

u ... 2 ...: Aplique lo siguiente dos veces:

>VGTG: Asigna cada par de números a si están en orden decreciente.

_: Y al revés.

Un 1 en la salida corresponde a un 1, 0paso anterior, que corresponde a a < b > cla entrada debido a la inversión.

s: Suma (e impresión)

isaacg
fuente
10

CJam ( 32 26 24 21 bytes)

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

La entrada esperada son números separados por espacios.

Demostración en línea ; conjunto de pruebas completo (la salida esperada es 1por caso de prueba).

Gracias a Martin por informarme que la versión actual de CJam mejora uno de los operadores utilizados, ahorrando 2 caracteres; y para un ahorro adicional de 3 caracteres.

Disección

Dos fases: deduplicar, luego identificar máximos locales en cada conjunto de tres.

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

JavaScript (ES6), 54 51 bytes

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

Explicación

Toma una serie de números

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)

Prueba

usuario81655
fuente
5

Pyth, 25 23 bytes

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

Explicación:

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
fuente
Agradable. Inusualmente, un puerto a CJam es más corto: 0q~0]{2ew::-:g0-}2*1-,por 22.
Peter Taylor
4

Julia, 66

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

Pad, diferenciar: y=diff([0;x;0]).
No haga caso de las mesetas: y=y[y.!=0].
Contar +a -los cruces por cero: sum((y[1:end-1].>0)&(y[2:end].<0)).

Rainer P.
fuente
3

MATLAB, 29 27 bytes

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

Función anónima que encuentra los picos en los datos y cuenta cuántos hay. 0 se antepone y se agrega a los datos para garantizar que los picos en los bordes se detecten según la pregunta.

Esto también funcionará con Octave . Puedes probar en línea aquí . Simplemente pegue el código anterior en la línea de comando y luego ejecútelo con ans([1,2,1,3,4,5,6,1])(o cualquier otra entrada).


A medida que los números son siempre + ve, podemos suponer que son mayores que cero, por lo que puede ahorrar mediante el uso de 2 bytes nnzen lugar de numel.

Tom Carpenter
fuente
3

Python 3, 75 bytes

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

Este es mi primer codegolf, por lo que puede haber algunos lugares para reducirlo, especialmente la d=((n==p)&d)+(n>p)parte. Sin embargo, funciona en todos los casos de prueba.

Cameron Aavik
fuente
¿No son esos 78 bytes ?
Jonathan Frech
3

Mathematica, 42 36 33 32 bytes

Gracias a Martin Büttner por guardar 1 byte.

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

PeakDetect simplemente hace casi todo!

Casos de prueba:

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
fuente
Creo que mi respuesta es lo suficientemente diferente de la suya para publicar otra.
LegionMammal978
@ LegionMammal978 El resultado de la entrada {1} es 1, como se esperaba.
njpipeorgan
Me refiero a {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978
@ LegionMammal978 Eso es complicado. No he encontrado una solución.
njpipeorgan
Mi solución actualizada simplemente aplana las "mesetas".
LegionMammal978
2

CJam, 27 26 bytes

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

Utiliza la codificación de longitud de ejecución para eliminar duplicados. Después de eso verificamos para cada triplete si el del medio es el número más grande.

Pruébalo aquí! Pasa la suite de prueba de Peter Taylor .

randomra
fuente
2

MATL , 22 bytes

0ih0hdZS49+c'21*?0'XXn

Utiliza la versión actual del idioma / compilador.

Ejemplo

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

Explicación

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

Mathematica, 55 39 36 35 bytes

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

¡Ahora funciona en todos los casos de prueba!

LegionMammal978
fuente
¡Guay! Pero se necesita FindPeaks [#, 0,0, -∞], de lo contrario, falla en el último caso de prueba.
njpipeorgan
Último / @ guarda un byte. ¿Y el último ", 0" podría ser innecesario?
njpipeorgan
El mismo truco para ti: Last/@->#&@@@
Martin Ender
2

Retina , 33 31 bytes

Gracias a Neil por guardar 2 bytes.

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

Pruébalo en línea!

Toma datos como una lista unaria separada por comas .

Martin Ender
fuente
\b(1+)(?<!\1 \1)( \1)*\b(?! \1)parece ahorrar 2 bytes?
Neil
@Neil por supuesto, gracias! :)
Martin Ender
1

JavaScript ES6, 96 94 bytes

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

Principio: colapsar mesetas en picos individuales, encontrar las selecciones que se definen como más altas que los elementos siguientes y anteriores.

Toma la entrada como una matriz.

Manifestación:

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

ES6, 50 48 bytes

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

Guardado 2 bytes gracias a @ user81655.

Sin 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
fuente
@ user81655 Gracias por llamar mi atención sobre esa sutileza. (No lo he usado .map()|antes)
Neil
1

MATL, 23

Como necesitamos usar esolangs basados ​​en pila para ser competitivos, reimplementé mi solución Julia en MATL.

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

Empuje 0, ingrese 0, concatene dos veces. 0i0hh=>x = [0, input(''), 0]

Diferenciar. d=>x = diff(x)

Duplicar t, convertir uno a booleano y usarlo para indexar el otro. tg)=>x=x(x!=0)

Duplicar de nuevo. t

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

Intercambiar. w

Segundo: [2,0])0<=>y2 = x(2:end)<0

Lógica y, cuenta los valores de verdad. *s=>sum(y1 & y2)

Rainer P.
fuente
¡O podrías Pyth, un lenguaje de golf procesal / funcional!
isaacg
OK, MATL es MATLAB para jugar golf, pero MATLAB está superando a MATL.
Usuario genérico
¡Muy agradable! Algunos consejos: [1,G]-> 5Lahorra 3 bytes. [2,0]-> 6Lahorra 3 bytes
Luis Mendo
1
@GenericUser Ya no :-) codegolf.stackexchange.com/a/69050/36398
Luis Mendo
@Rainer Estoy pensando en eliminar and( &) de MATL (y lo mismo para or). Siempre se puede reemplazar por *o, y a menudo solo *, como en este caso. ¿Qué piensas? De esa forma los personajes &y |podrían ser utilizados para otras funciones en el futuro.
Luis Mendo
1

Japt, 19 bytes

Eso fue más fácil de lo que pensaba, pero el comienzo es un poco inútil debido a un error.

Uu0;Up0 ä< ä> f_} l

Pruébalo en línea!

Cómo funciona

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.

Versión no competitiva, 15 bytes

Uu0 p0 ä< ä> è_

Hoy temprano, agregué la èfunción, que es como fpero devuelve el número de coincidencias en lugar de las coincidencias en sí. También arreglé un error en el Array.uque devolvería la longitud de la matriz en lugar de la matriz en sí.

Pruébalo en línea!

ETHproducciones
fuente
1

05AB1E , 9 bytes

Ô0.ø¥0‹ÔO

Pruébalo en línea!

Explicación:

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

Jalea , 27 bytes

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

Pruébalo en línea!

Zacharý
fuente
Gelatina sin TIO ??? lol
Christopher
Esto fue hace mucho tiempo, antes de que supiera cómo vincularme a TIO. Lo dejaré así para la posteridad.
Zacharý
Tornillo que arreglo
Christopher
> _ <_> _ <_> _ <_> _ <
Zacharý
0

GolfScript, 35

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

Prueba en línea

Básicamente elimina duplicados, agrega un 0 a ambos extremos y comprueba cuántos triples tienen un máximo en el centro.

Volatilidad
fuente
0

Java 8, 141 bytes

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

Probablemente se pueda jugar golf usando un enfoque diferente, o una matriz como entrada en lugar de List.

Explicación:

Pruébalo aquí

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
fuente