Le jeu BattleBlock Theatre contient parfois un puzzle qui est une version généralisée de Lights Out . Vous avez trois blocs adjacents, chacun indiquant un niveau entre 1 et 4 inclus avec des barres, par exemple:
|
||||
||
Si vous touchez un bloc, ce bloc ainsi que tout bloc adjacent augmentera son niveau (retour de 4 à 1). Le casse-tête est résolu lorsque les trois blocs affichent le même niveau (peu importe le niveau). Étant donné que l'ordre dans lequel vous touchez les blocs n'a pas d'importance, nous désignons une solution selon la fréquence à laquelle chaque bloc est touché. La solution optimale pour l'entrée ci-dessus serait 201
:
| --> || --> ||| |||
|||| | || |||
|| || || --> |||
Le jeu généralise très facilement n'importe quel nombre de blocs, bien que pour certains nombres, toutes les configurations ne soient pas résolubles.
Le défi
Étant donné une séquence de niveaux de blocs, indiquez à quelle fréquence chaque bloc doit être touché pour résoudre le puzzle. Par exemple, l'exemple ci-dessus serait donné en tant que 142
et pourrait donner 201
en conséquence. S'il n'y a pas de solution, renvoyez une sortie cohérente de votre choix, qui se distingue de toutes les solutions potentielles, par exemple, -1
ou une chaîne vide.
Vous pouvez écrire une fonction ou un programme, prendre une entrée via STDIN, un argument de ligne de commande ou un argument de fonction, dans n'importe quel format de liste ou de chaîne pratique, et également sorti via une valeur de retour ou en imprimant sur STDOUT.
Votre code doit renvoyer des résultats corrects pour tous les cas de test dans une minute sur une machine raisonnable. (Ce n'est pas une limite complètement stricte, donc si votre solution prend une minute et dix secondes, c'est bien, mais si cela prend 3 minutes, ce n'est pas le cas. Un bon algorithme les résoudra facilement en quelques secondes.)
Il s'agit du code golf, donc la réponse la plus courte (en octets) l'emporte.
Exemples
Les solutions ne sont pas uniques, vous pouvez donc obtenir des résultats différents.
Input Output
1 0
11 00
12 No solution
142 201
434 101
222 000
4113 0230
32444 No solution
23432 10301
421232 212301
3442223221221422412334 0330130000130202221111
22231244334432131322442 No solution
111111111111111111111222 000000000000000000000030
111111111111111111111234 100100100100100100100133
412224131444114441432434 113013201011001101012133
Pour autant que je sache, il y a exactement 4 solutions pour chaque entrée où le nombre de blocs est 0 mod 3, ou 1 mod 3, et il y a 0 ou 16 solutions où il est 2 mod 3.
la source
Réponses:
Python 2, 115 octets
Ceci est la version golfée du programme que j'ai écrit en discutant du problème avec Martin.
L'entrée est une liste via STDIN. La sortie est une liste représentant la dernière solution trouvée s'il y a une solution, ou zéro s'il n'y en a pas. Par exemple:
Pyth,
3229 octetsLe port obligatoire. Merci à @Jakube pour la sauvegarde de 3 octets.
La méthode de saisie est la même que ci-dessus, essayez-la en ligne .
Explication (longue et pleine de logique!)
Tout d'abord, deux observations de base:
Observation 1: Peu importe l'ordre dans lequel vous touchez les blocs
Observation 2: Si vous touchez un bloc 4 fois, c'est équivalent à le toucher une fois
En d'autres termes, s'il existe une solution, il existe une solution où le nombre de touches est compris entre 0 et 3 inclus.
Puisque modulo 4 est si agréable, faisons-le aussi avec les blocs. Pour le reste de cette explication, le niveau de bloc 0 est équivalent au niveau de bloc 4.
Désignons maintenant
a[k]
le niveau actuel de block
etx[k]
le nombre de fois où nous touchons le block
dans une solution. Soitn
également le nombre total de blocs. Comme l'a noté @Jakube, une solution doit satisfaire:où
C
est le niveau final sur lequel se trouvent tous les blocs, entre 0 et 3 inclus (rappelez-vous que nous traitons le niveau 4 comme le niveau 0) et toutes les équations ci-dessus sont vraiment des congruences modulo 4.Voici maintenant la partie amusante:
0 <= C <= 3
.Il y a trois cas basés sur le nombre de blocs modulo 3. L'explication pour chacun d'eux est la même - pour n'importe quel nombre de blocs, il existe un sous-ensemble de blocs qui, si vous touchez chacun d'eux une fois, augmente tous les niveaux de bloc de exactement 1.
Cela explique pourquoi il existe 4 solutions pour
0 mod 3
et1 mod 3
, et généralement 16 solutions pour2 mod 3
. Si vous avez déjà une solution, toucher les blocs comme ci-dessus donne une autre solution qui se retrouve à un niveau de bloc plus élevé (enroulant autour).Qu'est-ce que cela signifie? Nous pouvons choisir n'importe quel niveau de bloc final que
C
nous voulons! ChoisissonsC = 0
, car cela économise des octets.Maintenant, nos équations deviennent:
Et réorganisez:
Donc, ce que nous pouvons voir, si nous avons
x[0]
, nous pouvons utiliser toutes les équations, sauf la dernière, pour découvrir toutes les autresx[k]
. La dernière équation est une condition supplémentaire que nous devons vérifier.Cela nous donne un algorithme:
x[0]
x[k]
Cela donne la solution ci-dessus.
Alors pourquoi n'obtenons-nous parfois aucune solution
2 mod 3
? Examinons à nouveau ces deux modèles:Considérons maintenant les équations à ces positions, c'est-à-dire pour la première:
Additionnez-les:
Pour le second:
Ajoutez-les à nouveau:
Donc, si
(a[1] + a[4] + a[7] + a[10])
et(a[0] + a[3] + a[6] + a[9])
ne sont pas égaux, nous n'avons pas de solution. Mais s'ils sont égaux, nous obtenons 16 solutions. C'était len = 11
cas, mais bien sûr, cela se généralise à tout nombre qui est2 mod 3
- prendre la somme de chaque troisième élément à partir du deuxième, et comparer à la somme de chaque troisième élément à partir du premier.Maintenant enfin, est-il possible de comprendre ce qui
x[0]
doit être au lieu d'essayer toutes les possibilités? Après tout, puisque nous avons limité notre niveau cibleC
à 0, il n'y en a qu'unx[0]
qui donne une solution dans le cas0 mod 3
ou1 mod 3
(as4 solutions / 4 final levels = 1 solution for a specific final level
).La réponse est oui! Nous pouvons le faire pour
0 mod 3
:Ce qui se traduit par:
La soustraction donne:
De même pour
1 mod 3
nous pouvons faire ce modèle:Qui donne:
Celles-ci se généralisent bien sûr en étendant les indices par incréments de 3.
Car
2 mod 3
, puisque nous avons deux sous-ensembles qui couvrent chaque bloc, nous pouvons en choisir n'importe lequelx[0]
. En fait, cela est vrai pourx[0], x[1], x[3], x[4], x[6], x[7], ...
(essentiellement tout indice non conforme2 mod 3
, car ils ne sont couverts par aucun des sous-ensembles).Nous avons donc un moyen de choisir un
x[0]
au lieu d'essayer toutes les possibilités ...... mais la mauvaise nouvelle est que cela n'économise pas sur les octets (124 octets):
la source
J
au lieu deH
et 2 caractères, si vous sautez le dernier élémentPJ
au lieu de le découper.<J_1
.V4J]NVQaJ%_+s>J_2@QN4)I!eJPJB
Pyth,
727673663938 caractèresedit 4: Réalisé, que les calculs
Q[N]-Q[N+1]+solution[-3]
etQ[-2]-Q[-1]+solution[-3]
sont ident. Par conséquent, je sur-calcule la solution par 1 et filtre les solutions, où la dernière entrée est 0. Ensuite, j'éclate la dernière entrée. Heureusement, les cas spéciaux n'ont pas besoin d'un traitement supplémentaire avec cette approche. -27 caractèresedit 3: Application de quelques astuces de golf de FryAmTheEggman: -7 caractère
modifier 2: Utiliser le filtre, réduire et mapper: -3 caractère
modifier 1: Dans ma première version, je n'ai rien imprimé, s'il n'y avait pas de solution. Je ne pense pas que ce soit autorisé, donc +4 caractère.
Attend une liste d'entiers en entrée
[1,4,2]
et génère une solution valide[2,0,1]
s'il y en a une, sinon une liste vide[]
.Explication:
Soit
Q
la liste des 5 niveaux etY
la liste de la solution. Les équations suivantes doivent être respectées:Par conséquent, si nous utilisons tout
Y0
etY1
, nous pouvons calculerY2
,Y3
etY4
de la manière suivante.Que tous les niveaux sauf le dernier sont égaux (parce que nous n'avons pas utilisé l'équation
= Q4 + Y3 + Y4
. Pour vérifier, si ce dernier est également égal aux autres niveaux, nous pouvons simplement vérifier si(Q3 - Q4 + Y2) mod 4 == 0
. Remarquez que la partie gauche serait la valeurY5
Si je calcule la 6e partie de la solution, je peux simplement vérifier si elle est nulle.Dans mon approche, je répète simplement tous les départs possibles (
[0,0]
, à[3,3]
) et calcule la longueur (entrée) -1 entrées supplémentaires et filtre toutes les solutions qui se terminent par un zéro.il s'agit essentiellement des éléments suivants:
puis je filtre ces solutions possibles pour des solutions valides:
à cette liste de solutions j'ajoute une liste vide, pour qu'elle contienne au moins un élément
et prenez la première solution
h
, éclatez le dernier élémentp
et imprimez-leNotez que cela fonctionne également s'il n'y a qu'un seul bloc. Dans mon approche, j'obtiens la position de départ [0,0] et ne la prolonge pas. Comme la dernière entrée est 0, il imprime la solution [0].
Le deuxième cas spécial (2 blocs) n'est pas si spécial après tout. Je ne sais pas pourquoi j'ai trop compliqué les choses plus tôt.
la source
?**lQ]0qhQeQ<lQ3h+f!%-+ePQ@T_3eQ4mu+G]%+&H@G_3-@QH@QhH4UttQd^UT2]Y
est de 66 octets. La performance a été un peu touchée, mais elle exécute toujours le plus grand cas de test en <1s pour moi. Ping moi si vous voulez des explications sur certains des golfs; il n'y a pas assez d'espace dans ce commentaire;) J'espère que vous appréciez l'utilisation de Pyth: D+<list><int>
a le même effet que+<list>]<int>
, vous pouvez donc supprimer le premier]
. Aussi, très belle solution.~
? Cela ne semblait pas être le cas lorsque j'ai essayé~
para
-~<list>]<int>
équivaut àa<list><int>
.~
is+=
, whilea
is.append()
Rubis,
320313 caractèresPeut certainement être joué au golf plus. Ne produit rien pour les puzzles insolubles.
Version non golfée:
D'accord, celui-ci était amusant. Voici l'algorithme de base, avec
{n}
représentant n "touch" es sur le nombre au-dessus den
, comme démontré sur l'un des exemples:Je suis resté perplexe un peu ici. Comment puis-je transformer le
111...1110
en une série de mêmes chiffres? J'ai donc comparé ma solution et la bonne solution (remarque: le nombre de "touch" est un supérieur à ce qu'il devrait être car l'entrée est indexée 1, tandis que la sortie est indexée 0):J'ai remarqué que chaque numéro était éloigné de un du bon
mod 4
, alors je les ai marqués avec+
s,-
s et=
s:Cela a fonctionné pendant un certain temps, jusqu'à ce que je remarque que parfois le résultat final était
111...11112
ou11...1113
aussi! Heureusement, l'application répétée de la formule magique qui n'a aucun sens mais qui fonctionne a également trié ces problèmes.Alors voilà. Un programme qui commence à avoir du sens, mais se dégrade en hackiness de plus en plus laid au fur et à mesure. Je pense que c'est assez typique d'une solution de golf à code. :)
la source
exit if (r+=1)>5
pour(r+=1)>5&&exit
. De plus, la(code)while cond
syntaxe est plus courte quewhile cond \n code \n end
.Python 2,
294 289 285 281273 octetsDEMO
Je suis sûr que cela peut être joué plus loin ..
Voici les résultats des cas de test:
L'algorithme s'assure d'abord que les valeurs de tous les blocs, à l'exception du dernier bloc, sont les mêmes (en itérant et en ajoutant au "nombre de contacts" de tous les blocs sauf les 2 premiers). Ensuite, si le nombre de blocs le permet (
(num_of_blocks - 1) % 3 != 1
), revient en arrière et s'assure que les valeurs des autres blocs correspondent au dernier bloc. Imprimex
s'il n'y a pas de solution.la source