Wie viele Gipfel in meinem Gebirgszug?

27

Eine Liste positiver Ganzzahlen kann als quantisierte Bergkette dargestellt werden, wobei jeder Listeneintrag die Höhe eines vertikalen Abschnitts der Berge darstellt.

Zum Beispiel die Liste

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

kann der Bereich werden

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(Weniger poetische Leute nennen das vielleicht ein Balkendiagramm, aber ich schweife ab.)

Die Frage bei dieser Herausforderung lautet: Wie viele Gipfel gibt es in einer willkürlichen Liste im Gebirgszug? Wie viele lokale Maxima sind im Wesentlichen in der Liste enthalten?

Ein Gipfel ist definiert als zusammenhängender Abschnitt einer oder mehrerer Spalten des Gebirges, die alle gleich hoch sind, wobei die Spalten unmittelbar links und rechts niedriger sind.

Es ist leicht visuell zu erkennen, dass das Beispiel an diesen in Klammern gesetzten Stellen vier Peaks aufweist:

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

Beachten Sie, dass der (3, 3, 3)Plateau-Abschnitt als Peak gilt, da es sich um eine zusammenhängende Gruppe von Spalten handelt, deren Höhe höher ist als die der benachbarten Spalten.

Der letzte (3)zählt ebenfalls als Peak, da wir für die Zwecke dieser Herausforderung den linken Nachbarn der ganz linken Spalte und den rechten Nachbarn der ganz rechten Spalte als Höhe Null definieren.

Dies bedeutet , dass eine Liste mit nur einem Wert, zum Beispiel 1, 1, 1, kann als interpretiert wird 0, 1, 1, 1, 0und hat somit einen Peak, nicht none: 0, (1, 1, 1), 0.

Die einzige Liste mit Nullspitzen ist die leere Liste.

Herausforderung

Schreiben Sie eine Funktion oder ein Programm, das eine beliebige Liste positiver Ganzzahlen aufnimmt und die Anzahl der Gipfel im entsprechenden Gebirgszug ausgibt oder zurückgibt.

Der kürzeste Code in Bytes gewinnt. Tiebreaker ist früherer Beitrag.

Testfälle

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
Calvins Hobbys
quelle
Das Plateau kann also beliebig lang sein?
Nicoleel
@nicael Ja, es könnte sein
Calvins Hobbys
Können wir Eingaben als Array und nicht als Zeichenfolge annehmen?
Nicoleel
@nicael Ja, alles vernünftige
Calvins Hobbys

Antworten:

2

Pyth, 18 Bytes

su_>VGtG2eMr++ZQZ8

Basierend auf @ PeterTaylor's mehr als Lösung, aber mit einer Wendung.

++ZQZ: Fügen Sie auf beiden Seiten Nullen hinzu.

eMr ... 8: Wiederholungen entfernen.

u ... 2 ...: Wende zweimal Folgendes an:

>VGTG: Ordnen Sie jedes Zahlenpaar in absteigender Reihenfolge zu.

_: Und umgekehrt.

Eine 1 im Ausgang entspricht einer 1, 0im vorherigen Schritt, die a < b > caufgrund der Umkehrung in der Eingabe entspricht .

s: Summe (und print)

isaacg
quelle
10

CJam ( 32 26 24 21 Bytes)

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

Erwartete Eingabe sind durch Leerzeichen getrennte Zahlen.

Online-Demo ; vollständige Testsuite (die erwartete Ausgabe gilt für 1jeden Testfall).

Vielen Dank an Martin, der mich darüber informiert hat, dass die aktuelle Version von CJam einen der verwendeten Operatoren verbessert und 2 Zeichen gespart hat. und für eine weitere 3-Zeichen-Ersparnis.

Präparation

Zwei Phasen: deduplizieren, dann lokale Maxima in jeder Gruppe von drei identifizieren.

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

JavaScript (ES6), 54 51 Byte

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

Erläuterung

Nimmt eine Reihe von Zahlen

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)

Prüfung

user81655
quelle
5

Pyth, 25 23 Bytes

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

Erläuterung:

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
quelle
Nett. Ungewöhnlich ist ein Hafen zu CJam kürzer: 0q~0]{2ew::-:g0-}2*1-,für 22.
Peter Taylor
4

Julia, 66 Jahre

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

Pad, unterscheiden: y=diff([0;x;0]).
Ignorieren Sie die Plateaus: y=y[y.!=0].
Zählen +auf -Nulldurchgänge: sum((y[1:end-1].>0)&(y[2:end].<0)).

Rainer P.
quelle
3

MATLAB, 29 27 Bytes

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

Anonyme Funktion, die die Peaks in den Daten findet und zählt, wie viele es gibt. 0 wird vorangestellt und an die Daten angehängt, um sicherzustellen, dass Peaks ganz am Rand gemäß der Frage erkannt werden.

Dies funktioniert auch mit Octave . Sie können es hier online versuchen . Fügen Sie einfach den obigen Code in die Befehlszeile ein und führen Sie ihn dann mit ans([1,2,1,3,4,5,6,1])(oder einer anderen Eingabe) aus.


Da die Zahlen immer + ve sind, können wir davon ausgehen, dass sie größer als Null sind. Sie können also 2 Bytes einsparen, indem Sie nnzanstelle von verwenden numel.

Tom Carpenter
quelle
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

Dies ist mein erster Codegolf, daher kann es einige Stellen geben, an denen man Abstriche machen kann, insbesondere am d=((n==p)&d)+(n>p)Teil. Es funktioniert jedoch in allen Testfällen

