Berapa banyak puncak di pegunungan saya?


27

Daftar bilangan bulat positif dapat divisualisasikan sebagai jajaran gunung terukur di mana setiap entri daftar mewakili ketinggian satu bagian vertikal pegunungan.

Misalnya, daftarnya

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

bisa menjadi jangkauan

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(Orang yang kurang puitis mungkin menyebut ini bagan batang, tapi saya ngelantur.)

Pertanyaan dalam tantangan ini adalah: Berapa banyak puncak yang ada di pegunungan dari beberapa daftar yang berubah-ubah? Pada dasarnya, berapa banyak maksimum lokal yang ada dalam daftar?

Puncak didefinisikan sebagai bagian yang berdekatan dari satu atau lebih kolom dari pegunungan yang semuanya tingginya sama, di mana kolom langsung ke kiri dan kanan tingginya lebih rendah.

Secara visual mudah untuk mengetahui bahwa contoh memiliki empat puncak di lokasi yang di-kurung:

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

Perhatikan bagaimana bagian (3, 3, 3)dataran tinggi dihitung sebagai puncak karena merupakan kumpulan kolom berdekatan yang tingginya sama, lebih tinggi dari kolom tetangga.

Yang terakhir (3)dianggap sebagai puncak juga karena, untuk keperluan tantangan ini, kita akan mendefinisikan tetangga kiri kolom paling kiri dan tetangga kanan kolom paling kanan untuk keduanya menjadi tinggi nol.

Ini berarti bahwa daftar dengan hanya satu nilai, misalnya 1, 1, 1, dapat diartikan sebagai 0, 1, 1, 1, 0, dan dengan demikian memiliki satu puncak, tidak satupun: 0, (1, 1, 1), 0.

Satu-satunya daftar dengan nol puncak adalah daftar kosong.

Tantangan

Tulis fungsi atau program yang mengambil daftar bilangan bulat positif sembarang dan mencetak atau mengembalikan jumlah puncak dalam rentang gunung yang sesuai.

Kode terpendek dalam byte menang. Tiebreaker adalah posting sebelumnya.

Uji Kasus

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

Jadi, dataran tinggi bisa panjang dan sewenang-wenang?
nicael

@nicael Ya, itu bisa jadi
Hobi Calvin

Bisakah kita mengambil input sebagai array, bukan sebagai string?
nicael

@nicael Ya, sesuatu yang masuk akal
Hobi Calvin

Jawaban:


2

Pyth, 18 byte

su_>VGtG2eMr++ZQZ8

Berdasarkan @ PeterTaylor diulang lebih besar dari solusi, tetapi dengan twist.

++ZQZ: Tambahkan nol di kedua sisi.

eMr ... 8: Hapus pengulangan.

u ... 2 ...: Terapkan dua kali berikut ini:

>VGTG: Memetakan setiap pasangan angka ke apakah mereka dalam urutan menurun.

_: Dan terbalik.

A 1 dalam output sesuai dengan a 1, 0 pada langkah sebelumnya, yang sesuai dengan a < b > cdalam input karena pembalikan.

s: Sum (dan cetak)


10

CJam ( 32 26 24 21 byte)

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

Input yang diharapkan adalah angka yang dipisahkan ruang.

Demo online ; paket uji lengkap (output yang diharapkan adalah a1 per test case).

Terima kasih kepada Martin karena memberi tahu saya bahwa versi CJam saat ini meningkatkan salah satu operator yang digunakan, menghemat 2 karakter; dan untuk penghematan 3-ar lebih lanjut.

Pembedahan

Dua fase: deduplicate, kemudian identifikasi maxima lokal di setiap set tiga.

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

Penjelasan

Mengambil array angka

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)

Uji


5

Pyth, 25 23 byte

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

Penjelasan:

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              

Bagus. Tidak seperti biasanya, port ke CJam lebih pendek: 0q~0]{2ew::-:g0-}2*1-,untuk 22.
Peter Taylor

4

Julia, 66

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

Pad, membedakan: y=diff([0;x;0]).
Abaikan dataran tinggi: y=y[y.!=0].
Menghitung +ke -nol penyeberangan: sum((y[1:end-1].>0)&(y[2:end].<0)).


3

MATLAB, 29 27 byte

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

Fungsi anonim yang menemukan puncak dalam data dan menghitung berapa banyak. 0 didahului dan ditambahkan ke data untuk memastikan puncak di ujung terdeteksi sesuai pertanyaan.

Ini juga akan bekerja dengan Oktaf . Anda dapat mencoba online di sini . Cukup tempel kode di atas ke dalam baris perintah, dan kemudian jalankan dengan ans([1,2,1,3,4,5,6,1])(atau input apa pun lainnya).


