Порахуйте ASCII hamantaschen!


18

Сьогодні Пурім, на якому один звичай - видавати печиво у формі трикутника із начинкою, що називається hamantaschen (сингулярно: hamantasch ). Ще один звичай - сильно пити.

Я не найдосконаліший пекар .... У мене так багато гаманташень нерегулярного розміру, а стільки друзів подарувати їх! Якщо я надіслав вам зображення моїх файлів cookie, ви можете мені сказати, скільки я маю, якого розміру та наповнення? Але оскільки це Пурім, і я занадто п’яний, щоб читати багато коду, він повинен бути настільки малим кодом, скільки ви можете зробити.

Визначення

Розмір

Гаманташ може бути будь-якого розміру . Найменший гаманташ - розмір 1 і виглядає приблизно так:

/\  --
--  \/

Іноді множинні hamantaschen можуть перекриватися . Форма внизу вважається двома гаманташен (один розмір 1, один розмір 2):

 /\
/\ \
----

Деякі hamantaschen мають наповнення . Це буде показано, заповнивши все пробіл всередині символом. Зверніть увагу, що гаманташен розміром 1 не може мати заповнення.

Ми будемо називати hamantaschen на основі заповнення і розміру. Давайте скористаємося форматом, <filling> <size>і якщо він не заповнений, - <size>(ви можете використовувати пробіл замість а -, але розмітка цього не любить).

Ось . 2, А . 4, і - 3:

          /\
         /./\
 ----   /./  \
 \../  /./    \
  \/   --------

Це a @ 3, a . 2і a - 4:

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------

Ось щось складніше. Подивіться, як & 2менше заповнення менше, ніж ви очікували через нахил від перекриття - 3? Він має: a - 1, & 2a - 3і a & 4:

--------
\   \/&/
 \  /\/
  \/&/
   \/

Вхідні дані

Вам буде надано текстовий файл або один рядок з hamantaschen (необов’язковий трейлінг нового рядка та опціонально прокладений пробільний пробіл, щоб бути рівним).

Обмеження

  • Ви можете розраховувати, що рядок буде дійсним - тобто кожен персонаж, що не пробігає, сприяє вишуканому солодкому гаманташу (навіщо витрачати тісто?).
  • Можна також очікувати , що вона буде правильно заповнена чи ні , - то є, кожен hamantasch буде повністю наповненим послідовним ASCII символ - ASCII 32 для незаповненого, або що - небудь 32..127 для заповнення ( за виключення /, \і -).
  • Ці hamantaschen не укладаються в 3-пробіл. Все /і \буде видно. Все, -що не заблоковано, /і \буде видно. Наповнення приходить дуже останньою.
  • Усі hamantaschen матимуть видиму щонайменше половину своєї горизонтальної лінії (округлення).
  • Будь-який суміжний блок заповнення заповнює лише найменший гаманташ, який його оточує.

Вихід

Поверніть список "імен" усіх гаманташен, які можна знайти, що відповідають вищевказаним критеріям. Вихід може бути в будь-якій формі, яку ви хочете (рядок, хеш, stdout тощо).

Тестові справи

Тест №1

