Ekran blokady Androida

25

Wprowadzenie

Siedzisz w sali konferencyjnej na końcu długiego stołu. Rozejrzyj się i zobaczysz Tima Cooka, zarząd Apple, ducha Steve'a Jobsa i Jacka Donaghy. Apple zwołał to spotkanie, ponieważ zdali sobie sprawę, jak fajniejszy jest ekran blokady Androida, i chcą je zwiększyć. Wszyscy w pokoju patrzą na ciebie, gdy Duch Steve krzyczy: „Pomóż mi, CodeGolf Man! Jesteś moją jedyną nadzieją!”

Problem

Ekran blokady Androida to siatka kropek 3 x 3, które można połączyć, przesuwając palcem od jednej kropki do drugiej, tworząc ścieżkę. Hasło jest uważane za każdą możliwą ścieżkę, która zawiera dowolną liczbę kropek i wyklucza dowolną liczbę kropek. (W prawdziwym telefonie ścieżka musi mieć co najmniej 4 kropki. W przypadku tego wyzwania zignoruj ​​to ograniczenie). Apple planuje zastąpić siatkę 3 x 3 siatką M x N, która wynosi (M * N) / 9 razy lepiej!

Zasady:

  • Ścieżka zero kropek nie jest hasłem, ale ścieżka 1 kropka to
  • Ścieżka może się przecinać
  • Ścieżka nie może przejść bezpośrednio nad kropką bez uwzględnienia tej kropki
  • Kropki można użyć tylko raz
  • Ścieżki identyczne pod względem rotacji nie są tym samym hasłem
  • Ścieżki, które są identyczne, ale uporządkowane odwrotnie, nie są tym samym hasłem
  • Na przykład na siatce 3x3 z kropkami ponumerowanymi od 1 do 9:

    1 2 3
    4 5 6
    7 8 9
    

    Niektóre prawidłowe ścieżki to:

    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
    

    A niektóre nieprawidłowe ścieżki to:

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

    Twój wkład będzie składał się z trzech liczb:

    (M,N,d)
    

    Gdzie siatka to M x N, a d to długość ścieżki

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

    Twój program lub funkcja otrzyma dane wejściowe jako ciąg rozdzielany przecinkami i musi zwrócić liczbę możliwych haseł o tej długości. Na przykład:

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

    Obowiązują standardowe zasady gry w golfa, wygrywa najkrótszy kod!

    //If I've made a mistake or the rules are unclear, please correct me!
    
    Platatat
    źródło
    2
    Czy wejście jest ciągiem rozdzielanym przecinkami, czy trzema oddzielnymi parametrami?
    user80551,
    1
    @ user80551 Na podstawie kontekstu myślę, że będzie to ciąg znaków, jeśli zostanie wprowadzony do programu, lub oddzielne parametry, jeśli zostanie użyty do wywołania funkcji.
    user12205,
    1
    @Platatat, czy możesz odpowiedzieć na pytanie użytkownika 80551, ponieważ zaprojektowanie kodu jest bardzo ważne
    RononDex
    3
    Powinieneś zdecydować, czy będzie limit czasowy zarówno dla czasu kompilacji, jak i wykonania danego rozwiązania. Bez takiego ograniczenia łatwo jest napisać program, który teoretycznie weryfikuje, która ze wszystkich 256!kombinacji kropek na siatce 16 x 16 reprezentuje prawidłowy wzór odblokowania. W praktyce taki program nigdy się nie kończy.
    Dennis
    3
    Ale powiedziałem, że problem dotyczy systemu blokady Android ... Dlaczego więc nie miałbym stosować tych samych reguł, co system blokady Android?
    Platatat

    Odpowiedzi:

    14

    Python - 170 bajtów

    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))])
    

    Zdaję sobie sprawę, że nawiasy w środku sum([...])nie są absolutnie konieczne, ale istnieje duża kara wydajnościowa za ich nieuwzględnienie.

    Wyjście dla wszystkich 3x3:

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

    Produkuje:

    1624
    7152
    26016
    72912
    140704
    140704
    

    Do celów testowania / potwierdzania pierwszych 6 wartości dla płyty 4x5:

    20
    262
    3280
    39644
    459764
    5101232
    

    4x5 to ciekawy przypadek do weryfikacji, ponieważ ma skoki 2x2, 3x3 i 2x4.


    Krótkie wyjaśnienie

    Ogólnie rzecz biorąc, jest to wyczerpujące wyszukiwanie z łącznym przycinaniem. Na przykład, ponieważ p(3, 3, 4)jest to 1624, p(3, 3, 5)sprawdzi tylko 8120 możliwości, zamiast naiwnie sprawdzać wszystkie 15120. Większość logiki jest zawarta w warunku:

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

    W prostym języku angielskim można to rozumieć jako:

    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
    
    primo
    źródło
    2
    Czy możesz wyjaśnić, co tu się dzieje na świecie?
    1ıʇǝɥʇuʎs
    1
    Możesz zaoszczędzić kilka bajtów, będąc szestawem zamiast listy. Nie widzę dużego spadku wydajności wynikającego z upuszczenia nawiasów; dlaczego miałaby być taka kara?
    user2357112 obsługuje Monikę
    1
    @ user2357112 jeden sumuje się nad Generatorem, drugi nad Listą. Z CPython masz rację, nie ma dużej różnicy (tylko około 20% wolniej). Dzięki PyPy jest ponad 5 razy wolniejszy.
    primo
    1
    @ user2357112 Wreszcie rozumiem, co miałeś na myśli, definiując sjako zestaw. Moja lekcja języka python na dziś: {i}ocenia jako set([i]). Spodziewałbym się błędu składniowego. Dołączenie elementu do zestawu staje się wtedy s|{i}i pozwala również i in szostać zastąpione przez s&{i}.
    primo