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

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)


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

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


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              

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


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.


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


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

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

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

2

Mathematica, 55 39 36 35 bajtów

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

Teraz działa na wszystkich przypadkach testowych!


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


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


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

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


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,


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


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


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.