Plus Court Solveur de Sudoku
Par coyote, dimanche 3 mai 2009 à 10:03 - Python - #212 - rss
Voici un programme en Python de 173 caractères seulement qui serait le plus court solveur de sudoku connu actuellement :
def r(a): i=a.find('0') if i<0:print a [m in[(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)or a[j]for j in range(81)]or r(a[:i]+m+a[i+1:])for m in`14**7*9`]r(raw_input())
Ce programme est extrêmement compact et condensé, voire cryptique. Ce n’est pas la meilleure façon de programmer, mais ça révèle souvent la puissance cachée de certains langages. Ce programme est décrit en anglais et en détail ici, mais voici son principe en gros et en français:
def r(a): ... r(raw_input()) // définit la fonction “r” qui résout le sudoku, puis on l’appelle en passant en paramètre ce que l’utilisateur a entré au clavier. Ca doit être une chaine de 81 caractères contenant ligne par ligne les chiffres de 1 à 9 donnés, et des 0 aux emplacements vides.
i=a.find('0') if i<0:print a // au début de la fonction, on cherche le premier emplacement vide. Si on ne le trouve pas, on imprime le sudoku résolu
la partie principale de la fonction utilise deux concepts puissants de Python:
- la “lazy evaluation” qui fait que l’expression “a or b” est équivalente à “if not(a):b”
- la “compréhension de liste” qui permet de créer une liste en écrivant une boucle à l’intérieur de [crochets]. Par exemple “l = [x**2 for x in range(10)]” crée la liste des carrés des 10 premiers nombres entiers
Finalement, le [m in [...] or r(a[:i]+m+a[i+1:])for m in`14**7*9`] remplit successivement la grille avec les chiffres possibles en utilisant la ‘lazy evaluation’ une fois de plus : ce n’est que si le chiffre m n’est pas dans la liste d’exclusion qu’on execute la partie droite du or, laquelle appelle récursivement la fonction r en lui passant la grille en paramètre la grille a[:i]+m+a[i+1:]. Ici , l’opérateur + sert à concaténer des listes : d’abord les i-èmes premières cases, puis le chiffre m proposé pour la case vide, puis les cases à partir de la i+1 ème.
Ce programme utilise donc une approche “force brute” loin d’être optimale en temps de calcul : on essaie les chiffres possibles dans chaque case vide jusqu’à ce que ça marche.
Reste à découvrir une astuce de geek que je ne connaissais pas : 14**7*9 vaut 948721536, un nombre qui contient les chiffres 123456789, dans le désordre, mais ça va aussi pour notre application. Les backquotes ´…´ servent à former une chaine, comme d’ailleurs la fonction str(). L’avantage de ´14**7*9´sur “123456789″ ? ben c’est évident : il faut deux bytes de moins …
Source : Dr Goulu
Commentaires
Aucun commentaire n'est possible sur ce blog.