.. and the code that tries ( in a very dumb manner currently ) to find the shortest path between all dots ( it 'd be neat if it was optimized & not accepting lines crossing among other stuff, but this is a very quick & dumb take on the travelling salesman problem or one of its derivative ? .. )
If someone want to have fun ,why not allowing to specify ( or not ) start and/or end points & then let the magic happen ?
so, the ( ugly ) code, enjoy ! :)
<!DOCTYPE html>
<!--
Created using JS Bin
http://jsbin.com
Copyright (c) 2019 by anonymous (http://jsbin.com/qawemovawa/1/edit)
Released under the MIT license: http://jsbin.mit-license.org
-->
<meta name="robots" content="noindex">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style id="jsbin-css">
[#canvas](http://forum.espruino.com/search/?q=%23canvas) {
/*
width: 160px;
height: 80px;
*/
border : 1px solid blue;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script id="jsbin-javascript">
// https://www.youtube.com/watch?v=BAejnwN4Ccw
// Coding Challenge #35.2: Lexicographic Order: https://www.youtube.com/watch?v=goUlyp4rwiU
// Coding Challenge #35.3: Traveling Salesperson with Lexicographic Order
// Coding Challenge #35.4: Traveling Salesperson with Genetic Algorithm
// Coding Challenge #35.4: Traveling Salesperson with Genetic Algorithm and Crossover: https://www.youtube.com/watch?v=hnxn6DtLYcY
var cnvs = document.querySelector('#canvas');
var ctx = cnvs.getContext('2d');
//cnvs.width = 160;
//cnvs.height = 80;
cnvs.width = 160*2;
cnvs.height = 80*2;
// draw dot helper
var drawDot = function(ctx, x, y, rad){
ctx.beginPath();
ctx.arc(x, y, rad, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
}
// coords array from Illustrator
/*
var coordsArr = [[38.6038818359375,-28.5126953125],[53.5712890625,-20.8525390625],[67.61376953125,-23.0546875],[83.61376953125,-28.2216796875],[99.447265625,-23.0546875],[113.6318359375,-20.9112854003906],[128.481628417969,-28.4538269042969],[128.457397460938,-47.0709228515625],[113.490051269531,-54.731201171875],[99.44775390625,-52.5283203125],[83.447509765625,-47.361328125],[67.61376953125,-52.5283203125],[53.4285278320312,-54.671875],[38.5792846679688,-47.12939453125]];
for(var i=0; i< coordsArr.length; i++){
drawDot(ctx, coordsArr[i][0], cnvs.height + coordsArr[i][1], 2);
}*/
/* ==== following the "coding train" ==== */
// swapping helper
function swap(a, i, j){
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
// distance calculation helper
function dist(p1x, p1y, p2x, p2y){
return Math.sqrt( Math.pow((p1x - p2x), 2) + Math.pow((p1y - p2y), 2) );
}
function calcDistance(points){
var sum = 0;
for(var i=0; i < points.length-1; i++){
var d = dist(points[i][0], points[i][1],
points[i+1][0], points[i+1][1]);
sum += d;
}
return sum;
}
var cities = [];
var totalCities = 10;
var recordDistance;
var bestEver;
function setup(){
/* -- random pts --
for(var i=0; i< totalCities; i++){
var v = [Math.random()*cnvs.width, Math.random()*cnvs.height];
//var v = [10, 10];
cities[i] = v;
}
*/
///* -- pts from Illu
// 1st arr is "manually optimized"
//var coordsArr = [[38.6038818359375,-28.5126953125],[53.5712890625,-20.8525390625],[67.61376953125,-23.0546875],[83.61376953125,-28.2216796875],[99.447265625,-23.0546875],[113.6318359375,-20.9112854003906],[128.481628417969,-28.4538269042969],[128.457397460938,-47.0709228515625],[113.490051269531,-54.731201171875],[99.44775390625,-52.5283203125],[83.447509765625,-47.361328125],[67.61376953125,-52.5283203125],[53.4285278320312,-54.671875],[38.5792846679688,-47.12939453125]];
// 2nd array is "intentionally un-optimized" of the 1st
var coordsArr = [[38.5792846679688,-47.12939453125],[53.5712890625,-20.8525390625],[67.61376953125,-23.0546875],[38.6038818359375,-28.5126953125],[99.447265625,-23.0546875],[83.61376953125,-28.2216796875],[113.6318359375,-20.9112854003906],[128.457397460938,-47.0709228515625],[67.61376953125,-52.5283203125],[113.490051269531,-54.731201171875],[99.44775390625,-52.5283203125],[128.481628417969,-28.4538269042969],[83.447509765625,-47.361328125],[53.4285278320312,-54.671875],];
for(var i=0; i< coordsArr.length; i++){
cities[i] = [coordsArr[i][0], cnvs.height + coordsArr[i][1]];
}
totalCities = cities.length;
//*/
//console.log(cities);
var d = calcDistance(cities);
recordDistance = d;
bestEver = cities.slice();
console.log('recordDistance: ' + recordDistance);
}
function draw(){
// redraw
requestAnimationFrame(draw);
//setTimeout(draw, 200);
//console.log('drawing ..');
//ctx.clearRect(0, 0, cnvs.width, cnvs.height);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, cnvs.width, cnvs.height);
// draw dots
ctx.strokeStyle = 'white';
ctx.fillStyle = 'white';
for(var i=0; i< totalCities; i++){
drawDot(ctx, cities[i][0], cities[i][1], 4);
}
// draw current cities liaisons
ctx.strokeStyle = 'white';
ctx.strokeWeight = 2;
ctx.beginPath();
// connect via lines
for(var i=0; i< totalCities-1; i++){
ctx.moveTo(cities[i][0], cities[i][1]);
ctx.lineTo(cities[i+1][0], cities[i+1][1]);
}
ctx.closePath();
ctx.stroke();
// draw best cities liaisons
ctx.strokeStyle = 'blue';
ctx.strokeWeight = 4;
ctx.beginPath();
// connect via lines
for(var i=0; i< totalCities-1; i++){
ctx.moveTo(bestEver[i][0], bestEver[i][1]);
ctx.lineTo(bestEver[i+1][0], bestEver[i+1][1]);
}
ctx.closePath();
ctx.stroke();
// swap things
var i = Math.floor( Math.random()*cities.length);
var j = Math.floor( Math.random()*cities.length);
//cities = swap(cities, i, j);
swap(cities, i, j);
var d = calcDistance(cities);
if(d < recordDistance){
recordDistance = d;
bestEver = cities.slice();
console.log('recordDistance: ' + recordDistance);
}
}
setup();
draw();
</script>
</body>
</html>
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
.. and the code that tries ( in a very dumb manner currently ) to find the shortest path between all dots ( it 'd be neat if it was optimized & not accepting lines crossing among other stuff, but this is a very quick & dumb take on the travelling salesman problem or one of its derivative ? .. )
If someone want to have fun ,why not allowing to specify ( or not ) start and/or end points & then let the magic happen ?
so, the ( ugly ) code, enjoy ! :)