Skip to content

Instantly share code, notes, and snippets.

@TylerLeite
Last active February 6, 2020 23:48
Show Gist options
  • Save TylerLeite/426b6f0f9f4bd80f2885bfa37a27a862 to your computer and use it in GitHub Desktop.
Save TylerLeite/426b6f0f9f4bd80f2885bfa37a27a862 to your computer and use it in GitHub Desktop.
evolve symmetrical art
const fs = require('fs');
const PNG = require('pngjs').PNG;
W = 256;
H = 256;
AB = '0123456789';
PSIZE = 128;
GENS = 300;
function choice (arr) {
return arr[Math.floor(Math.random()*arr.length)];
}
function shuffle (array) {
let cur = array.length;
while (cur > 0) {
const r = Math.floor(Math.random() * cur);
cur -= 1;
const temp = array[cur];
array[cur] = array[r];
array[r] = temp;
}
return array;
};
function randomIndiv (width, height, alphabet) {
const out = [];
for (let i = 0; i < height; i++) {
const row = [];
for (let j = 0; j < width; j++) {
row.push(choice(alphabet))
}
out.push(row);
}
return out;
}
function printIndiv (indiv) {
let str = "";
for (let i = 0; i < indiv.length; i++) {
for (let j = 0; j < indiv[i].length; j++) {
str += indiv[i][j];
}
str += "\n";
}
console.log(str);
}
function imgfrom (best, i) {
const img = new PNG({width:W,height:H});
for (let y = 0; y < img.height; y++) {
for (let x = 0; x < img.width; x++) {
const idx = (img.width * y + x) << 2;
const col = best[y][x];
img.data[idx] = Math.floor(256/col);
img.data[idx + 1] = Math.floor(256/col);
img.data[idx + 2] = Math.floor(256/col);
img.data[idx + 3] = 0xFF;
}
}
const buf = PNG.sync.write(img);
fs.writeFileSync(__dirname + '/out/' + i + '.png', buf);
}
function fitness (indiv) {
let fitness = 0;
for (let i = 0; i < indiv.length; i++) {
for (let j = 0; j < indiv[i].length; j++) {
const h = indiv.length-1;
const w = indiv[j].length-1;
// if (indiv[i][j] == indiv[h-i][j]) { fitness += 1; }
// if (indiv[i][j] == indiv[i][w-j]) { fitness += 1; }
// if (indiv[i][j] == indiv[h-i][w-j]) { fitness += 1; }
fitness += 10 - Math.abs(indiv[i][j] - indiv[h-i][j]);
fitness += 10 - Math.abs(indiv[i][j] - indiv[i][w-j]);
fitness += 10 - Math.abs(indiv[i][j] - indiv[h-i][w-j]);
}
}
return fitness;
}
function crossover (indiv1, indiv2) {
let child = [];
for (let i = 0; i < indiv1.length; i++) {
let row = [];
for (let j = 0; j < indiv1[i].length; j++) {
if (Math.random() < 0.5) {
row.push(indiv1[i][j]);
} else {
row.push(indiv2[i][j]);
}
}
child.push(row);
}
return child;
}
pop = [];
for (let i = 0; i < PSIZE; i++) {
pop.push(randomIndiv(W, H, AB));
}
pop.sort((b, a) => (fitness(a) - fitness(b)));
best = null;
for (let i = 0; i < GENS; i++) {
new_p = pop.slice(0, PSIZE/2);
shuffle(new_p);
for (let j = 0; j < PSIZE/2; j+=2) {
new_p.push(crossover(new_p[j], new_p[j+1]));
}
while (new_p.length < PSIZE) {
new_p.push(randomIndiv(W, H, AB));
}
pop = new_p;
pop.sort((b, a) => (fitness(a) - fitness(b)));
best = pop[0]
console.log(i, fitness(pop[0]));
imgfrom(best, i);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment