Yerel Ekstremiteleri Bulma


14

Bir listeye giren ve yerel uçların bir listesini üreten bir işlev veya program yazın.

Bir listede [x_0, x_1, x_2...]yerel aşırı bir olduğunu x_iöyle ki x_(i-1) < x_ive x_(i+1) < x_iya x_(i-1) > x_ive x_(i+1) > x_i. Listenin ilk ve son öğelerinin hiçbir zaman yerel uçlar olamayacağına dikkat edin.

Bazı örnekler için

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

Bu kod golf yani kısa kod kazanır!


Doğru anladığımdan emin olmak için: Her iki taraftaki rakamlardan büyük sayılar?
undergroundmonorail

@undergroundmonorail Büyük veya küçük. Bu yüzden, ya komşularının hem daha büyük hem de daha küçük oldukları bir yerel minimum olması gerekiyor
Daniel Gratzer

Ah anlıyorum. Yanlış okudum
undergroundmonorail

2
ve dizinin ne hakkında 1 2 2 1bu olmamalı 2çok aşırı olarak değerlendirilebilir? - Biliyorum, bu çözümü çok daha zorlaştıracak ...
VX

Yanıtlar:


5

Mathematica 66 58 51

Mevcut Çözüm

Calle'nin katkısı sayesinde kısaldı.

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

Partition[#,3,1] üçlüleri bulur.

(a-b) (b-c)<0ancak ve ancak bu durum geçerlidir baltındaysa a, cya da yukarıdaki a, c. ve bakarsak farklılıkların işaretlerini alır. Yerel bir aşırı ya dönecektir {-1,1}ya {1,-1}.


Örnekler

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}


Daha Önceki Çözüm

Bu, tüm üçlü (tarafından üretilen Partition) örneklere bakar ve orta elemanın her iki uçtan daha az mı yoksa uçlardan daha büyük mü olduğunu belirler.

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

İlk Çözüm

Bu üçlüyü bulur ve bakar farklılıkların işaretlerini alır. Yerel bir aşırı ya dönecektir {-1,1}ya {1,-1}.

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

Misal

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}


Analiz :

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

% Burada kullanılan ilgili satır, önceki satırdan elde edilen sonuca karşılık gelir.

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}} ile farklılıkların işareti (-, 0, +) a -1ve a'dan oluşur 1. Mevcut davada bunlar:

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

Bu vakaların her biri için, x, x[[2]]ikinci terimi ifade eder. Bunlar yerel maxima ve minima olacak.

{10, 6, 9, 0, 1}


Mathematica stiliniz benimkinden çok daha özlü. Ne zaman "Wolfram Dili" demeye başlayacağız?
Michael Stern

Bunu görüyorum ! Mathematica grafik
Dr. belisarius

Michael Stern, Wolfram Dilinin sadece bir kısmı Raspberry Pi'de mevcut olan sürüm 10'da resmi hale geleceğinden şüpheleniyorum.
DavidC

BTW, birisi Math ML'yi grafiklere dönüştüren bir kod satırı ekledi. Neden olduğundan emin değilim.
DavidC

Neden yaptığını bilmiyorum. "Değiştirilmiş" kodda herhangi bir fark göremiyorum
Dr.Belisarius

6

J - 19 karakter

Yardımcı olamadı;)

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

Açıklama şu şekildedir:

  • 2-/\] - Bağımsız değişkenteki her bir öğe çifti üzerinde (her 2 öğe uzunluğunda ek), farkı ele alın.
  • 2*/\ - Şimdi yeni listenin her bir çiftinde ürünü alın.
  • 0> - Her sonucun 0'dan küçük olup olmadığını test edin. Bu, yalnızca çoğul bantların alternatif işaretler olması durumunda gerçekleşir, yani aynı işarete sahip olmaları veya sıfırlardan biri olması durumunda gerçekleşmez.
  • 0, - İlk öğenin aşırı bir öğe olmadığını beyan edin.
  • }: - Son elementi kesin, çünkü bu da aşırı olamaz.
  • #~ - Sol taraftaki listeden öğe seçmek için sağ taraftaki gerçek değerleri kullanın.

Kullanımı:

   (}:#~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

Umm, giriş 3, 4, 4, 4, 4, 5 ise bu işe yaramayabilir, yani 0'a 0 eklenirse "0 =" adımında sıfır alabilirsiniz.
Lord Soth

Ayrıca, bu dili bilmiyorum, ancak, ilk adımda imza atmak yerine, farkı olduğu gibi bırakabilirsiniz. Ardından, ikinci adımda, bunun yerine elemanları çarpın ve üçüncü adımda ürünün negatif olup olmadığını kontrol edebilirsiniz (bu da 0 problemini önler). Belki de bu daha kısa bir kodla sonuçlanabilir.
Lord Soth

