Écran de verrouillage Android

25

Intro

Vous êtes assis dans une salle du conseil au bout d'une longue table. Vous regardez autour de vous et voyez Tim Cook, le conseil d'administration d'Apple, le fantôme de Steve Jobs et Jack Donaghy. Apple a convoqué cette réunion parce qu'ils ont réalisé à quel point l'écran de verrouillage Android est plus cool et qu'ils veulent les 1-UP. Tout le monde dans la pièce vous regarde tandis que le fantôme Steve crie: "Aidez-moi, CodeGolf Man! Vous êtes mon seul espoir!"

Le problème

L'écran de verrouillage Android est une grille de points 3 x 3 qui peut être connectée en faisant glisser un doigt d'un point au suivant, créant un chemin. Un mot de passe est considéré comme tout chemin possible qui inclut un nombre quelconque de points et exclut un nombre illimité de points. (Sur un téléphone réel, le chemin doit être d'au moins 4 points. Pour ce défi, ignorez cette restriction.) Apple prévoit de remplacer la grille 3 x 3 par une grille M x N, qui est (M * N) / 9 fois mieux!

Règles:

  • Un chemin à zéro point n'est pas un mot de passe, mais un chemin à 1 point est
  • Un chemin peut se croiser
  • Un chemin ne peut pas traverser directement un point sans inclure ce point
  • Un point ne peut être utilisé qu'une seule fois
  • Les chemins identiques par rotation ne sont pas le même mot de passe
  • Les chemins identiques mais ordonnés à l'envers ne sont pas le même mot de passe
  • Par exemple, sur une grille 3x3 avec des points numérotés de 1 à 9:

    1 2 3
    4 5 6
    7 8 9
    

    Certains chemins valides sont:

    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
    

    Et certains chemins invalides sont:

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

    Votre entrée sera composée de trois chiffres:

    (M,N,d)
    

    Où la grille est M x N, et d est la longueur du chemin

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

    Votre programme ou fonction recevra l'entrée sous la forme d'une chaîne séparée par des virgules et devra renvoyer le nombre de mots de passe possibles de cette longueur. Par exemple:

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

    Les règles de golf du code standard s'appliquent, le code le plus court gagne!

    //If I've made a mistake or the rules are unclear, please correct me!
    
    Platatat
    la source
    2
    L'entrée est-elle une chaîne séparée par des virgules ou trois paramètres distincts?
    user80551
    1
    @ user80551 Selon le contexte, je pense que ce sera une chaîne si elle est entrée dans un programme, ou des paramètres séparés si elle est utilisée pour appeler la fonction.
    user12205
    1
    @Platatat pouvez-vous répondre à la question de user80551, car c'est vraiment important pour concevoir le code
    RononDex
    3
    Vous devez décider s'il y aura une limite de temps pour le temps de compilation et d'exécution d'une solution donnée. Sans une telle limite, il est facile d'écrire un programme qui, en théorie, vérifie laquelle de toutes les 256!permutations des points sur la grille 16 x 16 représente un modèle de déverrouillage valide. En pratique, un tel programme ne se terminerait jamais.
    Dennis
    3
    Mais j'ai dit que le problème était basé sur le système de verrouillage Android ... Alors pourquoi ne devrais-je pas utiliser les mêmes règles que le système de verrouillage Android?
    Platatat

    Réponses:

    14

    Python - 170 octets

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

    Je me rends compte que les supports à l'intérieur sum([...])ne sont pas strictement nécessaires, mais il y a une grande pénalité de performance pour ne pas les inclure.

    Sortie pour tous les 3x3:

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

    Produit:

    1624
    7152
    26016
    72912
    140704
    140704
    

    À des fins de test / confirmation, les 6 premières valeurs pour une carte 4x5:

    20
    262
    3280
    39644
    459764
    5101232
    

    4x5 est un cas intéressant à vérifier, car il a des sauts de cheville 2x2, 3x3 et 2x4.


    Brève explication

    En général, il s'agit d'une recherche exhaustive, avec élagage cumulatif. Par exemple, parce que p(3, 3, 4)est 1624, p(3, 3, 5)ne vérifiera que 8120 posibilités, plutôt que de vérifier naïvement tous les 15120. La plupart de la logique est contenue dans la condition:

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

    En clair, cela peut être compris comme:

    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
    la source
    2
    Pourriez-vous expliquer ce qui se passe ici dans le monde?
    ɐɔıʇǝɥʇuʎs
    1
    Vous pouvez enregistrer quelques octets en ayant sun ensemble au lieu d'une liste. Je ne vois pas la grande pénalité de performance de supprimer les crochets; pourquoi y aurait-il une telle pénalité?
    user2357112 prend en charge Monica
    1
    @ user2357112 l'un fait la somme sur un générateur, l'autre sur une liste. Avec CPython, vous avez raison, il n'y a pas beaucoup de différence (seulement environ 20% plus lent). Avec PyPy, c'est 5 fois plus lent.
    primo
    1
    @ user2357112 Je vois enfin ce que vous vouliez dire en définissant scomme un ensemble. Ma leçon de python pour aujourd'hui: {i}évalue comme set([i]). Je m'attendais à une erreur de syntaxe. Ajouter un élément à un ensemble devient alors s|{i}, et il permet également i in sd'être remplacé par s&{i}.
    primo