Skip to content

Commit 4a15e39

Browse files
author
bryc
committed
+pixicon, sudoku
1 parent d88e115 commit 4a15e39

File tree

6 files changed

+416
-0
lines changed

6 files changed

+416
-0
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# code
2+
3+
this is just a bunch of code (mostly js) not important enough for separate repos

pixicon/index.htm

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<script src=pixicon.js></script>
2+
<style>
3+
* {font: 14px Segoe UI,Trebuchet MS,Tahoma,sans-serif}
4+
body {background:#36393E;text-align:center;padding-top:64px}
5+
div#p {width: 552px;margin-right:3px}
6+
div#p2 {width: 277px}
7+
div#u, div#uu {
8+
box-shadow: 2px 2px 20px #232427;
9+
border-radius: 4px;
10+
padding: 8px;
11+
display: inline-flex;
12+
background: #5B616A
13+
}
14+
input,button {
15+
text-shadow: 0.6px 0.6px 0px #FFF;
16+
border-radius: 2px;
17+
margin: 3px;
18+
padding: 2px;
19+
outline: none;
20+
width: 547px;
21+
color: #555;
22+
text-align: center;
23+
border: none;
24+
background: #D8DADE;
25+
margin-top: 4px;
26+
height: 32px;
27+
box-shadow: 1px 1px 3px #232427;
28+
}
29+
30+
input {width:273px}
31+
input:hover,button:hover {background:#D0D2D7}
32+
button:active,input:focus{background:#C7C9CF;}
33+
button:active{cursor:pointer;}
34+
canvas {
35+
border-radius: 2px;box-shadow: 1px 1px 3px #232427;
36+
background: #EEE;
37+
margin: 3px;
38+
padding: 3px;
39+
border: 1px solid #EAEAEA;
40+
41+
}
42+
canvas#q{padding:6.2px 7px;width:256px; height:256px;} /* multiples of 8 only! */
43+
</style>
44+
45+
<div id=u >
46+
<div id=p><div id=o></div><button>Generate more</button></div>
47+
<div id=p2><canvas id=q width=256 height=256></canvas><input type=text placeholder='Type something here'></div>
48+
</div>
49+
50+
<script>
51+
function arst(a){return a.trim?Array.apply(0,Array(a.length)).map(function(x,i){return a[i].charCodeAt()}):String.fromCharCode.apply(0,a)}
52+
53+
var cyrb32 = function(data) {
54+
var i, tmp, sum = 0x9CB85729, len = data.length;
55+
for(i = 0; i < len; i++) {
56+
sum = sum + data[i];
57+
sum = sum + (sum << ((sum & 7)+1));
58+
}
59+
for(tmp = sum >>> 0; tmp > 0; tmp >>>= 1) {
60+
if(tmp & 1) sum = sum + (sum << ((sum & 7)+1)) + tmp;
61+
}
62+
return sum >>> 0;
63+
};
64+
65+
function more() {
66+
for(var i=0;i<cnt;i++) {pixicon(cnv[i]);}
67+
}
68+
69+
pixicon(document.querySelector("canvas#q"));
70+
document.querySelector("input").oninput = function() {
71+
pixicon(document.querySelector("canvas#q"), cyrb32(arst(this.value)));
72+
};
73+
74+
for(var cnt = 72, cnv = [], i = 0; i < cnt; i++) {
75+
var c = document.createElement("canvas");
76+
cnv.push(c);
77+
document.querySelector("div#o").appendChild(c);
78+
if(i===cnt-1) more(), document.querySelector("button").onclick=more;
79+
}
80+
</script>

pixicon/pixicon.js

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
function pixicon(t, r) {
2+
// HSL color generator.
3+
function i(t, r, e, i=0) {
4+
var set = [
5+
[999*t%360, 24+80*r%40, 26+70*e%40],
6+
[999*t%360, 9*r%10, 15+36*e%50],
7+
[999*t%360, 14*r%40, 37+36*e%40],
8+
];
9+
return "hsl("+~~set[i][0]+","+~~set[i][1]+"%,"+~~set[i][2]+"%)";
10+
}
11+
// LCG pseudorandom number generator.
12+
function LCG(seed) {
13+
function lcg(a) {return a * 48271 % 2147483647}
14+
seed = seed ? lcg(seed) : lcg(Math.random());
15+
return function() {return (seed = lcg(seed)) / 2147483648}
16+
}
17+
18+
var n = 16,
19+
q = n*2,
20+
l = n*n,
21+
a = [],
22+
rng = LCG(r),
23+
c = t.getContext("2d");
24+
25+
// Set canvas dimensions if not already set.
26+
// Condition improves performance on subsequent calls to existing canvas (Firefox).
27+
if(t.width !== q) {
28+
t.width = t.height = q;
29+
// Disable filtering when scaling canvas.
30+
t.style.imageRendering = "-moz-crisp-edges";
31+
t.style.imageRendering = "pixelated";
32+
}
33+
34+
// Reset transformation (for consistent rotation results).
35+
c.setTransform(1, 0, 0, 1, 0, 0);
36+
// Erase anything previously on the canvas context.
37+
c.clearRect(0, 0, t.width, t.height);
38+
// Set fill color for pixels.
39+
var color1 = i(rng(), rng(), rng(), rng()>=.9 ? 1:0);
40+
var color2 = i(rng(), rng(), rng(), rng()>=.8 ? 2:0);
41+
c.fillStyle = color1;
42+
43+
// Rotate canvas 90 degrees at random.
44+
rng() > .5 && c.rotate(Math.PI * .5)|c.translate(0, -t.width);
45+
46+
// Generate the number of pixels to occupy (threshold: within 25%-75%).
47+
var r = rng(), u = 0|(2*r*l+8*r+l)*.125;
48+
// Populate array with an amount of pixels (within threshold).
49+
for(var s = 0; s < u; s++)
50+
a[s] = 1;
51+
52+
// Shuffle pixel array (Fisher–Yates).
53+
// !!! NOTE: |0 is required to prevent an infinite loop in odd sizes. !!!
54+
for(var v, s = 0|l/2; s;)
55+
v = 0|rng() * s--,
56+
[a[s], a[v]] = [a[v], a[s]];
57+
58+
// Copy pixel array, then reverse & append (for symmetry).
59+
a = a.concat(a.slice().reverse());
60+
61+
for(var o = t.width/n, d=y=s= 0; s < l; s++, d = s%n)
62+
// Change color at halfway point.
63+
// NOTE: |0 is required for odd size multiples.
64+
(s === (0|l/2)) && ( c.fillStyle = color2),
65+
// Increment y axis.
66+
(s && !d) && y++,
67+
// Fill a square (pixel) on the canvas (x, y, width, height).
68+
(a[s]) && c.fillRect(o*d, o*y, o, o)
69+
}

sudoku/TODO.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
### TODO
2+
1. Sudoku state validation
3+
2. _(maybe)_ Click cells to cycle through numbers (Left and Right click - arrow keys as well?)
4+
5+
I should probably just start with this library: https://github.com/robatron/sudoku.js
6+
## Solver/generator:
7+
- http://www.sudokuwiki.org/sudoku.htm (original online solver)
8+
- https://codepen.io/pavlovsk/pen/XmjPOE
9+
- https://github.com/pocketjoso/sudokuJS
10+
- https://attractivechaos.github.io/plb/kudoku.html
11+
- https://www.codefellows.org/blog/sudoku-solver-from-scratch-in-javascript-tdd-style-a-tutorial/
12+
- https://stackoverflow.com/questions/42736648/sudoku-solver-in-js
13+
- https://20js.devpost.com/submissions/33526-sudoku-solver <-- 20 lines of code only
14+
- http://moriel.smarterthanthat.com/tips/javascript-sudoku-backtracking-algorithm/
15+
- http://www.kernel-panic.it/software/sudokiller/sudokiller.js.html
16+
- http://www.emanueleferonato.com/2015/06/23/pure-javascript-sudoku-generatorsolver/
17+
- https://curiosity-driven.org/sudoku-solver <-- also kinda short but is it full code?
18+
- https://gist.github.com/p01/1230481/95f6facb74f51d089bea87eba0f470cf3bbed83a <-- 140 byte hyper small p01 demoscene sudoku solver... maybe good?! but slow (which is fine?)
19+
- http://lahiri.me/fapanosss.html?#
20+
- https://www.openhub.net/p/sudoku_js
21+
- https://scriptographer.org/scripts/general-scripts/sudoku-generator-solver/ (ADOBE ILLUSTRATOR ONLY)
22+
## validator
23+
- https://medium.com/@0xsven/sudoku-validation-with-javascript-1297712093bf (article on validation)

sudoku/app.js

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
function bmap(val, mode = 0) {
2+
var i, data = mode ? [...val].map(a=>a.charCodeAt()) : val.slice(),
3+
tbl = [
4+
0x22, 0x26, 0x27, 0x3C, 0x3E, 0xB8, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
5+
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
6+
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
7+
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
8+
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xAD
9+
];
10+
for(i = 0; i < val.length; i++) {
11+
var idx = tbl.indexOf(data[i]);
12+
if(mode ? data[i]>255 : idx>-1) data[i] = mode ? tbl[data[i]-0x100] : 0x100+idx;
13+
}
14+
return mode ? data : String.fromCharCode.apply(0,data);
15+
}
16+
arst=a=>{return a.trim?[...a].map(a=>a.charCodeAt()):String.fromCharCode.apply(0,a)}
17+
18+
function cksm(d){for(var i=s=0;i<d.length;++i)s+=(s<<1)+d[i];s^=s<<9;s^=s<<16;return s>>>0}
19+
function eee(r,e){for(var n,f=[],o=0,t=[],h=0;256>h;h++)f[h]=h;for(h=0;256>h;h++)o=(o+f[h]+e[h%e.length])%256,n=f[h],f[h]=f[o],f[o]=n;h=0,o=0;for(var u=0;u<r.length;u++)h=(h+1)%256,o=(o+f[h])%256,n=f[h],f[h]=f[o],f[o]=n,t.push(r[u]^f[(f[h]+f[o])%256]);return t}
20+
21+
var crc8 = function(data) {
22+
for(var i=256, tbl=[], crc, j; i--; tbl[i]=crc&0xFF){
23+
j=8;for(crc=i;j--;)crc=crc&128?(crc<<1)^0x5a:crc<<1;
24+
}
25+
return function(data) {
26+
for(var i=0, crc=0; i<data.length; ++i)
27+
crc=tbl[(crc^data[i])%256];
28+
return crc;
29+
}
30+
}();
31+
32+
function loadPuzzle(str2) {
33+
if(!str2) {return}
34+
console.log(arst(str2) );
35+
// decode base64 to string
36+
var err = 0;
37+
//var str = atob(str2);
38+
console.log(str2)
39+
var arr = arst(atob(str2));
40+
// console.log(arr)
41+
//var arr = arrstr(str);
42+
43+
arr = [arr[0]].concat(eee(arr.slice(1), [arr[0]]) );
44+
var hex = Array.prototype.map.call(arr, x => ('00'+x.toString(16).toUpperCase()).slice(-2)).join(' ');
45+
console.log(arr.length, hex);
46+
// load nibble-frames into data array
47+
for(var i=1, data=[], sum, sum2; i<arr.length; i++) {
48+
var byte = arr[i];
49+
var nib1 = (byte & 0xF0) >> 4
50+
var nib2 = byte & 0x0F;
51+
data.push(nib1);
52+
// if the last nibble is 0, skip it (for odd nibble counts)
53+
if(i === arr.length-1 && nib2 === 0) break;
54+
data.push(nib2);
55+
}
56+
sum = arr[0]; sum2 = crc8(arr.slice(1));
57+
if(sum !== sum2) {
58+
err++;
59+
console.error("ERROR:", "Data checksum is invalid.");
60+
}
61+
// check data
62+
for(var t=0,i = 0, last; i < data.length; i++) {
63+
var c = data[i];
64+
// Check code 15 ----------------------------------------------------------
65+
if(c === 15 && data[i + 1] !== undefined && data[i + 2] !== undefined) {
66+
var digit = (data[i+1]<<4) + data[i+2];
67+
if(digit<16 || digit>80) {
68+
err++;
69+
console.error("ERROR:", "At position:", i, "Code 15 has bad size:", digit);
70+
}
71+
} else if(c === 15 && (data[i + 1] === undefined || data[i + 2] === undefined)) {
72+
err++;
73+
console.error("ERROR:", "At position:", i, "Code 15 is missing data");
74+
break;
75+
}
76+
// Check code 14 ----------------------------------------------------------
77+
if(c === 14 && data[i + 1] !== undefined) {
78+
var digit = data[i+1];
79+
if(digit<6) {
80+
err++;
81+
console.error("ERROR:", "At position:", i, "Code 14 has bad size:", digit);
82+
}
83+
} else if(c === 14 && data[i + 1] === undefined) {
84+
err++;
85+
console.error("ERROR:", "At position:", i, "Code 14 is missing data");
86+
break;
87+
}
88+
// Check for repeating compression codes
89+
if(
90+
((c > 9 && c < 16)) &&
91+
((last > 9 && last < 16))
92+
) {
93+
err++;
94+
console.error("ERROR:", "At position:", i, "Compression code repeat: ", "current:" + c, "last:" + last);
95+
}
96+
last = c;
97+
// Check how many cells represented in the data
98+
switch(c) {
99+
case 0xA: t+=2; break;
100+
case 0xB: t+=3; break;
101+
case 0xC: t+=4; break;
102+
case 0xD: t+=5; break;
103+
case 0xE: t+=data[i+1]; i += 1; break;
104+
case 0xF: t+=(data[i+1]<<4)+data[i+2]; i += 2; break;
105+
default : t+=1;
106+
}
107+
if(t > 81) {
108+
err++;
109+
console.error("ERROR:", "Data contains more than 81 cells.");
110+
break;
111+
}
112+
}
113+
if((last > 9 && last < 16)) {
114+
err++;
115+
console.error("ERROR:", "Compression code cannot be final frame in sequence.");
116+
}
117+
if(err > 0) {
118+
input.style.border = "1px solid red";
119+
input.style.background = "#FFF7F7";
120+
return false;
121+
} else {
122+
input.style.border = "";
123+
input.style.background = "";
124+
}
125+
info.innerHTML = "puzzHash: <code>" + cksm(arr).toString(36) + "</code>";
126+
for(var i = k = 0, t, y; i<81; i++, k++) {
127+
switch(data[k]) {
128+
case 0xA: y=1; t=2; break;
129+
case 0xB: y=1; t=3; break;
130+
case 0xC: y=1; t=4; break;
131+
case 0xD: y=1; t=5; break;
132+
case 0xE: y=2; t=data[k+1]; break;
133+
case 0xF: y=3; t=(data[k+1]<<4)+data[k+2]; break;
134+
default : y=0; t=0;
135+
}
136+
for(j=0; j<t; j++, i++) tbl[i].innerHTML="";
137+
k += y;
138+
139+
tbl[i].innerHTML = data[k] ? data[k]:"";
140+
}
141+
input.value = str2;
142+
}
143+
144+
function savePuzzle() {
145+
for(var i=j=0, data=[]; i<tbl.length; i++) {
146+
var c = parseInt(tbl[i].textContent) || "";
147+
if(c === "") j++;
148+
else {
149+
switch(true) {
150+
case j==2: data.push(0xA); break;
151+
case j==3: data.push(0xB); break;
152+
case j==4: data.push(0xC); break;
153+
case j==5: data.push(0xD); break;
154+
case j>15: data.push(0xF,j>>4,j&0xF); break;
155+
case j>5 : data.push(0xE,j); break;
156+
default : while(j--) data.push(0);
157+
}
158+
j = 0; data.push(c);
159+
}
160+
}
161+
var packed = [];
162+
for(var i = 0, len = data.length; i<len; i += 2) {
163+
var b = (i!==len-1)?data[i+1]:0; // 0 for missing nibble
164+
packed.push((data[i]<<4) + b);
165+
}
166+
167+
var crc = crc8(packed);
168+
var output = [crc].concat(eee(packed,[crc]));
169+
return btoa(arst(output)).replace(/=/g,"");
170+
}
171+
//////////////////////////////////////////////////////
172+
var tbl, info, input;
173+
window.onload = function() {
174+
tbl = document.querySelectorAll("table.sudoku td");
175+
info = document.querySelector("div.info");
176+
input = document.querySelector("input.code");
177+
for(var i = 0,y = true; i < tbl.length; i++) {
178+
tbl[i].contentEditable = "true";
179+
tbl[i].oninput = function(e){loadPuzzle(savePuzzle());}
180+
tbl[i].onkeypress = function(e) {
181+
if(e.keyCode<48||e.keyCode>57)return false;
182+
this.textContent = "";
183+
};
184+
}
185+
input.oninput = function() {
186+
if(input.value==""){for(j=0;j<81;j++)tbl[j].innerHTML=""}
187+
188+
if(input.value.length===81) {
189+
for(var packed=[], i = 0; i < 81; i += 2) {
190+
var num1 = Number(input.value[i]);
191+
var num2 = Number(input.value[i+1]);
192+
193+
var digit = 0;
194+
if(num1 >= 1 && num1 <= 9) digit += num1<<4;
195+
if(num2 >= 1 && num2 <= 9) digit += num2;
196+
packed.push(digit);
197+
}
198+
var crc = crc8(packed);
199+
var output = [crc].concat(eee(packed,[crc]))
200+
console.log(output);
201+
loadPuzzle( btoa(arst(output)).replace(/=/g,"") );
202+
203+
} else {
204+
loadPuzzle(input.value);
205+
}
206+
//var b64 = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}|[A-Za-z0-9+/]{2})$/;
207+
//if(b64.test(input.value))
208+
209+
};
210+
};

0 commit comments

Comments
 (0)