Покриття горизонту штрихами пензлем


43

З огляду на негативний список висоти цілих горизонтів, дайте відповідь, скільки безперебійних горизонтальних штрихів пензля висотою 1 одиниці потрібно для його покриття.

[1,3,2,1,2,1,5,3,3,4,2], візуалізовано як:

      5    
      5  4 
 3    5334 
 32 2 53342
13212153342

потрібно дев'ять мазок пензлем:

      1    
      2  3 
 4    5555 
 66 7 88888
99999999999

Приклади

[1,3,2,1,2,1,5,3,3,4,2]9

[5,8]8

[1,1,1,1]1

[]0

[0,0]0

[2]2

[2,0,2]4

[10,9,8,9]11


Для зацікавлених користувачів з високою оцінкою: Виходячи з цього відповідно до цього .
Адам

2
Отже, всі мазки кисті - горизонтальні?
tsh

1
@tsh Добрий момент. Додано.
Адам

Це був не кодогольф, але у мене було це питання для тестування коду інтерв'ю близько року тому.
luizfzs

Відповіді:


35

JavaScript (Node.js) , 38 байт

a=>a.map(v=>(n+=v>p&&v-p,p=v),p=n=0)|n

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

Просто жадібний алгоритм, який сканує зліва направо, лише малює лінії, якщо потрібно, і малює його якомога довше.

Дякую Арнольду, збережіть 2 3 байти


@Arnauld приємний улов. повністю забув це.
tsh

Як ти це зрозумів?
Адам

@ Adám Нічого магічного. Перший раз, коли я прочитав питання, мене збентежило те, як шукати, поки я не зрозумію, що всі рядки мають лише горизонтальний характер. І тоді ця формула мені просто прийшла в голову природно ....
tsh

4
магія, здається, добре підходить слово для опису цього процесу.
Адам

1
Хоча це початок широко використовуваного алгоритму, це пояснюється тут .
Адам

28

05AB1E ,  8 7  5 байт

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

0š¥þO

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

Як?

Для цього використовується алгоритм, який вперше знайшов @tsh . Якщо вам подобається ця відповідь, обов’язково підкріпіть їх відповідь !

Щоразу, коли хмарочос буде нижче або вище, ніж попередній, його можна пофарбувати "безкоштовно", просто подовживши мазки.

Наприклад, малювати хмарочоси і на малюнку нижче нічого не коштує.BC

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

будівель

Для першого хмарочоса нам завжди потрібно стільки мазків, скільки в ньому підлоги.

Перетворення цього на математику:

S=h0+i=1nmax(hihi1,0)

Якщо ми додамо до списку, це може бути спрощено до:0

S=i=1nmax(hihi1,0)

Прокоментував

0š¥þO     # expects a list of non-negative integers  e.g. [10, 9, 8, 9]
0š        # prepend 0 to the list                    -->  [0, 10, 9, 8, 9]
  ¥       # compute deltas                           -->  [10, -1, -1, 1]
   þ      # keep only values made of decimal digits
          # (i.e. without a minus sign)              -->  ["10", "1"]
    O     # sum                                      -->  11

Я думаю, що 0š¥ʒd}Oви економить байт.
Містер Xcoder

@ Don'tbeax-tripledot Я редагував свою відповідь саме на те, коли побачив ваш коментар;)
Arnauld

4
Красиве пояснення.
Адам

1
Заміна ʒd}на þдопоможе вам заощадити два байти.
Аднан

@Adnan Ах, приємно. Дякую!
Арнольд

7

Python 3 , 37 байт

lambda a:sum(a)-sum(map(min,a[1:],a))

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

-5 байт, перейшовши на Python 3, завдяки Sarien


Python 2 , 47 43 42 байт

lambda a:sum(a)-sum(map(min,a[1:],a[:-1]))

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

Alt:

lambda a:sum(a)-sum(map(min,zip(a[1:],a)))

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


У Python 3 ви можете викопати [: -1], зберігаючи 5 байт.
Саріен

@Sarien Спасибі: D, я не знав, що карта відрізняється в python 2 і 3
TFeld

7

Haskell , 32 байти

(0%)
p%(h:t)=max(h-p)0+h%t
p%_=0

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

Вдосконалення рішення Лінни, яке відстежує попередній елемент, pа не дивитись на наступний елемент. Це робить базовий регістр та рекурсивний виклик скороченим в обмін на необхідність виклику (0%).

max(h-p)0може бути max h p-pоднакової довжини.



5

K (oK) , 12 7 байт

-5 байт завдяки ngn!

