Ile szczytów w moim paśmie górskim?

27

Listę liczb całkowitych dodatnich można zwizualizować jako kwantowane pasmo górskie, gdzie każda pozycja listy reprezentuje wysokość jednego pionowego odcinka gór.

Na przykład lista

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

może stać się zasięgiem

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(Mniej poetyccy ludzie mogą nazwać to wykresem słupkowym, ale ja dygresję).

Pytanie w tym wyzwaniu brzmi: ile szczytów znajduje się w górach na dowolnej liście? Zasadniczo ile lokalnych maksimów znajduje się na liście?

Szczyt jest zdefiniowany jako ciągły odcinek jednej lub więcej kolumn pasma górskiego o równej wysokości, przy czym kolumny znajdujące się bezpośrednio po lewej i prawej stronie mają niższą wysokość.

Łatwo jest wizualnie stwierdzić, że przykład ma cztery szczyty w tych nawiasach:

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

Zwróć uwagę, jak (3, 3, 3)sekcja plateau liczy się jako szczyt, ponieważ jest to ciągły zestaw kolumn o równej wysokości, wyższej niż sąsiednie kolumny.

Ostatni (3)liczy się również jako szczyt, ponieważ dla celów tego wyzwania zdefiniujemy lewego sąsiada z lewej kolumny i prawego sąsiada z prawej kolumny, aby oba miały wysokość zero.

Oznacza to, że lista z tylko jedna wartość, na przykład 1, 1, 1, może być interpretowany jako 0, 1, 1, 1, 0, a tym samym ma jeden pik, a nie żaden: 0, (1, 1, 1), 0.

Jedyną listą z zerowymi pikami jest pusta lista.

Wyzwanie

Napisz funkcję lub program, który pobierze dowolną listę liczb całkowitych dodatnich i wypisze lub zwróci liczbę pików w odpowiednim paśmie górskim.

Najkrótszy kod w bajtach wygrywa. Tiebreaker jest wcześniejszym postem.

Przypadki testowe

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
Hobby Calvina
źródło
Więc płaskowyż może być dowolnie długi?
nicael
@nicael Tak, to może być
Calvin's Hobbies
Czy możemy brać dane wejściowe jako tablicę, a nie jako ciąg?
nicael
@nicael Tak, wszystko rozsądne
hobby Calvina

Odpowiedzi:

2

Pyth, 18 bajtów

su_>VGtG2eMr++ZQZ8

Oparty na @ PeterTaylor's powtórzył więcej niż rozwiązanie, ale z niespodzianką.

++ZQZ: Dodaj zera po obu stronach.

eMr ... 8: Usuń powtórzenia.

u ... 2 ...: Zastosuj dwukrotnie:

>VGTG: Zamapuj każdą parę liczb w kolejności malejącej.

_: I odwrotnie.

Wartość 1 na wyjściu odpowiada 1, 0wcześniejszemu etapowi, który odpowiada a < b > cna wejściu z powodu odwrócenia.

s: Suma (i wydrukuj)

isaacg
źródło
10

CJam ( 32 26 24 21 bajtów)

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

Oczekiwane dane wejściowe to liczby rozdzielone spacjami.

Demo online ; pełny pakiet testowy (oczekiwany wynik to 1przypadek testowy).

Dzięki Martinowi za poinformowanie mnie, że obecna wersja CJam ulepsza jednego z używanych operatorów, oszczędzając 2 znaki; i dla dalszego oszczędzania 3 znaków.

Sekcja

Dwie fazy: deduplikuj, a następnie określ lokalne maksima w każdym zestawie trzech.

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
źródło
7

JavaScript (ES6), 54 51 bajtów

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

Wyjaśnienie

Przyjmuje tablicę liczb

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)

Test

użytkownik 81655
źródło
5

Pyth, 25 23 bajtów

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

Wyjaśnienie:

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
źródło
Miły. Niezwykle port do CJam jest krótszy: 0q~0]{2ew::-:g0-}2*1-,za 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, różnicować: y=diff([0;x;0]).
Zignoruj płaskowyże: y=y[y.!=0].
Liczyć +się -przejść przez zero: sum((y[1:end-1].>0)&(y[2:end].<0)).

Rainer P.
źródło
3

MATLAB, 29 27 bajtów

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

Anonimowa funkcja znajdująca szczyty w danych i zliczająca ich liczbę. Wartość 0 jest dodawana i dodawana do danych, aby zapewnić wykrywanie pików na samych krawędziach zgodnie z pytaniem.

Będzie to również działać z Octave . Możesz spróbować online tutaj . Po prostu wklej powyższy kod do wiersza poleceń, a następnie uruchom go za pomocą ans([1,2,1,3,4,5,6,1])(lub dowolnego innego wejścia).


Ponieważ liczby są zawsze + ve, możemy założyć, że są większe od zera, więc możemy zapisać 2 bajty, używając nnzzamiast numel.

Tom Carpenter
źródło
3

Python 3, 75 bajtów

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

To jest mój pierwszy codegolf, więc mogą być na nim miejsca, zwłaszcza d=((n==p)&d)+(n>p)część. Działa jednak na wszystkich przypadkach testowych

Cameron Aavik
źródło
Czy to nie 78 bajtów ?
Jonathan Frech,
3

Mathematica, 42 36 33 32 bajty

Podziękowania dla Martina Büttnera za oszczędność 1 bajtu.

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

PeakDetect robi prawie wszystko!

