Визначте шаблон блокування Android


26

Скажімо, ви бачили, як ваш друг вводив свій пароль у свій телефон Android. Ви не пам'ятаєте, як вони зробили візерунок, але ви пам’ятаєте, як виглядає візерунок. Будучи заклопотаним другом, що ти хочеш знати, наскільки захищений їх пароль. Ваше завдання - обчислити всі способи створення певної схеми.

Як працюють шаблони Android

Візерунки малюються на 3х3 сітці вузлів. За малюнком один відвідує ряд вузлів, ніколи не піднімаючи палець від екрану. Кожен вузол, який вони відвідують, з'єднаний краєм з попереднім вузлом. Майте на увазі два правила.

  • Ви можете не один раз відвідувати один вузол

  • Край може не проходити через невидимий вузол

Зауважте, що, як правило, дуже складно виконати і, отже, не дуже часто зустрічатися в реальних комбінаціях андроїд-замків, можна пересуватися, як Лицар . Тобто, можна переходити з одного боку в не сусідній кут або навпаки. Ось два приклади моделей використання такого кроку:

Ось анімований Gif цього виконавця.

Розв’язання візерунка

Типовий візерунок може виглядати приблизно так:

З таким простим візерунком, як цей, існує два способи, як два намалювати візерунок. Можна починати з будь-якого з двох вільних кінців і проїжджати через виділені вузли до іншого. Хоча це справедливо для багатьох моделей, особливо тих, які зазвичай використовують люди, це не стосується всіх моделей.

Розглянемо таку схему:

Є два негайно впізнавані рішення. Один починається у верхньому лівому куті:

І один, починаючи з нижнього центру:

Однак через те, що рядку дозволено проходити через точку, коли вона вже була обрана, у верхній середині є додатковий візерунок:

Цей конкретний малюнок має 3 рішення, але шаблони можуть мати будь-яке місце між 1 і 4 рішеннями (потрібне цитування) .

Ось кілька прикладів кожного:

1.

2.

3.

4.

I / O

Вузол може бути представлений у вигляді цілих чисел від нуля до дев'яти включно, їх еквівалентів рядків або символів від a до i (або від A до I). Кожен вузол повинен мати унікальне представлення одного з цих наборів.

Рішення буде представлено упорядкованим контейнером, що містить представлення вузлів. Вузли повинні бути впорядковані в тому ж порядку, через який вони пройшли.

Візерунок буде представлений не упорядкованим контейнером з пар вузлів. Кожна пара являє собою край, починаючи з'єднуючи дві точки в парі. Представлення шаблонів не є унікальними.

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

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

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

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

З вузлами, розташованими за наступним малюнком:

0 1 2
3 4 5
6 7 8

Дозвольте {...}бути не [...]упорядкованим контейнером, (...)будьте упорядкованим контейнером і будьте парою.

Наступні входи та виходи повинні відповідати

{(1,4),(3,5),(5,8)} -> {[1,4,3,5,8]}
{(1,4),(3,4),(5,4),(8,5)} -> {[1,4,3,5,8]}
{(0,4),(4,5),(5,8),(7,8)} -> {[0,4,5,8,7],[7,8,5,4,0]}
{(0,2),(2,4),(4,7)} -> {[0,1,2,4,7],[1,0,2,4,7],[7,4,2,1,0]}
{(0,2),(2,6),(6,8)} -> {[0,1,2,4,6,7,8],[1,0,2,4,6,7,8],[8,7,6,4,2,1,0],[7,8,6,4,2,1,0]}
{(2,3),(3,7),(7,8)} -> {[2,3,7,8],[8,7,3,2]}
{(0,7),(1,2),(1,4),(2,7)} -> {[0,7,2,1,4],[4,1,2,7,0]}
{(0,4),(0,7),(1,3),(2,6),(2,8),(3,4),(5,7)} -> {[1,3,4,0,7,5,8,2,6]}
{(1,3),(5,8)} -> {}

Imgur альбом всіх тестів як фотографії можна знайти тут . Візерунки в синіх розчинах червоного кольору.

Оцінка балів

Це код гольфу. Виграє найменше байт.


