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

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)


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

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


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              

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


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.


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


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

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

2

Mathematica, 55 39 36 35 Bytes

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

Funktioniert jetzt auf allen Testfällen!


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


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


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

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


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!


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


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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.