<!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;
}
.cell {
border: 1px solid black;
display: inline-block;
height: 2rem;
width: 2rem;
position: absolute;
line-height: 2rem;
text-align: center;
}
{% 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()">Create</button>
</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>
<script src="script.js" ></script>
<script>
function updatePuzzle() {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var puzzle = random_puzzle(x,y);
for (var i=0;i<20;i++){
if (puzzle){break;}
puzzle = random_puzzle(x,y);
}
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";
})
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";
}
}
}
}
</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;
}
.cell {
border: 1px solid black;
display: inline-block;
height: 2rem;
width: 2rem;
position: absolute;
line-height: 2rem;
text-align: center;
}
.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()">Create</button>
</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>
<script src="script.js"></script>
<script>
function updatePuzzle() {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var puzzle = random_puzzle(x, y);
for (var i = 0; i < 20; i++) {
if (puzzle) {break;}
puzzle = random_puzzle(x, y);
}
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";
})
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";
}
}
}
}
</script>
</body>
</html>
const fs = require('fs');
const nunjucks = require('nunjucks');
var html = nunjucks.render("fullPuzzle.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 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 = []
for (var c in cols){
unitlist.push(cross(rows,[cols[c]]));
}
for (var r in rows){
unitlist.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));
}
}
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;
console.log(totalT);
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;
}
This repl generates a completed sudoku puzzle using constraint propagation.
To view this on TripleLog, click here.
This code is an adaption of Peter Norvig's sudoku solver.
Choose the size of the puzzle and then click the Create button. The output does look nice but you can see that something works.
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 script.js will generate a completed sudoku puzzle of the desired size.
Every puzzle will have the same top row with the numbers in order. These values can (and should) be shuffled. To generate an actual puzzle you will also need to do more work to figure out which cells to remove.
If you want to generate lots of puzzles you probably want to make it faster.