Перевірка горизонтальної змії для тварин ASCII


22

Нещодавно було кілька проблем із зміями домашніх тварин ASCII (наприклад, тут )

            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   

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

  • У кожному стовпці є лише один 0
  • Кожен з 0них "підключений" до цього 0і після нього (вертикально розташований лише на 0 або 1 рядок)

Остаточний вихід може бути trueабо 1якщо змія дійсна, falseабо 0якщо змія недійсна

Редагувати - Уточнення

Припустимо вхід:

  • Це рядок
  • Містить лише '', '0' та '\ n'
  • Має рівно 30 символів у кожному рядку
  • Має рівно 5 рядків

Тобто переконайтеся, що змія підключена і чи немає бродячих ознак. Не потрібно перевіряти "полотно", на якому змія друкується.


4
Привіт і ласкаво просимо до PPCG :) Це хороший виклик для першого повідомлення, але ви, мабуть, хочете додати ще кілька тестових випадків, які ловлять виняткових змій. Ви також, ймовірно, захочете вирішити, чи має змія бути представлена ​​нулями чи може бути будь-який символ. Надалі, будь ласка, подумайте про використання пісочниці . Удачі :)
FryAmTheEggman

5
Це сприймається як Стінг? Або його можна ввести як 2d масив?
JSchiff

6
Чи гарантовано, що вхід складається з 0 і пробілів? Що кожен рядок має довжину 30? Що є 5 рядків?
xnor

9
Оскільки це проблема вирішення питання, truthy/falseyа як не true/false?
Джонатан Аллан

3
@JSchiff Я впевнений, що байта змії?
MarioDS

Відповіді:


14

JavaScript (ES2018), 62 54 байти

s=>!/0(.{30}|.{60,62}(.{31})*)0|( .{30}){4} /s.test(s)

Введення - це один рядок:

  • без затримки нової лінії
  • містять лише пробіл, "0" та "\ n"
  • 30 символів у кожному рядку, 5 рядків, 154 символів загалом

Прапор sозначає крапка, що відповідає чому-небудь (включаючи '\ n'). Наразі ця функція підтримується Chrome 63+, Opera 50+, Safari 11.1+ і базується на даних таблиці . Ви можете протестувати цю функцію за допомогою підтримуваного браузера. Ви отримаєте виняток під час завантаження сторінки, якщо ваш браузер не підтримує цю функцію.

Як це працює:

  • Немає стовпця без « 0:
    • не збігаються /( .{30}){4} /
  • Немає двох 0s в одному стовпчику:
    • не збігаються /0.{30}(.{31})*0/
  • Ніхто 0не підключається до своїх сусідів:
    • не відповідають /0.{60}(.{31})*0/,/0.{62}(.{31})*0/

Об’єднайте всі ці регулярні виразки, і ви нарешті отримаєте цей.

Завдяки Мартину Ендеру зазначають, що один !оператор може заощадити 8 байт.


8

SnakeEx , 51 байт

Це, очевидно, правильна мова для завдання. : ^ D

s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$

Відповідає всьому входу, якщо це дійсна змія; не відповідає, якщо це не так. Спробуйте тут!

Пояснення

SnakeEx - це дводенна мова відповідності зразком . Програма складається зі списку визначень для "змій", які повзають навколо вхідних відповідних символів, змінюючи напрямки та нерестують інших змій. У нашій програмі ми визначаємо дві змії sта c.

Почнемо з того, cщо це простіше. Його визначення таке 0 *$, що має бути цілком читабельним, якщо ви знаєте регулярний вираз: match 0, з наступним нулем або більше пробілів, а потім край сітки. Основний улов тут: це узгодження може тривати в будь-якому напрямку. Ми будемо використовувати cяк змія вгору, так і вниз, щоб перевірити, чи немає 0в кожному стовпчику зайвих с.

Тепер про головну змію , s. Він приймає форму (...)%{30}, що означає "відповідати змісту дужок 30 разів" - один раз для кожного 0в змії. Все йде нормально. Що йде всередині дужок?

{c<L>}

Це породить нову cзмію, повернуту ліворуч на 90 градусів. Напрямок відносно напрямку sзмії, тому нова змія рухається у верхній частині сітки (головна змія рухається вправо). У cзмії перевіряє , що поточна комірка сітки являє собою 0і що кожна клітина над ним простір. Якщо він не вдається, весь матч виходить з ладу. Якщо це вдасться, ми продовжуємо с

{c<R>}

що робить те саме, тільки повернуто праворуч (у напрямку до нижньої частини сітки).