İyi yakalayın ve evet, bu iki karakter kazandırır. Güncelleniyor.
algorithmmshark

5

Javascript - 62 45 Karakter

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

Düzenle

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

4

Ruby, 83 70 60 55 49 karakter

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

Tüm yerel uçları STDOUT'a yazdırır.

<=>Gerçekten sevdiğim "uzay gemisi" operatörünü kullanır . (İlk şey ikinciden büyükse 1, küçükse -1, eşitse 0 döndürür. Bu nedenle, -2 veya 2'ye eklerse, ortadaki uç değer anlamına gelir.)

Artık değil, @daniero "bariz" yol aslında daha kısa olduğunu belirtti!

Yine değişti! Şimdi MT0'ın cevabında bulunan müthiş algoritmayı kullanıyor (ona +1!).

Ayrıca, each_conshangi nbir dizideki ardışık elemanların her bir grubunu seçer gibi . Ve takip etmek ifde ilginç.

Genel olarak, ne kadar zarif göründüğünü seviyorum.

Bazı örnek çalışmalar:

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

f=->a{a.each_cons(3){|x,y,z|p y if((x<=>y)+(z<=>y)).abs==2}}
X'i

@daniero Teşekkürler; Bunu yapabileceğini bile bilmiyordum! Düzenlendi
Kapı Tokmağı

Gerçekten mi? : D Btw, artık her dönem 3 karakter daha kısa olacak, bunu yapmak için genel ucuzdur x>y&&y<z||x<y&&y>z(uzay gemisi operatörü çok güzel Tho bile);)
daniero

Ayrıca ... !((x..z)===y)zekice olmasa da daha da kısadır
Charles

@Charles Ne zaman başarısız olur x < z.
Kapı tokmağı

3

C ++ - 208 karakter

Yine en uzun çözüm:

#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]<<' ';}

Kullanmak için tamsayılarınızı, ardından giriş akışını kilitleyecek herhangi bir karakteri girin; sayı olmayan karakterler çalışmalıdır.

Giriş: 0 1 0 x

Çıktı: 1


2 karakter kazanmak için a dequeyerine bir vectorkullanabilirsiniz.
Morwenn

Ayrıca, kullanmak yerine ive j, sen ilan edebilir int i;sağ toplanması ve yerine iki değişken bildirerek iki döngüler olduğu içinde kullanımdan sonra.
Morwenn

Son olarak, döngünüzdeki artıştan kurtulabilir i++ve if(v[++i]>[i-1]...tekrar bir karakter kazanmak için durumunuza başlayabilirsiniz .
Morwenn

2

Matlab - 45 bayt

x=input('');y=diff(x);x(find([0 y].*[y 0]<0))

2

Python 2.7-73 bayt

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

Çok etkileyici değil (Listenin ilk ve son hariç her öğesine bakın, komşularından daha büyük veya daha küçük olup olmadığına bakın). Çoğunlukla ben gönderiyorum çünkü herkes yapabileceğinizi x<y>zve çalıştıracağını bilmiyor . Bence bu biraz temiz.

Evet, x<y>zpython'un harika bir özelliğidir, ancak bu durumda aslında optimal değildir. Çarpma hilesi için VX sayesinde, bu bana hiç olmadı. Wrzlprmft, anonim bir işlev bildirmenin tuş vuruşlarından daha az olduğunu hatırlattı def x(y):.


if(l[i]-l[i-1])*(l[i]-l[i+1])>0kodu 11 karakter azaltacaktır ...
VX

@wrz Ah, haklısın. def e(l):\n Aynı sayıda karakter olduğu gerçeğinden atılmıştım e=lambda l:, ancak returnanahtar kelimeyi kullanmanıza gerek olmadığını unuttum . Teşekkürler!
undergroundmonorail

@vx Oh, bunu çok beğendim. Teşekkür ederim :) düzenlemek: Aslında bundan daha fazla tasarruf edebilirsiniz! Yana (l[i]-l[i-1])*(l[i]-l[i+1])olduğunu 1eğer l[i]yerel bir aşırı olduğunu ve 0aksi takdirde, kullanmak gerekmez >0. Python'un onu bir bool olarak yorumlamasına izin verebilirim. :)
undergroundmonorail

@wrz Zaten düzenlenmiş bir yorumu nasıl düzenleyeceğimi bilemiyorum (kurşun kalem simgesi düzenle düğmesinin yerini alıyor gibi görünüyor. Bu tasarımla mı?). Sadece eklemek istedim, eğer akıllı olsaydım, tek satırlık fonksiyonumun \n deklarasyonda hiç ihtiyaç duymadığını fark ederdim ! Bu iki karakteri kurtarabilirdi, ama dahil edilmesi returnhala buna değmez.
undergroundmonorail

