Знайдіть ємність 2D друкованих об'єктів


23

У вигаданому 2D світі набір 2D інструкцій друку для об'єкта може бути представлений переліком цілих чисел таким чином:

1 4 2 1 1 2 5 3 4

Кожне число представляє висоту об'єкта в цій конкретній точці. Вищевказаний список переводиться на наступний об'єкт при друкуванні:

      #
 #    # #
 #    ###
 ##  ####
#########

Потім ми наповнюємо її якомога більшою кількістю води, в результаті чого:

      #
 #~~~~#~#
 #~~~~###
 ##~~####
#########

Ми визначаємо ємність об'єкта бути одиницями води, яку об'єкт може вмістити, коли він повністю заповнений; у цьому випадку 11.

Строго кажучи, одиниця води ( ~) може існувати в місці, якщо і лише тоді, коли вона оточена двома суцільними блоками ( #) в одному ряду.

Виклик

Візьміть список позитивних цілих чисел як вхідні дані (у будь-якому форматі) та виведіть ємність об'єкта, надрукованого, коли список використовується як інструкції.

Можна припустити, що список містить щонайменше один елемент, а всі елементи знаходяться між 1 і 255.

Випробування

+-----------------+--------+
|      Input      | Output |
+-----------------+--------+
| 1               |      0 |
| 1 3 255 1       |      0 |
| 6 2 1 1 2 6     |     18 |
| 2 1 3 1 5 1 7 1 |      7 |
| 2 1 3 1 7 1 7 1 |      9 |
| 5 2 1 3 1 2 5   |     16 |
| 80 80 67 71     |      4 |
+-----------------+--------+

Відповіді:


15

Haskell, 54 байти

f l=(sum$zipWith min(scanl1 max l)$scanr1 max l)-sum l

Вирази scanl1 max lта scanr1 max lобчислити максимум виконання списку читання вперед і назад, тобто профіль води плюс суша, якщо вода піде в одному напрямку.

Походження:

      #
 #    # #
 #    ###
 ##  ####
#########

Зліва:

      #~~
 #~~~~#~#
 #~~~~###
 ##~~####
#########

Право:

~~~~~~#
~#~~~~#~#
~#~~~~###
~##~~####
#########

Тоді профіль загальної картини є мінімальним із них, що відповідає тому, де вода не просочується ні в одну сторону.

Мінімум:

      #
 #~~~~#~#
 #~~~~###
 ##~~####
#########

Нарешті, кількість води - це сума цього списку, що містить і воду, і землю, за вирахуванням суми вихідного списку, який містить лише землю.


9

Желе, 10 байт

U»\U«»\S_S

У той час як APL вимагає декількох круглих дужок, а J - двох символів, алгоритм прекрасний в Jelly.

     »\          Scan maximums left to right
U»\U             Scan maximums right to left
    «            Vectorized minimum
       S_S       Sum, subtract sum of input.

Спробуйте тут .


4

MATL , 14

Мою відповідь Matlab перекладено на MATL. алгоритм xnor.

Y>GPY>P2$X<G-s

Пояснення

Y>: cummax()(вхід неявно натискається на стек)

G: push введення (знову)

P: flip()

Y>: cummax()

P: flip()

2$X<: min([],[])(мінімум з двох аргументів)

G: push введення (знову)

-: -

s: sum()


Чи є MATL мовою заміни Matlab? Чи можете ви надати посилання у заголовку?
Аддісон Кримп

1
@FlagAsSpam Я думаю, що це трохи більше, ніж це: esolangs.org/wiki/MATL
Мартін Ендер

@ MartinBüttner Чи буде псевдокод цього ідентичний псевдокоду Matlab? Мені цікаво, чи це справа прямого перекладу, а не заснована на речі.
Аддісон Кримп

1
@FlagAsSpam MATL заснований на стеці, тому це, безумовно, не є простою заміною.
Мартін Ендер

Так, це прямий переклад. MATL заснований на стеці (зворотна польська нотація) з одним-трьома символами скорочень для операторів та функцій MATLAB . Див. [ Github.com/lmendo/MATL/blob/master/doc/MATL_spec.pdf] .
Райнер П.

3

Діалог APL, 17 байт

+/⊢-⍨⌈\⌊⌽∘(⌈\⌽)

Це монастирський поїзд, який приймає вхідний масив праворуч.

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

Інший спосіб зробити це - розділити масив на кожне місце, але це довше.

Спробуйте тут .


1
Точно так само я прийшов сюди писати. :-) Коли ми отримаємо подвійний (інакше) оператор, ви можете зберегти 3 байти за допомогою +/⊢-⍨⌈\⌊⌈\⍢⌽.
Адама

2

Матлаб, 47

Також використовуючи алгоритм xnor.

@(x)sum(min(cummax(x),flip(cummax(flip(x))))-x)

1

MATLAB, 116 113 109 106 байт

n=input('');s=0;v=0;l=nnz(n);for i=1:l-1;a=n(i);w=min([s max(n(i+1:l))]);if a<w;v=v+w-a;else s=a;end;end;v

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

Невикористаний код:

inputArray = input('');
leftHighPoint = inputArray(1);
volume = 0;
numPoints = nnz(inputArray);

for i = 1:numPoints-1
    currentPoint = inputArray(i); % Current value
    lowestHigh = min([max(inputArray(i+1:numPoints)) leftHighPoint]);

    if currentPoint < lowestHigh
        volume = volume + lowestHigh - currentPoint;
    else 
        leftHighPoint = currentPoint;
    end
end
volume

Перший раз, коли я спробував щось у гольф, MATLAB здається не найкращим для цього.


0

ES6, 101 байт

a=>(b=[],a.reduceRight((m,x,i)=>b[i]=m>x?m:x,0),r=m=0,a.map((x,i)=>r+=((m=x>m?x:m)<b[i]?m:b[i])-x),r)

Ще один порт алгоритму @ xnor.



0

Піп -l , 19 байт

$+J(ST0XgZD1`0.*0`)

Приймає вхідні числа як аргументи командного рядка. Або додайте -rпрапор, щоб прийняти їх як рядки stdin: Спробуйте в Інтернеті!

Пояснення

На відміну від усіх інших відповідей, у Піпі було фактично коротше побудувати (модифіковану версію) мистецтва ASCII та підрахувати водні одиниці.

Почнемо з gпереліку аргументів.

[1 4 2 1 5 2 3]

0Xgстворює список рядків з n нулів для кожного n in g.

[0 0000 00 0 00000 00 000]

ZD1потім скріплює ці рядки разом, використовуючи 1для заповнення будь-яких прогалин у отриманому прямокутному вкладеному списку:

[[0 0 0 0 0 0 0] [1 0 0 1 0 0 0] [1 0 1 1 0 1 0] [1 0 1 1 0 1 1] [1 1 1 1 0 1 1]]

STперетворює цей список у рядок. В -lпрапор вказує , що списки відформатований наступним чином : кожен вкладений список з'єднані без сепаратора, а на верхньому рівні роздільником є символ нового рядка. Отже, ми отримуємо цю багаторядкову рядок - по суті, діаграму об'єкта, але догори дном:

0000000
1001000
1011010
1011011
1111011

Потім ми знаходимо всі збіги регулярного виразів `0.*0`. Це відповідає двом самих зовнішніх стін і всьому між ними на кожній лінії.

[0000000 001000 011010 0110]

Jз'єднує ці рядки разом в одну велику струну і $+підсумовує її, даючи число 1s - що дорівнює кількості води, яку об'єкт може вмістити.

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