Зауважте, що ці нерести не впливають на положення вказівника сірника в основній змії. Вони трохи схожі на лукаголовки в регексе. (Може, тут ми могли б назвати їх "lookbesides"?) Тож після перевірки того, що ми вказуємо на a, 0а решта стовпця містить лише пробіли, нам потрібно насправді відповідати 0:

0

Тепер покажчик відповідності знаходиться на символі праворуч від поля 0. Нам потрібно перевірити три різні варіанти: кути змії вниз, змії кути вгору або змія йде прямо. Для цього ми можемо використовувати вираз АБО:

[...]

Всередині нашого АБО є три можливості:

(<R> <L>)

Поверніть праворуч, сумістіть пробіл і знову поверніть ліворуч (зміїні кути вниз).

(<L> <R>)

Поверніть ліворуч, сумістіть пробіл і знову поверніть праворуч (зміїні кути вгору).

_?

Зрівняти нуль або один підкреслення. Оскільки у введенні немає підкреслень, це завжди буде порожнім збігом (змія йде прямо).

Після відповідності одному з перерахованих вище трьох варіантів вказівник відповідності повинен вказувати на 0наступний стовпець, готовий знову відповідати викладеному в дужці виразом.


2

CJam , 35 34 байт

{z_{'0e=1=}%:*\'0f#2ew::-[W0X]-!*}

Спробуйте в Інтернеті! Введення - це прямокутний масив масивів символів. Припускає, що вхід містить лише і 0.

Пояснення:

{z_{'0e=1=}%:*\'0f#2ew::-[W0X]-!*}   Function taking a character matrix:
 z                                      Transpose.
   {      }%                            Consider whether each row
      e=                                  contains
        1=                                exactly one
    '0                                    of the character '0'.
            :*                            This must be true for every row.
                  #                     Next, find the position
               '0                         of the character '0'
                 f                        at every row
  _           \                           in the original input.
                       :-               Find the differences between
                      :                   each
                   2                      pair
                    ew                    of adjacent elements (in other words, compute
                                            the increments).
                                        For the snake to be valid, this array of increments
                                            must only contain {0, 1, -1}, so
                              -         Remove from this list
                         [   ]            the elements
                          W                 -1,
                           0                0,
                            X               and 1,
                               !          and then check whether the array is empty.
                                *       The previous code tested two different properties
                                          of the matrix; they both must be true for a
                                          valid snake.

2

05AB1E , 18 байт

ζDε0k}¥Ä2‹sεþg}ìPΘ

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

Пояснення

ζ                    # transpose
 D                   # duplicate
  ε  }               # for each row in the first copy (column of input)
   0k                # get the index of the first 0
      ¥Ä             # calculate absolute delta's
        2‹           # check that each is less than 2
          sε  }      # for each row in the second copy (column of input)
            þg       # calculate the length of the string with non-digits removed
               ì     # concatenate the lists
                P    # calculate product
                 Θ   # truthify (turn false values to 0)

2

Лушпиння , 12 байт

Залежно від уточнення правил, це може бути 11 байт або 13 байт .

±Λ=;1Ẋ×≈mηfT

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

Введення - це список рядків, що містять лише пробіли та 0; якщо потрібна одна струна, додайте програму до поділу на рядки. Посилання TIO вже робить це для наочності. Вихід 0 або 1; якщо будь-які фальшиві та непорочні значення добре, їх ±можна видалити.

Пояснення

±Λ=;1Ẋ×≈mηfT  Implicit input: a list of lines.
           T  Transpose into list of columns.
        m     For each column,
         ηf   get list of indices of truthy elements.
              In Husk, whitespace characters are falsy and other are truthy,
              so this gets us the indices of 0s on each column.
     Ẋ        For each adjacent pair of these index lists,
      ×       for all pairs drawn from the two lists,
       ≈      give 1 if they differ by at most 1, otherwise 0.
              For each adjacent pair, this produces a list of 1s and 0s.
 Λ            Do all of these lists
  =;1         equal [1]? Return either 0 or 30 (length of the outer list + 1).
±             Signum; convert to 0 or 1.

Ідея полягає в тому, ×≈щоб гарантувати, що (a) всі стовпці містять точно один 0, і (b) їх положення відрізняються щонайменше на один. Як приклад, розглянемо вхід з 8 стовпців

0  0  0 
 000 0  
  00   0

По-перше, mηfTперетворює його у список списків індексів

[[1],[2],[2,3],[1,2,3],[],[2],[1],[3]]

Потім Ẋ×≈дає

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