Przypadki testowe:

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
źródło
Uważam, że moja odpowiedź jest wystarczająco różna od twojej, aby opublikować inną.
LegionMammal978
@ LegionMammal978 Wynik danych wejściowych {1} wynosi 1, zgodnie z oczekiwaniami.
njpipeorgan
Mam na myśli {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978
@ LegionMammal978 To trudne. Nie znalazłem rozwiązania.
njpipeorgan
Moje zaktualizowane rozwiązanie po prostu spłaszcza „płaskowyże”.
LegionMammal978
2

CJam, 27 26 bajtów

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

Wykorzystuje kodowanie długości przebiegu do usunięcia duplikatów. Następnie sprawdzamy dla każdej trojaczki, czy środkowa jest największą liczbą.

Wypróbuj tutaj! Przechodzi zestaw testów Petera Taylora .

randomra
źródło
2

MATL , 22 bajty

0ih0hdZS49+c'21*?0'XXn

Używa bieżącej wersji języka / kompilatora.

Przykład

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

Wyjaśnienie

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
źródło
2

Mathematica, 55 39 36 35 bajtów

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

Teraz działa na wszystkich przypadkach testowych!

LegionMammal978
źródło
Fajne! Ale FindPeaks [#, 0,0, -∞] jest potrzebny, w przeciwnym razie nie powiedzie się w ostatnim przypadku testowym.
njpipeorgan
Last / @ zapisuje bajt. A ostatnie „0” może być niepotrzebne?
njpipeorgan
Ta sama sztuczka dla Ciebie: Last/@->#&@@@
Martin Ender
2

Retina , 33 31 bajtów

Dzięki Neil za zaoszczędzenie 2 bajtów.

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

Wypróbuj online!

Staje wejścia jako rozdzielonych przecinkami jednoargumentowy listy.

Martin Ender
źródło
\b(1+)(?<!\1 \1)( \1)*\b(?! \1)wydaje się oszczędzać 2 bajty?
Neil
@ Neil oczywiście, dzięki! :)
Martin Ender
1

JavaScript ES6, 96 94 bajtów

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

Zasada: zwinąć płaskowyże w pojedyncze szczyty, znajdź typy, które są zdefiniowane jako wyższe niż zarówno następny, jak i poprzedni element.

Pobiera dane wejściowe jako tablicę.

Próbny:

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

Nicość
źródło
1

ES6, 50 48 bajtów

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

Zaoszczędzono 2 bajty dzięki @ user81655.

Nie golfowany:

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
źródło
@ user81655 Dzięki za zwrócenie mojej uwagi na tę subtelność. (Nie korzystałem .map()|wcześniej.)
Neil
1

MATL, 23

Ponieważ musimy używać esolangów opartych na stosie, aby być konkurencyjnym, ponownie wdrożyłem swoje rozwiązanie Julia w MATL.

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

Naciśnij 0, wprowadź 0i połącz dwa razy. 0i0hh=>x = [0, input(''), 0]

Rozróżniać. d=>x = diff(x)

Duplikuj t, przekonwertuj jeden na wartość logiczną i użyj go do zindeksowania drugiego. tg)=>x=x(x!=0)

Powtórz ponownie. t

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

Wymieniać się. w

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

Logika i policz prawdziwe wartości. *s=>sum(y1 & y2)

Rainer P.
źródło
Lub możesz Pyth, język golfa proceduralnego / funkcjonalnego!
isaacg
OK, MATLAB jest MATLAB do gry w golfa, ale MATLAB bije MATLAB.
Użytkownik ogólny
Bardzo dobrze! Kilka wskazówek: [1,G]-> 5Loszczędza 3 bajty. [2,0]-> 6Lzapisuje 3 bajty
Luis Mendo,
1
@GenericUser Już nie :-) codegolf.stackexchange.com/a/69050/36398
Luis Mendo
@Rainer Zastanawiam się nad usunięciem and( &) z MATL (i to samo dla or). Zawsze można go zastąpić *o, a często tylko *, tak jak w tym przypadku. Co myślisz? W ten sposób znaki &i |mogą być używane do innych funkcji w przyszłości.
Luis Mendo,
1

Japt, 19 bajtów

To było łatwiejsze niż myślałem, ale początek jest nieco marnotrawiony z powodu błędu.

Uu0;Up0 ä< ä> f_} l

Wypróbuj online!

Jak to działa

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.

Wersja niekonkurencyjna, 15 bajtów

Uu0 p0 ä< ä> è_

Wcześniej dzisiaj dodałem èfunkcję, która przypomina, fale zwraca liczbę dopasowań, a nie same dopasowania. Naprawiłem również błąd, w którym Array.uzwracała długość tablicy zamiast samej tablicy.

Wypróbuj online!

ETHprodukcje
źródło
1

05AB1E , 9 bajtów

Ô0.ø¥0‹ÔO

Wypróbuj online!

Wyjaśnienie:

Ô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
szkocki
źródło
1

Galaretka , 27 bajtów

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

Wypróbuj online!

Zacharý
źródło
Galaretka bez TIO ??? lol
Christopher
To było dawno temu, zanim wiedziałem, jak połączyć się z TIO. Zostawię to dla potomności.
Zacharý
Śruba, którą naprawiam
Christopher
> _ <_> _ <_> _ <_> _ <
Zacharý
0

GolfScript, 35

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

Przetestuj online

Zasadniczo usuwa duplikaty, dodaje zero na obu końcach i sprawdza, ile trójek ma maksimum w środku.

Zmienność
źródło
0

Java 8, 141 bajtów

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

Prawdopodobnie można grać w golfa, stosując inne podejście lub tablicę jako dane wejściowe zamiast listy.

Wyjaśnienie:

Wypróbuj tutaj.

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
źródło