Скільки вершин у моєму гірському масиві?


27

Список позитивних цілих чисел можна візуалізувати як квантований гірський масив, де кожен запис списку представляє висоту одного вертикального ділянки гір.

Наприклад, список

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, 2, 2, 3, (4), 3, (5), 3, 2, 1, 2, (3, 3, 3), 2, 2, 1, (3)

Зверніть увагу, як (3, 3, 3)розріз плато вважається вершиною, оскільки це суміжний набір стовпчиків, рівних за висотою, вищий, ніж сусідні колони.

Останній (3)вважається також піком, тому що для цілей цього виклику ми визначимо лівий сусід крайнього лівого стовпця і правий сусід крайнього правого стовпця, щоб вони були нульовою висотою.

Це означає , що список тільки з одним значенням, наприклад 1, 1, 1, може бути інтерпретований як 0, 1, 1, 1, 0і , таким чином , має один пік, а НЕ ніхто: 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 Так, це могло бути
захоплення Кальвіна

Чи можемо ми приймати введення як масив, а не як рядок?
нікель

@nicael Так, що-небудь розумне
Хобі Кальвіна

Відповіді:


2

Піт, 18 байт

su_>VGtG2eMr++ZQZ8

На основі @ PeterTaylor повторюється більше, ніж рішення, але з поворотом.

++ZQZ: Додайте нулі з двох сторін.

eMr ... 8: Видаліть повтори.

u ... 2 ...: Застосовуйте наступне двічі:

>VGTG: Мапа кожної пари чисел у порядку зменшення.

_: І реверс.

А 1 на виході відповідає 1, 0попередньому етапу, який відповідає a < b > cвхідному сигналу через реверс.

s: Сума (та друк)


10

CJam ( 32 26 24 21 байт)

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

Очікуваний вхід - це розділені пробілами цифри.

Інтернет-демонстрація ; повний набір тестів (очікуваний вихід - 1за тестовий випадок).

Дякую Мартіну за те, що він повідомив мені, що поточна версія CJam покращує один із використовуваних операторів, економлячи 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)))

Pad, диференціюються: 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, ми можемо вважати, що вони більше нуля, тому можна зберегти 2 байти, використовуючи nnzзамість 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

Це мій перший кодогольф, тому на ньому можуть бути місця для скорочення, особливо d=((n==p)&d)+(n>p)деталі. Однак він працює на всіх тестових випадках



3

Mathematica, 42 36 33 32 байт

Завдяки Мартіну Бюттнеру за збереження 1 байта.

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

Я маю на увазі {1, 2, 2, 3, 4, 3, 5, 3, 2, 1, 2, 3, 3, 3, 2, 2, 1, 3}
LegionMammal978

@ 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

Математика, 55 39 36 35 байт

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

Тепер працює над усіма тестовими кейсами!


Класно! Але FindPeaks [#, 0,0, -∞] потрібен, інакше він не вдається для останнього тестового випадку.
njpipeorgan

Останнє / @ зберігає байт. І останні "0" можуть бути непотрібними?
njpipeorgan

Той самий трюк для вас: Last/@->#&@@@
Мартін Ендер

2

Сітківка , 33 31 байт

Завдяки Нілу за збереження 2 байтів.

\b(1+)(?<!\1,\1)(,\1)*\b(?!,\1)

Спробуйте в Інтернеті!

Приймає вхідний сигнал у вигляді розділених комами, одинарним список.


\b(1+)(?<!\1 \1)( \1)*\b(?! \1)здається, економить 2 байти?
Ніл

@Neil звичайно, дякую! :)
Мартін Ендер

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

Збережено 2 байти завдяки @ user81655.

Безголівки:

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

Оскільки нам потрібно використовувати esolangs на основі стека, щоб бути конкурентоспроможними, я повторно доповнив своє рішення Julia в MATL.

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

Натисніть 0, введіть 0, об'єднайте двічі. 0i0hh=>x = [0, input(''), 0]

Диференціюйте. d=>x = diff(x)

Скопіюйте t, перетворіть одне на булеве та використовуйте його для індексації іншого. tg)=>x=x(x!=0)

Знову повторюється. t

По-перше: [1,G])0>=>y1 = x(1:end-1)>0

Обмін. w

Друга: [2,0])0<=>y2 = x(2:end)<0

Логіка і, підраховуйте триєдні значення. *s=>sum(y1 & y2)


Або ви могли б Pyth, процедурна / функціональна мова для гольфу!
isaacg

Гаразд, MATL - це MATLAB для гри в гольф, але MATLAB б'є MATL.
Загальний користувач

Дуже хороша! Деякі поради: [1,G]-> 5Lзберігає 3 байти. [2,0]-> 6Lекономить 3 байти
Луїс Мендо


@Rainer Я думаю про видалення and( &) з MATL (і те саме для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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.