Введення №1:

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------
    /\
   /**\
  /*/\*\
 /*/..\*\
 --------

Вихід №1:

. 2
. 2
- 4
@ 3
* 4

Тест №2

Введення №2:

  /\----
 /\/\*\/
/ /\d\/
------

Вихід №2:

- 3
- 2
d 2
- 1    
* 2
- 1

Тест №3

Введення №3:

----
\/\/
/\/\  /\
---- /::\
     ----

Вихід №3:

- 1
- 1
- 2
- 1
- 1
- 2
: 2

Тест №4

Введення №4:

 /\/\
/ /\$\
-/--/\\
 --/--\
  /xxx/\
 /xxx/##\
 ---/----\
   /      \
   -------- 

Вихід №4:

$ 2
x 4
- 3
- 2
- 4
- 1
- 1
# 2

Недійсний тестовий випадок №5

Вхід:

/\
\/

Вихід:

Вам не потрібно з цим впоратися.


Як щодо тестового випадку, коли гаментащен перекриваються, але не мають однакової горизонтальної лінії? Можна навіть перекрити іншу горизонтальну лінію.
гордий haskeller

@proudhaskeller Добре, зроблено. Однак, і я просто вклав це в текст, це 2-пробіл. Ми будемо завжди бачити все /і \ , і -завжди буде начинка козир.
Не те, що Чарльз

2
@EasterlyIrk Є й інші важливі шматочки - читання «Книги Естер» (і буяння поганим хлопцям), роздача бідним - і менш фундаментальні речі, такі як одягання в костюм.
Не те, що Чарльз

1
знову актуальною!
downrep_nation

1
На основі початкового стовпця, що дорівнює нулю, усі ваші вершинні стовпці, крім (1,0), вимкнено на +1. Все-таки я знаю, що ви маєте на увазі, і я не згоден. Яка вказівка ​​є на те (2, 2), що верхній центр a, - 2а не лише праворуч і ліворуч від двох верхніх - 1s? Жодного, що я не бачу. І така ж логіка стосується і (3, 2). Якщо ви не хочете додати правило, щоб припустити максимально можливе hamantaschen ...
Michael Plotke

Відповіді:


4

C #, 496 452 байт

Редагувати: знайшов помилку з перевіркою меж ... але також роздягнув набір байтів, змушених був зрозуміти власний код. Розгортання локальної функції трохи допомогло та видалило специфічний код C # 7. Це питання було дуже цікавим.

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z=0,d,q,c,j,b;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L;var B=new int[H];for(d=W;(d=-d)>0||++z<H*H;)for(c=1,q=z%H;c<=z/H&q%W+c<W&q>=d&q<H+d&&D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47);q-=d+1,c+=2){for(b=0;j>q;)b+=D[--j-d]==45?2:0;for(char h='-',e;c==z/H&b>c;C.WriteLine(h+" "+c/2))for(b=c++;b>1;j=q+=d+1,b-=2)for(;j<q+b;)B[j]=h=B[j]<1&h==45&(e=D[j++])!=47&e!=92&e>32?e:h;}}}

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

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

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

Начинку можна знайти, вивчивши весь простір файлу cookie, шукаючи «невикористану» клітинку. Коли знайдена невикористана комірка, вона позначається як використана (оскільки ми збільшуємо дозволений розмір, ми знаємо, що це найменший файл cookie, який містить його), і записуємо заповнення.

Форматований та коментований код:

using C=System.Console;

class P
{
    static void Main()
    {
        //   32
        // - 45
        // / 47
        // \ 92
        // range 32..127 (no mod for you)

        string D="", // the whole map
            L; // initally each line of the map, later each line of output

        int W=0, // width
            H=0, // length (width * height)
            z=0, // search tracker
            d, // check direction (this is backwards (1 byte saving!))
            q, // check tracker
            c, // counter (truely, this is the distance from the right to the left)
            //M, // c max (now inlined as z/H)
            j, // horiontal tracker
            b; // - count, and reverse counter

        // read map and width
        for(;(L=C.ReadLine())!=null; // read a line, while we can
                H+=W=L.Length) // record the width, and increment height
            D+=L; // add the line to the map

        var B=new int[H]; // whether this filling has been used already (0 -> false, >0 -> true)

        for(d=W; // init direction
            (d=-d)>0|| // swap direction, else increment z (this allows us to run the check for the same z twice with opposite direction)
            ++z<H*H; // for all M, for all q (z<H -> M=z/H=0 -> no valid cookies, so we can safetly skip them)
            )
            for(//M=z/H, // c allow (now inlined)
                c=1, // reset counter
                q=z%H; // note position
                c<=z/H& // counter check
                // no need for a left check: if we run off the left end, then the right check will necessarily fail
                q%W+c<W& // right check
                q>=d& // high check
                q<H+d&& // low check (short-circuit lookups)
                D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47); // /\ or \/ check, and set j=q+c
                    q-=d+1, // move left tracker
                    c+=2) // increase counter (move right tracker)
            {
                // count the number of '-' into b
                for(b=0; // zero b
                    j>q; // for each element in the row below
                        ) // empty
                    b+=D[--j-d]==45?2:0; // add 2 to b if we tap a '-'

                // j = q

                // check valid before looking up cHaracter (so we don't mark unused stuff as taken)
                // if we are at the current max count, and we have enough -, then we are valid and should be commited
                for( // this runs either one or zero times, we only have a for here (rather than an if) so we can ditch a pair of braces
                    char h='-', // default filling
                         e; // filling we are considering
                    c==z/H&b>c;
                        C.WriteLine(h+" "+c/2)) // print filling and count
                    // continuously compute character
                    for(b=c++; // count b backwards, starting from c (add 1 to c so we can /2 in print)
                        b>1;j=q+=d+1,b-=2) // count q backwards toward z%H (where q came from), and b backwards toward 1 (for each row)
                        for(;j<q+b;) // for each cell in row
                            B[j]= // mark cell as taken (h,e > 0)
                            h= // record filling
                                B[j]<1& // check cell not already used
                                h==45& // '-'
                                (e=D[j++])!=47& // '/'
                                e!=92& // '\'
                                e>32 // ' '
                                ?e:h; // take first filling we can
                    // c runs out after this (exists both loops), so no need to action
            }
    }
}

Результати для 4-х тестових випадків:

testcase #1
. 2
. 2
@ 3
- 4
* 4

testcase #2
- 1
- 1
- 2
d 2
* 2
- 3

testcase #3
- 1
- 1
- 1
- 1
- 2
- 2
: 2

testcase #4
- 1
- 1
- 2
$ 2
# 2
- 3
x 4
- 4

Я вражений тим, наскільки це компактно в C #! Молодці!
Не те, що Чарльз

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