Có bao nhiêu đỉnh trong dãy núi của tôi?


27

Một danh sách các số nguyên dương có thể được hình dung như một dãy núi được lượng tử hóa trong đó mỗi mục nhập danh sách biểu thị chiều cao của một phần dọc của các ngọn núi.

Ví dụ, danh sách

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

có thể trở thành phạm vi

      x
    x x      
   xxxxx   xxx   x
 xxxxxxxx xxxxxx x
xxxxxxxxxxxxxxxxxx

(Những người ít thơ hơn có thể gọi đây là biểu đồ thanh, nhưng tôi lạc đề.)

Câu hỏi trong thử thách này là: Có bao nhiêu đỉnh nằm trong dãy núi của một số danh sách tùy ý? Về cơ bản, có bao nhiêu cực đại địa phương trong danh sách?

Một đỉnh được định nghĩa là một phần liền kề của một hoặc nhiều cột của dãy núi có chiều cao bằng nhau, trong đó các cột ngay bên trái và bên phải có chiều cao thấp hơn.

Thật dễ dàng để nói rằng ví dụ này có bốn đỉnh tại các vị trí được ngoặc đơn này:

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

Lưu ý cách phần (3, 3, 3)cao nguyên được tính là một đỉnh vì nó là một tập hợp các cột liền kề có chiều cao bằng nhau, cao hơn các cột lân cận.

Điểm cuối cùng cũng (3)được tính là một đỉnh vì vì mục đích của thử thách này, chúng ta sẽ xác định hàng xóm bên trái của cột ngoài cùng bên phải và hàng xóm bên phải của cột ngoài cùng bên phải có chiều cao bằng không.

Điều này có nghĩa là một danh sách chỉ có một giá trị, ví dụ 1, 1, 1, có thể được hiểu là 0, 1, 1, 1, 0, và do đó có một đỉnh chứ không phải không có : 0, (1, 1, 1), 0.

Danh sách duy nhất có đỉnh bằng không là danh sách trống.

Thử thách

Viết một hàm hoặc chương trình có trong một danh sách tùy ý các số nguyên dương và in hoặc trả về số lượng đỉnh trong phạm vi núi tương ứng.

Mã ngắn nhất tính bằng byte thắng. Tiebreaker là bài trước.

Các trường hợp thử nghiệm

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

Vậy, cao nguyên có thể độc đoán lâu dài?
nicael

@nicael Vâng, có thể là
Sở thích của Calvin

Chúng ta có thể lấy đầu vào là một mảng, không phải là chuỗi?
nicael

@nicael Vâng, bất cứ điều gì hợp lý
Sở thích của Calvin

Câu trả lời:


2

Bình thường, 18 byte

su_>VGtG2eMr++ZQZ8

Dựa trên @ PeterTaylor lặp đi lặp lại lớn hơn giải pháp, nhưng với một bước ngoặt.

++ZQZ: Thêm số không ở cả hai bên.

eMr ... 8: Hủy bỏ lặp lại.

u ... 2 ...: Áp dụng hai lần sau:

>VGTG: Ánh xạ từng cặp số để xem chúng có theo thứ tự giảm dần không.

_: Và ngược lại.

1 trong đầu ra tương ứng với một 1, 0bước trước, tương ứng với a < b > cđầu vào do sự đảo ngược.

s: Tổng (và in)


10

CJam ( 32 26 24 21 byte)

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

Đầu vào dự kiến ​​là các số được phân tách bằng dấu cách.

Bản demo trực tuyến ; bộ thử nghiệm đầy đủ (đầu ra dự kiến ​​là một 1trường hợp thử nghiệm).

Cảm ơn Martin đã thông báo cho tôi rằng phiên bản hiện tại của CJam cải thiện một trong những toán tử được sử dụng, tiết kiệm 2 ký tự; và để tiết kiệm thêm 3 char.

Mổ xẻ

Hai giai đoạn: lặp lại, sau đó xác định cực đại cục bộ trong mỗi bộ ba.

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

Giải trình

Có một dãy số

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)

Kiểm tra


5

Bình thường, 25 23 byte

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

Giải trình:

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              

Tốt đẹp. Bất thường, một cổng đến CJam ngắn hơn: 0q~0]{2ew::-:g0-}2*1-,cho 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, phân biệt : y=diff([0;x;0]).
Bỏ qua các cao nguyên : y=y[y.!=0].
Đếm +đến -không giao nhau : sum((y[1:end-1].>0)&(y[2:end].<0)).


3

MATLAB, 29 27 byte

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

Hàm ẩn danh tìm các đỉnh trong dữ liệu và đếm xem có bao nhiêu. 0 được thêm vào và gắn vào dữ liệu để đảm bảo các đỉnh ở các cạnh được phát hiện theo câu hỏi.

Điều này cũng sẽ làm việc với Octave . Bạn có thể thử trực tuyến tại đây . Chỉ cần dán đoạn mã trên vào dòng lệnh, rồi chạy nó với ans([1,2,1,3,4,5,6,1])(hoặc bất kỳ đầu vào nào khác).


Vì các số luôn luôn là + ve, chúng ta có thể giả sử chúng lớn hơn 0, vì vậy có thể tiết kiệm 2 byte bằng cách sử dụng nnzthay vì 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