1
Приємне запитання, я часто замислювався над тим, як у приват. :)
ThreeFx

Ви збираєтесь відповісти на це у brainflak? Тепер це було б вражаюче. : P
DJMcMayhem

Яка закономірність, яку можна вирішити лише одним способом? Я думаю, у вас є щонайменше 2, просто тривіально перевернувши стрілки.
ThreeFx

@DJMcMayhem Я спробую, але я не можу обіцяти
Wheat Wizard

@ThreeFx Спробуйте це для себе. Оскільки ви не можете зупинитися на вже відвіданому вузлі, але ви можете пройти через один зразок, можна зробити напрямним.
Пшеничний майстер

Відповіді:


3

Python 2.7, 493 430 байт

exec("L=['012','345','678','036','147','258','048','246'];L+=[i[::-1]IL];S=sorted;F=lambda t:''.join(str(i)It)\ndef N(x):\n s=' '.join(F(S(i))Ix)\nIL:s=s.replace(i[::2],i[:2]+' '+i[1:])\n return S(set(s.split()))\ndef P(s):\n e=0\nIL:e|=-1<s.find(i[::2])<s.find(i[1])\n return[zip(s[:-1],s[1:]),L][e]\nx=N(input());print[F(i)I__import__('itertools').permutations({iI`x`if i.isdigit()})if x==N(P(F(i)))]".replace('I',' for i in '))

Однорядкова версія обгортає програму exec("...".replace('I',' for i in '))так, що всі фор-цикли та генератори можуть бути коротшими за допомогою єдиного Iі економить 15 байт за цією більш читаною версією:

L=['012','345','678','036','147','258','048','246'];L+=[i[::-1]for i in L]
S=sorted;F=lambda t:''.join(str(i)for i in t)
def N(x):
 s=' '.join(F(S(i))for i in x)
 for i in L:s=s.replace(i[::2],i[:2]+' '+i[1:])
 return S(set(s.split()))
def P(s):
 e=0
 for i in L:e|=-1<s.find(i[::2])<s.find(i[1])
 return[zip(s[:-1],s[1:]),L][e]
x=N(input())
print[F(i)for i in __import__('itertools').permutations({i for i in`x`if i.isdigit()})if x==N(P(F(i)))]

Програма приймає введення таким чином, як показано (наприклад {(1,4),(3,4),(5,4),(8,5)}) або у вигляді списку рядків (наприклад ['14','34','54','85']) (або в інших дружніх форматах python) і повертає вихід у вигляді списку рядків. Тож у нас технічно є замовлений контейнер із замовленими контейнерами.

Функція Nнормалізує візерунок, щоб легко порівняти два візерунки. Нормалізація сортує пари, що позначають ребра (тому '02'замість '20'), використовуйте заміну рядків для розширення подвійних ребер (наприклад, '02'стає '01 12'), розбиває краї на набір для видалення дублікатів і сортує результат.

Функція Fзгладжує кордони вводів / рядків до рядків, тому ми можемо нормалізувати шляхи, вироблені різними способами.

Список Lмістить усі рядки на екрані.

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

Основна перевірка, необхідна для перевірки перестановки як рядка, s- -1<s.find(i[::2])<s.find(i[1])це виявлення помилки з рядком i. Наприклад, за допомогою рядка '210'код виявляє помилку, якщо вона '20'виникає (тобто її індекс перевищує -1) і '1'виникає після неї. Нам не потрібно турбуватися про те, що 1 не відбудеться, тому що 1 відобразиться в нормалізованому шаблоні, коли його не було на вході.


ПРИМІТКА. Я знаю, що заміна str(i)for i in t на map(str,t) і {i for i in`x`if i.isdigit()} з set('012345678')&set(`x`) зробить початковий код коротшим, але це все одно буде трохи довше заміщення I .


2
Falseможе бути, 1<0і в ній є марний пробіл F(i) for. +1.
Yytsi

@TuukkaX Спасибі, я особа підсунули , коли я побачив , що я залишив Falseв.
Лінус

['012','345','678','036','147','258','048','246']може бути '012 345 678 036 147 258 048 246'.split()'за -1 байт.
Містер Xcoder
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.