Блокування екрана Android


25

Вступ

Ви сидите в кімнаті правління в кінці довгого столу. Ви озираєтесь і бачите Тіма Кука, Раду директорів Apple, привид Стіва Джобса та Джека Донагі. Apple назвала цю зустріч, тому що вони зрозуміли, наскільки крутіший екран блокування Android, і хочуть їх 1-UP. Усі в кімнаті дивляться на вас, як привид Стіва кричить: "Допоможіть мені, CodeGolf Man! Ти єдина моя надія!"

Проблема

Екран блокування Android - це сітка 3 х 3 крапок, яку можна з'єднати, провевши пальцем від однієї точки до іншої, створюючи шлях. Паролем вважається будь-який можливий шлях, який включає будь-яку кількість крапок і виключає будь-яку кількість крапок. (На фактичному телефоні шлях повинен бути не менше 4 крапок. Для цього виклику ігноруйте це обмеження.) Apple планує замінити сітку 3 x 3 на сітку M x N, яка є (M * N) / 9 в рази краще!

Правила:

  • Шлях з нульовою крапкою не є паролем, але шлях з 1 крапкою є
  • Шлях може перетнути себе
  • Шлях не може перетинатися безпосередньо через крапку, не включаючи цю крапку
  • Точку можна використовувати лише один раз
  • Шляхи, однакові за обертанням, не є одним і тим же паролем
  • Шляхи, які однакові, але впорядковані в зворотному порядку, не є тим самим паролем
  • Наприклад, на сітці 3x3 з крапками, пронумерованими від 1 до 9:

    1 2 3
    4 5 6
    7 8 9
    

    Деякі дійсні шляхи:

    1
    3
    7,2,3
    1,5,9,2
    1,8,6,5,4
    4,2,3,5,6,7,8,9
    5,9,6,4
    

    І деякі недійсні шляхи:

    1,3
    1,9,5
    7,5,4,7
    4,6
    

    Ваш вхід буде три числа:

    (M,N,d)
    

    Де сітка M x N, а d - довжина шляху

    1 <= M <= 16
    1 <= N <= 16
    1 <= d <= M * N
    

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

    Input:  2,2,1 
    Output: 4
    Input:  2,2,2
    Output: 12
    Input:  7,4,1
    Output: 28
    

    Діють стандартні правила гольфу, найкоротший виграш коду!

    //If I've made a mistake or the rules are unclear, please correct me!
    

    2
    Чи вхідний рядок розділений комою або три окремі параметри?
    користувач80551

    1
    @ user80551 Виходячи з контексту, я думаю, що це буде рядок, якщо він вводиться в програму, або окремі параметри, якщо він використовується для виклику функції.
    користувач12205

    1
    @Platatat Ви можете, будь ласка, відповісти на запитання користувача80551, оскільки це дійсно важливо для розробки коду
    RononDex

    3
    Ви повинні вирішити, чи буде обмежений час як для компіляції, так і часу виконання даного рішення. Без такого обмеження легко написати програму, яка теоретично перевіряє, яка з усіх 256!перестановок точок на сітці 16 x 16 є дійсною схемою розблокування. На практиці така програма ніколи не припинятиметься.
    Денніс

    3
    Але я сказав, що проблема базується на системі блокування андроїд ... То чому я не повинен використовувати ті самі правила, що і система блокування андроїд?
    Плататат

    Відповіді:


    14

    Пітон - 170 байт

    from fractions import*
    p=lambda m,n,d,l=0,s=set():d<1or sum([p(m,n,d-1,i,s|{i})for i in range(m*n)if not(s and(s&{i}or set(range(l,i,abs(i-l)/gcd(i%n-l%n,i/n-l/n)))-s))])
    

    Я усвідомлюю, що дужки всередині sum([...])не є суворо необхідними, але існує великий штраф за невиконання.

    Вихід для всіх 3x3:

    for i in range(4, 10):
      print p(3, 3, i)
    

    Виробляє:

    1624
    7152
    26016
    72912
    140704
    140704
    

    Для тестування / підтвердження перші 6 значень для плати 4x5:

    20
    262
    3280
    39644
    459764
    5101232
    

    4x5 - цікавий випадок для перевірки, оскільки він має 2х2, 3х3 та 2х4 стрибки.


    Коротке пояснення

    Взагалі, це вичерпний пошук із кумулятивною обрізкою. Наприклад, оскільки p(3, 3, 4)це 1624, p(3, 3, 5)перевірятиме лише 8120 можливостей, а не наївно перевіряє всі 15120. Більшість логіки міститься в умові:

    if not(s and(s&{i}or set(range(l,i,abs(i-l)/gcd(i%n-l%n,i/n-l/n)))-s))
    

    У звичайній англійській мові це можна зрозуміти як:

    If no pegs have been used yet
         OR
       the target peg has not yet been used
         AND
       each of the pegs directly between the target peg and the
       current peg (a.k.a. "jumped over") have already been used
    

    2
    Чи можете ви пояснити, що в світі відбувається тут?
    ɐɔıʇǝɥʇuʎs

    1
    Ви можете зберегти кілька байт, sвстановивши набір замість списку. Я не бачу великих покарань продуктивності за відкидання дужок; навіщо було б таке покарання?
    user2357112 підтримує Моніку

    1
    @ user2357112 один підсумовує генератор, інший - за списком. З CPython ви маєте рацію, різниці немає (лише приблизно на 20% повільніше). З PyPy це в 5 разів повільніше.
    прим

    1
    @ user2357112 Я нарешті бачу, що ви мали на увазі, визначаючи sяк набір. Мій урок пітона на сьогодні: {i}оцінює як set([i]). Я б очікував синтаксичної помилки. Потім додавання елемента до набору стає s|{i}, і воно також дозволяє i in sзамінити на s&{i}.
    прима
    Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
    Licensed under cc by-sa 3.0 with attribution required.