Đây là codegolf đầu tiên của tôi vì vậy có thể có một số nơi để cắt giảm nó, đặc biệt là d=((n==p)&d)+(n>p)phần này. Tuy nhiên, nó hoạt động trên tất cả các trường hợp thử nghiệm


Là những người không 78 byte ?
Jonathan Frech

3

Toán học, 42 36 33 32 byte

Cảm ơn Martin Büttner vì đã tiết kiệm 1 byte.

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

PeakDetect chỉ cần làm hầu hết mọi thứ!

Các trường hợp thử nghiệm:

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

Tôi thấy câu trả lời của tôi đủ khác với câu trả lời của bạn.
LegionMammal978

@ LegionMammal978 Kết quả của đầu vào {1} là 1, như mong đợi.
njpipe

Ý tôi là {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978

@ LegionMammal978 Điều đó thật khó khăn. Tôi đã không tìm thấy một giải pháp.
njpipe

Giải pháp cập nhật của tôi chỉ làm phẳng "cao nguyên".
LegionMammal978


2

TOÁN , 22 byte

0ih0hdZS49+c'21*?0'XXn

Sử dụng phiên bản hiện tại của ngôn ngữ / trình biên dịch.

Thí dụ

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

Giải trình

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

Toán học, 55 39 36 35 byte

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

Bây giờ hoạt động trên tất cả các trường hợp thử nghiệm!


Mát mẻ! Nhưng FindPeaks [#, 0,0, -∞] là cần thiết, nếu không thì không thành công cho trường hợp thử nghiệm cuối cùng.
njpipe tổ chức

Last / @ lưu một byte. Và ", 0" cuối cùng có thể là không cần thiết?
njpipe tổ chức

Thủ thuật tương tự dành cho bạn: 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

Nguyên tắc: thu gọn các cao nguyên thành các đỉnh đơn, tìm các điểm được xác định là cao hơn cả các yếu tố tiếp theo và trước đó.

Đưa đầu vào như một mảng.

Bản giới thiệu:

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

Đã lưu 2 byte nhờ @ user81655.

Ung dung:

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 Cảm ơn bạn đã thu hút sự chú ý của tôi đến sự tinh tế đó. (Tôi chưa từng sử dụng .map()|trước đây.)
Neil

1

TOÁN, 23

Vì chúng tôi cần sử dụng esolang dựa trên stack để cạnh tranh, tôi đã thực hiện lại giải pháp Julia của mình trong MATL.

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

Đẩy 0, nhập 0, nối hai lần. 0i0hh=>x = [0, input(''), 0]

Phân biệt. d=>x = diff(x)

Nhân đôi t, chuyển đổi một thành boolean và sử dụng nó để lập chỉ mục khác. tg)=>x=x(x!=0)

Nhân đôi lần nữa. t

Đầu tiên: [1,G])0>=>y1 = x(1:end-1)>0

Trao đổi, giao dịch. w

Thứ hai: [2,0])0<=>y2 = x(2:end)<0

Logic và, đếm các giá trị trung thực. *s=>sum(y1 & y2)


Hoặc bạn có thể Pyth, một ngôn ngữ chơi golf thủ tục / chức năng!
isaacg

OK, MATL là MATLAB để chơi gôn, nhưng MATLAB đang đánh bại MATL.
Người dùng chung

Rất đẹp! Một số mẹo: [1,G]-> 5Ltiết kiệm 3 byte. [2,0]-> 6Ltiết kiệm 3 byte
Luis Mendo

1
@GenericUser Không còn nữa :-) codegolf.stackexchange.com/a/69050/36398
Luis Mendo

@Rainer Tôi đang nghĩ đến việc loại bỏ and( &) khỏi MATL (và tương tự cho or). Nó luôn có thể được thay thế bởi *o, và thường chỉ bằng *, như trong trường hợp này. Bạn nghĩ sao? Bằng cách đó, các ký tự &|có thể được sử dụng cho các chức năng khác trong tương lai.
Luis Mendo

1

Japt, 19 byte

Điều đó dễ hơn tôi nghĩ, nhưng sự khởi đầu hơi lãng phí do một lỗi.

Uu0;Up0 ä< ä> f_} l

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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.

Phiên bản không cạnh tranh, 15 byte

Uu0 p0 ä< ä> è_

Đầu ngày hôm nay, tôi đã thêm èchức năng, giống như fnhưng trả về số lượng trận đấu thay vì chính các trận đấu. Tôi cũng đã sửa một lỗiArray.u sẽ trả về độ dài của mảng chứ không phải chính mảng đó.

Hãy thử trực tuyến!


1

05AB1E , 9 byte

Ô0.ø¥0‹ÔO

Hãy thử trực tuyến!

Giải trình:

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

Kiểm tra trực tuyến

Về cơ bản loại bỏ các bản sao, thêm 0 vào cả hai đầu và kiểm tra xem có bao nhiêu bộ ba có cực đại ở trung tâm.


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

Có thể được đánh gôn bằng cách sử dụng một cách tiếp cận khác, hoặc một mảng làm đầu vào thay vì Danh sách.

Giải trình:

Hãy thử nó ở đây.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.