var x = 3;
var y = 3;
function cross(A, B){
//Cross product of elements in A and elements in B.
var arr = [];
var alen = A.length;
var blen = B.length;
for (var i=0;i<alen;i++){
for (var ii=0;ii<blen;ii++){
arr.push(A[i]+"-"+B[ii])
}
}
return arr
}
var digits = [];
var rows = [];
var cols = [];
var squares;
var unitlist = [];
var rowlist = [];
var collist = [];
var blocklist = [];
var units = {};
var peers = {};
function reset_puzzle(){
digits = [];
rows = [];
cols = [];
for (var i=1;i<x*y+1;i++){
rows.push(i);
cols.push(i);
digits.push(i);
}
squares = cross(rows, cols)
unitlist = [];
rowlist = [];
collist = [];
blocklist = [];
for (var c in cols){
unitlist.push(cross(rows,[cols[c]]));
collist.push(cross(rows,[cols[c]]));
}
for (var r in rows){
unitlist.push(cross([rows[r]],cols));
rowlist.push(cross([rows[r]],cols));
}
for (var i=0;i<y;i++){
var A = [];
for (var ii=0;ii<x;ii++){
A.push(i*x+ii+1);
}
for (var ii=0;ii<x;ii++){
var B = [];
for (var iii=0;iii<y;iii++){
B.push(ii*y+iii+1);
}
unitlist.push(cross(A,B));
blocklist.push(cross(A,B));
}
}
units = {};
peers = {};
for (var i in squares){
var s = squares[i];
units[s]=[];
peers[s]={};
for (var ii in unitlist){
var u = unitlist[ii];
for (var iii in u){
var uu = u[iii];
if (s == uu){
units[s].push(u);
for (var iiii in u){
if (u[iiii] != s){
peers[s][u[iiii]]=true;
}
}
break;
}
}
}
}
//console.log(squares);
//console.log(units);
//console.log(peers);
}
function create_grid(){
//To start, every square can be any digit;
reset_puzzle();
var values = {};
for (var i in squares){
var s = squares[i];
values[s]=digits;
}
return values
}
function assign(values, s, d){
//Eliminate all the other values (except d) from values[s] and propagate.
//Return values, except return False if a contradiction is detected.
var other_values = values[s].slice()
for (var i in other_values){
if (other_values[i] != d){
var elim = eliminate(values, s, other_values[i]);
if (!elim){return false;}
else {values = elim;}
}
}
return values;
}
function eliminate(values, s, d){
//Eliminate d from values[s]; propagate when values or places <= 2.
//Return values, except return False if a contradiction is detected.
var skipped = false;
var new_vals = values[s].slice();
for (var i=0;i<new_vals.length;i++){
if (new_vals[i] == d){
new_vals.splice(i,1);
skipped = true;
break;
}
}
if (!skipped){
return values //Already eliminated
}
values[s] = new_vals;
//If a square s is reduced to one value d2, then eliminate d2 from the peers.
if (values[s].length == 0){
return false //Contradiction: removed last value
}
else if (values[s].length == 1){
var d2 = values[s][0]
var my_peers = peers[s];
for (var i in my_peers){
var s2 = i;
var elim = eliminate(values, s2, d2);
if (!elim){
return false;
}
else {
values = elim;
}
}
}
//If a unit u is reduced to only one place for a value d, then put it there.
for (var i in units[s]){
var u = units[s][i];
var dplaces = 0;
var sz1 = u.length;
for (var ii=0;ii<sz1;ii++){
var s = u[ii];
var sz2 = values[s].length;
for (var iii=0;iii<sz2;iii++){
if (d == values[s][iii]){
if (dplaces != 0){
dplaces = -1;
ii=sz1+5;
}
else {
dplaces = s;
}
break;
}
else if (d < values[s][iii]) {
break;
}
}
}
if (dplaces == 0){
return false //Contradiction: no place for this value
}
else if (dplaces != -1){
//d can only be in one place in unit; assign it there
var a = assign(values, dplaces, d);
if (!a){
return false
}
else {
values = a;
}
}
}
return values
}
function random_puzzle(xx=3,yy=3){
//Make a random puzzle with N or more assignments. Restart on contradictions.
x = xx;
y = yy;
var values = create_grid();
var totalT = 0;
var misses = 0;
for (var i=0;i<x*y;i++){
var s = squares[i];
var v = digits[i];
values[s]=[v];
}
for (var i=x*y;i<x*y*x;i++){
var s = squares[i];
var minV = Math.floor((i%(x*y))/y);
minV *= y;
var maxV = minV + y;
var arr = [];
var idx = 0;
for (var ii=0;ii<x*y;ii++){
if (ii < minV || ii >= maxV){
arr[idx]=digits[ii];
idx++;
}
}
values[s] = arr;
}
for (var i=x*y*x;i<x*y*x*y;i++){
var s = squares[i];
var minV = i%(x*y);
var maxV = minV + 1;
var arr = [];
var idx = 0;
for (var ii=0;ii<x*y;ii++){
if (ii < minV || ii >= maxV){
arr[idx]=digits[ii];
idx++;
}
}
values[s] = arr;
}
var valuesOld = [];
var t1 = Date.now();
for (var i=0;i<x*y*x*y*200;i++){
var minOptions = x*y*2;
var sqs = [];
for (var ii in squares){
var ss = squares[ii];
if (values[ss].length > 1){
if (values[ss].length < minOptions){
minOptions = values[ss].length;
sqs = [ss];
}
else if (values[ss].length == minOptions){
sqs.push(ss);
}
}
}
if (minOptions == x*y*2){
break;
}
var s = sqs[Math.floor(Math.random()*sqs.length)];
var v = values[s][Math.floor(Math.random()*values[s].length)];
var vvOld = {};
for (var vv in values){
vvOld[vv]=values[vv].slice();
}
valuesOld.push(vvOld);
if (valuesOld.length >= 5){
valuesOld.splice(0,1);
}
values = assign(values, s, v);
if (!values){
misses++;
if (misses > 10){
break;
}
values = {};
for (var vv in valuesOld[0]){
values[vv]=valuesOld[0][vv].slice();
}
continue;
}
}
var t2 = Date.now();
totalT += t2-t1;
var pout = [];
for (var i=0;i<x*y;i++){
for (var ii=0;ii<x*y;ii++){
var s = squares[i*x*y+ii];
if (!values[s] || values[s].length != 1){return false;}
var v = values[s][0];
pout.push(v);
}
}
return pout;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="favicon.png">
<title></title>
<meta name="description" content="" />
<link href="style.css" rel="stylesheet" type="text/css" />
<style>
#container {
display: block;
position: relative;
top:0;
}
#container2 {
display: block;
position: relative;
left:calc(16 * 2rem);
}
@media (orientation: portrait) {
#container2 {
top:calc(16 * 2rem);
left: 0;
}
}
.cell {
border: 1px solid black;
display: inline-block;
height: 2rem;
width: 2rem;
position: absolute;
line-height: 2rem;
text-align: center;
cursor: pointer;
}
{% for i in range(1,17) %}
.row-{{i}} {
top: calc(2rem * {{i}});
}
.col-{{i}} {
left: calc(2rem * {{i}});
}
{% endfor %}
</style>
</head>
<body>
<div id="menu">
x: <input type="number" min="2" max="5" value="3" onchange="updatePuzzle()" id="x" />
y: <input type="number" min="2" max="5" value="3" onchange="updatePuzzle()" id="y" />
<button onclick="updatePuzzle(false)">Refresh Numbers</button>
<button onclick="loop100()">Try 100</button><span id="loopIndex"></span>
Pattern: <select id="pattern">
<option value="none">None</option>
<option value="horiz">Mirror Horizontal</option>
<option value="verti">Mirror Vertical</option>
<option value="diago">Mirror Diagonal</option>
<option value="ro180">Rotate 180</option>
<option value="rot90">Rotate 90</option>
</select>
PuzzleStr: <a id="puzzleLink"></a> <span id="puzzleStr"></span>
</div>
<div id="container">
{% for r in range(1,17) %}
{% for c in range(1,17) %}
<div class="cell row-{{r}} col-{{c}}" id="cell-{{r}}-{{c}}">
</div>
{% endfor %}
{% endfor %}
</div>
<div id="container2">
{% for r in range(1,17) %}
{% for c in range(1,17) %}
<div class="cell row-{{r}} col-{{c}}" id="fillable-{{r}}-{{c}}">
</div>
{% endfor %}
{% endfor %}
</div>
<script src="createSolved.js" ></script>
<script src="simpleSolver.js" ></script>
<script>
var els = document.querySelectorAll('.cell');
els.forEach((el) => {
el.style.display = "none";
el.style.borderRight = "1px dotted gray";
el.style.borderLeft = "1px dotted gray";
el.style.borderTop = "1px dotted gray";
el.style.borderBottom = "1px dotted gray";
el.style.background = "white";
el.addEventListener('click',clickCell);
})
var puzzle;
var selected = {};
function updatePuzzle(clear=true,solvableOnly=false) {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var puzzleOrdered = random_puzzle(x,y);
for (var i=0;i<20;i++){
if (puzzleOrdered){break;}
puzzleOrdered = random_puzzle(x,y);
}
puzzle = puzzleOrdered.slice();
var digitList = digits.slice();
for (var d in digits){
var dd = Math.floor(Math.random()*digitList.length);
var ddd = digitList[dd];
digitList.splice(dd,1);
for (var i in puzzleOrdered){
if (puzzleOrdered[i]==digits[d]){
puzzle[i]=ddd;
}
}
}
if (clear){
selected = {};
}
if (solvableOnly){
return partial_puzzle(true);
}
var els = document.querySelectorAll('.cell');
els.forEach((el) => {
el.style.display = "none";
el.style.borderRight = "1px dotted gray";
el.style.borderLeft = "1px dotted gray";
el.style.borderTop = "1px dotted gray";
el.style.borderBottom = "1px dotted gray";
if (clear){
el.style.background = "white";
}
})
for (var i=0;i<x*y;i++){
for (var ii=0;ii<x*y;ii++){
var el = document.getElementById('cell-'+(i+1)+"-"+(ii+1));
el.textContent = puzzle[i*x*y+ii];
el.style.display = "inline-block";
if (ii%y == y-1){
el.style.borderRight = "1px solid black";
}
if (ii%y == 0){
el.style.borderLeft = "1px solid black";
}
if (i%x == x-1){
el.style.borderBottom = "1px solid black";
}
if (i%x == 0){
el.style.borderTop = "1px solid black";
}
var el = document.getElementById('fillable-'+(i+1)+"-"+(ii+1));
el.textContent = "";
el.style.display = "inline-block";
if (ii%y == y-1){
el.style.borderRight = "1px solid black";
}
if (ii%y == 0){
el.style.borderLeft = "1px solid black";
}
if (i%x == x-1){
el.style.borderBottom = "1px solid black";
}
if (i%x == 0){
el.style.borderTop = "1px solid black";
}
}
}
if (!clear){return partial_puzzle();}
}
function partial_puzzle(solvableOnly){
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var fills = fillable_puzzle();
var fillColors = {};
for (var i in selected){
if (!selected[i]){continue;}
var s = squares[i];
var v = parseInt(puzzle[i]);
fills[s] = v;
}
var updated = true;
while (updated){
updated = false;
var pp = simpleSolve(fills);
pp.sort((a,b) => {return a[2] - b[2];})
var ppp = 1000;
for (var i in pp){
if (pp[i][2] > ppp){break;}
var s = pp[i][0];
var v = pp[i][1];
if (fills[s] == 0){
fills[s] = v;
fillColors[s] = pp[i][2];
ppp = pp[i][2];
updated = true;
}
}
}
var solvable = true;
if (solvableOnly){
for (var i=0;i<x*y;i++){
for (var ii=0;ii<x*y;ii++){
var s = i*x*y+ii;
var ss = squares[s];
if (fills[ss] == 0){
return false;
}
}
}
}
for (var i=0;i<x*y;i++){
for (var ii=0;ii<x*y;ii++){
var el = document.getElementById('cell-'+(i+1)+"-"+(ii+1));
var elf = document.getElementById('fillable-'+(i+1)+"-"+(ii+1));
var s = i*x*y+ii;
var v = parseInt(puzzle[s]);
el.textContent = v;
if (selected[s]){
el.style.background = "green";
elf.textContent = v;
continue;
}
elf.textContent = "";
var ss = squares[s];
if (fills[ss] != 0){
if (fillColors[ss] == 1){
el.style.background = "yellow";
}
else if (fillColors[ss] == 2){
el.style.background = "yellow";
}
else {
el.style.background = "#EEE";
}
}
else {
el.style.background = "white";
solvable = false;
}
}
}
var chars = ["1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G"]
var pStr = "";
for (var i in puzzle){
if (selected[i]){
pStr += chars[puzzle[i]-1];
}
else {
pStr += ".";
}
}
pStr += ",";
for (var i in puzzle){
pStr += chars[puzzle[i]-1];
}
document.getElementById('puzzleStr').textContent = pStr;
var a = document.getElementById('puzzleLink');
a.setAttribute('href',"https://triplelog.com/code/Sudoku-Server/?p="+pStr.split(",")[0]+"&x="+x+"&y="+y);
a.textContent = "Link";
return solvable;
}
function clickCell(evt){
var id = evt.currentTarget.id;
var rc = id.substring(5).split("-");
var r = parseInt(rc[0])-1;
var c = parseInt(rc[1])-1;
var s = r*x*y+c;
var smap = {};
smap[s]=true;
var mirror = document.getElementById('pattern').value;
if (mirror == "horiz"){
var cc = x*y-1-c;
var ss = r*x*y+cc;
smap[ss]=true;
}
else if (mirror == "verti"){
var rr = x*y-1-r;
var ss = rr*x*y+c;
smap[ss]=true;
}
else if (mirror == "diago"){
var rr = x*y-1-c;
var cc = x*y-1-r;
var ss = rr*x*y+cc;
smap[ss]=true;
}
else if (mirror == "ro180"){
var rr = x*y-1-r;
var cc = x*y-1-c;
var ss = rr*x*y+cc;
smap[ss]=true;
}
else if (mirror == "rot90"){
var rr = c;
var cc = x*y-1-r;
var ss = rr*x*y+cc;
smap[ss]=true;
var rrr = cc;
var ccc = x*y-1-rr;
ss = rrr*x*y+ccc;
smap[ss]=true;
var rrrr = ccc;
var cccc = x*y-1-rrr;
ss = rrrr*x*y+cccc;
smap[ss]=true;
}
if (!selected[s]){
for (var ss in smap){
selected[ss]=true;
}
}
else {
for (var ss in smap){
selected[ss]=false;
}
}
partial_puzzle();
}
function loop100() {
var el = document.getElementById('loopIndex');
el.textContent = "0/100";
for (var i=0;i<100;i++){
var solvable = updatePuzzle(false,i);
el.textContent = (i+1)+"/100";
if (solvable){
break;
}
}
el.textContent = "";
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="favicon.png">
<title></title>
<meta name="description" content="" />
<link href="style.css" rel="stylesheet" type="text/css" />
<style>
#container {
display: block;
position: relative;
top:0;
}
#container2 {
display: block;
position: relative;
left:calc(16 * 2rem);
}
@media (orientation: portrait) {
#container2 {
top:calc(16 * 2rem);
left: 0;
}
}
.cell {
border: 1px solid black;
display: inline-block;
height: 2rem;
width: 2rem;
position: absolute;
line-height: 2rem;
text-align: center;
cursor: pointer;
}
.row-1 {
top: calc(2rem * 1);
}
.col-1 {
left: calc(2rem * 1);
}
.row-2 {
top: calc(2rem * 2);
}
.col-2 {
left: calc(2rem * 2);
}
.row-3 {
top: calc(2rem * 3);
}
.col-3 {
left: calc(2rem * 3);
}
.row-4 {
top: calc(2rem * 4);
}
.col-4 {
left: calc(2rem * 4);
}
.row-5 {
top: calc(2rem * 5);
}
.col-5 {
left: calc(2rem * 5);
}
.row-6 {
top: calc(2rem * 6);
}
.col-6 {
left: calc(2rem * 6);
}
.row-7 {
top: calc(2rem * 7);
}
.col-7 {
left: calc(2rem * 7);
}
.row-8 {
top: calc(2rem * 8);
}
.col-8 {
left: calc(2rem * 8);
}
.row-9 {
top: calc(2rem * 9);
}
.col-9 {
left: calc(2rem * 9);
}
.row-10 {
top: calc(2rem * 10);
}
.col-10 {
left: calc(2rem * 10);
}
.row-11 {
top: calc(2rem * 11);
}
.col-11 {
left: calc(2rem * 11);
}
.row-12 {
top: calc(2rem * 12);
}
.col-12 {
left: calc(2rem * 12);
}
.row-13 {
top: calc(2rem * 13);
}
.col-13 {
left: calc(2rem * 13);
}
.row-14 {
top: calc(2rem * 14);
}
.col-14 {
left: calc(2rem * 14);
}
.row-15 {
top: calc(2rem * 15);
}
.col-15 {
left: calc(2rem * 15);
}
.row-16 {
top: calc(2rem * 16);
}
.col-16 {
left: calc(2rem * 16);
}
</style>
</head>
<body>
<div id="menu">
x: <input type="number" min="2" max="5" value="3" onchange="updatePuzzle()" id="x" />
y: <input type="number" min="2" max="5" value="3" onchange="updatePuzzle()" id="y" />
<button onclick="updatePuzzle(false)">Refresh Numbers</button>
Pattern: <select id="pattern">
<option value="none">None</option>
<option value="horiz">Mirror Horizontal</option>
<option value="verti">Mirror Vertical</option>
<option value="diago">Mirror Diagonal</option>
<option value="ro180">Rotate 180</option>
<option value="rot90">Rotate 90</option>
</select>
PuzzleStr: <a id="puzzleLink"></a> <span id="puzzleStr"></span>
</div>
<div id="container">
<div class="cell row-1 col-1" id="cell-1-1">
</div>
<div class="cell row-1 col-2" id="cell-1-2">
</div>
<div class="cell row-1 col-3" id="cell-1-3">
</div>
<div class="cell row-1 col-4" id="cell-1-4">
</div>
<div class="cell row-1 col-5" id="cell-1-5">
</div>
<div class="cell row-1 col-6" id="cell-1-6">
</div>
<div class="cell row-1 col-7" id="cell-1-7">
</div>
<div class="cell row-1 col-8" id="cell-1-8">
</div>
<div class="cell row-1 col-9" id="cell-1-9">
</div>
<div class="cell row-1 col-10" id="cell-1-10">
</div>
<div class="cell row-1 col-11" id="cell-1-11">
</div>
<div class="cell row-1 col-12" id="cell-1-12">
</div>
<div class="cell row-1 col-13" id="cell-1-13">
</div>
<div class="cell row-1 col-14" id="cell-1-14">
</div>
<div class="cell row-1 col-15" id="cell-1-15">
</div>
<div class="cell row-1 col-16" id="cell-1-16">
</div>
<div class="cell row-2 col-1" id="cell-2-1">
</div>
<div class="cell row-2 col-2" id="cell-2-2">
</div>
<div class="cell row-2 col-3" id="cell-2-3">
</div>
<div class="cell row-2 col-4" id="cell-2-4">
</div>
<div class="cell row-2 col-5" id="cell-2-5">
</div>
<div class="cell row-2 col-6" id="cell-2-6">
</div>
<div class="cell row-2 col-7" id="cell-2-7">
</div>
<div class="cell row-2 col-8" id="cell-2-8">
</div>
<div class="cell row-2 col-9" id="cell-2-9">
</div>
<div class="cell row-2 col-10" id="cell-2-10">
</div>
<div class="cell row-2 col-11" id="cell-2-11">
</div>
<div class="cell row-2 col-12" id="cell-2-12">
</div>
<div class="cell row-2 col-13" id="cell-2-13">
</div>
<div class="cell row-2 col-14" id="cell-2-14">
</div>
<div class="cell row-2 col-15" id="cell-2-15">
</div>
<div class="cell row-2 col-16" id="cell-2-16">
</div>
<div class="cell row-3 col-1" id="cell-3-1">
</div>
<div class="cell row-3 col-2" id="cell-3-2">
</div>
<div class="cell row-3 col-3" id="cell-3-3">
</div>
<div class="cell row-3 col-4" id="cell-3-4">
</div>
<div class="cell row-3 col-5" id="cell-3-5">
</div>
<div class="cell row-3 col-6" id="cell-3-6">
</div>
<div class="cell row-3 col-7" id="cell-3-7">
</div>
<div class="cell row-3 col-8" id="cell-3-8">
</div>
<div class="cell row-3 col-9" id="cell-3-9">
</div>
<div class="cell row-3 col-10" id="cell-3-10">
</div>
<div class="cell row-3 col-11" id="cell-3-11">
</div>
<div class="cell row-3 col-12" id="cell-3-12">
</div>
<div class="cell row-3 col-13" id="cell-3-13">
</div>
<div class="cell row-3 col-14" id="cell-3-14">
</div>
<div class="cell row-3 col-15" id="cell-3-15">
</div>
<div class="cell row-3 col-16" id="cell-3-16">
</div>
<div class="cell row-4 col-1" id="cell-4-1">
</div>
<div class="cell row-4 col-2" id="cell-4-2">
</div>
<div class="cell row-4 col-3" id="cell-4-3">
</div>
<div class="cell row-4 col-4" id="cell-4-4">
</div>
<div class="cell row-4 col-5" id="cell-4-5">
</div>
<div class="cell row-4 col-6" id="cell-4-6">
</div>
<div class="cell row-4 col-7" id="cell-4-7">
</div>
<div class="cell row-4 col-8" id="cell-4-8">
</div>
<div class="cell row-4 col-9" id="cell-4-9">
</div>
<div class="cell row-4 col-10" id="cell-4-10">
</div>
<div class="cell row-4 col-11" id="cell-4-11">
</div>
<div class="cell row-4 col-12" id="cell-4-12">
</div>
<div class="cell row-4 col-13" id="cell-4-13">
</div>
<div class="cell row-4 col-14" id="cell-4-14">
</div>
<div class="cell row-4 col-15" id="cell-4-15">
</div>
<div class="cell row-4 col-16" id="cell-4-16">
</div>
<div class="cell row-5 col-1" id="cell-5-1">
</div>
<div class="cell row-5 col-2" id="cell-5-2">
</div>
<div class="cell row-5 col-3" id="cell-5-3">
</div>
<div class="cell row-5 col-4" id="cell-5-4">
</div>
<div class="cell row-5 col-5" id="cell-5-5">
</div>
<div class="cell row-5 col-6" id="cell-5-6">
</div>
<div class="cell row-5 col-7" id="cell-5-7">
</div>
<div class="cell row-5 col-8" id="cell-5-8">
</div>
<div class="cell row-5 col-9" id="cell-5-9">
</div>
<div class="cell row-5 col-10" id="cell-5-10">
</div>
<div class="cell row-5 col-11" id="cell-5-11">
</div>
<div class="cell row-5 col-12" id="cell-5-12">
</div>
<div class="cell row-5 col-13" id="cell-5-13">
</div>
<div class="cell row-5 col-14" id="cell-5-14">
</div>
<div class="cell row-5 col-15" id="cell-5-15">
</div>
<div class="cell row-5 col-16" id="cell-5-16">
</div>
<div class="cell row-6 col-1" id="cell-6-1">
</div>
<div class="cell row-6 col-2" id="cell-6-2">
</div>
<div class="cell row-6 col-3" id="cell-6-3">
</div>
<div class="cell row-6 col-4" id="cell-6-4">
</div>
<div class="cell row-6 col-5" id="cell-6-5">
</div>
<div class="cell row-6 col-6" id="cell-6-6">
</div>
<div class="cell row-6 col-7" id="cell-6-7">
</div>
<div class="cell row-6 col-8" id="cell-6-8">
</div>
<div class="cell row-6 col-9" id="cell-6-9">
</div>
<div class="cell row-6 col-10" id="cell-6-10">
</div>
<div class="cell row-6 col-11" id="cell-6-11">
</div>
<div class="cell row-6 col-12" id="cell-6-12">
</div>
<div class="cell row-6 col-13" id="cell-6-13">
</div>
<div class="cell row-6 col-14" id="cell-6-14">
</div>
<div class="cell row-6 col-15" id="cell-6-15">
</div>
<div class="cell row-6 col-16" id="cell-6-16">
</div>
<div class="cell row-7 col-1" id="cell-7-1">
</div>
<div class="cell row-7 col-2" id="cell-7-2">
</div>
<div class="cell row-7 col-3" id="cell-7-3">
</div>
<div class="cell row-7 col-4" id="cell-7-4">
</div>
<div class="cell row-7 col-5" id="cell-7-5">
</div>
<div class="cell row-7 col-6" id="cell-7-6">
</div>
<div class="cell row-7 col-7" id="cell-7-7">
</div>
<div class="cell row-7 col-8" id="cell-7-8">
</div>
<div class="cell row-7 col-9" id="cell-7-9">
</div>
<div class="cell row-7 col-10" id="cell-7-10">
</div>
<div class="cell row-7 col-11" id="cell-7-11">
</div>
<div class="cell row-7 col-12" id="cell-7-12">
</div>
<div class="cell row-7 col-13" id="cell-7-13">
</div>
<div class="cell row-7 col-14" id="cell-7-14">
</div>
<div class="cell row-7 col-15" id="cell-7-15">
</div>
<div class="cell row-7 col-16" id="cell-7-16">
</div>
<div class="cell row-8 col-1" id="cell-8-1">
</div>
<div class="cell row-8 col-2" id="cell-8-2">
</div>
<div class="cell row-8 col-3" id="cell-8-3">
</div>
<div class="cell row-8 col-4" id="cell-8-4">
</div>
<div class="cell row-8 col-5" id="cell-8-5">
</div>
<div class="cell row-8 col-6" id="cell-8-6">
</div>
<div class="cell row-8 col-7" id="cell-8-7">
</div>
<div class="cell row-8 col-8" id="cell-8-8">
</div>
<div class="cell row-8 col-9" id="cell-8-9">
</div>
<div class="cell row-8 col-10" id="cell-8-10">
</div>
<div class="cell row-8 col-11" id="cell-8-11">
</div>
<div class="cell row-8 col-12" id="cell-8-12">
</div>
<div class="cell row-8 col-13" id="cell-8-13">
</div>
<div class="cell row-8 col-14" id="cell-8-14">
</div>
<div class="cell row-8 col-15" id="cell-8-15">
</div>
<div class="cell row-8 col-16" id="cell-8-16">
</div>
<div class="cell row-9 col-1" id="cell-9-1">
</div>
<div class="cell row-9 col-2" id="cell-9-2">
</div>
<div class="cell row-9 col-3" id="cell-9-3">
</div>
<div class="cell row-9 col-4" id="cell-9-4">
</div>
<div class="cell row-9 col-5" id="cell-9-5">
</div>
<div class="cell row-9 col-6" id="cell-9-6">
</div>
<div class="cell row-9 col-7" id="cell-9-7">
</div>
<div class="cell row-9 col-8" id="cell-9-8">
</div>
<div class="cell row-9 col-9" id="cell-9-9">
</div>
<div class="cell row-9 col-10" id="cell-9-10">
</div>
<div class="cell row-9 col-11" id="cell-9-11">
</div>
<div class="cell row-9 col-12" id="cell-9-12">
</div>
<div class="cell row-9 col-13" id="cell-9-13">
</div>
<div class="cell row-9 col-14" id="cell-9-14">
</div>
<div class="cell row-9 col-15" id="cell-9-15">
</div>
<div class="cell row-9 col-16" id="cell-9-16">
</div>
<div class="cell row-10 col-1" id="cell-10-1">
</div>
<div class="cell row-10 col-2" id="cell-10-2">
</div>
<div class="cell row-10 col-3" id="cell-10-3">
</div>
<div class="cell row-10 col-4" id="cell-10-4">
</div>
<div class="cell row-10 col-5" id="cell-10-5">
</div>
<div class="cell row-10 col-6" id="cell-10-6">
</div>
<div class="cell row-10 col-7" id="cell-10-7">
</div>
<div class="cell row-10 col-8" id="cell-10-8">
</div>
<div class="cell row-10 col-9" id="cell-10-9">
</div>
<div class="cell row-10 col-10" id="cell-10-10">
</div>
<div class="cell row-10 col-11" id="cell-10-11">
</div>
<div class="cell row-10 col-12" id="cell-10-12">
</div>
<div class="cell row-10 col-13" id="cell-10-13">
</div>
<div class="cell row-10 col-14" id="cell-10-14">
</div>
<div class="cell row-10 col-15" id="cell-10-15">
</div>
<div class="cell row-10 col-16" id="cell-10-16">
</div>
<div class="cell row-11 col-1" id="cell-11-1">
</div>
<div class="cell row-11 col-2" id="cell-11-2">
</div>
<div class="cell row-11 col-3" id="cell-11-3">
</div>
<div class="cell row-11 col-4" id="cell-11-4">
</div>
<div class="cell row-11 col-5" id="cell-11-5">
</div>
<div class="cell row-11 col-6" id="cell-11-6">
</div>
<div class="cell row-11 col-7" id="cell-11-7">
</div>
<div class="cell row-11 col-8" id="cell-11-8">
</div>
<div class="cell row-11 col-9" id="cell-11-9">
</div>
<div class="cell row-11 col-10" id="cell-11-10">
</div>
<div class="cell row-11 col-11" id="cell-11-11">
</div>
<div class="cell row-11 col-12" id="cell-11-12">
</div>
<div class="cell row-11 col-13" id="cell-11-13">
</div>
<div class="cell row-11 col-14" id="cell-11-14">
</div>
<div class="cell row-11 col-15" id="cell-11-15">
</div>
<div class="cell row-11 col-16" id="cell-11-16">
</div>
<div class="cell row-12 col-1" id="cell-12-1">
</div>
<div class="cell row-12 col-2" id="cell-12-2">
</div>
<div class="cell row-12 col-3" id="cell-12-3">
</div>
<div class="cell row-12 col-4" id="cell-12-4">
</div>
<div class="cell row-12 col-5" id="cell-12-5">
</div>
<div class="cell row-12 col-6" id="cell-12-6">
</div>
<div class="cell row-12 col-7" id="cell-12-7">
</div>
<div class="cell row-12 col-8" id="cell-12-8">
</div>
<div class="cell row-12 col-9" id="cell-12-9">
</div>
<div class="cell row-12 col-10" id="cell-12-10">
</div>
<div class="cell row-12 col-11" id="cell-12-11">
</div>
<div class="cell row-12 col-12" id="cell-12-12">
</div>
<div class="cell row-12 col-13" id="cell-12-13">
</div>
<div class="cell row-12 col-14" id="cell-12-14">
</div>
<div class="cell row-12 col-15" id="cell-12-15">
</div>
<div class="cell row-12 col-16" id="cell-12-16">
</div>
<div class="cell row-13 col-1" id="cell-13-1">
</div>
<div class="cell row-13 col-2" id="cell-13-2">
</div>
<div class="cell row-13 col-3" id="cell-13-3">
</div>
<div class="cell row-13 col-4" id="cell-13-4">
</div>
<div class="cell row-13 col-5" id="cell-13-5">
</div>
<div class="cell row-13 col-6" id="cell-13-6">
</div>
<div class="cell row-13 col-7" id="cell-13-7">
</div>
<div class="cell row-13 col-8" id="cell-13-8">
</div>
<div class="cell row-13 col-9" id="cell-13-9">
</div>
<div class="cell row-13 col-10" id="cell-13-10">
</div>
<div class="cell row-13 col-11" id="cell-13-11">
</div>
<div class="cell row-13 col-12" id="cell-13-12">
</div>
<div class="cell row-13 col-13" id="cell-13-13">
</div>
<div class="cell row-13 col-14" id="cell-13-14">
</div>
<div class="cell row-13 col-15" id="cell-13-15">
</div>
<div class="cell row-13 col-16" id="cell-13-16">
</div>
<div class="cell row-14 col-1" id="cell-14-1">
</div>
<div class="cell row-14 col-2" id="cell-14-2">
</div>
<div class="cell row-14 col-3" id="cell-14-3">
</div>
<div class="cell row-14 col-4" id="cell-14-4">
</div>
<div class="cell row-14 col-5" id="cell-14-5">
</div>
<div class="cell row-14 col-6" id="cell-14-6">
</div>
<div class="cell row-14 col-7" id="cell-14-7">
</div>
<div class="cell row-14 col-8" id="cell-14-8">
</div>
<div class="cell row-14 col-9" id="cell-14-9">
</div>
<div class="cell row-14 col-10" id="cell-14-10">
</div>
<div class="cell row-14 col-11" id="cell-14-11">
</div>
<div class="cell row-14 col-12" id="cell-14-12">
</div>
<div class="cell row-14 col-13" id="cell-14-13">
</div>
<div class="cell row-14 col-14" id="cell-14-14">
</div>
<div class="cell row-14 col-15" id="cell-14-15">
</div>
<div class="cell row-14 col-16" id="cell-14-16">
</div>
<div class="cell row-15 col-1" id="cell-15-1">
</div>
<div class="cell row-15 col-2" id="cell-15-2">
</div>
<div class="cell row-15 col-3" id="cell-15-3">
</div>
<div class="cell row-15 col-4" id="cell-15-4">
</div>
<div class="cell row-15 col-5" id="cell-15-5">
</div>
<div class="cell row-15 col-6" id="cell-15-6">
</div>
<div class="cell row-15 col-7" id="cell-15-7">
</div>
<div class="cell row-15 col-8" id="cell-15-8">
</div>
<div class="cell row-15 col-9" id="cell-15-9">
</div>
<div class="cell row-15 col-10" id="cell-15-10">
</div>
<div class="cell row-15 col-11" id="cell-15-11">
</div>
<div class="cell row-15 col-12" id="cell-15-12">
</div>
<div class="cell row-15 col-13" id="cell-15-13">
</div>
<div class="cell row-15 col-14" id="cell-15-14">
</div>
<div class="cell row-15 col-15" id="cell-15-15">
</div>
<div class="cell row-15 col-16" id="cell-15-16">
</div>
<div class="cell row-16 col-1" id="cell-16-1">
</div>
<div class="cell row-16 col-2" id="cell-16-2">
</div>
<div class="cell row-16 col-3" id="cell-16-3">
</div>
<div class="cell row-16 col-4" id="cell-16-4">
</div>
<div class="cell row-16 col-5" id="cell-16-5">
</div>
<div class="cell row-16 col-6" id="cell-16-6">
</div>
<div class="cell row-16 col-7" id="cell-16-7">
</div>
<div class="cell row-16 col-8" id="cell-16-8">
</div>
<div class="cell row-16 col-9" id="cell-16-9">
</div>
<div class="cell row-16 col-10" id="cell-16-10">
</div>
<div class="cell row-16 col-11" id="cell-16-11">
</div>
<div class="cell row-16 col-12" id="cell-16-12">
</div>
<div class="cell row-16 col-13" id="cell-16-13">
</div>
<div class="cell row-16 col-14" id="cell-16-14">
</div>
<div class="cell row-16 col-15" id="cell-16-15">
</div>
<div class="cell row-16 col-16" id="cell-16-16">
</div>
</div>
<div id="container2">
<div class="cell row-1 col-1" id="fillable-1-1">
</div>
<div class="cell row-1 col-2" id="fillable-1-2">
</div>
<div class="cell row-1 col-3" id="fillable-1-3">
</div>
<div class="cell row-1 col-4" id="fillable-1-4">
</div>
<div class="cell row-1 col-5" id="fillable-1-5">
</div>
<div class="cell row-1 col-6" id="fillable-1-6">
</div>
<div class="cell row-1 col-7" id="fillable-1-7">
</div>
<div class="cell row-1 col-8" id="fillable-1-8">
</div>
<div class="cell row-1 col-9" id="fillable-1-9">
</div>
<div class="cell row-1 col-10" id="fillable-1-10">
</div>
<div class="cell row-1 col-11" id="fillable-1-11">
</div>
<div class="cell row-1 col-12" id="fillable-1-12">
</div>
<div class="cell row-1 col-13" id="fillable-1-13">
</div>
<div class="cell row-1 col-14" id="fillable-1-14">
</div>
<div class="cell row-1 col-15" id="fillable-1-15">
</div>
<div class="cell row-1 col-16" id="fillable-1-16">
</div>
<div class="cell row-2 col-1" id="fillable-2-1">
</div>
<div class="cell row-2 col-2" id="fillable-2-2">
</div>
<div class="cell row-2 col-3" id="fillable-2-3">
</div>
<div class="cell row-2 col-4" id="fillable-2-4">
</div>
<div class="cell row-2 col-5" id="fillable-2-5">
</div>
<div class="cell row-2 col-6" id="fillable-2-6">
</div>
<div class="cell row-2 col-7" id="fillable-2-7">
</div>
<div class="cell row-2 col-8" id="fillable-2-8">
</div>
<div class="cell row-2 col-9" id="fillable-2-9">
</div>
<div class="cell row-2 col-10" id="fillable-2-10">
</div>
<div class="cell row-2 col-11" id="fillable-2-11">
</div>
<div class="cell row-2 col-12" id="fillable-2-12">
</div>
<div class="cell row-2 col-13" id="fillable-2-13">
</div>
<div class="cell row-2 col-14" id="fillable-2-14">
</div>
<div class="cell row-2 col-15" id="fillable-2-15">
</div>
<div class="cell row-2 col-16" id="fillable-2-16">
</div>
<div class="cell row-3 col-1" id="fillable-3-1">
</div>
<div class="cell row-3 col-2" id="fillable-3-2">
</div>
<div class="cell row-3 col-3" id="fillable-3-3">
</div>
<div class="cell row-3 col-4" id="fillable-3-4">
</div>
<div class="cell row-3 col-5" id="fillable-3-5">
</div>
<div class="cell row-3 col-6" id="fillable-3-6">
</div>
<div class="cell row-3 col-7" id="fillable-3-7">
</div>
<div class="cell row-3 col-8" id="fillable-3-8">
</div>
<div class="cell row-3 col-9" id="fillable-3-9">
</div>
<div class="cell row-3 col-10" id="fillable-3-10">
</div>
<div class="cell row-3 col-11" id="fillable-3-11">
</div>
<div class="cell row-3 col-12" id="fillable-3-12">
</div>
<div class="cell row-3 col-13" id="fillable-3-13">
</div>
<div class="cell row-3 col-14" id="fillable-3-14">
</div>
<div class="cell row-3 col-15" id="fillable-3-15">
</div>
<div class="cell row-3 col-16" id="fillable-3-16">
</div>
<div class="cell row-4 col-1" id="fillable-4-1">
</div>
<div class="cell row-4 col-2" id="fillable-4-2">
</div>
<div class="cell row-4 col-3" id="fillable-4-3">
</div>
<div class="cell row-4 col-4" id="fillable-4-4">
</div>
<div class="cell row-4 col-5" id="fillable-4-5">
</div>
<div class="cell row-4 col-6" id="fillable-4-6">
</div>
<div class="cell row-4 col-7" id="fillable-4-7">
</div>
<div class="cell row-4 col-8" id="fillable-4-8">
</div>
<div class="cell row-4 col-9" id="fillable-4-9">
</div>
<div class="cell row-4 col-10" id="fillable-4-10">
</div>
<div class="cell row-4 col-11" id="fillable-4-11">
</div>
<div class="cell row-4 col-12" id="fillable-4-12">
</div>
<div class="cell row-4 col-13" id="fillable-4-13">
</div>
<div class="cell row-4 col-14" id="fillable-4-14">
</div>
<div class="cell row-4 col-15" id="fillable-4-15">
</div>
<div class="cell row-4 col-16" id="fillable-4-16">
</div>
<div class="cell row-5 col-1" id="fillable-5-1">
</div>
<div class="cell row-5 col-2" id="fillable-5-2">
</div>
<div class="cell row-5 col-3" id="fillable-5-3">
</div>
<div class="cell row-5 col-4" id="fillable-5-4">
</div>
<div class="cell row-5 col-5" id="fillable-5-5">
</div>
<div class="cell row-5 col-6" id="fillable-5-6">
</div>
<div class="cell row-5 col-7" id="fillable-5-7">
</div>
<div class="cell row-5 col-8" id="fillable-5-8">
</div>
<div class="cell row-5 col-9" id="fillable-5-9">
</div>
<div class="cell row-5 col-10" id="fillable-5-10">
</div>
<div class="cell row-5 col-11" id="fillable-5-11">
</div>
<div class="cell row-5 col-12" id="fillable-5-12">
</div>
<div class="cell row-5 col-13" id="fillable-5-13">
</div>
<div class="cell row-5 col-14" id="fillable-5-14">
</div>
<div class="cell row-5 col-15" id="fillable-5-15">
</div>
<div class="cell row-5 col-16" id="fillable-5-16">
</div>
<div class="cell row-6 col-1" id="fillable-6-1">
</div>
<div class="cell row-6 col-2" id="fillable-6-2">
</div>
<div class="cell row-6 col-3" id="fillable-6-3">
</div>
<div class="cell row-6 col-4" id="fillable-6-4">
</div>
<div class="cell row-6 col-5" id="fillable-6-5">
</div>
<div class="cell row-6 col-6" id="fillable-6-6">
</div>
<div class="cell row-6 col-7" id="fillable-6-7">
</div>
<div class="cell row-6 col-8" id="fillable-6-8">
</div>
<div class="cell row-6 col-9" id="fillable-6-9">
</div>
<div class="cell row-6 col-10" id="fillable-6-10">
</div>
<div class="cell row-6 col-11" id="fillable-6-11">
</div>
<div class="cell row-6 col-12" id="fillable-6-12">
</div>
<div class="cell row-6 col-13" id="fillable-6-13">
</div>
<div class="cell row-6 col-14" id="fillable-6-14">
</div>
<div class="cell row-6 col-15" id="fillable-6-15">
</div>
<div class="cell row-6 col-16" id="fillable-6-16">
</div>
<div class="cell row-7 col-1" id="fillable-7-1">
</div>
<div class="cell row-7 col-2" id="fillable-7-2">
</div>
<div class="cell row-7 col-3" id="fillable-7-3">
</div>
<div class="cell row-7 col-4" id="fillable-7-4">
</div>
<div class="cell row-7 col-5" id="fillable-7-5">
</div>
<div class="cell row-7 col-6" id="fillable-7-6">
</div>
<div class="cell row-7 col-7" id="fillable-7-7">
</div>
<div class="cell row-7 col-8" id="fillable-7-8">
</div>
<div class="cell row-7 col-9" id="fillable-7-9">
</div>
<div class="cell row-7 col-10" id="fillable-7-10">
</div>
<div class="cell row-7 col-11" id="fillable-7-11">
</div>
<div class="cell row-7 col-12" id="fillable-7-12">
</div>
<div class="cell row-7 col-13" id="fillable-7-13">
</div>
<div class="cell row-7 col-14" id="fillable-7-14">
</div>
<div class="cell row-7 col-15" id="fillable-7-15">
</div>
<div class="cell row-7 col-16" id="fillable-7-16">
</div>
<div class="cell row-8 col-1" id="fillable-8-1">
</div>
<div class="cell row-8 col-2" id="fillable-8-2">
</div>
<div class="cell row-8 col-3" id="fillable-8-3">
</div>
<div class="cell row-8 col-4" id="fillable-8-4">
</div>
<div class="cell row-8 col-5" id="fillable-8-5">
</div>
<div class="cell row-8 col-6" id="fillable-8-6">
</div>
<div class="cell row-8 col-7" id="fillable-8-7">
</div>
<div class="cell row-8 col-8" id="fillable-8-8">
</div>
<div class="cell row-8 col-9" id="fillable-8-9">
</div>
<div class="cell row-8 col-10" id="fillable-8-10">
</div>
<div class="cell row-8 col-11" id="fillable-8-11">
</div>
<div class="cell row-8 col-12" id="fillable-8-12">
</div>
<div class="cell row-8 col-13" id="fillable-8-13">
</div>
<div class="cell row-8 col-14" id="fillable-8-14">
</div>
<div class="cell row-8 col-15" id="fillable-8-15">
</div>
<div class="cell row-8 col-16" id="fillable-8-16">
</div>
<div class="cell row-9 col-1" id="fillable-9-1">
</div>
<div class="cell row-9 col-2" id="fillable-9-2">
</div>
<div class="cell row-9 col-3" id="fillable-9-3">
</div>
<div class="cell row-9 col-4" id="fillable-9-4">
</div>
<div class="cell row-9 col-5" id="fillable-9-5">
</div>
<div class="cell row-9 col-6" id="fillable-9-6">
</div>
<div class="cell row-9 col-7" id="fillable-9-7">
</div>
<div class="cell row-9 col-8" id="fillable-9-8">
</div>
<div class="cell row-9 col-9" id="fillable-9-9">
</div>
<div class="cell row-9 col-10" id="fillable-9-10">
</div>
<div class="cell row-9 col-11" id="fillable-9-11">
</div>
<div class="cell row-9 col-12" id="fillable-9-12">
</div>
<div class="cell row-9 col-13" id="fillable-9-13">
</div>
<div class="cell row-9 col-14" id="fillable-9-14">
</div>
<div class="cell row-9 col-15" id="fillable-9-15">
</div>
<div class="cell row-9 col-16" id="fillable-9-16">
</div>
<div class="cell row-10 col-1" id="fillable-10-1">
</div>
<div class="cell row-10 col-2" id="fillable-10-2">
</div>
<div class="cell row-10 col-3" id="fillable-10-3">
</div>
<div class="cell row-10 col-4" id="fillable-10-4">
</div>
<div class="cell row-10 col-5" id="fillable-10-5">
</div>
<div class="cell row-10 col-6" id="fillable-10-6">
</div>
<div class="cell row-10 col-7" id="fillable-10-7">
</div>
<div class="cell row-10 col-8" id="fillable-10-8">
</div>
<div class="cell row-10 col-9" id="fillable-10-9">
</div>
<div class="cell row-10 col-10" id="fillable-10-10">
</div>
<div class="cell row-10 col-11" id="fillable-10-11">
</div>
<div class="cell row-10 col-12" id="fillable-10-12">
</div>
<div class="cell row-10 col-13" id="fillable-10-13">
</div>
<div class="cell row-10 col-14" id="fillable-10-14">
</div>
<div class="cell row-10 col-15" id="fillable-10-15">
</div>
<div class="cell row-10 col-16" id="fillable-10-16">
</div>
<div class="cell row-11 col-1" id="fillable-11-1">
</div>
<div class="cell row-11 col-2" id="fillable-11-2">
</div>
<div class="cell row-11 col-3" id="fillable-11-3">
</div>
<div class="cell row-11 col-4" id="fillable-11-4">
</div>
<div class="cell row-11 col-5" id="fillable-11-5">
</div>
<div class="cell row-11 col-6" id="fillable-11-6">
</div>
<div class="cell row-11 col-7" id="fillable-11-7">
</div>
<div class="cell row-11 col-8" id="fillable-11-8">
</div>
<div class="cell row-11 col-9" id="fillable-11-9">
</div>
<div class="cell row-11 col-10" id="fillable-11-10">
</div>
<div class="cell row-11 col-11" id="fillable-11-11">
</div>
<div class="cell row-11 col-12" id="fillable-11-12">
</div>
<div class="cell row-11 col-13" id="fillable-11-13">
</div>
<div class="cell row-11 col-14" id="fillable-11-14">
</div>
<div class="cell row-11 col-15" id="fillable-11-15">
</div>
<div class="cell row-11 col-16" id="fillable-11-16">
</div>
<div class="cell row-12 col-1" id="fillable-12-1">
</div>
<div class="cell row-12 col-2" id="fillable-12-2">
</div>
<div class="cell row-12 col-3" id="fillable-12-3">
</div>
<div class="cell row-12 col-4" id="fillable-12-4">
</div>
<div class="cell row-12 col-5" id="fillable-12-5">
</div>
<div class="cell row-12 col-6" id="fillable-12-6">
</div>
<div class="cell row-12 col-7" id="fillable-12-7">
</div>
<div class="cell row-12 col-8" id="fillable-12-8">
</div>
<div class="cell row-12 col-9" id="fillable-12-9">
</div>
<div class="cell row-12 col-10" id="fillable-12-10">
</div>
<div class="cell row-12 col-11" id="fillable-12-11">
</div>
<div class="cell row-12 col-12" id="fillable-12-12">
</div>
<div class="cell row-12 col-13" id="fillable-12-13">
</div>
<div class="cell row-12 col-14" id="fillable-12-14">
</div>
<div class="cell row-12 col-15" id="fillable-12-15">
</div>
<div class="cell row-12 col-16" id="fillable-12-16">
</div>
<div class="cell row-13 col-1" id="fillable-13-1">
</div>
<div class="cell row-13 col-2" id="fillable-13-2">
</div>
<div class="cell row-13 col-3" id="fillable-13-3">
</div>
<div class="cell row-13 col-4" id="fillable-13-4">
</div>
<div class="cell row-13 col-5" id="fillable-13-5">
</div>
<div class="cell row-13 col-6" id="fillable-13-6">
</div>
<div class="cell row-13 col-7" id="fillable-13-7">
</div>
<div class="cell row-13 col-8" id="fillable-13-8">
</div>
<div class="cell row-13 col-9" id="fillable-13-9">
</div>
<div class="cell row-13 col-10" id="fillable-13-10">
</div>
<div class="cell row-13 col-11" id="fillable-13-11">
</div>
<div class="cell row-13 col-12" id="fillable-13-12">
</div>
<div class="cell row-13 col-13" id="fillable-13-13">
</div>
<div class="cell row-13 col-14" id="fillable-13-14">
</div>
<div class="cell row-13 col-15" id="fillable-13-15">
</div>
<div class="cell row-13 col-16" id="fillable-13-16">
</div>
<div class="cell row-14 col-1" id="fillable-14-1">
</div>
<div class="cell row-14 col-2" id="fillable-14-2">
</div>
<div class="cell row-14 col-3" id="fillable-14-3">
</div>
<div class="cell row-14 col-4" id="fillable-14-4">
</div>
<div class="cell row-14 col-5" id="fillable-14-5">
</div>
<div class="cell row-14 col-6" id="fillable-14-6">
</div>
<div class="cell row-14 col-7" id="fillable-14-7">
</div>
<div class="cell row-14 col-8" id="fillable-14-8">
</div>
<div class="cell row-14 col-9" id="fillable-14-9">
</div>
<div class="cell row-14 col-10" id="fillable-14-10">
</div>
<div class="cell row-14 col-11" id="fillable-14-11">
</div>
<div class="cell row-14 col-12" id="fillable-14-12">
</div>
<div class="cell row-14 col-13" id="fillable-14-13">
</div>
<div class="cell row-14 col-14" id="fillable-14-14">
</div>
<div class="cell row-14 col-15" id="fillable-14-15">
</div>
<div class="cell row-14 col-16" id="fillable-14-16">
</div>
<div class="cell row-15 col-1" id="fillable-15-1">
</div>
<div class="cell row-15 col-2" id="fillable-15-2">
</div>
<div class="cell row-15 col-3" id="fillable-15-3">
</div>
<div class="cell row-15 col-4" id="fillable-15-4">
</div>
<div class="cell row-15 col-5" id="fillable-15-5">
</div>
<div class="cell row-15 col-6" id="fillable-15-6">
</div>
<div class="cell row-15 col-7" id="fillable-15-7">
</div>
<div class="cell row-15 col-8" id="fillable-15-8">
</div>
<div class="cell row-15 col-9" id="fillable-15-9">
</div>
<div class="cell row-15 col-10" id="fillable-15-10">
</div>
<div class="cell row-15 col-11" id="fillable-15-11">
</div>
<div class="cell row-15 col-12" id="fillable-15-12">
</div>
<div class="cell row-15 col-13" id="fillable-15-13">
</div>
<div class="cell row-15 col-14" id="fillable-15-14">
</div>
<div class="cell row-15 col-15" id="fillable-15-15">
</div>
<div class="cell row-15 col-16" id="fillable-15-16">
</div>
<div class="cell row-16 col-1" id="fillable-16-1">
</div>
<div class="cell row-16 col-2" id="fillable-16-2">
</div>
<div class="cell row-16 col-3" id="fillable-16-3">
</div>
<div class="cell row-16 col-4" id="fillable-16-4">
</div>
<div class="cell row-16 col-5" id="fillable-16-5">
</div>
<div class="cell row-16 col-6" id="fillable-16-6">
</div>
<div class="cell row-16 col-7" id="fillable-16-7">
</div>
<div class="cell row-16 col-8" id="fillable-16-8">
</div>
<div class="cell row-16 col-9" id="fillable-16-9">
</div>
<div class="cell row-16 col-10" id="fillable-16-10">
</div>
<div class="cell row-16 col-11" id="fillable-16-11">
</div>
<div class="cell row-16 col-12" id="fillable-16-12">
</div>
<div class="cell row-16 col-13" id="fillable-16-13">
</div>
<div class="cell row-16 col-14" id="fillable-16-14">
</div>
<div class="cell row-16 col-15" id="fillable-16-15">
</div>
<div class="cell row-16 col-16" id="fillable-16-16">
</div>
</div>
<script src="createSolved.js" ></script>
<script src="simpleSolver.js" ></script>
<script>
var els = document.querySelectorAll('.cell');
els.forEach((el) => {
el.style.display = "none";
el.style.borderRight = "1px dotted gray";
el.style.borderLeft = "1px dotted gray";
el.style.borderTop = "1px dotted gray";
el.style.borderBottom = "1px dotted gray";
el.style.background = "white";
el.addEventListener('click',clickCell);
})
var puzzle;
var puzzleData = {1:0,2:0,3:0,4:0,5:0,'blanks':0};
var selected = {};
function updatePuzzle(clear=true,visual=true) {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var puzzleOrdered = random_puzzle(x,y);
for (var i=0;i<20;i++){
if (puzzleOrdered){break;}
puzzleOrdered = random_puzzle(x,y);
}
puzzle = puzzleOrdered.slice();
var digitList = digits.slice();
for (var d in digits){
var dd = Math.floor(Math.random()*digitList.length);
var ddd = digitList[dd];
digitList.splice(dd,1);
for (var i in puzzleOrdered){
if (puzzleOrdered[i]==digits[d]){
puzzle[i]=ddd;
}
}
}
if (clear){
selected = {};
}
var els = document.querySelectorAll('.cell');
els.forEach((el) => {
el.style.display = "none";
el.style.borderRight = "1px dotted gray";
el.style.borderLeft = "1px dotted gray";
el.style.borderTop = "1px dotted gray";
el.style.borderBottom = "1px dotted gray";
if (clear){
el.style.background = "white";
}
})
for (var i=0;i<x*y;i++){
for (var ii=0;ii<x*y;ii++){
var el = document.getElementById('cell-'+(i+1)+"-"+(ii+1));
el.textContent = puzzle[i*x*y+ii];
el.style.display = "inline-block";
if (ii%y == y-1){
el.style.borderRight = "1px solid black";
}
if (ii%y == 0){
el.style.borderLeft = "1px solid black";
}
if (i%x == x-1){
el.style.borderBottom = "1px solid black";
}
if (i%x == 0){
el.style.borderTop = "1px solid black";
}
var el = document.getElementById('fillable-'+(i+1)+"-"+(ii+1));
el.textContent = "";
el.style.display = "inline-block";
if (ii%y == y-1){
el.style.borderRight = "1px solid black";
}
if (ii%y == 0){
el.style.borderLeft = "1px solid black";
}
if (i%x == x-1){
el.style.borderBottom = "1px solid black";
}
if (i%x == 0){
el.style.borderTop = "1px solid black";
}
}
}
if (!clear){partial_puzzle(visual);}
}
function partial_puzzle(visual=true){
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
puzzleData = {1:0,2:0,3:0,4:0,5:0,'blanks':x*y*x*y};
var fills = fillable_puzzle();
var fillColors = {};
for (var i in selected){
if (!selected[i]){continue;}
var s = squares[i];
var v = parseInt(puzzle[i]);
fills[s] = v;
}
//console.log(Date.now());
var updated = true;
while (updated){
updated = false;
var pp = simpleSolve(fills);
pp.sort((a,b) => {return a[2] - b[2];})
var ppp = 1000;
for (var i in pp){
if (pp[i][2] > ppp && pp[i][2] > 2){break;}
var s = pp[i][0];
var v = pp[i][1];
if (fills[s] == 0){
//if (pp[i][2] >= 3){
//console.log(s,v,pp[i][2]);
//updated = false;
//break;
//}
fills[s] = v;
fillColors[s] = pp[i][2];
ppp = pp[i][2];
puzzleData[ppp]++;
updated = true;
}
}
}
for (var f in fills){
if (fills[f] != 0){
puzzleData.blanks--;
}
}
//if (puzzleData.blanks == 0){
// console.log(JSON.stringify(puzzleData));
//}
if (puzzleData[3]+puzzleData[4]+puzzleData[5] > 0){
console.log(JSON.stringify(puzzleData));
}
if (!visual){return;}
//console.log(Date.now());
for (var i=0;i<x*y;i++){
for (var ii=0;ii<x*y;ii++){
var el = document.getElementById('cell-'+(i+1)+"-"+(ii+1));
var elf = document.getElementById('fillable-'+(i+1)+"-"+(ii+1));
var s = i*x*y+ii;
if (selected[s]){
el.style.background = "green";
var v = parseInt(puzzle[s]);
elf.textContent = v;
continue;
}
elf.textContent = "";
var ss = squares[s];
if (fills[ss] != 0){
if (fillColors[ss] == 1){
el.style.background = "yellow";
}
else if (fillColors[ss] == 2){
el.style.background = "orange";
}
else if (fillColors[ss] == 3){
el.style.background = "#FF8C00";
}
else {
el.style.background = "#FF3C00";
}
}
else {
el.style.background = "white";
}
}
}
var chars = ["1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G"]
var pStr = "";
for (var i in puzzle){
if (selected[i]){
pStr += chars[puzzle[i]-1];
}
else {
pStr += ".";
}
}
pStr += ",";
for (var i in puzzle){
pStr += chars[puzzle[i]-1];
}
document.getElementById('puzzleStr').textContent = pStr;
var a = document.getElementById('puzzleLink');
a.setAttribute('href',"https://triplelog.com/code/Sudoku-Server/?p="+pStr.split(",")[0]+"&x="+x+"&y="+y);
a.textContent = "Link";
}
function clickCell(evt){
var id = evt.currentTarget.id;
var rc = id.substring(5).split("-");
var r = parseInt(rc[0])-1;
var c = parseInt(rc[1])-1;
var s = r*x*y+c;
var smap = {};
smap[s]=true;
var mirror = document.getElementById('pattern').value;
if (mirror == "horiz"){
var cc = x*y-1-c;
var ss = r*x*y+cc;
smap[ss]=true;
}
else if (mirror == "verti"){
var rr = x*y-1-r;
var ss = rr*x*y+c;
smap[ss]=true;
}
else if (mirror == "diago"){
var rr = x*y-1-c;
var cc = x*y-1-r;
var ss = rr*x*y+cc;
smap[ss]=true;
}
else if (mirror == "ro180"){
var rr = x*y-1-r;
var cc = x*y-1-c;
var ss = rr*x*y+cc;
smap[ss]=true;
}
else if (mirror == "rot90"){
var rr = c;
var cc = x*y-1-r;
var ss = rr*x*y+cc;
smap[ss]=true;
var rrr = cc;
var ccc = x*y-1-rr;
ss = rrr*x*y+ccc;
smap[ss]=true;
var rrrr = ccc;
var cccc = x*y-1-rrr;
ss = rrrr*x*y+cccc;
smap[ss]=true;
}
if (!selected[s]){
for (var ss in smap){
selected[ss]=true;
}
}
else {
for (var ss in smap){
selected[ss]=false;
}
}
partial_puzzle();
}
function loop100() {
console.log(Date.now());
for (var i=0;i<100;i++){
updatePuzzle(false,false);
}
console.log(Date.now());
}
</script>
</body>
</html>
const fs = require('fs');
const nunjucks = require('nunjucks');
var html = nunjucks.render("genPuzzle.html", {});
fs.writeFileSync("index.html", html);
var x = 3;
var y = 3;
function cross(A, B){
//Cross product of elements in A and elements in B.
var arr = [];
var alen = A.length;
var blen = B.length;
for (var i=0;i<alen;i++){
for (var ii=0;ii<blen;ii++){
arr.push(A[i]+"-"+B[ii])
}
}
return arr
}
var digits = [];
var rows = [];
var cols = [];
var squares;
var unitlist = [];
var rowlist = [];
var collist = [];
var blocklist = [];
var units = {};
var peers = {};
function fillable_puzzle(){
digits = [];
rows = [];
cols = [];
for (var i=1;i<x*y+1;i++){
rows.push(i);
cols.push(i);
digits.push(i);
}
squares = cross(rows, cols)
unitlist = [];
rowlist = [];
collist = [];
blocklist = [];
for (var c in cols){
unitlist.push(cross(rows,[cols[c]]));
collist.push(cross(rows,[cols[c]]));
}
for (var r in rows){
unitlist.push(cross([rows[r]],cols));
rowlist.push(cross([rows[r]],cols));
}
for (var i=0;i<y;i++){
var A = [];
for (var ii=0;ii<x;ii++){
A.push(i*x+ii+1);
}
for (var ii=0;ii<x;ii++){
var B = [];
for (var iii=0;iii<y;iii++){
B.push(ii*y+iii+1);
}
unitlist.push(cross(A,B));
blocklist.push(cross(A,B));
}
}
units = {};
peers = {};
for (var i in squares){
var s = squares[i];
units[s]=[];
peers[s]={};
for (var ii in unitlist){
var u = unitlist[ii];
for (var iii in u){
var uu = u[iii];
if (s == uu){
units[s].push(u);
for (var iiii in u){
if (u[iiii] != s){
peers[s][u[iiii]]=true;
}
}
break;
}
}
}
}
var fills = {};
for (var i in squares){
var s = squares[i];
fills[s]=0;
}
return fills
}
function finishUnit(fills){
var possiblePlays = [];
var allunits = [rowlist,collist,blocklist];
for (var u in allunits){
for (var ui in allunits[u]){
var unit = allunits[u][ui];
var count = 0;
var cell = -1;
var current = {};
for (var i in unit){
if (fills[unit[i]] == 0){
count++;
cell = unit[i];
}
else {
current[fills[unit[i]]]=true;
}
}
if (count == 1){
for (var i in digits){
if (!current[digits[i]]){
possiblePlays.push([cell,digits[i],1]);
break;
}
}
}
}
}
return possiblePlays;
}
function fitSpotBasic(fills,s,v){
for (var u in units[s]){
for (var i in units[s][u]){
var ss = units[s][u][i];
if (fills[ss] == v){
return false;
}
}
}
return true;
}
function oneSpotInUnit(fills){
var possiblePlays = [];
var allunits = [rowlist,collist,blocklist];
for (var u in allunits){
for (var ui in allunits[u]){
var unit = allunits[u][ui];
for (var vi in digits){
var v = digits[vi];
var count = 0;
var cell = -1;
for (var i in unit){
if (fills[unit[i]] == 0){
if (fitSpotBasic(fills,unit[i],v)){
count++;
cell = unit[i];
}
}
else if (fills[unit[i]] == v){
//value already in unit
count = 0;
break;
}
}
if (count == 1){
possiblePlays.push([cell,v,2]);
}
}
}
}
return possiblePlays;
}
function oneDigitInSpot(fills){
var possiblePlays = [];
for (var si in squares){
var s = squares[si];
if (fills[s] != 0){continue;}
var count = 0;
var out = -1;
for (var vi in digits){
var v = digits[vi];
if (fitSpotBasic(fills,s,v)){
count++;
if (count > 1){
break;
}
out = v;
}
}
if (count == 1){
possiblePlays.push([s,out,2]);
}
}
return possiblePlays;
}
function simpleSolve(fills){
var possiblePlays = [];
possiblePlays = possiblePlays.concat(finishUnit(fills));
possiblePlays = possiblePlays.concat(oneSpotInUnit(fills));
possiblePlays = possiblePlays.concat(oneDigitInSpot(fills));
return possiblePlays;
}
This repl allows you to create sudoku puzzles of any size with custom patterns of given digits.
To view this on TripleLog, click here.
Choose the size of the puzzle and then click the Refresh Numbers button. A completed puzzle and an unfinished puzzle will appear. Click the cells you wish to be givens for the solver. If you want to force a pattern, set the option in the Pattern dropdown.
As you add more cells, the solver will try to find a solution. Any cells that can be determined will have a colored background. If every cell has a colored background, then the puzzle is solvable.
Once you have created a solvable puzzle that you like you can copy the string to create a puzzle wherever. The string includes the unfinished puzzle followed by a comma and then the finished puzzle. You might only need the first part for most uses.
If a puzzle is not completely solvable you can try refreshing the numbers. The cells you have selected will remain selected but a new puzzle will be the basis. The different numbers will change which cells are solvable.
To try lots of options until a solvable puzzle is generated, click the Try 100 button. Up to 100 puzzles will be created until a solvable puzzle is produced.
Add CSS by editing the style.css file that is linked to in the head section or inline edit the style section in the head.
The createSolved.js will generate a completed sudoku puzzle of the desired size. Then it tries to solve based on the cells given.
You can edit the simpleSolver.js file to add/edit the solving techniques.
The solver only knows basic techniques so the puzzles will not require any advanced solving strategies.
You will need to install node and modules to run the makehtml.js file to regenerate the index file if you make changes.