Вода тримається в шестикутній скульптурі стрижня


22

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

Після сильного дощу скульптура сповнена води. Скільки води утримується?

Вхідні дані

Ваша програма повинна прочитати (через stdin або файл) ряд рядків, що складаються з пар пробілів і пар цифр із зазначенням довжини стрижнів у цьому форматі:

  aa  bb
cc  dd  ee
  ff  gg

Кожен стрижень (як тут тут) приклеюється максимум на 6 навколишніх стрижнів, як показано в прикладах. Пропущені стрижні - це отвори і не збирають воду. Наприклад, вхід

  04  04
04  01  03
  04  04

буде представляти таку скульптуру:

введіть тут опис зображення

Центральний стрижень - це висота 1(я не знайшов гарного кута, де він також видно). Тепер стовпчик над цим стрижнем міг утримувати 2 см води, перш ніж він перепливе над 3стрижнем праворуч. Оскільки жоден з інших стрижнів не може утримувати над собою жодної води, відповідь буде 2. Ось ще два складні приклади:

Example 2:
55  34  45  66
  33  21  27
23  12  01  77
  36  31  74
answer = 35 (  2 on top of 21 
             +11 on top of 12
             +22 on top of 01, before everything overflows over 23)

Example 3:
        35  36  77  22                      23  32  54  24
      33  07  02  04  21                  54  07  07  07  76
    20  04  07  07  01  20              54  11  81  81  07  76
  20  67  67  22  07  01  78          54  07  81  07  81  09  76
20  67  07  67  22  22  07  44  55  54  07  81  07  07  61  07  20
  67  57  50  50  07  07  14  03  02  15  81  99  91  07  81  04
67  07  50      50  87  39  45  41  34  81  07  07  89  07  81  79
  67  07  50  50  07  07  07  27  07  27  81  07  07  79  81  78
20  67  67  07  07  07  07  99  33  46  02  81  07  07  81  01  20
  33  07  07  01  05  01  92          20  02  81  07  81  15  32
    22  07  20  20  07  20              63  02  80  81  15  32
      45  20  01  20  39                  20  15  07  15  32
        23  20  20  29  43  21  18  41  20  66  66  43  21
      90                  99  47  07  20
    50                      20  02  48
  70                          56  20
                                90

answer = 1432

Вихідні дані

Ваша програма повинна вивести єдине ціле число, даючи об’єм води в кубічних сантиметрах.

Оцінка

Ваш рахунок - це кількість байтів вашого вихідного коду. Найменші виграші.

Стандартні лазівки, як правило, заборонені.

Ця головоломка була натхненна питанням SPOJ .


4
Перші два рази, коли я прочитав це, у мене виникли проблеми з візуалізацією, тому я взяв на себе сміття додати діаграму та трохи більше пояснень для першого прикладу. Сподіваюся, ви не заперечуєте.
Мартін Ендер

Це дійсно схоже на інші виклики, пов’язані з наповненням водою фігур.
FUZxxl

2
@FUZxxl У нас є інші подібні проблеми?
Оптимізатор

1
@FUZxxl Я лише згадую цей виклик , який дуже відрізняється.
Мартін Ендер

@Optimizer Цей дещо схожий.
Згарб

Відповіді:


4

Пітон 2, 222 байти

import sys
y=h=v=0;B={}
for l in sys.stdin:
 z=y;y+=2j
 while l:
    if"0"<l:B[z]=int(l[:2])
    l=l[2:];z+=1
while B:C=B;B={b:B[b]for b in B if(h<B[b])+sum(3>abs(c-b)for c in B)/7};a=C==B;h+=a;v+=a*sum(h>B[b]for b in B)
print v

Читає вхід через STDIN і записує результат у STDOUT.

Пояснення

Починаємо з нуля і поступово збільшуємо рівень води так: Припустимо, що рівень води h , і ми хочемо додати 1 сантиметр води. Ми будемо називати шестикутники висотою h або менше, ті, які вже збираються (або вже знаходяться) під водою, " зануреними ". Вода буде проливатися через будь-який занурений шестикутник, який не оточений шістьма сусідами. Ми усуваємо всі такі шестикутники; Звичайно, зараз деякі інші затоплені шестикутники можуть мати менше шести сусідів, і їх також потрібно усунути. Ми продовжуємо таким чином до зближення, тобто до тих пір, поки всі інші занурені шестикутники не матимуть рівно шести сусідів. У цей момент ми додаємо кількість занурених шестикутників (набраний об'єм води) до загальної кількості та збільшуємо рівень води.

Врешті-решт всі шестикутники будуть усунені, і ми зупинимось.


Ви повинні мати можливість голити персонажа, використовуючи -3<c-b<3 замість цього 3>abs(c-b).
DLosc

@DLosc Ах, але це складні цифри;)
Ell

Захоплююче. Не впіймав цього.
DLosc

2

Рубін 299

f=->i{s={}
l=i.lines
y=0
l.map{|r|x=0
r.scan(/../){s[[x,y]]=[v=$&.to_i,v<1?0:99];x+=1}
y+=1}
loop{break if s.map{|c,r|x,y=c
m = [[-1,-1],[1,-1],[-2,0],[2,0],[1,-1],[1,1]].map{|w,z|s[[x+w,y+z]]}.map{|n|n ?n[0]+n[1]:0}.min
r[1]=[0,m-r[0]].max if r[0]+r[1]>m&&r[1]>0}.none?}
s.map{|c,r|r[1]}.reduce :+}

Короткий опис алгоритму:

  • аналізує вхід, і для кожного стрижня зберігається двоелементний масив форми [rod_height, water_height]
  • стрижні розміщуються в хеші та індексуються їх x, y координатами
  • частина води, що протікає, враховує висоту стрижня / води безпосередніх сусідів

Трохи більш читабельна версія доступна тут: http://ideone.com/cWkamV

Запустіть версію для гольфу в Інтернеті з тестами: http://ideone.com/3SFjPN


scanприймає блок-аргумент. Ви можете просто зробити scan(/../){...}замість "сканування (/../). Карта {| v | ...} . (You don't need the | v |`, тому що всередині scanблоку ви можете $&, $1і т. Д.)
Йорданія,

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