Basic k-nearest-neighbour

by Scott Kaye

JavaScript

// Small function to convert things like #ff00ff or #f0f to [255, 0, 255]
const hexToRgb = hex => {
  hex = hex.replace(/#/,"");
  if (!(hex.length - 3)) hex = [...hex].map(c => c + c).join("");
  return hex
    .match(/[a-f0-9]{2}/gi)
    .map(n => parseInt(n, 16));
};

class KNN {
	constructor() {
  	this.nodes = [];
  };
  
  normalize() {
  	let values = [];
    
    // Load all values from each cell into an array
    this.nodes.forEach(node => {
    	node.in.forEach((v, i) => {
      	if (!values[i]) values[i] = [];
      	values[i].push(v);
      });
    });
    
    // Find maximum and minimum values in each cell
    this.maxes = values.map(arr => Math.max.apply(Math.max, arr));
    this.mins = values.map(arr => Math.min.apply(Math.min, arr));
    
    // Normalize each cell in each node
    this.nodes.forEach(node => {
    	node.normalized = node.in.map((v, i) => (v / this.maxes[i]) + this.mins[i]);
    });
  };

	// Can call train([ array of objects with in and out keys ]) or train(input, output)
  train(nodes, out) {
  	if (out === undefined) {
			this.nodes.push.apply(this.nodes, nodes);
			this.normalize();
    }
    else {
    	this.nodes.push({
      	in: nodes,
        out: out
      });
      this.normalize();
    }
  };
  
  solve(problem, sweetSpot = 0.15) {
  	// Normalize problem
    let normalizedProblem = problem.map((v, i) => (v / this.maxes[i]) + this.mins[i]);
  
  	// Calculate match of normalized problem with each normalized node
    // The "match" value here is an arbitrary meaningless score; higher number = better match
    // A match of 0 means no points were lost, and is the highest score possible.
    let newNodes = this.nodes.map(node => {
    	node.match = 0;
      normalizedProblem.forEach((v, i) => {
      	let diff = node.normalized[i] - v;
      	node.match += diff < sweetSpot ? diff : -diff;
      });
      
    	return node;
    });
    
    // Sort by match rating (higher is better)
    newNodes.sort((a, b) => {
    	if...