Простейшая черепица пола

10

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

Пол является частью квадратной сетки. Каждая квадратная плитка окрашена либо в лазурный, либо в черный цвет (представлена aи bна входе).

Пример этаж:

  aaaa
ababab
aaaaa

Мета-черепица

  • построен из Nпо Mпрямоугольной мета-плитке лазурных и черных квадратов
  • используемые мета-плитки идентичны до перевода (вы не можете вращать или отражать их)
  • если стороны двух мета-плиток соединены, они должны соединиться по всей их длине (т.е. мета-тайлы разбивают пространство по сетке)

Пример мета-плитки:

ba
aa

и мета-тайлинг, созданный им:

       .
       .
       .
    babababa
    aaaaaaaa
... babababa ...
    aaaaaaaa    
    babababa
    aaaaaaaa
       .
       .
       .

Эта мета-мозаика создает верхний показанный этаж, как показывают левые буквы:

       .
       .
       .
    ********
    ***aaaa*
... *ababab* ...
    *aaaaa**    
    ********
    ********
       .
       .
       .

Мета-мозаика проще, чем другая, если область ее мета-мозаики меньше. Наш пример имеет площадь, 2*2 = 4которая является наименьшей возможной для пола примера. Таким образом, вывод должен быть 4для примера.

вход

  • Строка, состоящая из символов a b spaceи newlineсодержащая хотя бы один aили b.
  • Буквы ( ab) образуют одну 4-связную (бок о бок) форму.
  • В начале строк не будет лишних пробелов, т.е. будет хотя бы одна строка, начинающаяся с aили b.
  • Вы можете выбрать один из двух форматов ввода:

    • Нет лишних пробелов в конце строк (как видно из примеров).
    • Пробелы с правой стороны строк, чтобы все строки имели одинаковую длину с самой длинной строкой.
  • Трейлинг новой строки необязателен

Вывод

  • Единственное целое число, область наименьшего возможного мета-тайла, чья мозаика содержит входной этаж.

Примеры

Примеры ограничены тире. Три части примера - это ввод, вывод и одна из возможных наименьших мета-плиток.

a

1

a
-----------------
 aaaa
aaa
a

1

a
-----------------
aabaab
abaa
aaba

6

aab
aba
-----------------
aabaab
a  a a
aabab

18

aabaab
aaaaaa
aababa
-----------------
ba
aaab

8

baaa
aaab
-----------------
 aaaa
ababb
aaaa

10

aaaaa
ababb
-----------------
 a aa
ab ba
 aba

6

aa
ab
ba
-----------------
 aaaa
abab
aaaa

4

aa
ab
-----------------
ba
 ba
  b

4

ba
ab
-----------------
baa
aba
aab

9

baa
aba
aab
-----------------
 aaaa
aabaa
aaaa

6

aaa
aab

Это код гольф, поэтому выигрывает самый короткий вход.

randomra
источник
@Ypnypn Каждый угол должен касаться 3 других углов (кроме мета-плиток на краю плитки). Я сказал это как «если стороны двух мета-плиток соединены, они должны соединиться по всей их длине». Так что ваш приведенный пример незаконен.
Рандомра

Ответы:

3

C - 208 байтов

w,q,n,m,r,g,u;t(char*f){for(w=0;f[w++]-10;);for(q=1;;q++)for(n=1;m=q/n,n<=q;++n)if(n*m==q){char t[q];bzero(t,q);r=q;for(g=0;f[g];++g){u=g/w%m*n+g%w%n;r=t[u]+f[g]-195?r:0;if(f[g]&64)t[u]=f[g];}if(r)return r;}}

Эквивалентный код перед игрой в гольф:

#include <stdio.h>
#include <strings.h>

int t(char* f) {
    int w = 0;
    for ( ; f[w++] - 10; );

    for (int q = 1; ; q++) {
        char t[q];
        for (int n = 1; n <= q; ++n) {
            int m = q / n;
            if (n * m == q) {
                bzero(t, q);
                int r = q;
                for (int g = 0; f[g]; ++g) {
                    int u = g / w % m * n + g % w % n;
                    if (t[u] + f[g] == 195) {
                        r = 0;
                    }
                    if (f[g] & 64) {
                        t[u] = f[g];
                    }
                }
                if (r) {
                    return r;
                }
            }
        }
    }
}

Алгоритм является довольно грубой силой, поэтому должно быть достаточно очевидно, как он работает на основе кода. В любом случае, вот несколько комментариев:

  • Ожидается, что вход будет иметь форму с завершающими пробелами, чтобы все строки имели одинаковую длину.
  • Первый цикл находит ширину, ища первый символ новой строки.
  • Внешний цикл превышает размеры мета-ячеек-кандидатов q. Выход с returnмета-плитки, когда пол может покрыть пол. Обратите внимание, что циклу не нужно другое условие выхода, поскольку всегда есть решение (наихудший случай - размер ввода).
  • Первый вложенный цикл и последующие ifперечисляют допустимые комбинации ширины / высоты мета-тайла для размера q.
  • Массив символов, соответствующий размеру метафайла-кандидата, инициализируется нулями.
  • Внутренний цикл перебирает все плитки на полу.
  • u является индексом в мета-тайле, который соответствует тайлу пола.
  • Если как плитка для пола, так и плитка для мета-мозаики имеют одинаковое значение aили bотличаются (сумма a = 97и b = 98есть 195), существует несоответствие, и размер мета-мозаики с указанными размерами не будет работать.
  • В противном случае, если мозаичный элемент равен aили b, цвет мозаичного изображения копируется в мета-мозаику-кандидат.
  • Возвращает размер мета-плитки, когда было выполнено успешное совпадение, т.е. если попытка совпадения не была отмечена как неудачная.

Используемый тестовый код:

#include <stdio.h>

extern int t(char* s);

int main()
{
    printf("%d\n", t(
        "a\n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "aaa  \n"
        "a    \n"
    ));
    printf("%d\n", t(
        "aabaab\n"
        "abaa  \n"
        "aaba  \n"
    ));
    printf("%d\n", t(
        "aabaab\n"
        "a  a a\n"
        "aabab \n"
    ));
    printf("%d\n", t(
        "ba  \n"
        "aaab\n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "ababb\n"
        "aaaa \n"
    ));
    printf("%d\n", t(
        " a aa\n"
        "ab ba\n"
        " aba \n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "abab \n"
        "aaaa \n"
    ));
    printf("%d\n", t(
        "ba \n"
        " ba\n"
        "  b\n"
    ));
    printf("%d\n", t(
        "baa\n"
        "aba\n"
        "aab\n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "aabaa\n"
        "aaaa \n"
    ));
    return 0;
}

Вывод:

1
1
6
18
8
10
6
4
4
9
6
Рето Коради
источник