Back to index

gcompris  8.2.2
sudoku.py
Go to the documentation of this file.
00001 #  gcompris - sudoku
00002 #
00003 # Copyright (C) 2005 Bruno Coudoin
00004 #
00005 #   This program is free software; you can redistribute it and/or modify
00006 #   it under the terms of the GNU General Public License as published by
00007 #   the Free Software Foundation; either version 2 of the License, or
00008 #   (at your option) any later version.
00009 #
00010 #   This program is distributed in the hope that it will be useful,
00011 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 #   GNU General Public License for more details.
00014 #
00015 #   You should have received a copy of the GNU General Public License
00016 #   along with this program; if not, write to the Free Software
00017 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 #
00019 import gnomecanvas
00020 import gcompris
00021 import gcompris.utils
00022 import gcompris.skin
00023 import gcompris.bonus
00024 import gcompris.score
00025 import gtk
00026 import gtk.gdk
00027 import random
00028 from gettext import gettext as _
00029 
00030 class Gcompris_sudoku:
00031   """Sudoku game"""
00032 
00033 
00034   def __init__(self, gcomprisBoard):
00035     self.gcomprisBoard = gcomprisBoard
00036 
00037     self.gcomprisBoard.disable_im_context = True
00038 
00039     # These are used to let us restart only after the bonus is displayed.
00040     # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
00041     self.board_paused  = 0;
00042     self.gamewon       = 0;
00043 
00044     # It holds the canvas items for each square
00045     self.sudo_square = []       # The square Rect Item
00046     self.sudo_number = []       # The square Text Item
00047     self.sudo_symbol = []       # The square Symbol Item
00048 
00049     self.valid_chars = []       # The valid chars for the sudoku are calculated from the dataset
00050 
00051     # Holds the coordinate of the current square
00052     self.cursqre = None
00053 
00054     self.normal_square_color = 0xbebbc9ffL
00055     self.highl_square_color  = 0x8b83a7ffL
00056     self.focus_square_color  = 0x555555ffL
00057     self.fixed_square_color  = 0x8bAAa7ffL
00058     self.error_square_color  = 0xff77a7ffL
00059     self.lines_color         = 0xebe745ffL
00060 
00061     # These colors must be different or it won't work
00062     self.fixed_number_color  = 0x000cffffL
00063     self.user_number_color   = 0x000bffffL
00064 
00065     self.root_sudo = None
00066 
00067     self.sudoku = None          # The current sudoku data
00068     self.sudo_size = 0          # the size of the current sudoku
00069     self.sudo_region = None     # the modulo region in the current sudoku
00070 
00071     self.timer = 0              # The timer that highlights errors
00072 
00073     self.symbolize_level_max = 4 # Last level in which we set symbols
00074     self.symbols = [
00075       gcompris.utils.load_pixmap("images/rectangle.png"),
00076       gcompris.utils.load_pixmap("images/circle.png"),
00077       gcompris.utils.load_pixmap("images/rhombus.png"),
00078       gcompris.utils.load_pixmap("images/triangle.png"),
00079       gcompris.utils.load_pixmap("images/star.png")
00080       ]
00081 
00082   def start(self):
00083 
00084     # Init the sudoku dataset
00085     self.sudoku = self.init_item_list()
00086 
00087     self.gcomprisBoard.level=1
00088     self.gcomprisBoard.maxlevel=len(self.sudoku)
00089     self.gcomprisBoard.sublevel=1
00090 
00091     pixmap = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("button_reload.png"))
00092     if(pixmap):
00093       gcompris.bar_set_repeat_icon(pixmap)
00094       gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_REPEAT_ICON)
00095     else:
00096       gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_REPEAT)
00097 
00098     gcompris.set_background(self.gcomprisBoard.canvas.root(),
00099                             gcompris.skin.image_to_skin("gcompris-bg.jpg"))
00100     gcompris.bar_set_level(self.gcomprisBoard)
00101 
00102     # Create our rootitem. We put each canvas item in it so at the end we
00103     # only have to kill it. The canvas deletes all the items it contains automaticaly.
00104     self.rootitem = self.gcomprisBoard.canvas.root().add(
00105       gnomecanvas.CanvasGroup,
00106       x=0.0,
00107       y=0.0
00108       )
00109 
00110     self.next_level()
00111 
00112     self.pause(0);
00113 
00114 
00115 
00116   def end(self):
00117 
00118     # Remove the root item removes all the others inside it
00119     self.rootitem.destroy()
00120     self.rootitem = None
00121     gcompris.score.end()
00122 
00123   def ok(self):
00124     print("Gcompris_sudoku ok.")
00125 
00126 
00127   def repeat(self):
00128     self.display_sudoku(self.sudoku[self.gcomprisBoard.level-1][self.gcomprisBoard.sublevel-1])
00129 
00130   def config(self):
00131     print("Gcompris_sudoku config.")
00132 
00133 
00134   def key_press(self, keyval, commit_str, preedit_str):
00135 
00136     if(self.cursqre == None):
00137       return False
00138 
00139     utf8char = gtk.gdk.keyval_to_unicode(keyval)
00140     strn = u'%c' % utf8char
00141 
00142     if(strn in self.valid_chars):
00143 
00144       if self.is_legal(strn):
00145         self.sudo_number[self.cursqre[0]][self.cursqre[1]].set(
00146           text = strn.encode('UTF-8'),
00147           )
00148 
00149         # Maybe it's all done
00150         if self.is_solved():
00151           self.cursqre = None
00152           self.gamewon = 1
00153           gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.FLOWER)
00154 
00155     else:
00156       # Erase the old number there
00157       if ((keyval == gtk.keysyms.BackSpace) or
00158           (keyval == gtk.keysyms.Delete) or
00159           (keyval == gtk.keysyms.space)):
00160         self.sudo_number[self.cursqre[0]][self.cursqre[1]].set(
00161           text = "",
00162           )
00163 
00164       else:
00165         # No key processing done
00166         return False
00167 
00168     # Return  True  if you did process a key
00169     # Return  False if you did not processed a key
00170     #         (gtk need to send it to next widget)
00171     return True
00172 
00173   def pause(self, pause):
00174 
00175     self.board_paused = pause
00176 
00177     # When the bonus is displayed, it call us first
00178     # with pause(1) and then with pause(0)
00179     # the game is won
00180     if(self.gamewon == 1 and pause == 0):
00181       self.gamewon = 0
00182       if(self.increment_level()):
00183         self.next_level()
00184 
00185     return
00186 
00187 
00188 
00189   def set_level(self, level):
00190     self.gcomprisBoard.level = level;
00191     self.gcomprisBoard.sublevel = 1;
00192     gcompris.bar_set_level(self.gcomprisBoard)
00193     self.next_level()
00194 
00195 # ---- End of Initialisation
00196 
00197   # Code that increments the sublevel and level
00198   # And bail out if no more levels are available
00199   # return True if continue, False if bail out
00200   def next_level(self):
00201 
00202     # Randomize symbols
00203     for j in range(0, len(self.symbols)):
00204         # Select a random new position to set the J symbol
00205         old_symbol = self.symbols[j]
00206         new_pos = random.randint(0,len(self.symbols)-1)
00207         self.symbols[j] = self.symbols[new_pos]
00208         self.symbols[new_pos] = old_symbol
00209 
00210     self.display_sudoku(self.sudoku[self.gcomprisBoard.level-1][self.gcomprisBoard.sublevel-1])
00211 
00212     gcompris.score.start(gcompris.score.STYLE_NOTE, 610, 485,
00213                          len(self.sudoku[self.gcomprisBoard.level-1]))
00214     gcompris.score.set(self.gcomprisBoard.sublevel)
00215 
00216     return True
00217 
00218   # Code that increments the sublevel and level
00219   # And bail out if no more levels are available
00220   # return True if continue, False if bail out
00221   def increment_level(self):
00222     self.gcomprisBoard.sublevel += 1
00223 
00224     if(self.gcomprisBoard.sublevel > len(self.sudoku[self.gcomprisBoard.level-1])):
00225       # Try the next level
00226       self.gcomprisBoard.sublevel=1
00227       self.gcomprisBoard.level += 1
00228       # Set the level in the control bar
00229       gcompris.bar_set_level(self.gcomprisBoard);
00230 
00231       if(self.gcomprisBoard.level>self.gcomprisBoard.maxlevel):
00232         # the last board is finished : bail out
00233         gcompris.bonus.board_finished(gcompris.bonus.FINISHED_RANDOM)
00234         return False
00235 
00236     return True
00237 
00238   #
00239   # Set a symbol in the sudoku
00240   #
00241   def set_sudoku_symbol(self, text, x, y):
00242     pixmap = self.get_pixmap_symbol(self.valid_chars, text)
00243 
00244     self.sudo_symbol[x][y].set(
00245       pixbuf = pixmap
00246       )
00247     self.sudo_symbol[x][y].show()
00248 
00249     self.sudo_number[x][y].set(
00250       text = text
00251       )
00252 
00253 
00254   #
00255   # Event on a placed symbol. Means that we remove it
00256   #
00257   def hide_symbol_event(self, item, event, data):
00258 
00259     if(self.gamewon):
00260       return False
00261 
00262     if event.type == gtk.gdk.BUTTON_PRESS:
00263       item.hide()
00264       self.sudo_number[data[0]][data[1]].set(
00265         text = ""
00266         )
00267 
00268   #
00269   # This function is being called uppon a click on a symbol on the left
00270   # If a square has the focus, then the clicked square is assigned there
00271   #
00272   def symbol_item_event(self, item, event, text):
00273 
00274     if(self.gamewon):
00275       return False
00276     #
00277     # MOTION EVENT
00278     # ------------
00279     if event.type == gtk.gdk.MOTION_NOTIFY:
00280       if event.state & gtk.gdk.BUTTON1_MASK:
00281         x=event.x
00282         y=event.y
00283 
00284         item.set(
00285           x= x,
00286           y= y)
00287 
00288         return True
00289     #
00290     # MOUSE DRAG STOP
00291     # ---------------
00292     if event.type == gtk.gdk.BUTTON_RELEASE:
00293       if event.button == 1:
00294         x=event.x
00295         y=event.y
00296 
00297         cx = float(item.get_data("orig_x"))
00298         cy = float(item.get_data("orig_y"))
00299         item.set(
00300           x= cx,
00301           y= cy)
00302 
00303         target_item = self.gcomprisBoard.canvas.get_item_at(x, y)
00304 
00305         if target_item:
00306           # Get it's sudo coord
00307           x = target_item.get_data("sudo_x")
00308           if x:
00309             x = int(x)
00310 
00311           y = target_item.get_data("sudo_y")
00312           if y:
00313             y = int(y)
00314 
00315           self.cursqre = (x, y)
00316           if self.is_legal(text):
00317             self.set_sudoku_symbol(text, x, y)
00318 
00319             # Maybe it's all done
00320             if self.is_solved():
00321               self.gamewon = 1
00322               gcompris.bonus.display(gcompris.bonus.WIN,
00323                                      gcompris.bonus.FLOWER)
00324 
00325         return True
00326 
00327     return False
00328 
00329   #
00330   # This function is being called uppon a click on any little square
00331   #
00332   def square_item_event(self, widget, event, square):
00333 
00334     if(self.gamewon):
00335       return False
00336 
00337     # Check it's a user editable square
00338     oldcolor = self.sudo_number[square[0]][square[1]].get_property('fill_color_rgba')
00339     if oldcolor == self.fixed_number_color:
00340       return False
00341 
00342     if event.type == gtk.gdk.ENTER_NOTIFY:
00343       if self.cursqre != square:
00344         self.sudo_square[square[0]][square[1]].set(
00345           fill_color_rgba = self.highl_square_color,
00346           )
00347     elif event.type == gtk.gdk.LEAVE_NOTIFY:
00348       if self.cursqre == square:
00349         self.sudo_square[square[0]][square[1]].set(
00350           fill_color_rgba = self.focus_square_color,
00351           )
00352       else:
00353         self.sudo_square[square[0]][square[1]].set(
00354           fill_color_rgba = self.normal_square_color,
00355           )
00356     elif event.type == gtk.gdk.BUTTON_PRESS:
00357       if(self.cursqre):
00358         self.sudo_square[self.cursqre[0]][self.cursqre[1]].set(
00359           fill_color_rgba = self.normal_square_color,
00360           )
00361       self.cursqre = square
00362       self.sudo_square[square[0]][square[1]].set(
00363         fill_color_rgba = self.focus_square_color,
00364         )
00365       return True
00366 
00367     return False
00368 
00369   # Highlight the given item to show it's the one that causes the resufal
00370   # to pose a number
00371   def set_on_error(self, items):
00372     for item in items:
00373       item.set(
00374         fill_color_rgba= self.error_square_color
00375         )
00376 
00377     self.timer = gtk.timeout_add(3000, self.unset_on_error, items)
00378 
00379   def unset_on_error(self, items):
00380     if(self.rootitem):
00381       for item in items:
00382         item.set(
00383           fill_color_rgba= self.fixed_square_color
00384           )
00385 
00386 
00387   # Return True or False if the given number is possible
00388   #
00389   def is_legal(self, number):
00390 
00391     if((self.cursqre[0] == None) or
00392        (self.cursqre[1] == None)):
00393       return
00394 
00395     possible = True
00396     bad_square = []
00397 
00398     if(self.cursqre == None):
00399       return possible
00400 
00401     # Check this number is not already in a row
00402     for x in range(0,self.sudo_size):
00403 
00404       if x == self.cursqre[0]:
00405          continue
00406 
00407       item = self.sudo_number[x][self.cursqre[1]]
00408       othernumber = item.get_property('text').decode('UTF-8')
00409 
00410       if(number == othernumber):
00411         bad_square.append(self.sudo_square[x][self.cursqre[1]])
00412         possible = False
00413 
00414     # Check this number is not already in a column
00415     for y in range(0,self.sudo_size):
00416 
00417       if y == self.cursqre[1]:
00418         continue
00419 
00420       item = self.sudo_number[self.cursqre[0]][y]
00421       othernumber = item.get_property('text').decode('UTF-8')
00422 
00423       if(number == othernumber):
00424         bad_square.append(self.sudo_square[self.cursqre[0]][y])
00425         possible = False
00426 
00427     #
00428     # Check this number is in a region
00429     #
00430 
00431     # Region is the modulo place to set region if defined
00432     region = None
00433     if(self.sudo_region.has_key(self.sudo_size)):
00434       region=self.sudo_region[self.sudo_size]
00435 
00436     if(region):
00437       # First, find the top-left square of the region
00438       top_left=[self.cursqre[0]/region*region, self.cursqre[1]/region*region]
00439       for x in range(0,region):
00440         for y in range(0,region):
00441           # Do not check the current square
00442           if (top_left[0] + x == self.cursqre[0] and
00443           top_left[1] + y == self.cursqre[1]):
00444             continue
00445 
00446           item = self.sudo_number[top_left[0] + x][top_left[1] + y]
00447           othernumber = item.get_property('text').decode('UTF-8')
00448 
00449           if(number == othernumber):
00450             bad_square.append(self.sudo_square[top_left[0] + x][top_left[1] + y])
00451             possible = False
00452 
00453     if not possible:
00454       self.set_on_error(bad_square)
00455 
00456     return possible
00457 
00458   # Return True or False if the given sudoku is solved
00459   # We don't really check it's solved, only that all squares
00460   # have a value. This works because only valid numbers can
00461   # be entered up front.
00462   #
00463   def is_solved(self):
00464 
00465     for x in range(0,self.sudo_size):
00466       for y in range(0,self.sudo_size):
00467         item = self.sudo_number[x][y]
00468         number = item.get_property('text').decode('UTF-8')
00469         if(number == ""):
00470           return False
00471 
00472     return True
00473 
00474   #
00475   # Display valid number (or chars)
00476   #
00477   def display_valid_chars(self, sudo_size, valid_chars):
00478 
00479     square_width = (gcompris.BOARD_HEIGHT-50)/sudo_size
00480     square_height = square_width
00481 
00482     x_init = 20
00483     y_init = (gcompris.BOARD_HEIGHT - square_height*sudo_size)/2
00484 
00485     for y in range(0,sudo_size):
00486 
00487       # For low levels, we symbolize the letters
00488       if(self.gcomprisBoard.level<self.symbolize_level_max):
00489         pixmap = self.get_pixmap_symbol(valid_chars, valid_chars[y])
00490         zoom = (square_width*0.5) / pixmap.get_width()
00491 
00492         cx = int(x_init + (pixmap.get_width() * zoom)/2)
00493         cy = int(y_init + square_height * y + square_height/2)
00494 
00495         item = self.root_sudo.add(
00496           gnomecanvas.CanvasPixbuf,
00497           pixbuf = pixmap,
00498           x= cx,
00499           y= cy,
00500           width= pixmap.get_width() * zoom,
00501           height= pixmap.get_height() * zoom,
00502           width_set=True,
00503           height_set=True,
00504           anchor=gtk.ANCHOR_CENTER
00505           )
00506         item.connect("event", self.symbol_item_event, valid_chars[y])
00507         # This item is clickeable and it must be seen
00508         item.connect("event", gcompris.utils.item_event_focus)
00509 
00510         # Save it's coordinate origines for the drag and drop
00511         item.set_data('orig_x', str(cx))
00512         item.set_data('orig_y', str(cy))
00513 
00514       else:
00515         # Shadow
00516         self.root_sudo.add(
00517           gnomecanvas.CanvasText,
00518           x= x_init+1.5,
00519           y= y_init + square_height * y + square_height/2 + 1.5,
00520           text= valid_chars[y],
00521           font=gcompris.skin.get_font("gcompris/title"),
00522           fill_color="black"
00523           )
00524         # Text
00525         self.root_sudo.add(
00526           gnomecanvas.CanvasText,
00527           x= x_init,
00528           y= y_init + square_height * y + square_height/2,
00529           text= valid_chars[y],
00530           font=gcompris.skin.get_font("gcompris/title"),
00531           fill_color="white"
00532           )
00533 
00534   # Return a symbol pixmap
00535   def get_pixmap_symbol(self, valid_chars, text):
00536     if (not text in valid_chars):
00537       # Return our first item. It will be hidden anyway.
00538       return self.symbols[0]
00539 
00540     return self.symbols[valid_chars.index(text)]
00541 
00542   #
00543   # Display the given sudoku (the board and the data)
00544   #
00545   def display_sudoku(self, sudoku):
00546 
00547     # Reinit the sudoku globals
00548     if self.timer:
00549       gtk.timeout_remove(self.timer)
00550 
00551     self.sudo_square = []       # The square Rect Item
00552     self.sudo_number = []       # The square Text Item
00553     self.sudo_symbol = []       # The square Symbol Item
00554 
00555     # The valid chars for the sudoku are calculated from the dataset
00556     self.valid_chars = []
00557 
00558     self.cursqre = None
00559 
00560     self.sudo_size = len(sudoku[0])
00561 
00562     if(self.root_sudo):
00563       self.root_sudo.destroy()
00564 
00565     # Create our rootitem. We put each canvas item in it so at the end we
00566     # only have to kill it. The canvas deletes all the items it contains
00567     # automaticaly.
00568     self.root_sudo = self.rootitem.add(
00569       gnomecanvas.CanvasGroup,
00570       x=0.0,
00571       y=0.0
00572       )
00573 
00574 
00575     # Region is the modulo place to set region (if defined)
00576     region = None
00577     if(self.sudo_region.has_key(self.sudo_size)):
00578       region=self.sudo_region[self.sudo_size]
00579 
00580     square_width = (gcompris.BOARD_HEIGHT-50)/self.sudo_size
00581     square_height = square_width
00582     x_init = (gcompris.BOARD_WIDTH - square_width*self.sudo_size)/2 - 40
00583     y_init = (gcompris.BOARD_HEIGHT - square_height*self.sudo_size)/2
00584 
00585     for x in range(0,self.sudo_size):
00586       line_square = []
00587       line_number = []
00588       line_symbol = []
00589 
00590       for y in range(0,self.sudo_size):
00591 
00592         # Get the data from the dataset
00593         text  = sudoku[y][x]
00594         color = self.fixed_number_color
00595         square_color = self.fixed_square_color
00596         if text == '.':
00597           text  = ""
00598           color = self.user_number_color
00599           square_color = self.normal_square_color
00600         else:
00601           if(not text in self.valid_chars):
00602             self.valid_chars.append(text)
00603 
00604         # The background of the square
00605         item = self.root_sudo.add(
00606           gnomecanvas.CanvasRect,
00607           fill_color_rgba = square_color,
00608           x1= x_init + square_width * x,
00609           y1= y_init + square_height * y,
00610           x2= x_init + square_width * (x+1),
00611           y2= y_init + square_height * (y+1),
00612           width_units=1.0,
00613           outline_color_rgba= 0x144B9DFFL
00614           )
00615         line_square.append(item)
00616         if(self.gcomprisBoard.level>=self.symbolize_level_max):
00617           item.connect("event", self.square_item_event, (x,y))
00618 
00619         # Save it's sudo coord for the drag and drop
00620         item.set_data('sudo_x', str(x))
00621         item.set_data('sudo_y', str(y))
00622 
00623         # For low levels, we symbolize the letters
00624         if(self.gcomprisBoard.level<self.symbolize_level_max):
00625           pixmap = self.get_pixmap_symbol(self.valid_chars, text)
00626           zoom = (square_width*0.8) / pixmap.get_width()
00627           item = self.root_sudo.add(
00628             gnomecanvas.CanvasPixbuf,
00629             pixbuf = pixmap,
00630             x= x_init + square_width * x + square_width/2,
00631             y= y_init + square_height * y + square_height/2,
00632             width= pixmap.get_width() * zoom,
00633             height= pixmap.get_height() * zoom,
00634             width_set=True,
00635             height_set=True,
00636             anchor=gtk.ANCHOR_CENTER
00637             )
00638           line_symbol.append(item)
00639 
00640           # Save it's sudo coord for the drag and drop
00641           item.set_data('sudo_x', str(x))
00642           item.set_data('sudo_y', str(y))
00643 
00644           if(not text):
00645             item.hide()
00646             # This item is clickeable and it must be seen
00647             #item.connect("event", gcompris.utils.item_event_focus)
00648             item.connect("event", self.hide_symbol_event, (x, y))
00649 
00650         #
00651         #
00652         #
00653 
00654         item = self.root_sudo.add(
00655           gnomecanvas.CanvasText,
00656           x= x_init + square_width * x + square_width/2,
00657           y= y_init + square_height * y + square_height/2,
00658           text= text,
00659           fill_color_rgba= color,
00660           font=gcompris.skin.get_font("gcompris/content"),
00661           )
00662         if(self.gcomprisBoard.level<self.symbolize_level_max):
00663           item.hide()
00664 
00665         line_number.append(item)
00666 
00667         if(region):
00668           if(y>0 and y%region==0):
00669             self.root_sudo.add (
00670               gnomecanvas.CanvasLine,
00671               points=(x_init - 5,
00672                       y_init + square_height * y,
00673                       x_init + (square_width * self.sudo_size) + 5,
00674                       y_init + square_height * y),
00675               fill_color_rgba=self.lines_color,
00676               width_units=2.5,
00677               )
00678 
00679       self.sudo_square.append(line_square)
00680       self.sudo_number.append(line_number)
00681       self.sudo_symbol.append(line_symbol)
00682 
00683       if(region):
00684         if(x>0 and x%region==0):
00685           self.root_sudo.add (
00686             gnomecanvas.CanvasLine,
00687             points=(x_init + square_width * x,
00688                     y_init - 5,
00689                     x_init + square_width * x,
00690                     y_init + square_height * self.sudo_size + 5),
00691             fill_color_rgba=self.lines_color,
00692             width_units=2.5,
00693             )
00694 
00695     if(self.gcomprisBoard.level>=self.symbolize_level_max):
00696       self.valid_chars.sort()
00697     self.display_valid_chars(self.sudo_size, self.valid_chars)
00698 
00699   # return the list of items (data) for this game
00700   def init_item_list(self):
00701 
00702     # It's hard coded that sudoku of size x have y region.
00703     # If not defined there, it means no region
00704     #
00705     # Sudoku size : Number of region
00706     #
00707     self.sudo_region = {
00708       9: 3,
00709       4: 2
00710       }
00711 
00712     # It's a list of level which is a list of sudoku data
00713     sudoku_list = \
00714       [
00715        [ # Level 1
00716         [
00717          ['A','C','.'],
00718          ['.','B','A'],
00719          ['B','.','.']
00720         ],
00721         [
00722          ['C','A','.'],
00723          ['.','.','C'],
00724          ['B','.','.']
00725         ],
00726         [
00727          ['A','B','.'],
00728          ['C','.','B'],
00729          ['B','.','A']
00730         ],
00731         [
00732          ['.','B','.'],
00733          ['.','C','.'],
00734          ['.','A','.']
00735         ],
00736        ],
00737        [ # Level 2
00738         [
00739          ['C','.','.','D'],
00740          ['.','.','B','.'],
00741          ['A','.','.','.'],
00742          ['.','.','D','.']
00743         ],
00744         [
00745          ['.','B','.','A'],
00746          ['.','.','B','.'],
00747          ['C','.','D','.'],
00748          ['.','.','.','C']
00749         ],
00750         [
00751          ['A','.','B','.'],
00752          ['.','C','.','A'],
00753          ['.','.','.','D'],
00754          ['D','.','C','.']
00755         ],
00756         [
00757          ['.','A','.','.'],
00758          ['C','.','A','B'],
00759          ['.','.','C','.'],
00760          ['D','.','.','A']
00761         ],
00762         [
00763          ['C','.','.','D'],
00764          ['B','.','A','.'],
00765          ['.','B','.','A'],
00766          ['.','.','.','.']
00767         ],
00768         [
00769          ['.','A','C','.'],
00770          ['.','.','.','D'],
00771          ['C','.','.','A'],
00772          ['.','B','.','.']
00773         ],
00774         [
00775          ['.','C','.','D'],
00776          ['B','.','.','.'],
00777          ['.','.','.','.'],
00778          ['C','A','.','B']
00779         ],
00780         [
00781          ['B','.','.','C'],
00782          ['.','A','.','.'],
00783          ['.','.','D','.'],
00784          ['.','B','.','.']
00785         ],
00786        ],
00787        [ # Level 3
00788         [
00789          ['A','B','C','D','E'],
00790          ['.','A','B','C','D'],
00791          ['.','.','A','B','C'],
00792          ['.','.','.','A','B'],
00793          ['.','.','.','.','A']
00794         ],
00795         [
00796          ['A','B','.','D','.'],
00797          ['.','.','D','E','A'],
00798          ['C','.','.','A','.'],
00799          ['D','E','.','.','C'],
00800          ['.','A','B','.','D']
00801         ],
00802         [
00803          ['.','C','.','A','.'],
00804          ['A','.','B','.','C'],
00805          ['.','B','.','C','.'],
00806          ['D','.','C','.','A'],
00807          ['.','A','E','.','B']
00808         ],
00809         [
00810          ['C','B','.','.','D'],
00811          ['.','.','D','C','.'],
00812          ['D','.','B','.','E'],
00813          ['.','A','.','D','C'],
00814          ['E','.','.','B','.']
00815         ],
00816         [
00817          ['D','.','.','B','E'],
00818          ['.','E','A','.','.'],
00819          ['A','C','.','.','B'],
00820          ['.','.','B','C','.'],
00821          ['C','B','.','A','.']
00822         ],
00823         [
00824          ['.','.','C','D','.'],
00825          ['B','.','.','.','C'],
00826          ['.','C','.','B','D'],
00827          ['C','.','D','A','.'],
00828          ['D','E','.','.','A']
00829         ],
00830        ],
00831        [ # Level 4
00832         [
00833          ['1','2','3','4','5'],
00834          ['.','1','2','3','4'],
00835          ['.','.','1','2','3'],
00836          ['.','.','.','1','2'],
00837          ['.','.','.','.','1']
00838         ],
00839         [
00840          ['1','2','.','4','.'],
00841          ['.','.','4','5','1'],
00842          ['3','.','.','1','.'],
00843          ['4','5','.','.','3'],
00844          ['.','1','2','.','4']
00845         ],
00846         [
00847          ['.','3','.','1','.'],
00848          ['1','.','2','.','3'],
00849          ['.','2','.','3','.'],
00850          ['4','.','3','.','1'],
00851          ['.','1','5','.','2']
00852         ],
00853         [
00854          ['3','2','.','.','4'],
00855          ['.','.','4','3','.'],
00856          ['4','.','2','.','5'],
00857          ['.','1','.','4','3'],
00858          ['5','.','.','2','.']
00859         ],
00860         [
00861          ['4','.','.','2','5'],
00862          ['.','5','1','.','.'],
00863          ['1','3','.','.','2'],
00864          ['.','.','2','3','.'],
00865          ['3','2','.','1','.']
00866         ],
00867         [
00868          ['.','.','3','4','.'],
00869          ['2','.','.','.','3'],
00870          ['.','3','.','2','4'],
00871          ['3','.','4','1','.'],
00872          ['4','5','.','.','1']
00873         ],
00874        ],
00875        [ # Level 5
00876         [
00877          ['3','.','.','.','.','5','6','.','2'],
00878          ['.','6','2','7','1','.','.','4','.'],
00879          ['1','.','.','9','.','.','.','5','.'],
00880          ['8','.','.','.','.','.','2','6','.'],
00881          ['.','3','.','.','8','.','.','7','.'],
00882          ['.','9','7','.','.','.','.','.','1'],
00883          ['.','5','.','.','.','.','.','.','6'],
00884          ['.','8','.','.','6','7','4','2','.'],
00885          ['6','.','3','1','.','.','.','.','8']
00886         ],
00887         [
00888          ['9','3','1','.','.','7','.','2','8'],
00889          ['.','.','.','.','3','6','.','.','.'],
00890          ['4','.','6','.','.','2','.','.','.'],
00891          ['6','2','.','.','.','.','9','1','.'],
00892          ['1','.','.','.','2','.','.','.','4'],
00893          ['.','4','8','.','.','.','.','6','5'],
00894          ['.','.','.','9','.','.','3','.','2'],
00895          ['.','.','.','2','7','.','.','.','.'],
00896          ['3','7','.','4','.','.','5','9','1']
00897         ],
00898         [
00899          ['.','.','9','.','6','.','.','.','.'],
00900          ['2','.','6','4','.','.','1','.','.'],
00901          ['.','.','3','1','8','.','5','.','.'],
00902          ['.','.','2','.','.','.','.','.','1'],
00903          ['7','9','.','.','.','.','.','6','8'],
00904          ['1','.','.','.','.','.','3','.','.'],
00905          ['.','.','7','.','9','2','8','.','.'],
00906          ['.','.','1','.','.','8','6','.','5'],
00907          ['.','.','.','.','3','.','4','.','.']
00908          ],
00909         [
00910          ['.','7','6','.','.','5','.','.','8'],
00911          ['.','8','.','.','.','.','.','5','.'],
00912          ['.','.','2','.','6','1','4','3','.'],
00913          ['8','.','.','.','1','.','.','.','.'],
00914          ['.','.','.','6','.','3','.','.','.'],
00915          ['.','.','.','.','7','.','.','.','1'],
00916          ['.','9','5','4','8','.','3','.','.'],
00917          ['.','2','.','.','.','.','.','8','.'],
00918          ['7','.','.','9','.','.','1','6','.']
00919         ],
00920         [
00921          ['.','7','6','3','.','.','9','.','.'],
00922          ['3','8','.','7','4','.','.','5','.'],
00923          ['9','.','2','.','.','.','.','.','.'],
00924          ['.','.','9','.','.','.','.','.','.'],
00925          ['.','1','.','6','.','3','.','4','.'],
00926          ['.','.','.','.','.','.','6','.','.'],
00927          ['.','.','.','.','.','.','3','.','2'],
00928          ['.','2','.','.','3','7','.','8','9'],
00929          ['.','.','8','.','.','2','1','6','.']
00930         ],
00931         [
00932          ['.','7','6','.','.','5','.','1','.'],
00933          ['.','8','.','.','4','.','.','.','6'],
00934          ['9','.','2','.','.','.','4','.','.'],
00935          ['.','.','.','5','.','.','.','2','.'],
00936          ['.','1','7','.','.','.','8','4','.'],
00937          ['.','4','.','.','.','8','.','.','.'],
00938          ['.','.','5','.','.','.','3','.','2'],
00939          ['6','.','.','.','3','.','.','8','.'],
00940          ['.','3','.','9','.','.','1','6','.']
00941         ],
00942         [
00943          ['.','7','.','.','2','5','.','1','8'],
00944          ['3','.','.','.','.','9','2','.','.'],
00945          ['.','.','.','.','6','.','4','3','.'],
00946          ['.','.','.','.','.','4','7','2','.'],
00947          ['.','.','.','.','.','.','.','.','.'],
00948          ['.','4','3','2','.','.','.','.','.'],
00949          ['.','9','5','.','8','.','.','.','.'],
00950          ['.','.','4','1','.','.','.','.','9'],
00951          ['7','3','.','9','5','.','.','6','.']
00952         ],
00953         [
00954          ['.','.','.','3','.','5','9','.','.'],
00955          ['3','8','.','.','.','.','2','.','6'],
00956          ['9','5','.','.','6','.','.','.','.'],
00957          ['.','.','9','.','1','4','.','.','3'],
00958          ['.','.','.','.','.','.','.','.','.'],
00959          ['5','.','.','2','7','.','6','.','.'],
00960          ['.','.','.','.','8','.','.','7','2'],
00961          ['6','.','4','.','.','.','.','8','9'],
00962          ['.','.','8','9','.','2','.','.','.']
00963         ],
00964         [
00965          ['.','.','6','.','2','5','.','.','8'],
00966          ['.','8','.','.','.','9','.','.','6'],
00967          ['9','.','.','.','.','.','4','.','.'],
00968          ['.','6','.','.','1','.','.','2','3'],
00969          ['.','.','.','6','.','3','.','.','.'],
00970          ['5','4','.','.','7','.','.','9','.'],
00971          ['.','.','5','.','.','.','.','.','2'],
00972          ['6','.','.','1','.','.','.','8','.'],
00973          ['7','.','.','9','5','.','1','.','.']
00974         ],
00975         [
00976          ['.','.','6','.','.','5','9','1','8'],
00977          ['.','.','.','7','4','.','.','5','.'],
00978          ['9','.','.','.','6','.','.','3','.'],
00979          ['.','.','.','5','.','.','7','.','.'],
00980          ['2','.','.','.','.','.','.','.','5'],
00981          ['.','.','3','.','.','8','.','.','.'],
00982          ['.','9','.','.','8','.','.','.','2'],
00983          ['.','2','.','.','3','7','.','.','.'],
00984          ['7','3','8','9','.','.','1','.','.']
00985         ],
00986         [
00987          ['.','.','.','5','.','4','.','.','.'],
00988          ['2','3','4','8','.','.','.','1','.'],
00989          ['.','.','.','.','1','3','8','.','2'],
00990          ['.','5','.','4','7','2','.','.','1'],
00991          ['.','7','.','.','.','.','.','6','.'],
00992          ['4','.','.','6','9','5','.','2','.'],
00993          ['7','.','1','3','5','.','.','.','.'],
00994          ['.','9','.','.','.','1','4','5','7'],
00995          ['.','.','.','7','.','9','.','.','.']
00996         ],
00997         [
00998          ['.','.','.','.','.','.','6','.','.'],
00999          ['2','.','.','8','6','.','9','.','5'],
01000          ['5','.','7','.','1','3','8','.','2'],
01001          ['6','.','8','.','7','.','.','.','1'],
01002          ['.','7','.','.','3','.','.','6','.'],
01003          ['4','.','.','.','9','.','7','.','8'],
01004          ['7','.','1','3','5','.','2','.','9'],
01005          ['3','.','6','.','8','1','.','.','7'],
01006          ['.','.','5','.','.','.','.','.','.']
01007         ],
01008         [
01009          ['.','8','9','5','.','4','.','7','3'],
01010          ['2','.','.','.','6','7','.','.','5'],
01011          ['.','.','.','9','.','.','.','4','2'],
01012          ['6','5','.','.','.','.','.','.','.'],
01013          ['.','7','2','1','3','8','5','6','.'],
01014          ['.','.','.','.','.','.','.','2','8'],
01015          ['7','4','.','.','.','6','.','.','.'],
01016          ['3','.','.','2','8','.','.','.','7'],
01017          ['8','2','.','7','.','9','1','3','.']
01018         ],
01019         [
01020          ['.','8','9','.','2','4','.','.','3'],
01021          ['.','.','.','.','.','.','.','1','.'],
01022          ['5','.','.','.','1','3','8','.','2'],
01023          ['6','.','.','4','.','2','.','.','.'],
01024          ['.','7','2','1','.','8','5','6','.'],
01025          ['.','.','.','6','.','5','.','.','8'],
01026          ['7','.','1','3','5','.','.','.','9'],
01027          ['.','9','.','.','.','.','.','.','.'],
01028          ['8','.','.','7','4','.','1','3','.']
01029         ],
01030         [
01031          ['.','.','.','.','.','.','.','9','8'],
01032          ['.','.','.','.','.','4','1','.','.'],
01033          ['8','4','3','6','.','.','2','.','.'],
01034          ['9','.','5','.','.','3','.','.','.'],
01035          ['3','2','.','.','.','.','.','8','7'],
01036          ['.','.','.','9','.','.','3','.','1'],
01037          ['.','.','2','.','.','5','7','3','6'],
01038          ['.','.','7','1','.','.','.','.','.'],
01039          ['5','9','.','.','.','.','.','.','.']
01040         ],
01041         [
01042          ['2','.','.','3','5','7','.','.','.'],
01043          ['7','.','9','2','.','.','.','6','.'],
01044          ['.','.','.','.','.','.','.','.','.'],
01045          ['9','.','.','.','.','.','.','2','4'],
01046          ['.','.','6','5','4','1','9','.','.'],
01047          ['4','7','.','.','.','.','.','.','1'],
01048          ['.','.','.','.','.','.','.','.','.'],
01049          ['.','3','.','.','.','8','5','.','9'],
01050          ['.','.','.','7','3','6','.','.','2']
01051         ],
01052         [
01053          ['.','.','1','.','5','7','4','.','.'],
01054          ['.','.','9','2','.','.','.','.','.'],
01055          ['8','4','.','6','.','.','.','7','.'],
01056          ['.','.','5','.','.','3','.','2','.'],
01057          ['3','.','.','.','.','.','.','.','7'],
01058          ['.','7','.','9','.','.','3','.','.'],
01059          ['.','8','.','.','.','5','.','3','6'],
01060          ['.','.','.','.','.','8','5','.','.'],
01061          ['.','.','4','7','3','.','8','.','.']
01062         ],
01063         [
01064          ['2','6','.','3','.','.','.','9','.'],
01065          ['7','.','.','2','.','4','.','6','.'],
01066          ['.','.','.','.','.','9','.','.','.'],
01067          ['9','.','5','.','7','.','6','.','4'],
01068          ['.','.','.','.','.','.','.','.','.'],
01069          ['4','.','8','.','6','.','3','.','1'],
01070          ['.','.','.','4','.','.','.','.','.'],
01071          ['.','3','.','1','.','8','.','.','9'],
01072          ['.','9','.','.','.','6','.','1','2']
01073         ],
01074         [
01075          ['4','9','.','.','.','.','.','1','.'],
01076          ['.','8','.','.','.','2','5','.','.'],
01077          ['1','.','5','.','.','.','6','.','.'],
01078          ['7','.','.','6','4','.','.','.','.'],
01079          ['5','.','.','7','.','3','.','.','8'],
01080          ['.','.','.','.','2','1','.','.','4'],
01081          ['.','.','8','.','.','.','3','.','1'],
01082          ['.','.','1','9','.','.','.','7','.'],
01083          ['.','7','.','.','.','.','.','2','5']
01084         ],
01085         [
01086          ['9','6','.','4','1','7','.','2','3'],
01087          ['.','.','8','.','9','5','6','.','1'],
01088          ['.','.','.','6','.','.','.','.','9'],
01089          ['.','.','.','.','2','.','9','.','.'],
01090          ['4','7','.','.','5','.','.','8','6'],
01091          ['.','.','6','.','4','.','.','.','.'],
01092          ['8','.','.','.','.','3','.','.','.'],
01093          ['6','.','3','1','7','.','5','.','.'],
01094          ['1','9','.','5','8','4','.','6','2']
01095         ],
01096         [
01097          ['.','.','.','4','.','7','8','.','.'],
01098          ['7','3','.','.','.','5','6','.','.'],
01099          ['.','1','4','.','3','.','7','.','.'],
01100          ['5','8','.','.','.','6','.','.','.'],
01101          ['4','.','.','3','.','1','.','.','6'],
01102          ['.','.','.','8','.','.','.','7','5'],
01103          ['.','.','2','.','6','.','4','1','.'],
01104          ['.','.','3','1','.','.','.','9','8'],
01105          ['.','.','7','5','.','4','.','.','.']
01106         ],
01107         [
01108          ['9','.','5','.','.','7','8','2','.'],
01109          ['7','.','.','2','.','.','.','4','.'],
01110          ['.','1','.','6','3','.','.','.','9'],
01111          ['.','.','1','7','2','.','9','.','.'],
01112          ['.','.','.','3','.','1','.','.','.'],
01113          ['.','.','6','.','4','9','1','.','.'],
01114          ['8','.','.','.','6','3','.','1','.'],
01115          ['.','4','.','.','.','2','.','.','8'],
01116          ['.','9','7','5','.','.','3','.','2']
01117         ],
01118         [
01119          ['9','6','.','4','1','7','8','.','3'],
01120          ['.','.','8','2','9','5','.','.','.'],
01121          ['2','.','.','6','3','.','.','.','9'],
01122          ['.','.','.','7','.','.','.','3','4'],
01123          ['4','.','.','.','5','.','.','.','6'],
01124          ['3','2','.','.','.','9','.','.','.'],
01125          ['8','.','.','.','6','3','.','.','7'],
01126          ['.','.','.','1','7','2','5','.','.'],
01127          ['1','.','7','5','8','4','.','6','2']
01128         ],
01129         [
01130          ['.','.','1','.','.','4','7','.','3'],
01131          ['7','.','.','.','6','.','.','5','.'],
01132          ['.','.','2','7','.','8','.','.','6'],
01133          ['.','9','.','.','4','.','.','.','.'],
01134          ['.','.','.','3','.','9','.','.','.'],
01135          ['.','.','.','.','5','.','.','2','.'],
01136          ['6','.','.','9','.','7','4','.','.'],
01137          ['.','7','.','.','8','.','.','.','1'],
01138          ['4','.','8','6','.','.','3','.','.']
01139         ],
01140         [
01141          ['.','.','1','.','.','.','.','9','.'],
01142          ['7','.','.','1','.','3','.','5','.'],
01143          ['.','.','.','.','9','8','1','.','6'],
01144          ['.','9','.','.','4','.','.','.','.'],
01145          ['.','8','4','.','.','.','6','1','.'],
01146          ['.','.','.','.','5','.','.','2','.'],
01147          ['6','.','5','9','3','.','.','.','.'],
01148          ['.','7','.','4','.','2','.','.','1'],
01149          ['.','2','.','.','.','.','3','.','.']
01150         ],
01151         [
01152          ['8','.','.','.','2','4','.','.','.'],
01153          ['7','.','9','1','.','.','.','.','.'],
01154          ['.','5','.','.','9','.','.','4','.'],
01155          ['.','.','6','.','.','.','8','3','.'],
01156          ['2','.','4','.','.','.','6','.','5'],
01157          ['.','3','7','.','.','.','9','.','.'],
01158          ['.','1','.','.','3','.','.','8','.'],
01159          ['.','.','.','.','.','2','5','.','1'],
01160          ['.','.','.','6','1','.','.','.','9']
01161         ],
01162         [
01163          ['.','.','1','.','2','.','.','.','.'],
01164          ['.','.','9','.','6','3','.','.','.'],
01165          ['3','.','.','.','.','8','1','4','.'],
01166          ['.','9','.','.','.','.','8','3','.'],
01167          ['.','.','4','.','7','.','6','.','.'],
01168          ['.','3','7','.','.','.','.','2','.'],
01169          ['.','1','5','9','.','.','.','.','2'],
01170          ['.','.','.','4','8','.','5','.','.'],
01171          ['.','.','.','.','1','.','3','.','.']
01172         ],
01173         [
01174          ['.','6','.','5','.','4','7','.','3'],
01175          ['.','.','9','.','.','.','.','5','.'],
01176          ['3','.','2','.','9','.','.','.','.'],
01177          ['5','.','6','.','.','.','8','.','.'],
01178          ['.','8','.','.','.','.','.','1','.'],
01179          ['.','.','7','.','.','.','9','.','4'],
01180          ['.','.','.','.','3','.','4','.','2'],
01181          ['.','7','.','.','.','.','5','.','.'],
01182          ['4','.','8','6','.','5','.','7','.']
01183         ],
01184         [
01185          ['.','.','.','.','2','.','.','9','.'],
01186          ['.','.','.','.','6','3','.','.','8'],
01187          ['3','.','.','.','.','8','1','4','.'],
01188          ['.','.','.','.','4','.','8','.','7'],
01189          ['.','8','4','.','.','.','6','1','.'],
01190          ['1','.','7','.','5','.','.','.','.'],
01191          ['.','1','5','9','.','.','.','.','2'],
01192          ['9','.','.','4','8','.','.','.','.'],
01193          ['.','2','.','.','1','.','.','.','.']
01194         ],
01195         [
01196          ['8','.','1','.','.','4','.','.','.'],
01197          ['.','.','.','.','6','.','.','5','.'],
01198          ['3','.','2','7','.','.','.','.','6'],
01199          ['.','9','.','.','4','.','.','.','7'],
01200          ['2','.','.','3','.','9','.','.','5'],
01201          ['1','.','.','.','5','.','.','2','.'],
01202          ['6','.','.','.','.','7','4','.','2'],
01203          ['.','7','.','.','8','.','.','.','.'],
01204          ['.','.','.','6','.','.','3','.','9']
01205         ],
01206         [
01207          ['.','.','.','.','2','.','9','4','3'],
01208          ['5','3','.','9','.','.','.','8','.'],
01209          ['.','.','.','.','.','1','6','.','7'],
01210          ['.','.','.','3','.','.','8','.','4'],
01211          ['.','.','.','2','7','9','.','.','.'],
01212          ['9','.','3','.','.','5','.','.','.'],
01213          ['7','.','9','6','.','.','.','.','.'],
01214          ['.','6','.','.','.','4','.','7','5'],
01215          ['1','4','5','.','8','.','.','.','.']
01216         ],
01217         [
01218          ['.','7','1','5','.','.','9','4','.'],
01219          ['5','.','.','9','6','.','.','8','2'],
01220          ['.','9','.','.','.','.','.','.','.'],
01221          ['2','5','.','3','.','.','8','9','.'],
01222          ['.','.','.','2','7','9','.','.','.'],
01223          ['.','1','3','.','.','5','.','2','6'],
01224          ['.','.','.','.','.','.','.','1','.'],
01225          ['3','6','.','.','9','4','.','.','5'],
01226          ['.','4','5','.','.','2','3','6','.']
01227         ],
01228         [
01229          ['6','7','1','5','2','.','.','.','.'],
01230          ['5','.','.','9','6','7','.','.','2'],
01231          ['.','.','.','.','.','.','6','.','.'],
01232          ['.','.','7','3','.','6','8','9','.'],
01233          ['4','.','6','2','.','9','5','.','1'],
01234          ['.','1','3','8','.','5','7','.','.'],
01235          ['.','.','9','.','.','.','.','.','.'],
01236          ['3','.','.','1','9','4','.','.','5'],
01237          ['.','.','.','.','8','2','3','6','9']
01238         ],
01239         [
01240          ['.','7','.','5','2','.','.','4','3'],
01241          ['5','.','.','.','.','7','1','8','2'],
01242          ['.','9','.','.','.','1','6','.','.'],
01243          ['.','5','.','3','1','6','8','9','.'],
01244          ['.','.','.','.','.','.','.','.','.'],
01245          ['.','1','3','8','4','5','.','2','.'],
01246          ['.','.','9','6','.','.','.','1','.'],
01247          ['3','6','8','1','.','.','.','.','5'],
01248          ['1','4','.','.','8','2','.','6','.']
01249         ],
01250         [
01251          ['.','.','.','1','6','.','.','2','7'],
01252          ['.','.','7','.','8','9','.','6','.'],
01253          ['1','.','6','.','5','.','.','8','9'],
01254          ['.','.','.','5','.','.','2','3','8'],
01255          ['.','.','.','8','2','3','.','.','.'],
01256          ['8','2','3','.','.','1','.','.','.'],
01257          ['5','1','.','.','3','.','9','.','2'],
01258          ['.','8','.','7','1','.','4','.','.'],
01259          ['6','7','.','.','9','5','.','.','.']
01260         ],
01261         [
01262          ['.','.','8','1','.','.','.','2','7'],
01263          ['.','.','7','.','8','9','.','.','.'],
01264          ['.','.','6','2','.','.','3','8','.'],
01265          ['7','.','1','5','.','6','.','3','8'],
01266          ['.','.','.','.','.','.','.','.','.'],
01267          ['8','2','.','9','.','1','6','.','5'],
01268          ['.','1','4','.','.','8','9','.','.'],
01269          ['.','.','.','7','1','.','4','.','.'],
01270          ['6','7','.','.','.','5','8','.','.']
01271         ],
01272         [
01273          ['.','3','.','.','.','4','.','2','.'],
01274          ['2','.','.','.','8','9','1','.','4'],
01275          ['1','.','.','2','.','.','3','8','.'],
01276          ['7','.','1','.','.','6','.','.','8'],
01277          ['.','6','.','.','.','.','.','9','.'],
01278          ['8','.','.','9','.','.','6','.','5'],
01279          ['.','1','4','.','.','8','.','.','2'],
01280          ['3','.','9','7','1','.','.','.','6'],
01281          ['.','7','.','4','.','.','.','1','.']
01282         ],
01283         [
01284          ['9','.','8','.','.','.','5','2','.'],
01285          ['.','.','7','3','.','.','.','6','.'],
01286          ['.','4','.','.','.','.','.','8','9'],
01287          ['7','.','.','5','.','6','2','3','.'],
01288          ['.','.','5','.','2','.','7','.','.'],
01289          ['.','2','3','9','.','1','.','.','5'],
01290          ['5','1','.','.','.','.','.','7','.'],
01291          ['.','8','.','.','.','2','4','.','.'],
01292          ['.','7','2','.','.','.','8','.','3']
01293         ],
01294         [
01295          ['8','.','.','2','4','.','.','.','.'],
01296          ['7','.','.','.','1','3','.','8','2'],
01297          ['6','5','.','.','8','9','1','.','4'],
01298          ['.','.','.','.','.','7','2','1','6'],
01299          ['.','1','7','.','3','.','4','5','.'],
01300          ['5','9','6','1','.','.','.','.','.'],
01301          ['3','.','5','8','9','.','.','4','1'],
01302          ['1','7','.','3','6','.','.','.','8'],
01303          ['.','.','.','.','7','1','.','.','5']
01304         ],
01305         [
01306          ['8','.','.','2','.','6','.','.','.'],
01307          ['.','.','9','.','1','3','.','.','2'],
01308          ['6','.','2','7','8','.','.','3','.'],
01309          ['.','.','3','.','.','.','.','1','6'],
01310          ['.','.','7','6','.','8','4','.','.'],
01311          ['5','9','.','.','.','.','8','.','.'],
01312          ['.','6','.','.','9','2','7','.','1'],
01313          ['1','.','.','3','6','.','9','.','.'],
01314          ['.','.','.','4','.','1','.','.','5']
01315         ],
01316         [
01317          ['8','3','.','2','.','.','.','9','.'],
01318          ['.','4','.','.','.','3','.','8','.'],
01319          ['.','.','.','.','8','9','1','.','4'],
01320          ['.','8','.','9','.','.','2','.','.'],
01321          ['2','.','.','6','.','8','.','.','9'],
01322          ['.','.','6','.','.','4','.','7','.'],
01323          ['3','.','5','8','9','.','.','.','.'],
01324          ['.','7','.','3','.','.','.','2','.'],
01325          ['.','2','.','.','.','1','.','6','5']
01326         ],
01327         [
01328          ['.','3','1','2','4','.','.','.','.'],
01329          ['.','.','9','5','1','.','6','8','.'],
01330          ['6','.','.','.','.','.','.','3','.'],
01331          ['.','8','.','9','.','7','2','.','.'],
01332          ['2','.','7','.','.','.','4','.','9'],
01333          ['.','.','6','1','.','4','.','7','.'],
01334          ['.','6','.','.','.','.','.','.','1'],
01335          ['.','7','4','.','6','5','9','.','.'],
01336          ['.','.','.','.','7','1','3','6','.']
01337         ],
01338         [
01339          ['.','.','7','.','.','.','.','5','.'],
01340          ['1','.','4','.','.','3','7','.','6'],
01341          ['.','6','5','7','4','2','9','.','3'],
01342          ['2','.','.','4','.','5','6','3','9'],
01343          ['.','.','.','3','.','7','.','.','.'],
01344          ['4','8','3','9','.','6','.','.','5'],
01345          ['9','.','8','2','5','4','1','6','.'],
01346          ['5','.','2','6','.','.','3','.','8'],
01347          ['.','1','.','.','.','.','5','.','.']
01348         ],
01349         [
01350          ['.','.','7','.','.','.','.','.','2'],
01351          ['.','2','.','.','.','3','.','8','6'],
01352          ['.','6','5','7','4','.','9','.','3'],
01353          ['.','.','.','4','.','.','6','.','.'],
01354          ['.','5','9','.','.','.','8','4','.'],
01355          ['.','.','3','.','.','6','.','.','.'],
01356          ['9','.','8','.','5','4','1','6','.'],
01357          ['5','4','.','6','.','.','.','9','.'],
01358          ['7','.','.','.','.','.','5','.','.']
01359         ],
01360         [
01361          ['.','.','7','1','.','8','4','5','2'],
01362          ['1','.','4','.','.','3','.','.','6'],
01363          ['.','.','5','.','.','2','9','.','3'],
01364          ['.','.','.','.','.','5','.','3','.'],
01365          ['.','.','9','3','.','7','8','.','.'],
01366          ['.','8','.','9','.','.','.','.','.'],
01367          ['9','.','8','2','.','.','1','.','.'],
01368          ['5','.','.','6','.','.','3','.','8'],
01369          ['7','1','6','8','.','9','5','.','.']
01370         ],
01371         [
01372          ['3','.','7','.','.','.','.','5','.'],
01373          ['.','2','.','5','9','.','.','.','.'],
01374          ['8','6','.','.','.','2','.','1','.'],
01375          ['2','.','.','.','8','5','.','.','9'],
01376          ['.','5','.','.','2','.','.','4','.'],
01377          ['4','.','.','9','1','.','.','.','5'],
01378          ['.','3','.','2','.','.','.','6','7'],
01379          ['.','.','.','.','7','1','.','9','.'],
01380          ['.','1','.','.','.','.','5','.','4']
01381         ],
01382         [
01383          ['6','8','.','2','.','7','.','3','.'],
01384          ['.','2','9','.','.','6','8','7','.'],
01385          ['5','.','.','.','8','4','.','.','.'],
01386          ['3','.','5','.','.','.','.','8','.'],
01387          ['.','.','.','7','.','8','.','.','.'],
01388          ['.','7','.','.','.','.','4','.','3'],
01389          ['.','.','.','8','4','.','.','.','7'],
01390          ['.','5','8','1','.','.','9','4','.'],
01391          ['.','6','.','5','.','9','.','1','8']
01392         ],
01393         [
01394          ['6','.','4','2','1','7','.','.','.'],
01395          ['.','2','.','.','.','6','.','.','.'],
01396          ['5','3','7','9','.','.','2','.','1'],
01397          ['3','.','.','.','.','.','7','8','6'],
01398          ['.','4','6','.','.','.','1','9','.'],
01399          ['8','7','1','.','.','.','.','.','3'],
01400          ['9','.','3','.','.','2','6','5','7'],
01401          ['.','.','.','1','.','.','.','4','.'],
01402          ['.','.','.','5','7','9','3','.','8']
01403         ],
01404         [
01405          ['6','8','.','.','1','.','.','3','.'],
01406          ['1','.','.','3','.','6','.','7','4'],
01407          ['.','.','7','9','.','4','2','.','1'],
01408          ['3','.','5','4','.','.','.','.','6'],
01409          ['.','.','.','.','.','.','.','.','.'],
01410          ['8','.','.','.','.','5','4','.','3'],
01411          ['9','.','3','8','.','2','6','.','.'],
01412          ['7','5','.','1','.','3','.','.','2'],
01413          ['.','6','.','.','7','.','.','1','8']
01414         ],
01415         [
01416          ['6','.','4','.','.','.','5','.','9'],
01417          ['1','.','.','.','.','.','8','7','.'],
01418          ['5','3','.','9','8','.','.','.','1'],
01419          ['.','.','5','.','.','1','.','8','.'],
01420          ['.','4','.','7','3','8','.','9','.'],
01421          ['.','7','.','6','.','.','4','.','.'],
01422          ['9','.','.','.','4','2','.','5','7'],
01423          ['.','5','8','.','.','.','.','.','2'],
01424          ['4','.','2','.','.','.','3','.','8']
01425         ],
01426         [
01427          ['.','.','.','.','5','6','1','.','.'],
01428          ['.','.','.','8','1','.','.','6','4'],
01429          ['6','4','.','7','9','.','.','5','.'],
01430          ['9','.','7','.','8','.','5','4','.'],
01431          ['4','.','.','.','.','.','.','.','8'],
01432          ['.','5','6','.','2','.','7','.','3'],
01433          ['.','6','.','.','3','7','.','8','5'],
01434          ['3','9','.','.','4','8','.','.','.'],
01435          ['.','.','2','5','6','.','.','.','.']
01436         ],
01437         [
01438          ['.','.','.','.','.','.','1','.','9'],
01439          ['5','.','9','.','.','2','.','6','.'],
01440          ['6','.','.','7','9','.','8','5','.'],
01441          ['9','.','7','3','8','.','5','.','6'],
01442          ['.','.','.','6','.','5','.','.','.'],
01443          ['8','.','6','.','2','4','7','.','3'],
01444          ['.','6','4','.','3','7','.','.','5'],
01445          ['.','9','.','1','.','.','6','.','7'],
01446          ['7','.','2','.','.','.','.','.','.']
01447         ],
01448         [
01449          ['2','.','8','4','.','.','.','.','9'],
01450          ['5','.','9','8','1','2','.','.','.'],
01451          ['.','.','1','.','9','.','.','5','.'],
01452          ['.','.','7','.','.','.','5','4','6'],
01453          ['.','1','3','6','.','5','2','9','.'],
01454          ['8','5','6','.','.','.','7','.','.'],
01455          ['.','6','.','.','3','.','9','.','.'],
01456          ['.','.','.','1','4','8','6','.','7'],
01457          ['7','.','.','.','.','9','4','.','1']
01458         ],
01459         [
01460          ['2','.','8','4','5','.','.','7','.'],
01461          ['.','.','9','.','1','2','3','.','4'],
01462          ['6','.','.','7','.','.','8','5','.'],
01463          ['.','.','.','.','8','.','5','4','6'],
01464          ['4','1','.','.','.','.','.','9','8'],
01465          ['8','5','6','.','2','.','.','.','.'],
01466          ['.','6','4','.','.','7','.','.','5'],
01467          ['3','.','5','1','4','.','6','.','.'],
01468          ['.','8','.','.','6','9','4','.','1']
01469         ],
01470         [
01471          ['7','9','.','5','.','1','.','.','.'],
01472          ['.','5','1','.','.','.','.','.','6'],
01473          ['.','8','.','.','.','9','.','.','2'],
01474          ['.','.','.','2','5','.','.','8','1'],
01475          ['.','.','.','.','.','.','.','.','.'],
01476          ['8','4','.','.','7','3','.','.','.'],
01477          ['1','.','.','6','.','.','.','7','.'],
01478          ['5','.','.','.','.','.','8','1','.'],
01479          ['.','.','.','3','.','2','.','6','5']
01480         ],
01481         [
01482          ['.','.','.','.','6','.','.','.','.'],
01483          ['.','.','1','.','.','.','.','9','6'],
01484          ['.','.','4','.','3','9','.','.','.'],
01485          ['.','6','7','.','.','4','3','8','.'],
01486          ['2','.','.','8','.','6','.','.','7'],
01487          ['.','4','5','1','.','.','6','2','.'],
01488          ['.','.','.','6','8','.','2','.','.'],
01489          ['5','2','.','.','.','.','8','.','.'],
01490          ['.','.','.','.','1','.','.','.','.']
01491         ],
01492         [
01493          ['.','.','.','.','6','1','.','3','.'],
01494          ['.','.','.','.','.','.','7','9','.'],
01495          ['.','.','4','7','3','.','.','.','2'],
01496          ['.','6','.','.','5','.','.','8','.'],
01497          ['2','.','3','.','.','.','5','.','7'],
01498          ['.','4','.','.','7','.','.','2','.'],
01499          ['1','.','.','.','8','5','2','.','.'],
01500          ['.','2','6','.','.','.','.','.','.'],
01501          ['.','7','.','3','1','.','.','.','.']
01502         ],
01503         [
01504          ['.','.','.','.','.','1','4','3','8'],
01505          ['.','.','.','.','.','.','.','9','6'],
01506          ['.','.','.','.','.','9','1','.','2'],
01507          ['.','.','.','.','.','4','3','.','1'],
01508          ['2','.','.','8','.','6','.','.','7'],
01509          ['8','.','5','1','.','.','.','.','.'],
01510          ['1','.','9','6','.','.','.','.','.'],
01511          ['5','2','.','.','.','.','.','.','.'],
01512          ['4','7','8','3','.','.','.','.','.']
01513         ],
01514         [
01515          ['.','7','1','6','.','.','9','.','.'],
01516          ['4','.','.','.','.','.','3','.','1'],
01517          ['.','.','.','8','.','2','.','7','.'],
01518          ['.','5','.','.','.','.','4','.','.'],
01519          ['2','.','.','1','.','5','.','.','3'],
01520          ['.','.','3','.','.','.','.','9','.'],
01521          ['.','1','.','2','.','4','.','.','.'],
01522          ['6','.','8','.','.','.','.','.','2'],
01523          ['.','.','4','.','.','9','1','5','.']
01524         ],
01525         [
01526          ['2','.','7','.','6','.','.','.','.'],
01527          ['4','3','.','.','.','9','2','.','.'],
01528          ['.','6','5','4','.','.','.','.','.'],
01529          ['.','7','.','.','.','.','1','.','2'],
01530          ['.','.','6','8','1','7','5','.','.'],
01531          ['5','.','3','.','.','.','.','9','.'],
01532          ['.','.','.','.','.','8','3','5','.'],
01533          ['.','.','1','9','.','.','.','2','7'],
01534          ['.','.','.','.','3','.','6','.','1']
01535         ],
01536         [
01537          ['.','9','.','.','.','1','4','8','5'],
01538          ['.','.','8','7','.','.','2','.','6'],
01539          ['.','6','.','.','.','2','9','.','3'],
01540          ['8','7','.','.','9','.','1','.','.'],
01541          ['.','2','.','8','.','7','.','3','.'],
01542          ['.','.','3','.','2','.','.','9','8'],
01543          ['6','.','2','1','.','.','.','5','.'],
01544          ['3','.','1','.','.','6','8','.','.'],
01545          ['7','8','9','2','.','.','.','4','.']
01546         ],
01547         [
01548          ['2','.','.','3','.','.','.','8','.'],
01549          ['.','.','.','7','.','.','2','.','6'],
01550          ['.','6','.','4','8','.','9','7','3'],
01551          ['8','.','.','.','9','.','1','.','2'],
01552          ['9','.','.','8','1','7','.','.','4'],
01553          ['5','.','3','.','2','.','.','.','8'],
01554          ['6','4','2','.','7','8','.','5','.'],
01555          ['3','.','1','.','.','6','.','.','.'],
01556          ['.','8','.','.','.','5','.','.','1']
01557         ],
01558         [
01559          ['.','.','.','.','.','1','.','8','.'],
01560          ['4','.','.','.','.','.','2','1','6'],
01561          ['.','6','.','4','8','.','.','.','3'],
01562          ['.','.','4','5','9','.','.','6','.'],
01563          ['9','.','6','.','1','.','5','.','4'],
01564          ['.','1','.','.','2','4','7','.','.'],
01565          ['6','.','.','.','7','8','.','5','.'],
01566          ['3','5','1','.','.','.','.','.','7'],
01567          ['.','8','.','2','.','.','.','.','.']
01568         ],
01569         [
01570          ['.','.','9','2','.','.','.','.','4'],
01571          ['.','.','6','.','.','3','1','.','.'],
01572          ['4','.','.','1','.','.','5','.','.'],
01573          ['.','3','.','8','.','.','9','.','1'],
01574          ['.','.','.','3','.','4','.','.','.'],
01575          ['1','.','4','.','.','6','.','5','.'],
01576          ['.','.','7','.','.','2','.','.','3'],
01577          ['.','.','1','7','.','.','6','.','.'],
01578          ['9','.','.','.','.','1','4','.','.']
01579         ],
01580         [
01581          ['.','.','9','.','6','.','.','.','.'],
01582          ['2','.','6','4','.','.','1','.','.'],
01583          ['.','.','3','1','8','.','5','.','.'],
01584          ['.','.','2','.','.','.','.','.','1'],
01585          ['7','9','.','.','.','.','.','6','8'],
01586          ['1','.','.','.','.','.','3','.','.'],
01587          ['.','.','7','.','9','2','8','.','.'],
01588          ['.','.','1','.','.','8','6','.','5'],
01589          ['.','.','.','.','3','.','4','.','.']
01590         ],
01591        ]
01592       ]
01593 
01594 
01595     # Randomize each level in the list
01596     for l in range(0, len(sudoku_list)):
01597       for j in range(0, len(sudoku_list[l])):
01598         # Select a random new position to set the J sudoku
01599         old_sudo = sudoku_list[l][j]
01600         new_pos = random.randint(0,len(sudoku_list[l])-1)
01601         sudoku_list[l][j] = sudoku_list[l][new_pos]
01602         sudoku_list[l][new_pos] = old_sudo
01603 
01604 
01605 
01606     return sudoku_list
01607