К (ок) порт рішення 05AB1E Arnauld (і рішення JavaScript TSH в):

+/0|-':

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

J , 15 байт

Порт AJ архіву 05AB1E Arnauld (і рішення JavaScript в tsh):

1#.0>./2-~/\0,]

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

Моє наївне рішення:

J , 27 байт

1#.2(1 0-:])\0,@|:@,~1$~"0]

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


2
oK: кожен попередній ( ':) використовує неявний елемент ідентичності ( 0for -) перед списком, тому 0,це зайве. можна опустити , { x}щоб зробити його склад:+/0|-':
СПП

@ngn Спасибі! Мабуть, я забув це:Some primitive verbs result in a different special-cased initial value: +, *, - and & are provided with 0, 1, 0 or the first element of the sequence, respectively
Гален Іванов

5

Haskell , 34 32 байти

2 байти, оброблені Лінн

g x=sum$max 0<$>zipWith(-)x(0:x)

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

Отже, для початку ми маємо zipWith(-). Це займає два списки і створює новий список їх парних відмінностей. Потім поєднуємо його з xі (0:x). (0:)це функція, яка додає нуль до передньої частини списку, і, комбінуючи його, zipWith(-)ми отримуємо відмінності між послідовними елементами цього списку та нулем на передній частині. Потім повертаємо всі негативні до нуля за допомогою (max 0<$>). Це створює новий список, де кожен елемент - це кількість нових штрихів, які необхідно розпочати на кожній вежі. Щоб отримати загальну суму, ми просто підсумовуємо їх sum.


2
g x=sum$max 0<$>zipWith(-)x(0:x)становить 32 байти :)
Лінн

Як цеsum.zipWith((max 0.).(-))<*>(0:)
Лінн

@Lynn Вашому другому потрібні будуть додаткові дужки, оскільки .пріоритет має більше <*>.
Пшеничний майстер

3

Japt , 8 байт

-2 байти від @Shaggy

mîT Õ¸¸è

Пояснення

mîT Õ¸¸è      Full program. Implicit input U
                e.g. U = [2,0,2]
mîT             Map each item X and repeat T(0) X times
                     U = ["00","","00"]
    Õ           Transpose rows with columns
                     U = ["0 0","0 0"]
     ¸¸         Join using space and then split in space
                     U = ["0","0","0","0"]
        è       Return the count of the truthy values

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


8 байт:mîT Õ¸¸è
Кудлатий

1
Доречно використання A.y()прокладки 's, до речі.
Кудлатий



3

Japt , 7 6 байт

änT fq

Спробуй це

1 байт збережено завдяки Оліверу.

änT xwT    :Implicit input of integer array
än         :Consecutive differences / Deltas
  T        :  After first prepending 0
    f      :Filter elements by
     q     :  Square root (The square root of a negative being NaN)
           :Implicitly reduce by addition and output


Гарний, @Oliver; не подумав би про це.
Кудлатий


2

Сітківка 0,8,2 , 21 байт

\d+
$*
(1+)(?=,\1)

1

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

\d+
$*

Перетворити в одинарне.

(1+)(?=,\1)

Видаліть усі перекриття наступною вежею, яка не потребує нового обведення.

1

Порахуйте решту штрихів.


2

Лист звичайний, 88 87 байт

(lambda(s)(let((o 0))(dolist(c s)(incf o(max 0 c))(mapl(lambda(y)(decf(car y)c))s))o))

нескорочений

(lambda (skyline)
  (let ((output 0))
    (dolist (current-skyscraper-height skyline)
      (incf output (max 0 current-skyscraper-height))
      (mapl (lambda (skyscraper)
              (decf (car skyscraper) current-skyscraper-height))
            skyline))
    output)))

Перевірте це

Коли одна вежа пофарбована, вона має ряд мазків, рівних її висоті. Ці мазки перекладаються на всі наступні, що вказується тут, віднімаючи поточну висоту вежі від усіх інших веж (і її саму, але це не має значення). Якщо наступна вежа буде коротшою, то вона буде висунута на від’ємне число, і це від’ємне число згодом буде відніматися з веж, які слідують за цим (вказуючи мазки, які не могли бути переведені з попередньої вежі на наступну). Він фактично просто віднімає число від усіх висот вежі, включаючи попередні, але це не має значення, оскільки ми не дивимось на попередні знову.


Ласкаво просимо до PPCG. Чи можете ви надати посилання на онлайн-тестування для зручності перевірки?
Джонатан Фрех

Так, абсолютно. rextester.com/TKBU14782 Відповідь буде оновлено найближчим часом
Charlim