Кожен 1відповідає парі індексів, які відрізняються максимум на 1, а кожен 0відповідає парі, яка не відповідає. Кожен результат дорівнює [1]точно, коли обидва списки мають один індекс, а показники відрізняються щонайменше на 1.


2

Python 2 , 71 байт

f=lambda s:s[1]<' 'or'0'in s[::31]in' %s '%s[1::31]in'%6s'%0*2*f(s[1:])

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

Вводиться як багаторядковий рядок. Тестовий випадок від Bubbler .

Перший стовпчик витягується як, s[::31]а другий як s[1::31]і перевіряється на дійсність. Ми повторюємо sвидалення першого символу, викликаючи перевірку послідовних пар стовпців.

Для перевірки двох стовпців використовується ланцюжок порівняння Python для inоб'єднання декількох чеків:

  • '0'in s[::31] перевіряє наявність першого стовпця принаймні одного 0
  • s[::31]in' %s '%s[1::31]перевіряє, що перший стовпець є підрядком другого сендвічу стовпця між двома пробілами, що забезпечує положення 0переміщених максимум на один пробіл
  • ' %s '%s[1::31]in'%6s'%0*2перевіряє, чи містить другий стовпець щонайбільше один 0.

Закінчення *f(s[1:])також змушує рекурсивний випадок бути істинним.


Тепер, коли я замислююся над цим, Python є приголомшливою мовою для цих "змійних" проблем. : P
MustacheMoses

2

C (gcc) ,246 245 232 215 212 байт