2

Haskell 50

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

1
bu yalnızca yerel maksimum değeri kontrol eder, minimum değer eklemeniz gerekir || x <min pn
karakfa

x>p&&x>nbir karakterden daha az x>max p n:-)
yatima2975

sonra boşluk ,da gerekli değildir.
karakfa

1
değişim x>p&&x>niçin (x>p)==(x>n)yerel minimum için de 4 daha karakter ekler.
karakfa

2

Jöle , 8 bayt

IṠIỊ¬T‘ị

Çevrimiçi deneyin!

açıklama

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

Bir eleman sadece sol komşusuyla olan farkının sağ komşusuyla olan farkının tersi bir işarete sahip olması durumunda yerel bir uç değerdir, yani farklılıkların işaretleri 2 veya -2 ile farklılık gösterir. Jelly, "belirli özelliklere sahip öğeleri bul" ile ilgilenmek için bir dizi yararlı ilkeye sahiptir (özellikle, bir listede belirli özelliklere sahip öğeleri bulabilir ve bunu farklı bir listeden öğeleri ayıklamak için kullanabiliriz), yani geri çevirebiliriz orijinal liste aşağı yukarı doğrudan (1 ile dengelememiz gerekiyor çünkü orijinal listenin ilk ve son öğeleri fark almada kayboldu).


1

Numpy ile Python - 81 74 67 bayt ( satırsız 61 54 import)

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

Girişin Numpy dizisi olması gerekir.


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 karakter

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

Kısaca J veya APL gibi bir dili yenme umudum yok, ama yine de şapkamı yine de yüzüğe atacağım. Açıklama:

  • Herhangi bir anda, a, bve ctutma x_i, x_(i-1)vex_(i-2)
  • b-cve a-btürevi yaklaşık olarak öncesi ve sonrasıx_(i-1)
  • Ürünleri negatifse, biri negatif ve diğeri pozitiftir x_(i-1), bu nedenle yerel bir uçtur, bu yüzden yazdır

1

Brachylog , 17 bayt

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

Çevrimiçi deneyin!

Girişi değişken üzerinden alır ve çıktıyı çıktı değişkeni üzerinden üretir .

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.

Değerlerin çalışmasının olmadığı garanti edilebilirse, s₃{{⌉|⌋}.&bh}dört bayt tasarruf eder.



1

Wolfram Dili (Mathematica) , 43 42 bayt

#~Pick~ArrayFilter[#[[2]]!=Median@#&,#,1]&

Çevrimiçi deneyin!

Sanırım Nothingçok uzun ...

#~Pick~                                  &  (* select elements of the input where, *)
       ArrayFilter[                 ,#,1]   (*  when considering the block of length 1 *)
                                            (*    on either side of that element, *)
                   #[[2]]!=Median@#&        (*  its median is not that element *)

1

05AB1E , 11 10 bayt

¥.±¥Ä2Q0šÏ

Çevrimiçi deneyin veya birkaç test vakasını doğrulayın .

Açıklama:

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

Örnek kullanım:

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

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

0

Haskell, 70C

Golf versiyonu

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

Ungolfed sürümü

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

Javascript: 102 karakter

function h(a){for(u=i=[];++i<a.length-1;)if(x=a[i-1],y=a[i],z=a[i+1],(x-y)*(y-z)<0)u.push(y);return u}

0

APL, 19 bayt

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

20 char J versiyonunu APL'ye çevirdim. Ama ilk ve son basamağı kaldırmak yerine başlangıca ve sona sıfır ekliyorum. Aksi takdirde J sürümü gibi çalışır.

- resmi parametre omega. Bu fonksiyonun girdisidir.


Biz bunu yaparken, ben 22 karakterleri de bir K sürümü var: {x@1+&0>2_*':-':0 0,x}. Argüman iki öğeden daha kısaysa , bu karakterlerden 6'sı ( 2_ve 0 0,) bir uzunluk hatasına karşı korumaya harcanır, bu nedenle bu sorun için değilse 16 olur ... Eylem de biraz farklıdır - Boole listesini bir endeksler listesine ekleyin 1+&ve xbunu tekrar endekslemek için kullanın - ancak daha kısa ve aynı zamanda yapmak için çok K-ish bir şey.
algorithmmshark

K versiyonunuz APL versiyonumu geçecekti. Kodumun en az iki numaraya ihtiyacı var.
user10639

0

Python 2 , 59 bayt

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

Çevrimiçi deneyin!

Bu işlev çoğunlukla, listenin öğelerini listenin kendisi yerine bağımsız değişken olarak alarak endekslemenin maliyetli işini önler. Listede birden fazla öğe kalsa da, her adımda maksimum değeri kontrol ederek listeyi tekrar tekrar oluşturuyoruz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.