Молодці. +1 за приємне, робоче перше повідомлення. Розважайте гольф.
Джонатан Фрех

1

05AB1E , 13 10 байт

Z>Lε@γPO}O

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

Z            # Get the maximum of the (implicit) input-list
 >           # Increase it by 1 (if the list only contains 0s)
  L          # Create a list in the range [1, max]
   ε         # Map each value to:
    @        #  Check if this value is >= for each value in the (implicit) input
     γ       #  Split into chunks of adjacent equal digits
      P      #  Take the product of each inner list
       O     #  Take the sum
        }O   # And after the map: take the sum (which is output implicitly)

1

C # (Visual C # Interactive Compiler) з прапором /u:System.Math, 47 байт

n=>n.Select((a,i)=>i<1?a:Max(a-n[i-1],0)).Sum()

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

Стара версія, з прапором /u:System.Math, 63 байти

n=>n.Aggregate((0,0),(a,b)=>(a.Item1+Max(0,b-a.Item2),b)).Item1

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

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


1

Pyth, 8 байт

s>#0.++0

Ще один порт чудової відповіді @ tsh . Приймає суму ( s) позитивних значень ( >#0) дельт (. +) Вхідного сигналу з попередньою кількістю 0 (тривалістю +0QQ виведено).

Спробуйте в Інтернеті тут або одразу підтвердіть усі тестові випадки тут .

Метод з'єднання рядків, 10 байт

Це було рішення, про яке я писав, перш ніж переглядати інші відповіді.

lcj.t+d*LN

Тестовий набір.

lcj.t+d*LNQ   Implicit: Q=eval(input()), b=<newline>, N=<quote mark>
              Trailing Q inferred
        L Q   Map each element of Q...
       * N    ... to N repeated that many times
     +b       Prepend a newline
   .t         Transpose, padding with spaces
  j           Join on newlines
 c            Split on whitespace
l             Take the length, implicit print

1

Clojure, 50 байт

#((reduce(fn[[s n]i][(+(max(- i n)0)s)i])[0 0]%)0)

Спробуйте в Інтернеті! (Чому це не друкує нічого?)

#( ; begin anonymous function
    (reduce
        (fn [[s n] i] ; internal anonymous reducing function, destructures accumulator argument into a sum and the previous item
            [(+ (max (- i n) 0) s ; the sum part of the accumulator becomes the previous sum plus the larger of zero and the difference between the current number and the last one, which is how many new strokes need to be started at this point
            i]) ; ...and the previous item part becomes the current item
        [0 0] ; the initial value of the accumulator gives no strokes yet, and nothing for them to cover yet
        %) ; reduce over the argument to the function
    0) ; and get the sum element of the last value of the accumulator.

Ласкаво просимо до PPCG! Я нічого не знаю про Clojure, але швидкий пошук показує, що вам потрібно буде оцінити ледачий цикл. Спробуйте в Інтернеті! (Порада: ви можете використовувати кнопку посилання для автоматичного форматування відповіді). Сподіваюсь, ви тримаєтесь і отримуйте задоволення!
Джо Кінг

1

Java (JDK) , 57 байт

a->{int s=0,p=0;for(int x:a)s-=(x>p?p:x)-(p=x);return s;}

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

Інший порт TSH «s Javascript відповідь . Тому переконайтесь, що ви їх відхилили.

Зауважте, що я використовував віднімання замість додавання, оскільки це дозволило мені записати (p=x)як правильний операнд у тому самому операторі.


0

MATL , 15 14 13 байт

ts:<~"@Y'x]vs

Вхід - вектор стовпця, який використовується ;як роздільник.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

t       % Implicit input: column vector. Duplicate
s       % Sum
:       % Range from 1 to that. Gives a row vector
<~      % Greater or equal? Element-wise with broadcast
"       % For each column
  @     %   Push current columnn
  Y'    %   Run-length encoding. Gives vector of values (0, 1) and vector of lengths
  x     %   Delete vector of lengths
]       % End
v       % Vertically concatenate. May give an empty array
s       % Sum. Implicit display

0

Perl 5, 21 байт

$\+=$_>$'&&$_-$';//}{

ТІО

Як

  • -p+ }{+ $\хитрість
  • //відповідає порожньому рядку, щоб наступний рядок постматч $'містив попередній рядок
  • $\+=$_>$'&&$_-$'накопичити різницю між поточним рядком та попереднім, якщо поточний більший за попередній, (також можна записати $\+=$_-$' if$_>$', але perl не розбирає $\+=$_-$'if$_>$'те саме)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.