You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
5.8 KiB
Python

1 year ago
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
def generate_sudoku():
base = 3
side = base*base
# pattern for a baseline valid solution
def pattern(r,c): return (base*(r%base)+r//base+c)%side
# randomize rows, columns and numbers (of valid base pattern)
from random import sample
def shuffle(s): return sample(s,len(s))
rBase = range(base)
rows = [ g*base + r for g in shuffle(rBase) for r in shuffle(rBase) ]
cols = [ g*base + c for g in shuffle(rBase) for c in shuffle(rBase) ]
nums = shuffle(range(1,base*base+1))
# produce board using randomized baseline pattern
board = [ [nums[pattern(r,c)] for c in cols] for r in rows ]
# for line in board: print(line)
# solution = board
# print(solution)
squares = side*side
empties = squares * 3//5
# empties = squares * diff
# print(squares)
# print(empties)
# print(squares * 13//20)
for p in sample(range(squares),empties):
board[p//side][p%side] = 0
# numSize = len(str(side))
# for line in board:
# print(*(f"{n or '.':{numSize}} " for n in line))
def expandLine(line):
1 year ago
return line[0]+line[5:9].join([line[1:5]*(base-1)]*base)+line[9:13]
# return line[0]+line[3:7].join([line[1:3]*(base-1)]*base)+line[3:5]
1 year ago
# return line[0]+line[3:5].join([line[1:3]*(base-1)]*base)+line[5:7]
1 year ago
# return line[0]+line[4:7].join([line[1:4]*(base-1)]*base)+line[7:10]
line0 = expandLine("╔═══╤═══╦═══╗")
line1 = expandLine("║ . │ . ║ . ║")
line2 = expandLine("╟───┼───╫───╢")
line3 = expandLine("╠═══╪═══╬═══╣")
line4 = expandLine("╚═══╧═══╩═══╝")
1 year ago
# line0 = expandLine("╔═╤═╦═╗")
# line1 = expandLine("║.│.║.║")
# line2 = expandLine("╟─┼─╫─╢")
# line3 = expandLine("╠═╪═╬═╣")
# line4 = expandLine("╚═╧═╩═╝")
# line0 = expandLine("╔═╤═╦═╗")
# line1 = expandLine("║.│.║.║")
# line2 = expandLine("╟─┼─╫─╢")
# line3 = expandLine("╠═╪═╬═╣")
# line4 = expandLine("╚═╧═╩═╝")
1 year ago
# line0 = expandLine("╔══╤══╦══╗")
# line1 = expandLine("║. │. ║. ║")
# line2 = expandLine("╟──┼──╫──╢")
# line3 = expandLine("╠══╪══╬══╣")
# line4 = expandLine("╚══╧══╩══╝")
1 year ago
symbol = " 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
nums = [ [""]+[symbol[n] for n in row] for row in board ]
output = []
# print(line0)
output.append(line0)
for r in range(1,side+1):
output.append("".join(n+s for n,s in zip(nums[r-1],line1.split("."))))
output.append([line2,line3,line4][(r%side==0)+(r%base==0)])
# print( "".join(n+s for n,s in zip(nums[r-1],line1.split("."))) )
# print([line2,line3,line4][(r%side==0)+(r%base==0)])
# print('=')
# print(output)
# for x in output:
# print(x)
# print('-')
return output
def convert_to_image(sudoku):
# sample text and font
# unicode_text = u"Unicode Characters: \u00C6 \u00E6 \u00B2 \u00C4 \u00D1 \u220F"
unicode_text = sudoku[0]
1 year ago
verdana_font = ImageFont.truetype("application/IBMPlexMono-Medium.ttf", 16, encoding="unic")
1 year ago
# get the line size
text_width, text_height = verdana_font.getsize(unicode_text)
# create a blank canvas with extra space between lines
canvas = Image.new('RGB', (text_width + 10, (text_height*(len(sudoku)-1))), (255, 255, 255))
# canvas.convert('L')
# draw the text onto the text canvas, and use black as the text color
draw = ImageDraw.Draw(canvas)
# for x in sudoku:
pos = 0
for x in sudoku:
unicode_text = x
draw.text((5,pos), unicode_text, font = verdana_font, fill = "#000000")
pos += (text_height-2)
# save the blank canvas to a file
# fn = lambda x : 255 if x > 200 else 0
# canvas.convert('L').point(fn, mode='1')
canvas.save("sudoku.png", "PNG")
# img = Image.new('RGB', (200, 100))
# d = ImageDraw.Draw(img)
# d.text((30, 20), sudoku[0], fill=(255, 0, 0))
# text_width, text_height = d.textsize(sudoku[0])
# print(text_width, text_height)
if __name__ == '__main__':
su = generate_sudoku()
for x in su:
print(x)
convert_to_image(su)
print(su)
# for x in generate_sudoku():
# print(x)
# print(board)
# import random
# from itertools import islice
# print([*islice(shortSudokuSolve(board),2)][0])
# print([*islice(shortSudokuSolve(board),2)][1])
# if [*islice(shortSudokuSolve(board),2)][0] == [*islice(shortSudokuSolve(board),2)][1]:
# print('ay')
# else:
# print('er')
# while True:
# solved = [*islice(shortSudokuSolve(board),2)]
# # print(len(solved))
# # print(solved)
# if len(solved)==1:
# # print('yay!')
# break
# diffPos = [(r,c) for r in range(9) for c in range(9)
# if solved[0][r][c] != solved[1][r][c] ]
# r,c = random.choice(diffPos)
# board[r][c] = solution[r][c]
# # print(board)
# print(r,c)
# # print(board)
# print(board)
# print(solution)
# print('ysy')
# def expandLine(line):
# return line[0]+line[5:9].join([line[1:5]*(base-1)]*base)+line[9:13]
# line0 = expandLine("╔═══╤═══╦═══╗")
# line1 = expandLine("║ . │ . ║ . ║")
# line2 = expandLine("╟───┼───╫───╢")
# line3 = expandLine("╠═══╪═══╬═══╣")
# line4 = expandLine("╚═══╧═══╩═══╝")
# symbol = " 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# nums = [ [""]+[symbol[n] for n in row] for row in board ]
# output = []
# print(line0)
# output.append(line0)
# for r in range(1,side+1):
# output.append("".join(n+s for n,s in zip(nums[r-1],line1.split("."))))
# output.append([line2,line3,line4][(r%side==0)+(r%base==0)])
# print( "".join(n+s for n,s in zip(nums[r-1],line1.split("."))) )
# print([line2,line3,line4][(r%side==0)+(r%base==0)])
# print('==')
# print(output)
# for x in output:
# print(x)
# print('--')
# return output