私の山脈にはいくつの山がありますか?


27

正の整数のリストは、各リストエントリが山の1つの垂直セクションの高さを表す、量子化された山の範囲として視覚化できます。

たとえば、リスト

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

範囲になることができます

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(詩の少ない人はこれを棒グラフと呼ぶかもしれませんが、私は脱線します。)

この課題の問題は、任意のリストの山の範囲にいくつのピークがあるかということです。本質的に、リストにはいくつの極大がありますか?

ピークは、すべて同じ高さの山脈の1つまたは複数の列の連続したセクションとして定義されます。ここで、左右の列の高さは低くなります。

この例では、括弧で囲まれた位置に4つのピークがあることが視覚的にわかりやすくなります。

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

(3, 3, 3)プラトーセクションは、隣接する列よりも高さが等しい連続した列のセットであるため、ピークとしてカウントされることに注意してください。

(3)この課題の目的のために、左端の列の左隣と右端の列の右隣を両方とも高さゼロに定義するため、最後もピークとしてカウントされます。

これは、たとえば値が1つだけのリストは1, 1, 1として解釈できるため0, 1, 1, 1, 0、なしではなく1つのピークがあることを意味します0, (1, 1, 1), 0

ピークがゼロの唯一のリストは空のリストです。

チャレンジ

正の整数の任意のリストを取り込んで、対応する山脈のピークの数を出力または返す関数またはプログラムを作成します。

バイト単位の最短コードが優先されます。Tiebreakerは以前の投稿です。

テストケース

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

それでは、プラトーは任意の長さにすることができますか?
ニカエル

@nicaelはい、可能性があります
カルビンの趣味

入力を文字列ではなく配列として受け取ることはできますか?
ニカエル

@nicaelはい、合理的なもの
カルビンの趣味

回答:


2

Pyth、18バイト

su_>VGtG2eMr++ZQZ8

@PeterTaylorのソリューションよりも優れた繰り返しに基づいていますが、ひねりがあります。

++ZQZ:両側にゼロを追加します。

eMr ... 8:繰り返しを削除します。

u ... 2 ...:次を2回適用します。

>VGTG:数値の各ペアを、それらが降順であるかどうかにマップします。

_:そして逆。

出力の1は、1, 0前のステップのa に対応しa < b > cます。これは、反転による入力のa に対応します。

s:合計(および印刷)


10

CJam(32 26 24 21バイト)

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

予想される入力はスペースで区切られた数字です。

オンラインデモ ; 完全なテストスイート(予想される出力は1テストケースごとです)。

現在のバージョンのCJamが使用する演算子の1つを改善し、2文字を節約することを知らせてくれたMartinに感謝します。さらに3文字節約します。

解剖

2つのフェーズ:重複排除してから、3つの各セットで局所的な最大値を特定します。

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バイト

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

説明

数字の配列を受け取ります

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)

テスト


5

Pyth、25 23バイト

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

説明:

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              

いいね 珍しく、CJamへのポートは短いです:0q~0]{2ew::-:g0-}2*1-,22.のための
ピーター・テイラー

4

ジュリア、66

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

パッド、区別:y=diff([0;x;0])
高原を無視しますy=y[y.!=0]。ゼロクロッシングまで
カウント+-ますsum((y[1:end-1].>0)&(y[2:end].<0))


3

MATLAB、29 27バイト

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

データのピークを検出し、その数をカウントする匿名関数。0がデータの先頭に追加されて、質問のとおりにエッジのピークが確実に検出されるようにします。

これはOctaveでも動作します。こちらからオンラインで試すことができます。上記のコードをコマンドラインに貼り付け、それからans([1,2,1,3,4,5,6,1])(または他の入力)で実行します。


数値は常に+ veであるため、ゼロより大きいと想定できるため、nnzではなくを使用して2バイトを節約できますnumel


3

Python 3、75バイト

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

これは私の最初のcodegolfであるため、特にそのd=((n==p)&d)+(n>p)部分を削減する場所があるかもしれません。しかし、それはすべてのテストケースで動作します


それらは78バイトではありませんか?
ジョナサンフレッチ

3

Mathematica、42 36 33 32バイト

1バイトを節約してくれたMartinBüttnerに感謝します。

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

PeakDetect ほぼすべてを行うだけです!

テストケース:

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

私の答えは、あなたの答えとは別のものを投稿するのに十分に異なっていると思います。
LegionMammal978

@ LegionMammal978入力{1}の結果は、予想どおり1です。
-njpipeorgan


@ LegionMammal978それはトリッキーです。解決策が見つかりません。
-njpipeorgan

私の更新されたソリューションは、単に「プラトー」を平らにします。
LegionMammal978


2

MATL、22バイト

0ih0hdZS49+c'21*?0'XXn

用途 、現在のバージョンの言語/コンパイラのを。

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

説明

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バイト

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

すべてのテストケースで動作するようになりました!


クール!ただし、FindPeaks [#、0,0、-∞]は必要です。それ以外の場合は、最後のテストケースで失敗します。
njpipeorgan

Last / @はバイトを保存します。そして最後の「、0」は不要かもしれません?
-njpipeorgan

あなたのための同じトリック:Last/@->#&@@@
マーティン・エンダー


1

JavaScriptのES6、96の 94バイト

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

原則:プラトーを単一のピークにまとめ、次の要素と前の要素の両方よりも高いと定義されているピックを見つけます。

入力を配列として受け取ります。

デモ:

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バイト

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

@ user81655のおかげで2バイト節約されました。

ゴルフをしていない:

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その繊細さに注意を向けてくれてありがとう。(私は.map()|前に使用していません。)
ニール

1

MATL、23

競争力を高めるにはスタックベースのエソランを使用する必要があるため、MATLでジュリアソリューションを再実装しました。

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

プッシュ0、入力は、0二回連結します。0i0hh=>x = [0, input(''), 0]

差別化します。d=>x = diff(x)

Duplicate t、一方をブール値に変換し、それを使用して他方にインデックスを付けます。tg)=>x=x(x!=0)

もう一度複製します。 t

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

交換する。 w

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

ロジックと、真理値を数えます。*s=>sum(y1 & y2)


または、手続き型/機能型のゴルフ言語であるPythを使用できます。
isaacg

OK、MATLはゴルフのためのMATLABですが、MATLABはMATLに勝っています。
汎用ユーザー

非常に素晴らしい!いくつかのヒント:[1,G]-> 5L3バイト節約します。[2,0]-> 6L3バイト節約
ルイスメンドー

1
@GenericUserもうありません:-) codegolf.stackexchange.com/a/69050/36398
ルイスメンドー

@Rainer MATL からand&)を削除することを考えています(およびor)も同じです。この場合のように*o、常にに置き換えられ、多くの場合は単に*に置き換えられます。どう思いますか?そのような文字&とは、|将来的に他の機能を使用することができます。
ルイスメンドー

1

Japt、19バイト

それは思ったよりも簡単でしたが、バグのために最初は少し無駄です。

Uu0;Up0 ä< ä> f_} l

オンラインでお試しください!

使い方

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.

非競合バージョン、15バイト

Uu0 p0 ä< ä> è_

今日、è関数を追加しました。これはf、一致自体ではなく、一致の数を返します。またArray.u、配列自体ではなく配列の長さを返すバグを修正しました。

オンラインでお試しください!


1

05AB1E、9バイト

Ô0.ø¥0‹ÔO

オンラインでお試しください!

説明:

Ô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

Java 8、141バイト

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

おそらく、異なるアプローチを使用するか、Listの代わりに入力として配列を使用することでゴルフができます。

説明:

ここで試してみてください。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.