Cameron Aavik
quelle
Sind das nicht 78 Bytes ?
Jonathan Frech
3

Mathematica, 42 36 33 32 Bytes

Vielen Dank an Martin Büttner für das Speichern von 1 Byte.

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

PeakDetect macht einfach fast alles!

Testfälle:

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
quelle
Ich finde, meine Antwort unterscheidet sich ausreichend von Ihrer, um eine andere zu posten.
LegionMammal978
@ LegionMammal978 Das Ergebnis der Eingabe {1} ist erwartungsgemäß 1.
njpipeorgan
Ich meine {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978
@ LegionMammal978 Das ist knifflig. Ich habe keine Lösung gefunden.
njpipeorgan
Meine aktualisierte Lösung glättet nur "Hochebenen".
LegionMammal978
2

MATL , 22 Bytes

0ih0hdZS49+c'21*?0'XXn

Verwendet die aktuelle Version der Sprache / des Compilers.

Beispiel

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

Erläuterung

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

Mathematica, 55 39 36 35 Bytes

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

Funktioniert jetzt auf allen Testfällen!

LegionMammal978
quelle
Cool! FindPeaks [#, 0,0, -∞] wird jedoch benötigt, da es sonst für den letzten Testfall fehlschlägt.
njpipeorgan
Last / @ speichert ein Byte. Und die letzte ", 0" könnte unnötig sein?
njpipeorgan
Gleicher Trick für Sie: Last/@->#&@@@
Martin Ender
2

Retina , 33 31 Bytes

Vielen Dank an Neil für das Speichern von 2 Bytes.

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

Probieren Sie es online!

Übernimmt die Eingabe als durch Kommas getrennte, unäre Liste.

Martin Ender
quelle
\b(1+)(?<!\1 \1)( \1)*\b(?! \1)scheint 2 Bytes zu sparen?
Neil
@Neil natürlich danke! :)
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

Prinzip: Plateaus in einzelne Peaks zerlegen, die Picks finden, die als höher als die nächsten und vorherigen Elemente definiert sind.

Übernimmt die Eingabe als Array.

Demo:

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

ES6, 50 48 Bytes

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

2 Bytes dank @ user81655 gespeichert.

Ungolfed:

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
quelle
@ user81655 Vielen Dank, dass Sie mich auf diese Feinheiten aufmerksam gemacht haben. (Ich habe vorher nicht verwendet .map()|.)
Neil
1

MATL, 23

Da wir Stack-basierte Esolangs verwenden müssen, um wettbewerbsfähig zu sein, habe ich meine Julia- Lösung in MATL neu implementiert.

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

Zweimal drücken 0, eingeben 0, verketten. 0i0hh=>x = [0, input(''), 0]

Unterscheiden. d=>x = diff(x)

Duplizieren t, konvertieren Sie einen in einen Booleschen Wert und indizieren Sie den anderen.tg)=>x=x(x!=0)

Nochmal duplizieren. t

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

Austausch. w

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

Logik und zählen die Wahrheitswerte. *s=>sum(y1 & y2)

Rainer P.
quelle
Oder Sie könnten Sie Pyth, eine prozedurale / funktionale Golfsprache!
Isaacg
OK, MATL ist MATLAB zum Golfen, aber MATLAB schlägt MATL.
Generischer Benutzer
Sehr schön! Einige Tipps: [1,G]-> 5LSpart 3 Bytes. [2,0]-> 6Lspart 3 Bytes
Luis Mendo
1
@GenericUser Nicht mehr :-) codegolf.stackexchange.com/a/69050/36398
Luis Mendo
@ Rainer Ich denke über das Entfernen and( &) aus MATL (und das gleiche für or). Es kann wie in diesem Fall immer *ound oft durch nur ersetzt *werden. Was denkst du? Auf diese Weise können die Zeichen &und |in Zukunft für andere Funktionen verwendet werden.
Luis Mendo
1

Japt, 19 Bytes

Das war einfacher als ich dachte, aber der Anfang ist aufgrund eines Fehlers etwas verschwenderisch.

Uu0;Up0 ä< ä> f_} l

Probieren Sie es online!

Wie es funktioniert

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.

Nicht konkurrierende Version, 15 Bytes

Uu0 p0 ä< ä> è_

Heute habe ich die èFunktion hinzugefügt , die wie folgt istf aber die Anzahl der Übereinstimmungen und nicht die Übereinstimmungen selbst zurückgibt. Ich habe auch einen Fehler behoben, bei dem Array.udie Länge des Arrays und nicht das Array selbst zurückgegeben wurde.

Probieren Sie es online!

ETHproductions
quelle
1

05AB1E , 9 Bytes

Ô0.ø¥0‹ÔO

Probieren Sie es online!

Erläuterung:

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

Gelee , 27 Bytes

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

Probieren Sie es online!

Zacharý
quelle
Gelee ohne TIO ??? lol
Christopher
Dies war vor langer Zeit, bevor ich wusste, wie man sich mit TIO verbindet. Ich werde es für die Nachwelt so belassen.
Zacharý
Schraube dat ich fix
Christopher
> _ <_> _ <_> _ <_> _ <
Zacharý
0

GolfScript, 35

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

Online testen

Entfernt im Allgemeinen Duplikate, fügt an beiden Enden eine 0 hinzu und überprüft, wie viele Tripel ein Maximum in der Mitte haben.

Flüchtigkeit
quelle
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;}

Kann wahrscheinlich mit einem anderen Ansatz oder einem Array als Eingabe anstelle von List gespielt werden.

Erläuterung:

Probieren Sie es hier aus.

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
quelle