#define F)exit(1);
#define L for(i=l=0;i<30;i++)
#define X b[7][i]
char b[8][31];k,j,l;main(i){for(;j++<5;){gets(b);L{if(i[*b]>47){if(X++F memset(b[j+1]+i-1,l=1,3);}else if(!X&b[j][i]F}k+=!!l;}if(k<5 F L if(!X F}

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

Я подумав, що я візьму до цього свою улюблену мову (хоча, як я бачу з багатьох інших, менших записів, це, мабуть, далеко не ідеально підходить для такого роду викликів) і C, чим я міг би керувати. Підхід програми до проблеми є відносно простим, лише з великою кількістю байтових копійок; він приймає змію на stdin і дає її результат у зворотному значенні main (таким чином, вихідний код;як вимагається в проблемі 0 вказує недійсну змію і 1 дійсну, навіть якщо для вихідного коду це дивнояк типова для вихідних кодів 0 - дійсна змія, а 1 - недійсна змія). З розширеними макросами та деяким приємним пробілом це схоже на наступне:

char b[8][31];l,j,k;                           //Declares a buffer to work in, initialized all to 0; l j and k default to int and as globals are init to 0
main(i) {                                      //This is run no-args, so argc is 1 and the undeclared type defaults to int.
  for (; j++ < 5;) {                           //Iterating over each row, 1-indexed for convenience accessing the buffer
    gets(b);                                   //Reads into b[0] because of stack array decl layout
    for (i = l = 0; i < 30; i++) {             //j and l both init each time we begin this overall loop
      if (i[*b] > 47) {                        //Did we read a zero?
        if(b[7][i]++) exit(1);                 //If the snake already had a zero in this column, fail out
        memset(b[j+1] + i-1, l = 1, 3);        //Expect them on the next row in the columns left and right of this one (also set l)
      } else if (!b[7][i] & b[j][i]) exit(1);  //If we didn't read a zero, and we had reason to expect one this row, and there wasn't already a zero in this column, fail out
    }
    k+=!!l;                                    //Adds 1 to k iff l is nonzero 
  } if (k < 5) exit(1);                        //If less than 5 rows had zeroes in them, fail out
  for(i = l = 0 ; i < 30; i++) {               //l isn't relevant in this loop but saves some bytes when sharing a macro with the other horizontal loop
    if(!b[7][i]) exit(1);                      //If any columns didn't have zeroes, fail out
  }                                            //Else, snake is valid. main default returns 0.
}

Рядки введення зчитуються в перший рядок буфера, наступні п'ять - для відстеження, які місця очікуються (читати: повинні) мати нулі в рядку після кожного поточного, а останній - для відстеження того, чи є нуль вже були прочитані в заданій колонці, у будь-якому рядку. Програма обробляє кожен ряд по черзі.

Це зовсім не надійний ( gets()є лише початком), і вхід повинен містити всі відповідні пробіли (наприклад, немає залишеного пробілу білого простору), а gcc виводить попередження та примітки про функціональність stdlib, ліворуч неявно оголошене тощо, але, C la vie.

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

Завдяки користувачеві202729 за бл. Збережено 26 байт.



Ви можете пропустити пробіл між #define Fі )на –1 байт.
користувач202729

Крім того, оскільки вхід має лише \n(10), <space>(32) і 0(48), ви можете перевірити за ==48допомогою >47(-1 байт). / Ви можете видалити ={0}при ініціалізації, bякщо змінна є глобальною. Аналогічно складіть kглобальний і i(нетипізований -> int) параметр main(замість argcякого є 1).
користувач202729

Дякую! Відредагований ще до того, як я побачив останні пропозиції; Я відзначу шлях через них (це iяк argcгеній). Перші чернетки цього проекту складали понад 400 байт; мені знадобилося досить довго, щоб перетягнути його до моїх особистих цілей 300, а потім 256, тож, можливо, буде більше способів зменшити це, що я пропустив.
SevenStarConstellation

Вирішив зробити k, jі lвсі глобальні економії заощадити на тому, щоб мати окремі intдекларації, тоді зрозумів, що за замовчуванням я можу піти, не виходячи з типу повністю. Знову дякую!
SevenStarConstellation

1

MATL , 18 17 байт

32>&fun30=wd|2<vA

Вхід - це двовимірний масив символів. Для змії може використовуватися будь-який непросторовий персонаж.

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

Пояснення

32>      % Implicit input. Transform non-space into 1, space into 0
&f       % Push vector of row indices and vector of column indices of nonzeros
u        % Unique: vector of deduplicated entries
n        % Length
30=      % Does it equal 30? (*)
w        % Swap. Moves vector of row indices to top
d|       % Absolute consecutive differences
2<       % Is each value less than 2? (**)
v        % Concatenate results (*) and (**) vertically
A        % All: true if all entries are nonzero. Implicit display

1
Специфікація передбачає, що довжина лінії 30 є гарантована, тому я думаю, ви можете заощадити кілька.
Джонатан Аллан

@JonathanAllan Дякую! Я використовую, un30=щоб перевірити, чи всі індекси стовпців різні, і жоден із 30 стовпців не порожній. Можливо, я можу це перевірити прямо, але я не бачу, як
Луїс Мендо


1

Желе , 19 байт

Zn⁶T€L€=1$$;FIỊ$$$Ạ

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

-2 байти завдяки панові Xcoder

Пояснення

Zn⁶T€L€=1$$;FIỊ$$$Ạ  Main Link
Z                    Transpose the matrix of characters
                         (string -> list of chars in Jelly)
 n⁶                  != " " (vectorizing)
   T€                For each column, get (row) indices of snake parts
     L€=1$$          For each index list, is its length 1? (that is, exactly one snake part per column)
           ;     $   Append (helper part)
            FIỊ$$    helper part:
            F        flatten index list
             I       get increments/forward differences
              Ị      are the values insignificant? (|z| <= 1)
                  Ạ  Are these all true?

Введення - це список рядків


@ Mr.Xcoder Так, не вдається, представлення желейних рядків випускає лол. виправлено унгольфінгом 1 байт
HyperNeutrino

1

Желе , (14? *) 13 байт

Zn⁶T€z-IỊ0-¦Ȧ

Монадійне посилання, що містить список з п'яти рядків *, кожна довжиною 30 складається з пробілів та будь-яких інших символів (наприклад, 0s), і повертає ціле число (1, якщо змія, визначена, 0 інакше)

* Якщо вхід повинен бути одним рядком (список символів), тоді додайте a, щоб розділити рядок у стрічках рядків.

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

Як?

Zn⁶T€z-IỊ0-¦Ȧ - Link: list of lists of characters, Lines
Z             - transpose the lines -> columns
  ⁶           - literal space character
 n            - not equal? -> 0 where there were spaces and 1 where there were "0"s
   T€         - truthy indices for each -> e.g. [0,0,1,0,0] -> [3] or [0,1,1,0,0] -> [2,3]
              -                           note: [0,0,0,0,0] -> []
      -       - literal minus one
     z        - transpose with filler (-1) -> {valid: a single list of heights {top:1,...,bottom:5}
              -                              invalid: list of >1 lists, some of which contain -1
              -                                       ...OR an empty list (no 0s in the input at all)}
       I      - differences -> {up:-1; down:1; flat:0; invalid:-6,-5,...,-2,2,...4}
        Ị     - insignificant (abs(z)<=1) -? {up/down/flat:1; invalid:0}
           ¦  - sparse application///
         0    - ...action: literal zero
          -   - ...to indices: [-1] -> make penultimate list into a zero (when one exists)
            Ȧ - any & all -> when flattened:{empty or contains a 0:0; otherwise:1}

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

@LuisMendo хе-х, і виправивши, що я врятував три, тож ще раз дякую!
Джонатан Аллан

... е, але я представив інше. Виправлено ще 3 :(
Джонатан Аллан

Непогана кількість байтів, хоча :-)
Луїс Мендо

1

Stax , 20 байт CP437

Å┴m▐◘5)ît╢V¼≥+╝╜►º½ê

24 байти при розпакуванні,

LM{'0|Ic%vChm:-{Jh!f%29=

Запуск та налагодження в Інтернеті!

Можливо, це не найкращий гольф, але я думаю, що метод є новим та цікавим.

Пояснення

LM                          Load the input string as a 2d array of characters, and transpose it

  {         m               Map array with block
   '0|I                     Get all indices of substring "0"
       c%vC                 Map to nothing if the indices are not unique
           h                Otherwise map to the unique index

             :-             Take pairwise difference

               {   f        Filter array with block
                Jh!         Only keep 0, 1 and -1

                    %29=    Check whether the final array has exactly 29 elements

1

J , 38, 37 30 байт

-8 байт завдяки FrownyFrog

[:($e.~[:(-:*)2-/\])@:I.'0'=|:

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


1
Як щодо [:(-:*)2-/\, перевірте, чи всі відмінності −1, 0 або 1.
FrownyFrog

@FrownyFrog Так, це набагато швидше! Дякую!
Гален Іванов

@ FrownyFrog Хм, я цього не усвідомлював. Я спробую це виправити. Дякую, що вказали на це.
Гален Іванов

1
[:(#@{.=[:(-:*)2-/\])@:I.'0'=|:
FrownyFrog

1
О, це теж працює[:($e.~[:(-:*)2-/\])@:I.'0'=|:
FrownyFrog

1

Желе , 16 байт

Zµi€”0IỊ;ċ€⁶=4ƊẠ

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

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

Пояснення

Zµi€”0IỊ;ċ€⁶=4ƊẠ | Monadic full program.
Z                | Transpose.
 µ               | Start a new monadic chain.
  i€”0           | Retrieve the first index of 0 in each column.
      IỊ         | Check whether their increments are insignificant (element-wise).
        ;     Ɗ  | Append the result of the following:
         ċ€⁶     | In each list of characters, count the occurrences of a space.
            =4   | Check whether they equal 4 (returns a boolean array).
               Ạ | All. Check whether all the elements are truthy.


0

Python 2 і Python 3 , 122 120 119 байт

lambda s:s.count('0')<31and all(s[i-31*(i>30):31*(i<124)-~i:31].strip(' ')for i,x in enumerate(s,1)if' '<x)and' '<s[62]

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

Формат введення - це один рядок довжиною 154 (5 х 30 символів, 4 нові рядки):

'''
            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   '''[1:] # to exclude starting newline

Якщо голова не повинна бути центральним рядом

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

Python 2 та Python 3 , 124 123 байт

lambda s:s.count('0')<31and all(s[i-31*(i>30):31*(i<124)-~i:31].strip(' ')for i,x in enumerate(s,1)if' '<x)and'0'in s[::31]

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


Редагувати:

  • Скорочуйте 2 байти шляхом зміни рівностей ( ==) на нерівності для кожного коду.
  • Виявив помилки в менш обмежувальній версії та переглянув її. (На щастя, це не надто страшно, тому я міг би зберегти всі версії подібними за довжиною.) Додаткові тестові випадки ви можете побачити в двох останніх посиланнях TIO.
  • Знайшов звисаючий байт у рішеннях Py2, зробивши all()трюк безглуздим у Py3, тому об’єднав обидві версії.

0

Excel (VBA), 68 байт

Використання негайного вікна Cell[A6]в якості виводу.

[A1:AD5]="=CHOOSE(ROUND(RAND()+1,),0,"""")":[A6]="=COUNT(A1:AD5)=30"





0

Python 3 , 197 185 байт

У командному рядку do verify.py<snake.txtабо в bash do cat snake.txt | python verify.py. Де snake.txtфайл, що містить змію для перевірки.

Якщо змія вірна, нічого не вийде. Якщо це неправильно, Python призведе до помилки індексу.

import sys
s=sys.stdin.read().split("\n")
x=0
exec('t,y="",0\nwhile y<5:t+=s[y][x];y+=1\ns+=[t];x+=1;'*30)
s=list(map(lambda l:len(l.rstrip()),s))
while y<35:"ee"[abs(s[y]-s[y+1])];y+=2

О, не помічав, що мої результати повинні бути правдивими чи хибними. Чи повертається код помилки, що повертається?
MustacheMoses

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