極値を見つける


14

リストを取り込んで、極値のリストを作成する関数またはプログラムを作成します。

リストでは[x_0, x_1, x_2...]、ローカルの極値はそのx_iようなx_(i-1) < x_iand x_(i+1) < x_iまたはx_(i-1) > x_iand x_(i+1) > x_iです。リストの最初と最後の要素が極値になることはありません。

だからいくつかの例

local_extremes([1, 2, 1]) = [2]
local_extremes([0, 1, 0, 1, 0]) = [1, 0, 1]
local_extremems([]) = []

これはコードゴルフなので、最短のコードが勝ちます!


私が正しく理解していることを確認するために:どちらかの側の数字より大きい数字?
地下

@undergroundmonorailより大きいかより小さい。それはどちらか、彼らは両方とも小さくしていることの隣人は、両方の大きい局所的最小値、または最大値である必要がありますので
ダニエルGratzer

ああなるほど。誤解
地下

2
シーケンス1 2 2 1については、それら2も極端なものとみなすべきではありませんか?-私が知っている、これは...解決策ははるかに困難になるだろう
VX

回答:


5

Mathematica 66 58 51

現在のソリューション

Calleの貢献により短縮されました。

Cases[Partition[#,3,1],{a_,b_,c_}/;(a-b) (b-c)<0⧴b]&

Partition[#,3,1] トリプルを見つけます。

(a-b) (b-c)<0場合にのみ真であるb以下であるacまたは上記ac。見て、違いの兆候を見てください。局所的な極端は、{-1,1}またはのいずれかを返します{1,-1}


Cases[Partition[#, 3, 1], {a_, b_, c_} /; (a - b) (b - c) < 0 :> b] &[{1, 2, 1}]
Cases[Partition[#, 3, 1], {a_, b_, c_} /; (a - b) (b - c) < 0 :> b] &[{0, 1, 0, 1, 0}]
Cases[Partition[#, 3, 1], {a_, b_, c_} /; (a - b) (b - c) < 0 :> b] &[{}]
Cases[Partition[#, 3, 1], {a_, b_, c_} /; (a - b) (b - c) < 0 :> b] &[{9, 10, 7, 6, 9, 0, 3, 3, 1, 10}]

{2}
{
1、0、1}
{ } {10、6、9、0、1 }


以前のソリューション

これは、すべてのトリプル(で生成されるPartition)の例を見て、中央の要素が両方の極値より小さいか、極値より大きいかを決定します。

Cases[Partition[#,3,1],{a_,b_,c_}/;(b<ab<c)∨(b>ab>c)⧴b]& ;

最初の解決策

これはトリプルを見つけ、違いの兆候を調べます。局所的な極端は、{-1,1}またはのいずれかを返します{1,-1}

Cases[Partition[#,3,1],x_/;Sort@Sign@Differences@x=={-1,1}⧴x[[2]]]&

Cases[Partition[#,3,1],x_/;Sort@Sign@Differences@x=={-1,1}:>x[[2]]]&[{9, 10, 7, 6, 9, 0, 3, 3, 1, 10}]

{10、6、9、0、1}


分析

Partition[{9, 10, 7, 6, 9, 0, 3, 3, 1, 10}]

{{9、10、7}、{10、7、6}、{7、6、9}、{6、9、0}、{9、0、3}、{0、3、3}、{ 3、3、1}、{3、1、10}}

% 前の各行の結果を参照します。

Differences/@ %

{{1、-3}、{-3、-1}、{-1、3}、{3、-9}、{-9、3}、{3、0}、{0、-2}、 {-2、9}}

Sort@Sign@Differences@x=={-1,1}{{9、10、7}、{10、7、6}、{7、6、9}、{6、9、0}、{9、0、3}、{0、3、からトリプルを識別します3}、{3、3、1}、{3、1、10}} 。差の符号(-、0、+)はa -1とaで構成され1ます。現在の場合、それらは次のとおりです。

{{9、10、7}、{7、6、9}、{6、9、0}、{9、0、3}、{3、1、10}}

これらの各ケースで、x x[[2]]は2番目の用語を指します。それらはすべて極大値と極小値になります。

{10、6、9、0、1}


Mathematicaスタイルは私のMathematicaスタイルよりもはるかに簡潔です。「Wolfram Language」と呼ぶようになるのはいつですか?
マイケルスターン14


Michael Stern、Wolfram Languageはバージョン10でのみ公式になると思いますが、その一部はすでにRaspberry Piで利用可能です。
DavidC

ところで、誰かがMath MLをグラフィックスに変換するコード行を挿入しました。理由はわかりません。
DavidC 14

彼がそれをした理由はわかりません。私は「変更」のコード内の任意の違いを見ることができない
ベリサリウス博士は

6

J-19文字

それを助けることができませんでした;)

(}:#~0,0>2*/\2-/\])

説明は次のとおりです。

  • 2-/\] -引数の各要素のペア(各2項目の長い中置記号)で、差を取ります。
  • 2*/\ -次に、新しいリストの各ペアで製品を取得します。
  • 0> -各結果が0より小さいかどうかをテストします。これは、被乗数に交互の符号がある場合にのみ発生します。
  • 0, -最初の要素は極端な要素ではないことを宣言します。
  • }: -最後の要素を切り取ります。極端なことはできないためです。
  • #~ -右側の真の値を使用して、左側のリストからアイテムを選択します。

使用法:

   (}:#~0,0>2*/\2-/\]) 1 2 1
2
   (}:#~0,0>2*/\2-/\]) 0 1 0 1 0
1 0 1
   (}:#~0,0>2*/\2-/\]) i.0   NB. i.0 is the empty list (empty result also)

   (}:#~0,0>2*/\2-/\]) 3 4 4 4 2 5
2

入力は、たとえば、ある3、4、4、4、4、5の場合は0を0に追加された場合うーん、これは、つまり、あなたが「0 =」ステップでゼロを仕事を得ることができないかもしれない
主Soth

また、私はこの言語については知りませんが、最初のステップでサインをとる代わりに、違いをそのままにしておくことができます。次に、2番目のステップで代わりに要素を乗算し、3番目で積が負であるかどうかを確認できます(これにより、0の問題も回避されます)。おそらく、これによりコードが短くなる可能性があります。
ロードSoth 14

良いキャッチ、そしてはい、これは2文字を節約します。更新中。
algorithmshark 14

5

Javascript- 62 45文字

f=a=>a.filter((x,i)=>i&&i<a.length-1&&(a[i-1]-x)*(a[i+1]-x)>0)

編集

f=a=>a.filter((x,i)=>(a[i-1]-x)*(a[i+1]-x)>0)

4

ルビー、83 70 60 55 49文字

f=->a{a.each_cons(3){|x,y,z|p y if(x-y)*(z-y)>0}}

すべてのローカル極値をSTDOUTに出力します。

<=>私が本当に好きな「宇宙船」演算子を使用します。(最初の値が2番目の値より大きい場合は1を返し、小さい場合は-1を返し、等しい場合は0を返します。したがって、-2または2に加算すると、真ん中が極端になります。)

@danieroが指摘したように、「明白な」方法は実際には短いとはもう言えません。

再び変更されました!現在では、MT0の答えにある素晴らしいアルゴリズムを使用しています(彼に+1!)。

また、配列内の連続した要素のeach_consnグループを選択するのが好きです。そして、トレーリングifも面白いです。

全体として、私はそれがどれほどエレガントに見えるかが好きです。

いくつかのサンプルの実行:

irb(main):044:0> f[[1,2,1]]
2
=> nil
irb(main):045:0> f[[1,0,1,0,1]]
0
1
0
=> nil
irb(main):046:0> f[[]]
=> nil
irb(main):047:0> f[[1,2,3,4,5,4,3,2,1]]
5
=> nil
irb(main):048:0> f[[1,1,1,1,1]]
=> nil
irb(main):049:0> f[[10,0,999,-45,3,4]]
0
999
-45
=> nil

xを3つの変数にアンパックする方がf=->a{a.each_cons(3){|x,y,z|p y if((x<=>y)+(z<=>y)).abs==2}}
簡単

@danieroありがとう。そんなことができるとは知りませんでした!編集
ドアノブ

本当に?:Dところで、今では各用語が3文字短くなり、全体的に安価になっていますx>y&&y<z||x<y&&y>z(宇宙船のオペレーターでさえ非常にきれいです);)
ダニエル14

また、... !((x..z)===y)のように巧妙ではないが、さらに短いです
未チャールズその

@Charlesそれは失敗したときx < z
ドアノブ

3

C ++-208文字

最長のソリューション:

#include<iostream>
#include<deque>
using namespace std;
int main(){deque<int>v;int i;while(cin){cin>>i;v.push_back(i);}for(i=0;i<v.size()-2;)if(v[++i]>v[i-1]&v[i]>v[i+1]|v[i]<v[i-1]&v[i]<v[i+1])cout<<v[i]<<' ';}

使用するには、整数を入力してから、入力ストリームをクラッシュさせる文字を入力します-数字以外の文字はすべて機能します。

入力: 0 1 0 x

出力: 1


aのdeque代わりにa vectorを使用して2文字を獲得できます。
モーウェン14

また、代わりに使用するij、あなたが宣言することができint i;、右収集し、代わりに2つの変数を宣言するの二つのループをある中で、使用後。
モーウェン14

最後に、i++forループの増分を取り除き、if(v[++i]>[i-1]...1つの文字を再度取得するために条件を開始できます。
モーウェン14


2

Python 2.7-73バイト

e=lambda l:[l[i]for i in range(1,len(l)-1)if(l[i]-l[i-1])*(l[i]-l[i+1])]

あまり印象的ではありません(最初と最後を除くリストのすべての要素を見て、隣よりも大きいか小さいかを確認してください)。誰もがあなたがそれを実行しx<y>z、機能させることができると知っているわけではないので、私はほとんどそれを投稿しています。私はそれがちょっときちんとしていると思います。

はい、x<y>zPythonのクールな機能ですが、この場合、実際には最適ではありません。乗算のトリックを提供してくれたVXのおかげで、それは私にはまったく起こりませんでした。Wrzlprmftは、匿名関数を宣言する方がのキーストロークより少ないことを思い出しましたdef x(y):


if(l[i]-l[i-1])*(l[i]-l[i+1])>0... 11文字でコードが減少する
VX

@wrzああ、あなたは正しい。とdef e(l):\n 同じ文字数であるという事実に私はがっかりしましたe=lambda l:が、returnキーワードを使用する必要がないことを忘れていました。ありがとう!
地下

@vxああ、私はそれがとても好きです。ありがとう:) 編集:実際にはそれ以上を節約できます!以来で(l[i]-l[i-1])*(l[i]-l[i+1])ある1場合l[i]、ローカル極端で、0そうでない場合、私が使用する必要はありません>0。Pythonにそれをboolとして解釈させることができます。:)
地下

@wrz既に編集されているコメントを編集する方法がわかりません(鉛筆アイコンが編集ボタンに置​​き換わっているようです。これは設計によるものですか?)。私はちょうどそれを追加したかったです、もし私が賢いなら、私は自分の1行の関数が\n 宣言でまったく必要ないことに気付いていたでしょう!それは2人のキャラクターを救ったでしょうが、それを含めることはreturnまだ価値がありません。
地下

2

ハスケル50

f a=[x|(p,x,n)<-zip3 a(tail a)(drop 2 a),x>p&&x>n]

1
これはローカル最大値のみをチェックします。最小値を追加する必要があるため|| x <min pn
karakfa 14

x>p&&x>nより1通の小さい文字があるx>max p n:-)
yatima2975

後のスペース,も必要ありません。
karakfa 14

1
極小値に変更x>p&&x>n(x>p)==(x>n)、さらに4文字を追加します。
karakfa

2

ゼリー、8バイト

IṠIỊ¬T‘ị

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

説明

IṠIỊ¬T‘ị
I          Differences between adjacent elements {of the input}
 Ṡ         Take the sign of each difference
  I        Differences between adjacent difference signs
   Ị       Mark the elements that are     in the range -1..1 inclusive
    ¬                                 not
     T     Take the indexes of the marked elements
      ‘      with an offset of 1
       ị   Index back into the original list

左隣との差が右隣との差と反対の符号を持つ場合、つまり、差の符号が2または-2異なる場合、要素は局所的な極値にすぎません。Jellyには、「特定のプロパティを持つ要素を見つける」(特に、特定のプロパティを持つ要素を1つのリストで見つけ、それを使用して別のリストから要素を抽出する)を処理するための便利なプリミティブが多数あります。つまり、元のリストを多かれ少なかれ直接(元のリストの最初と最後の要素が差分取得で失われたため、1だけオフセットする必要があります)。


1

Numpyを使用したPython – 81 74 67バイト(行なしの61 54 import

import numpy
e=lambda a:a[1:-1][(a[2:]-a[1:-1])*(a[1:-1]-a[:-2])<0]

入力はNumpy配列である必要があります。


1

C、83

x,y,z;main(){y=z=0;while(scanf("%d",&x)){(y-z)*(y-x)>0?printf("%d ",y):1;z=y,y=x;}}

1

awk-32文字

{c=b;b=a;a=$0;$0=b}(b-c)*(a-b)<0

JやAPLのような言語を簡潔に打ち負かす望みはありませんが、とにかくリングに帽子を投げると思いました。説明:

  • 任意の時点で、ab、およびcホールドx_ix_(i-1)x_(i-2)
  • b-ca-b前後の導関数を近似するx_(i-1)
  • それらの積が負である場合、一方が負で、他方が正x_(i-1)であるため、局所的な極端であるため、印刷

1

Brachylog、17バイト

s₃{b≠h.&k≠&{⌉|⌋}}

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

入力変数から入力を受け取り、生成する出力変数を介して出力します。

s₃{             }    For a length-3 substring of the input:
  {b                 its last two elements
    ≠                are distinct,
     h               and the first of those elements is
      .              the output variable;
       &k            its first two elements
         ≠           are also distinct;
          &{⌉| }     either its largest element
          &{ |⌋}     or its smallest element
                }    is also the output variable.

値の実行が存在しないことが保証される場合、s₃{{⌉|⌋}.&bh}4バイトを節約します。




1

05AB1E11 10 バイト

¥.±¥Ä2Q0šÏ

オンラインそれを試してみたり、さらにいくつかのテストケースを検証します

説明:

¥           # Get the forward differences (deltas) of the (implicit) input-list
            #  i.e. [9,10,7,6,9,0,3,3,1,10] → [1,-3,-1,3,-9,3,0,-2,9]
          # Get the signum of each delta (-1 if neg.; 0 if 0; 1 if pos.)
            #  → [1,-1,-1,1,-1,1,0,-1,1]
   ¥        # Get the forward differences of that list again
            #  → [-2,0,2,-2,2,-1,-1,2]
    Ä       # Convert each integer to its absolute value
            #  → [2,0,2,2,2,1,1,2]
     2Q     # And now check which ones are equal to 2 (1 if truthy; 0 if falsey)
            #  → [1,0,1,1,1,0,0,1]
       0š   # Prepend a 0
            #  → [0,1,0,1,1,1,0,0,1]
         Ï  # And only leave the values in the (implicit) input-list at the truthy indices
            #  → [10,6,9,0,1]
            # (after which the result is output implicitly)

0

PHP、116 114 113

function _($a){for(;$a[++$i+1];)if(($b=$a[$i])<($c=$a[$i-1])&$b<($d=$a[$i+1])or$b>$c&$b>$d)$r[]=$a[$i];return$r;}

使用例:

print_r(_(array(2, 1, 2, 3, 4, 3, 2, 3, 4)));

Array
(
    [0] => 1
    [1] => 4
    [2] => 2
)

0

ハスケル、70C

ゴルフバージョン

e(a:b:c:r)
 |a<b&&b>c||a>b&&b<c=b:s
 |True=s
 where s=e(b:c:r)
e _=[]

非ゴルフバージョン

-- if it's possible to get three elements from the list, take this one
extrema (a:b:c:rest)
    | a<b && b>c = b:rec
    | a>b && b<c = b:rec
    | otherwise = rec
    where rec = extrema (b:c:rest)
-- if there are fewer than three elements in the list, there are no extrema
extrema _ = []


0

APL、19バイト

{⍵/⍨0,⍨0,0>2×/2-/⍵}

20文字のJバージョンをAPLに変換しました。ただし、最初と最後の数字を削除する代わりに、先頭と末尾にゼロを追加します。それ以外の場合は、Jバージョンと同じように機能します。

-仮パラメータのオメガ。これは関数への入力です。


私たちがそれに取り組んでいる間、私は22文字のKバージョンも持っています:{x@1+&0>2_*':-':0 0,x}。これらの文字のうち6つ(2_0 0,)は、引数が2項目より短い場合に長さエラーから保護するために費やされるため、その問題がない場合は16 ...になります。ブールリストをインデックスのリストに追加し、1+&それを使用してx再度インデックスを作成します。
algorithmshark 14

あなたのKバージョンは私のAPLバージョンを打ち負かすでしょう。私のコードには少なくとも2つの数字が必要です。
user10639 14

0

Python 2、59バイト

f=lambda l=0,c=0,*r:r and(c,)*(l<c>r[0]or l>c<r[0])+f(c,*r)

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

この関数は、リスト自体ではなくリストの要素を引数として使用することにより、インデックス作成のコストのかかるビジネスをほとんど回避します。リストには複数の要素が残っていますが、リストを再帰的に作成し、各ステップで最大値をチェックします。

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