Karena angkanya selalu + ve, kita dapat menganggap mereka lebih besar dari nol, jadi dapat menghemat 2 byte dengan menggunakan nnz alih-alih numel.


3

Python 3, 75 byte

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

Ini adalah codegolf pertama saya jadi mungkin ada beberapa tempat untuk mengurangi itu, terutama d=((n==p)&d)+(n>p)bagian. Namun itu bekerja pada semua test case


Apakah itu bukan 78 byte ?
Jonathan Frech

3

Mathematica, 42 36 33 32 byte

Terima kasih kepada Martin Büttner karena menghemat 1 byte.

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

PeakDetect lakukan hampir semuanya!

Kasus uji:

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

Saya menemukan jawaban saya cukup berbeda dari Anda untuk memposting yang lain.
LegionMammal978

@ LegionMammal978 Hasil input {1} adalah 1, seperti yang diharapkan.
njpipeorgan

Maksud saya {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978

@ LegionMammal978 Itu rumit. Saya belum menemukan solusinya.
njpipeorgan

Solusi saya yang diperbarui hanya meratakan "dataran tinggi".
LegionMammal978


2

MATL , 22 byte

0ih0hdZS49+c'21*?0'XXn

Menggunakan versi bahasa saat ini / kompiler.

Contoh

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

Penjelasan

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 byte

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

Sekarang bekerja pada semua test case!


Keren! Tetapi FindPeaks [#, 0,0, -∞] diperlukan, jika tidak gagal untuk kasus uji terakhir.
njpipeorgan

Terakhir / @ menyimpan satu byte. Dan yang terakhir ", 0" mungkin tidak perlu?
njpipeorgan

Trik yang sama untuk Anda: Last/@->#&@@@
Martin Ender


1

JavaScript ES6, 96 94 byte

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

Prinsip: runtuh dataran tinggi menjadi puncak tunggal, temukan pilihan yang didefinisikan lebih tinggi daripada elemen berikutnya dan sebelumnya.

Mengambil input sebagai 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 byte

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

Disimpan 2 byte berkat @ user81655.

Tidak Disatukan:

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 Terima kasih telah menarik perhatian saya pada kehalusan itu. (Saya belum pernah menggunakan .map()|sebelumnya.)
Neil

1

MATL, 23

Karena kita perlu menggunakan esolang berbasis stack agar kompetitif, saya mengimplementasikan kembali solusi Julia saya di MATL.

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

Tekan 0, masukan 0,, gabungkan dua kali.0i0hh=>x = [0, input(''), 0]

Membedakan. d=>x = diff(x)

Gandakan t, konversi satu ke boolean dan gunakan untuk mengindeks yang lain. tg)=>x=x(x!=0)

Gandakan lagi. t

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

Bertukar. w

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

Logika dan, hitung nilai kebenarannya. *s=>sum(y1 & y2)


Atau Anda bisa Pyth, bahasa golf prosedural / fungsional!
isaacg

OK, MATL adalah MATLAB untuk bermain golf, tetapi MATLAB mengalahkan MATL.
Pengguna Generik

Sangat bagus! Beberapa tips: [1,G]-> 5Lmenghemat 3 byte. [2,0]-> 6Lmenghemat 3 byte
Luis Mendo

1
@GenericUser Tidak lagi :-) codegolf.stackexchange.com/a/69050/36398
Luis Mendo

@Rainer Saya berpikir untuk menghapus and( &) dari MATL (dan sama untuk or). Itu selalu bisa digantikan oleh *o, dan sering dengan adil *, seperti dalam kasus ini. Apa yang kamu pikirkan? Dengan begitu karakter &dan |bisa digunakan untuk fungsi lain di masa depan.
Luis Mendo

1

Japt, 19 byte

Itu lebih mudah dari yang saya kira, tetapi awalnya sedikit boros karena bug.

Uu0;Up0 ä< ä> f_} l

Cobalah online!

Bagaimana itu bekerja

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.

Versi yang tidak bersaing, 15 byte

Uu0 p0 ä< ä> è_

Sebelumnya hari ini, saya menambahkan èfungsi, yang seperti ftetapi mengembalikan jumlah pertandingan daripada pertandingan itu sendiri. Saya juga memperbaiki bug di mana Array.uakan mengembalikan panjang array daripada array itu sendiri.

Cobalah online!


1

05AB1E , 9 byte

Ô0.ø¥0‹ÔO

Cobalah online!

Penjelasan:

Ô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=},,

Tes online

Pada dasarnya menghapus duplikat, menambahkan 0 untuk kedua ujungnya, dan memeriksa berapa banyak tiga kali lipat memiliki maksimum di tengah.


0

Java 8, 141 byte

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

Mungkin bisa bermain golf dengan menggunakan pendekatan yang berbeda, atau array sebagai input, bukan daftar.

Penjelasan:

Coba di sini.

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.