Implementing k-Means Clustering From Scratch Using JavaScript

One rainy weekend, I decided to implement k-means data clustering from scratch using JavaScript. My original intention was to refactor one of my existing C# implementations, and that’s how I started out.

But I soon realized that, in the back of my mind for quite some time, I wasn’t completely satisfied with my existing implementations. They just didn’t feel right. The old implementations worked of course, but the program organization and details somehow bothered me.

And so I set out to implement k-means clustering using JavaScript without referring to any of my earlier implementations. Bottom line: I was very happy with the new version. It’s significantly simpler and easier to understand. Briefly, my older implementations looked like:

cluster():
loop trials times
  clustering = clusterOnce() (using inner loop maxIter times)
  track best clustering found
end-loop
return best clustering found

The modular approach, using functions clusterOnce() and cluster(), seems logical, but for various technical reasons, such as having to deal with multiple return values or out-parameters, the modular implementation is surprisingly tricky. My new approach ditches the modular organization, which somewhat paradoxically made the implementation simpler.

For my demo, I used one of my standard synthetic datasets. Each line represents are person. The raw data looks like:

F,short,24,arkansas,29500,liberal
M,tall,39,delaware,51200,moderate
F,short,63,colorado,75800,conservative
M,medium,36,illinois,44500,moderate
F,short,27,colorado,28600,liberal
. . .

The fields are sex, height, age, State (one of four), income, and political leaning (one of three). There are 240 data items. The k-means algorithm requires strictly numeric data so the raw data was encoded and normalized:

0.5, 0.25, 0.12, 0.25, 0.00, 0.00, 0.00, 0.1496, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.42, 0.00, 0.00, 0.25, 0.00, 0.5024, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.90, 0.00, 0.25, 0.00, 0.00, 0.9024, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.36, 0.00, 0.00, 0.00, 0.25, 0.3935, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.18, 0.00, 0.25, 0.00, 0.00, 0.1350, 0.0000, 0.0000, 0.3333
. . .

The sex variable is encoded as M = 0.0, F = 0.5. Height is equal-interval encoded as short = 0.25, medium = 0.50, tall = 0.75. Age is normalized by dividing by 100. State is one-over-n-hot encoded as Arkansas = (0.25 0 0 0) and so on. Income is normalized by dividing by 100,000. Political leaning is encoded using one-over-n-hot encoding as conservative = (0.3333 0 0) and so on.

The demo begins by loading the normalized and encoded data from file into memory:

function main()
{
  console.log("Begin k-means clustering w JavaScript ");
  let dataFile = ".\\Data\\people_normalized.txt";
  let X = loadTxt(dataFile, ",",
    [0,1,2,3,4,5,6,7,8,9,10], "#");
  console.log("\nX data: ");
  let decs = [1,2,2,2,2,2,2,4,4,4,4];
  matShow(X, decs, 4, true); // decs, 4 rows, indices
. . .

The KMeans object is instantiated and the data is clustered like so:

  // 2. instantiate KMeans object
  console.log("Clustering with k=3 ");
  let k = 3;
  let seed = 2;
  let km = new KMeans(k, seed);

  // 3. cluster
  km.cluster(X);
  console.log("Done ");
. . .

The clustering results are displayed:

  // 4. show results
  console.log("Clustering: ");
  vecShow(km.clustering);
. . .

The clustering results are:

Clustering:
 2 1 0 2 2 0 0 2 2 1 2 2 2 1 0 0 1 2 2 2
 0 1 0 0 2 0 0 0 2 0 1 1 2 2 0 0 1 1 1 2
 0 0 1 0 1 2 1 0 2 0 1 0 0 0 1 1 0 2 1 2
 2 0 0 0 0 1 2 0 1 0 2 1 0 2 2 2 0 0 1 0
 1 1 1 1 0 1 1 0 0 1 0 2 0 0 1 2 2 2 2 0
 2 0 2 0 1 0 2 1 0 0 2 1 2 2 0 1 0 1 2 2
 2 0 0 2 2 1 0 2 1 2 1 0 2 2 1 2 2 2 1 2
 0 2 1 1 0 1 2 1 0 0 2 0 2 1 2 2 1 0 2 0
 2 1 2 0 2 2 2 2 2 1 1 1 1 2 1 0 2 0 2 2
 2 0 0 1 0 1 0 2 1 1 2 1 1 1 1 1 2 0 2 0
 1 2 0 2 2 2 0 1 1 0 0 2 2 1 0 0 1 1 2 1
 1 2 1 2 1 0 1 1 1 1 2 1 2 2 1 2 2 2 2 1

Data item [0] is in cluster ID = 2, data item [1] is in cluster ID = 1, and so on.

The demo displays the resulting k=3 means and the within-cluster sum of squares (WCSS) measure of clustering goodness using these statements:

. . .
  console.log("Means: ");
  matShow(km.means, decs, k, true);

  console.log("WCSS: ");
  console.log(km.WCSS.toFixed(4).toString());

  console.log("End demo ");

The output is:

Means:
[  0]  0.5   0.32   0.69   0.07   0.08   0.05   0.05   0.6542   0.1576   0.1531   0.0225
[  1]  0.0   0.63   0.66   0.08   0.06   0.08   0.03   0.6758   0.0390   0.1645   0.1299
[  2]  0.3   0.40   0.19   0.09   0.06   0.09   0.02   0.2568   0.1049   0.1123   0.1161

WCSS:
49.3195

In my earlier implementations, I included a method to create a list of clustered data indexes. It makes more sense to ditch that because it’s simple to construct from the clustering array result. For example:

. . .
  // 5. construct clustered data indexes
  let clustered = [];
  for (let cid = 0; cid "lt" k; ++cid)
    clustered[cid] = [];
  for (let i = 0; i "lt" X.length; ++i) {
    let cid = km.clustering[i];
    clustered[cid].push(i.toString() + " ");
  }

  for (let cid = 0; cid "lt" k; ++cid) {
    console.log("cluster " + cid.toString() + ": ");
    vecShow(clustered[cid]);
  }
console.log("End demo ");

This code produces:

cluster 0:
 2  5  6 14 15 20 22 23 25 26 27 29 34 35 40 41 43 47 49 51
52 53 56 61 62 63 64 67 69 72 76 77 79 84 87 88 90 92 93 99
101 103 105 108 109 114 116 121 122 126 131 140 144 148 149 151 157 159 163 175
177 181 182 184 186 197 199 202 206 209 210 214 215 225

cluster 1:
 1  9 13 16 21 30 31 36 37 38 42 44 46 50 54 55 58 65 68 71
78 80 81 82 83 85 86 89 94 104 107 111 115 117 125 128 130 134 138 142
143 145 147 153 156 161 169 170 171 172 174 183 185 188 189 191 192 193 194 195
200 207 208 213 216 217 219 220 222 224 226 227 228 229 231 234 239

cluster 2:
 0  3  4  7  8 10 11 12 17 18 19 24 28 32 33 39 45 48 57 59
60 66 70 73 74 75 91 95 96 97 98 100 102 106 110 112 113 118 119 120
123 124 127 129 132 133 135 136 137 139 141 146 150 152 154 155 158 160 162 164
165 166 167 168 173 176 178 179 180 187 190 196 198 201 203 204 205 211 212 218
221 223 230 232 233 235 236 237 238

Good fun and a satisfying experience.



Because I grew up in the 1950s and 1960s, I was exposed to midcentury modern space age art. Although simple, the style is difficult to get right. Here is a cluster of three images that I think are nicely done.


Demo code. Replace “lt” (less than), “gt”, “lte”, “gte”, “and” with Boolean operator symbols (my blog editor chokes on symbols).

// kmeans.js
// node.js 16.14.1

let FS = require('fs');  // to read data file

// ----------------------------------------------------------

class KMeans
{
  constructor(k, seed)
  {
    this.nc = k;  // use "k" for indexing
    this.seed = seed + 0.5;  // avoid 0

    this.data;
    this.N;   // number data items
    this.dim; // number elements each item

    this.clustering;  // best found
    this.means;  // best found
    this.WCSS;  // best found
  }

  // --------------------------------------------------------

  cluster(data)
  {
    this.data = data;
    this.N = data.length;
    this.dim = data[0].length;

    this.clustering = this.vecMake(this.N, 0);
    this.means = this.matMake(this.nc, this.dim);
    this.WCSS = Number.MAX_VALUE; // absurdly large

    let trials = this.nc * 100;
    let maxIter = this.nc * 100;

    for (let t = 0; t "lt" trials; ++t) {
      // make a random partition clustering
      this.seed += t; // seed based on trial
      let currClustering = this.vecMake(this.N, 0);

      let cid = 0;
      for (let i = 0; i "lt" this.N; ++i) {
        currClustering[i] = cid++;  // 0,1,2,0,1,2..
        if (cid == this.nc) cid = 0;
      }
      
      // shuffle
      for (let i = 0; i "lt" this.N; ++i) {
        let r = this.nextInt(i, this.N); // Fisher-Yates
        let tmp = currClustering[i];
        currClustering[i] = currClustering[r];
        currClustering[r] = tmp;
      }

      // compute initial means from initial clustering
      let currMeans = this.matMake(this.nc, this.dim, 0);
      let counts = this.vecMake(this.nc, 0);
      for (let i = 0; i "lt" this.N; ++i) {
        let cid = currClustering[i];
        ++counts[cid];
        for (let j = 0; j "lt" this.dim; ++j) {
          currMeans[cid][j] += this.data[i][j];
        }
      }
      for (let k = 0; k "lt" this.nc; ++k) {
        for (let j = 0; j "lt" this.dim; ++j) {
          currMeans[k][j] /= counts[k];
        }
      }
      
      // cluster until no change, no 0-counts
      let iter = 0;
      while (iter "lt" maxIter) {
        ++iter;
        let ok = this.updateClustering(currClustering,
          currMeans);
        if (ok == false) break;  // no change or bad
        this.updateMeans(currMeans, currClustering);
      }

      // compute the WCSS of the clustering
      let currWCSS = 0.0;
      for (let i = 0; i "lt" this.N; ++i) {
        let cid = currClustering[i];
        let mean = currMeans[cid];
        for (let j = 0; j "lt" this.dim; ++j) {
          currWCSS += (this.data[i][j] - 
            currMeans[cid][j]) * (this.data[i][j] -
              currMeans[cid][j]);
        } 
      }

      // was a new best clustering found?
      // because initial WCSS so large, will hapen 
      // at least once
      if (currWCSS "lt" this.WCSS) {
        this.WCSS = currWCSS;
        for (let i = 0; i "lt" this.N; ++i) {
          this.clustering[i] = currClustering[i];
        }
        for (let k = 0; k "lt" this.nc; ++k) {
          for (let j = 0; j "lt" this.dim; ++j) {
            this.means[k][j] = currMeans[k][j];
          }
        }
      } // new best clustering

    } // trials
  } // cluster()

  // --------------------------------------------------------
  // primary workers: updateClustering(), updateMeans()
  // --------------------------------------------------------

  updateClustering(clustering, means)
  {
    // update clustering in-place using means
    // return true if a good new clustering produced
    // assumes no 0-counts

    // proposed new clustering
    let newClustering = this.vecMake(this.N, 0);

    // distance from an item to each mean
    let distances = this.vecMake(this.nc, 0.0); 
    for (let i = 0; i "lt" this.N; ++i) {
      for (let k = 0; k "lt" this.nc; ++k) {
        distances[k] = 
          this.eucDist(this.data[i], means[k]);
        let newClusterID = this.argMin(distances);
        newClustering[i] = newClusterID;
      }
    }
    // was there a change in clustering?
    if (this.areEqual(clustering, newClustering) == true) {
      return false;  // no change so done
    }
    // does new clustering create a 0-count?
    let counts = this.vecMake(this.nc, 0);
    for (let i = 0; i "lt" this.N; ++i) {
      ++counts[newClustering[i]];
    }
    for (let k = 0; k "lt" this.nc; ++k) {
      if (counts[k] == 0) {
        return false;  // exit out
      }
    }
    // there was a change and no 0-counts so update in-place
    for (let i = 0; i "lt" this.N; ++i) {
      clustering[i] = newClustering[i];
    }
    return true;
  }

  // --------------------------------------------------------

  updateMeans(means, clustering)
  {
    // update means in-place using clustering
    let newMeans = this.matMake(this.nc, this.dim, 0.0);
    let counts = this.vecMake(this.nc, 0);
    for (let i = 0; i "lt" this.N; ++i) {
      let cid = clustering[i];
      ++counts[cid];
      for (let j = 0; j "lt" this.dim; ++j) {
        newMeans[cid][j] += this.data[i][j];
      }
    }
    for (let k = 0; k "lt" this.nc; ++k) {
      for (let j = 0; j "lt" this.dim; ++j) {
        if (counts[k] == 0) console.log("***** FATAL *** ");
        newMeans[k][j] /= counts[k];
      }
    }   

    for (let k = 0; k "lt" this.nc; ++k) {
      for (let j = 0; j "lt" this.dim; ++j) {
        means[k][j] = newMeans[k][j];
      }
    }
  }

  // --------------------------------------------------------
  // helpers: eucDist(), argMin(), areEqual(), matMake(), 
  // vecMake(), nextDouble(), nextInt()
  // --------------------------------------------------------

  eucDist(v1, v2)
  {
    let sum = 0.0;
    for (let i = 0; i "lt" v1.length; ++i) {
      sum += (v1[i] - v2[i]) * (v1[i] - v2[i]);
    }
    return Math.sqrt(sum);
  }

  // --------------------------------------------------------

  argMin(v)
  {
    let minVal = v[0];
    let minIdx = 0;
    for (let i = 0; i "lt" v.length; ++i) {
      if (v[i] "lt" minVal){
        minVal = v[i];
        minIdx = i;
      }
    }
    return minIdx;
  }

  // --------------------------------------------------------

  areEqual(v1, v2)
  {
    for (let i = 0; i "lt" v1.length; ++i) {
      if (v1[i] != v2[i]) {
        return false;
      }
    }
    return true;
  }

  // --------------------------------------------------------

  matMake(rows, cols, val)
  {
    let result = [];
    for (let i = 0; i "lt" rows; ++i) {
      result[i] = [];
      for (let j = 0; j "lt" cols; ++j) {
        result[i][j] = val;
      }
    }
    return result;
  }

  // --------------------------------------------------------

  vecMake(n, val)
  {
    let result = [];
    for (let i = 0; i "lt" n; ++i) {
      result[i] = val;
    }
    return result;
  }

  // --------------------------------------------------------

  nextDouble() // next double
  {
    // semi-sort-of random
    let x = Math.sin(this.seed) * 1000;
    let result = x - Math.floor(x);  // [0.0,1.0)
    this.seed = result;  // for next call
    return result;
  }

  // --------------------------------------------------------

  nextInt(lo, hi)
  {
    let x = this.nextDouble();
    return Math.trunc((hi - lo) * x + lo);
  }

  // --------------------------------------------------------

} // class KMeans

// ----------------------------------------------------------
// helpers for main(): loadTxt(), vecShow(), matShow()
// ----------------------------------------------------------

function loadTxt(fn, delimit, usecols, comment) 
{
  // efficient but mildly complicated
  let all = FS.readFileSync(fn, "utf8");  // giant string
  all = all.trim();  // strip final crlf in file
  let lines = all.split("\n");  // array of lines

  // count number non-comment lines
  let nRows = 0;
  for (let i = 0; i "lt" lines.length; ++i) {
    if (!lines[i].startsWith(comment))
      ++nRows;
  }
  nCols = usecols.length;
  let result = [];
  for (let i = 0; i "lt" nRows; ++i) {
    result[i] = [];
    for (let j = 0; j "lt" nCols; ++j) {
      result[i][j] = 0.0;
    }
  }
  
  let r = 0;  // into lines
  let i = 0;  // into result[][]
  while (r "lt" lines.length) {
    if (lines[r].startsWith(comment)) {
      ++r;  // next row
    }
    else {
      let tokens = lines[r].split(delimit);
      for (let j = 0; j "lt" nCols; ++j) {
        result[i][j] = parseFloat(tokens[usecols[j]]);
      }
      ++r;
      ++i;
    }
  }

  // if just 1 col, convert matrix result to vector
  if (usecols.length == 1) {
    let vecResult = [];
    let k = 0;
    for (let i = 0; i "lt" nRows; ++i) {
      for (let j = 0; j "lt" nCols; ++j) {
        vecResult[k++] = result[i][j];
      }
    }
    return vecResult;
  }

  return result;
} // loadTxt()

// ----------------------------------------------------------

function vecShow(v)
{
  for (let i = 0; i "lt" v.length; ++i) {
    if (i "gt" 0 "and" i % 20 == 0) console.log("");
    process.stdout.write(v[i].toString().padStart(3));
  }
  process.stdout.write("\n");
}

function matShow(m, decs, numRows, showIndices)
{
  // let rows = m.length;
  // let cols = m[0].length;
  for (let i = 0; i "lt" numRows; ++i) {
    if (showIndices == true)
      process.stdout.write("[" + i.toString().
        padStart(3, ' ') + "] ");
    for (let j = 0; j "lt" m[0].length; ++j) {
      let v = m[i][j];
      if (Math.abs(v) "lt" 1.0e-8) v = 0.0  // avoid -0
      let vv = v.toFixed(decs[j]);
      let s = vv.toString().padStart(decs[j]+3, ' ');
      process.stdout.write(s);
      process.stdout.write("  ");
    }
    process.stdout.write("\n");
  }
  if (numRows "lt" m.length) console.log(". . .");
}

// ----------------------------------------------------------

function main()
{
  console.log("\nBegin k-means clustering w JavaScript ");

  // 1. load normalized data from file into memory
  // sex, height, age, State(4), income, politics(3)
  console.log("\nLoading normalized people data ");
  let dataFile = ".\\Data\\people_normalized.txt";
  let X = loadTxt(dataFile, ",",
    [0,1,2,3,4,5,6,7,8,9,10], "#");
  console.log("\nX data: ");
  let decs = [1,2,2,2,2,2,2,4,4,4,4];
  matShow(X, decs, 4, true); // decs, 4 rows, indices

  // 2. instantiate KMeans object
  console.log("\nClustering with k=3 ");
  let k = 3;
  let seed = 2;
  let km = new KMeans(k, seed);

  // 3. cluster
  km.cluster(X);
  console.log("Done ");

  // 4. show results
  console.log("\nClustering: ");
  vecShow(km.clustering);

  console.log("\nMeans: ");
  matShow(km.means, decs, k, true);

  console.log("\nWCSS: ");
  console.log(km.WCSS.toFixed(4).toString());

  console.log("\nEnd demo ");
}

// ----------------------------------------------------------

main();

Data:

# people_normalized.txt
#
# sex (M = 0.0, F = 0.5)
# height (short = 0.25, medium = 0.50, tall = 0.75)
# age (min = 18, max = 68)
# State [Arkansas = (0.25 0 0 0), Colorado = (0 0.25 0 0),
#   Delaware (0 0 0.25 0), Illinois (0 0 0 0.25)]
# income (min = 20,300.00 max = 81,800.00)
# politics [(conservative = 0.3333 0 0), moderate (0 0.3333 0),
#   liberal (0 0 0.3333)]
# 
0.5, 0.25, 0.12, 0.25, 0.00, 0.00, 0.00, 0.1496, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.42, 0.00, 0.00, 0.25, 0.00, 0.5024, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.90, 0.00, 0.25, 0.00, 0.00, 0.9024, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.36, 0.00, 0.00, 0.00, 0.25, 0.3935, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.18, 0.00, 0.25, 0.00, 0.00, 0.1350, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.64, 0.00, 0.25, 0.00, 0.00, 0.5886, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.64, 0.00, 0.00, 0.00, 0.25, 0.5642, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.02, 0.00, 0.00, 0.25, 0.00, 0.2016, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.08, 0.00, 0.00, 0.00, 0.25, 0.1203, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.42, 0.00, 0.00, 0.25, 0.00, 0.4358, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.32, 0.25, 0.00, 0.00, 0.00, 0.3106, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.08, 0.00, 0.00, 0.00, 0.25, 0.2146, 0.3333, 0.0000, 0.0000
0.5, 0.50, 0.34, 0.00, 0.00, 0.25, 0.00, 0.2423, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.30, 0.00, 0.25, 0.00, 0.00, 0.4244, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.54, 0.00, 0.25, 0.00, 0.00, 0.5496, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.48, 0.00, 0.00, 0.00, 0.25, 0.4943, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.30, 0.00, 0.25, 0.00, 0.00, 0.4309, 0.0000, 0.3333, 0.0000
0.5, 0.75, 0.14, 0.00, 0.00, 0.25, 0.00, 0.1577, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.26, 0.00, 0.25, 0.00, 0.00, 0.4244, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.18, 0.25, 0.00, 0.00, 0.00, 0.1984, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.60, 0.00, 0.00, 0.00, 0.25, 0.5480, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.92, 0.00, 0.00, 0.00, 0.25, 0.8293, 0.0000, 0.0000, 0.3333
0.5, 0.50, 0.86, 0.00, 0.25, 0.00, 0.00, 0.8472, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.72, 0.00, 0.00, 0.00, 0.25, 0.6618, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.22, 0.25, 0.00, 0.00, 0.00, 0.2602, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.64, 0.00, 0.00, 0.25, 0.00, 0.5642, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.74, 0.00, 0.00, 0.00, 0.25, 0.6862, 0.3333, 0.0000, 0.0000
0.5, 0.50, 0.44, 0.00, 0.00, 0.00, 0.25, 0.5220, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.08, 0.25, 0.00, 0.00, 0.00, 0.0537, 0.0000, 0.0000, 0.3333
0.5, 0.25, 1.00, 0.00, 0.25, 0.00, 0.00, 0.9447, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.84, 0.00, 0.00, 0.00, 0.25, 0.8358, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.32, 0.00, 0.00, 0.25, 0.00, 0.4260, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.14, 0.00, 0.00, 0.25, 0.00, 0.2732, 0.3333, 0.0000, 0.0000
0.0, 0.25, 0.26, 0.00, 0.00, 0.00, 0.25, 0.4650, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.50, 0.00, 0.00, 0.25, 0.00, 0.4504, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.80, 0.00, 0.25, 0.00, 0.00, 0.7333, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.74, 0.00, 0.00, 0.00, 0.25, 0.6569, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.50, 0.00, 0.25, 0.00, 0.00, 0.5008, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.50, 0.00, 0.00, 0.25, 0.00, 0.5350, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.06, 0.25, 0.00, 0.00, 0.00, 0.2748, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.74, 0.00, 0.00, 0.25, 0.00, 0.7203, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.92, 0.00, 0.25, 0.00, 0.00, 0.8862, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.46, 0.00, 0.00, 0.00, 0.25, 0.6260, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.92, 0.00, 0.00, 0.25, 0.00, 0.8520, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.76, 0.00, 0.00, 0.00, 0.25, 0.7528, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.26, 0.00, 0.00, 0.25, 0.00, 0.2553, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.94, 0.00, 0.00, 0.25, 0.00, 0.8098, 0.0000, 0.0000, 0.3333
0.5, 0.75, 0.74, 0.00, 0.00, 0.00, 0.25, 0.7154, 0.3333, 0.0000, 0.0000
0.0, 0.25, 0.14, 0.25, 0.00, 0.00, 0.00, 0.3252, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.56, 0.00, 0.00, 0.25, 0.00, 0.4992, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.36, 0.00, 0.00, 0.00, 0.25, 0.5398, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.68, 0.00, 0.00, 0.00, 0.25, 0.6146, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.86, 0.00, 0.00, 0.25, 0.00, 0.7740, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.78, 0.00, 0.00, 0.25, 0.00, 0.7382, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.56, 0.00, 0.25, 0.00, 0.00, 0.5252, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.88, 0.25, 0.00, 0.00, 0.00, 0.7561, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.74, 0.00, 0.00, 0.00, 0.25, 0.6894, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.08, 0.00, 0.00, 0.25, 0.00, 0.1203, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.64, 0.00, 0.00, 0.00, 0.25, 0.6927, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.28, 0.00, 0.00, 0.00, 0.25, 0.3496, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.06, 0.00, 0.00, 0.25, 0.00, 0.2488, 0.3333, 0.0000, 0.0000
0.5, 0.50, 0.52, 0.00, 0.25, 0.00, 0.00, 0.5154, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.56, 0.00, 0.00, 0.00, 0.25, 0.5106, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.88, 0.00, 0.25, 0.00, 0.00, 0.8033, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.78, 0.00, 0.00, 0.00, 0.25, 0.7496, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.98, 0.00, 0.00, 0.00, 0.25, 0.9024, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.22, 0.25, 0.00, 0.00, 0.00, 0.2276, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.70, 0.00, 0.00, 0.00, 0.25, 0.6472, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.52, 0.25, 0.00, 0.00, 0.00, 0.5610, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.56, 0.00, 0.25, 0.00, 0.00, 0.5203, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.04, 0.00, 0.00, 0.00, 0.25, 0.1593, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.40, 0.00, 0.00, 0.00, 0.25, 0.5398, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.64, 0.00, 0.25, 0.00, 0.00, 0.6228, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.30, 0.00, 0.25, 0.00, 0.00, 0.3610, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.30, 0.00, 0.25, 0.00, 0.00, 0.3089, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.16, 0.00, 0.25, 0.00, 0.00, 0.3268, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.80, 0.25, 0.00, 0.00, 0.00, 0.8195, 0.3333, 0.0000, 0.0000
0.5, 0.75, 0.50, 0.00, 0.00, 0.00, 0.25, 0.4504, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.56, 0.25, 0.00, 0.00, 0.00, 0.7171, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.84, 0.25, 0.00, 0.00, 0.00, 0.8358, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.48, 0.25, 0.00, 0.00, 0.00, 0.4650, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.76, 0.00, 0.00, 0.25, 0.00, 0.5870, 0.0000, 0.0000, 0.3333
0.0, 0.25, 0.88, 0.00, 0.25, 0.00, 0.00, 0.7480, 0.0000, 0.0000, 0.3333
0.0, 0.25, 0.64, 0.25, 0.00, 0.00, 0.00, 0.7236, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.58, 0.00, 0.00, 0.00, 0.25, 0.5154, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.98, 0.00, 0.25, 0.00, 0.00, 0.9772, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.44, 0.00, 0.00, 0.25, 0.00, 0.4894, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.48, 0.00, 0.25, 0.00, 0.00, 0.4569, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.92, 0.25, 0.00, 0.00, 0.00, 0.8407, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.58, 0.25, 0.00, 0.00, 0.00, 0.6244, 0.0000, 0.0000, 0.3333
0.5, 0.50, 0.54, 0.00, 0.25, 0.00, 0.00, 0.5285, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.14, 0.00, 0.00, 0.25, 0.00, 0.3350, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.40, 0.25, 0.00, 0.00, 0.00, 0.4569, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.74, 0.00, 0.00, 0.25, 0.00, 0.6455, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.52, 0.25, 0.00, 0.00, 0.00, 0.6553, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.30, 0.25, 0.00, 0.00, 0.00, 0.3366, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.32, 0.00, 0.00, 0.25, 0.00, 0.3041, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.18, 0.00, 0.25, 0.00, 0.00, 0.2179, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.28, 0.00, 0.25, 0.00, 0.00, 0.3317, 0.0000, 0.3333, 0.0000
0.5, 0.75, 0.48, 0.00, 0.00, 0.00, 0.25, 0.4341, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.12, 0.00, 0.00, 0.25, 0.00, 0.3252, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.48, 0.00, 0.25, 0.00, 0.00, 0.4878, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.14, 0.00, 0.00, 0.25, 0.00, 0.1252, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.66, 0.00, 0.25, 0.00, 0.00, 0.6130, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.74, 0.00, 0.25, 0.00, 0.00, 0.7024, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.52, 0.25, 0.00, 0.00, 0.00, 0.4472, 0.0000, 0.0000, 0.3333
0.0, 0.25, 0.00, 0.25, 0.00, 0.00, 0.00, 0.3171, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.98, 0.00, 0.25, 0.00, 0.00, 0.8341, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.54, 0.00, 0.00, 0.25, 0.00, 0.4829, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.60, 0.25, 0.00, 0.00, 0.00, 0.5772, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.14, 0.00, 0.25, 0.00, 0.00, 0.3041, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.98, 0.25, 0.00, 0.00, 0.00, 0.9431, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.38, 0.00, 0.00, 0.25, 0.00, 0.3528, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.28, 0.25, 0.00, 0.00, 0.00, 0.3642, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.60, 0.25, 0.00, 0.00, 0.00, 0.5967, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.96, 0.00, 0.00, 0.25, 0.00, 0.8894, 0.0000, 0.0000, 0.3333
0.5, 0.75, 0.86, 0.25, 0.00, 0.00, 0.00, 0.8081, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.80, 0.00, 0.00, 0.25, 0.00, 0.7902, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.02, 0.25, 0.00, 0.00, 0.00, 0.0602, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.40, 0.00, 0.00, 0.25, 0.00, 0.3691, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.18, 0.25, 0.00, 0.00, 0.00, 0.2618, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.48, 0.25, 0.00, 0.00, 0.00, 0.4504, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.84, 0.25, 0.00, 0.00, 0.00, 0.8293, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.18, 0.00, 0.00, 0.25, 0.00, 0.2358, 0.3333, 0.0000, 0.0000
0.5, 0.75, 0.22, 0.00, 0.25, 0.00, 0.00, 0.2732, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.50, 0.25, 0.00, 0.00, 0.00, 0.5919, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.60, 0.25, 0.00, 0.00, 0.00, 0.5919, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.18, 0.00, 0.00, 0.25, 0.00, 0.1480, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.52, 0.25, 0.00, 0.00, 0.00, 0.5675, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.10, 0.00, 0.25, 0.00, 0.00, 0.0976, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.36, 0.00, 0.25, 0.00, 0.00, 0.5317, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.92, 0.00, 0.00, 0.25, 0.00, 0.8488, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.22, 0.00, 0.00, 0.25, 0.00, 0.1577, 0.0000, 0.0000, 0.3333
0.0, 0.25, 0.30, 0.25, 0.00, 0.00, 0.00, 0.4715, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.96, 0.00, 0.25, 0.00, 0.00, 0.8894, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.06, 0.00, 0.00, 0.25, 0.00, 0.2276, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.18, 0.25, 0.00, 0.00, 0.00, 0.2016, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.22, 0.25, 0.00, 0.00, 0.00, 0.1870, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.26, 0.25, 0.00, 0.00, 0.00, 0.4602, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.36, 0.00, 0.00, 0.25, 0.00, 0.3366, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.62, 0.00, 0.25, 0.00, 0.00, 0.5756, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.20, 0.25, 0.00, 0.00, 0.00, 0.2943, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.50, 0.00, 0.00, 0.25, 0.00, 0.5902, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.56, 0.00, 0.25, 0.00, 0.00, 0.6260, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.78, 0.25, 0.00, 0.00, 0.00, 0.8049, 0.3333, 0.0000, 0.0000
0.0, 0.25, 0.68, 0.00, 0.00, 0.25, 0.00, 0.6358, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.26, 0.00, 0.00, 0.25, 0.00, 0.3772, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.74, 0.25, 0.00, 0.00, 0.00, 0.6780, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.64, 0.25, 0.00, 0.00, 0.00, 0.5870, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.60, 0.00, 0.25, 0.00, 0.00, 0.5789, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.08, 0.00, 0.00, 0.25, 0.00, 0.2309, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.82, 0.00, 0.00, 0.25, 0.00, 0.7545, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.32, 0.25, 0.00, 0.00, 0.00, 0.3659, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.92, 0.25, 0.00, 0.00, 0.00, 0.9252, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.22, 0.00, 0.00, 0.25, 0.00, 0.2146, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.32, 0.00, 0.25, 0.00, 0.00, 0.3724, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.86, 0.25, 0.00, 0.00, 0.00, 0.8894, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.92, 0.00, 0.00, 0.25, 0.00, 0.8260, 0.3333, 0.0000, 0.0000
0.0, 0.25, 0.22, 0.25, 0.00, 0.00, 0.00, 0.3415, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.90, 0.00, 0.25, 0.00, 0.00, 0.8179, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.22, 0.00, 0.25, 0.00, 0.00, 0.3203, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.66, 0.25, 0.00, 0.00, 0.00, 0.6894, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.12, 0.00, 0.00, 0.25, 0.00, 0.2829, 0.3333, 0.0000, 0.0000
0.5, 0.50, 0.60, 0.00, 0.25, 0.00, 0.00, 0.6049, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.00, 0.25, 0.00, 0.00, 0.00, 0.1154, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.00, 0.25, 0.00, 0.00, 0.00, 0.0000, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.30, 0.00, 0.25, 0.00, 0.00, 0.2911, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.04, 0.00, 0.00, 0.25, 0.00, 0.2358, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.22, 0.00, 0.00, 0.25, 0.00, 0.2065, 0.0000, 0.0000, 0.3333
0.0, 0.25, 0.52, 0.00, 0.00, 0.25, 0.00, 0.6943, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.94, 0.00, 0.00, 0.25, 0.00, 1.0000, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.76, 0.25, 0.00, 0.00, 0.00, 0.7057, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.68, 0.00, 0.00, 0.25, 0.00, 0.6195, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.22, 0.00, 0.25, 0.00, 0.00, 0.4602, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.58, 0.00, 0.25, 0.00, 0.00, 0.6276, 0.0000, 0.3333, 0.0000
0.5, 0.50, 1.00, 0.25, 0.00, 0.00, 0.00, 0.8504, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.26, 0.00, 0.00, 0.25, 0.00, 0.2553, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.86, 0.00, 0.25, 0.00, 0.00, 0.6862, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.02, 0.00, 0.25, 0.00, 0.00, 0.0195, 0.0000, 0.0000, 0.3333
0.5, 0.75, 0.40, 0.00, 0.00, 0.25, 0.00, 0.3691, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.16, 0.25, 0.00, 0.00, 0.00, 0.3577, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.86, 0.00, 0.25, 0.00, 0.00, 0.7659, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.44, 0.25, 0.00, 0.00, 0.00, 0.4260, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.62, 0.25, 0.00, 0.00, 0.00, 0.7301, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.76, 0.25, 0.00, 0.00, 0.00, 0.7675, 0.3333, 0.0000, 0.0000
0.0, 0.25, 0.60, 0.00, 0.25, 0.00, 0.00, 0.7431, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.68, 0.25, 0.00, 0.00, 0.00, 0.5854, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.00, 0.25, 0.00, 0.00, 0.00, 0.1545, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.76, 0.00, 0.00, 0.25, 0.00, 0.6341, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.68, 0.00, 0.25, 0.00, 0.00, 0.7171, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.00, 0.00, 0.25, 0.00, 0.00, 0.1350, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.80, 0.25, 0.00, 0.00, 0.00, 0.7463, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.42, 0.00, 0.25, 0.00, 0.00, 0.5659, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.56, 0.25, 0.00, 0.00, 0.00, 0.6927, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.44, 0.00, 0.25, 0.00, 0.00, 0.4211, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.84, 0.25, 0.00, 0.00, 0.00, 0.8520, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.36, 0.00, 0.25, 0.00, 0.00, 0.3317, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.52, 0.25, 0.00, 0.00, 0.00, 0.5203, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.20, 0.25, 0.00, 0.00, 0.00, 0.1789, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.72, 0.00, 0.00, 0.25, 0.00, 0.6878, 0.3333, 0.0000, 0.0000
0.0, 0.50, 0.66, 0.25, 0.00, 0.00, 0.00, 0.6650, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.28, 0.00, 0.25, 0.00, 0.00, 0.4195, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.74, 0.25, 0.00, 0.00, 0.00, 0.6894, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.14, 0.00, 0.00, 0.25, 0.00, 0.0959, 0.0000, 0.0000, 0.3333
0.5, 0.50, 0.30, 0.00, 0.00, 0.25, 0.00, 0.2764, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.22, 0.00, 0.25, 0.00, 0.00, 0.4211, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.94, 0.25, 0.00, 0.00, 0.00, 0.8520, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.50, 0.00, 0.25, 0.00, 0.00, 0.5057, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.72, 0.00, 0.25, 0.00, 0.00, 0.7236, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.86, 0.00, 0.25, 0.00, 0.00, 0.8520, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.68, 0.00, 0.25, 0.00, 0.00, 0.7041, 0.3333, 0.0000, 0.0000
0.5, 0.25, 0.24, 0.00, 0.25, 0.00, 0.00, 0.2146, 0.0000, 0.0000, 0.3333
0.5, 0.25, 0.22, 0.25, 0.00, 0.00, 0.00, 0.1805, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.58, 0.00, 0.00, 0.25, 0.00, 0.6358, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.42, 0.00, 0.25, 0.00, 0.00, 0.4472, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.58, 0.00, 0.00, 0.25, 0.00, 0.5154, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.62, 0.25, 0.00, 0.00, 0.00, 0.6228, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.90, 0.00, 0.00, 0.25, 0.00, 0.7659, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.24, 0.25, 0.00, 0.00, 0.00, 0.3073, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.86, 0.00, 0.00, 0.25, 0.00, 0.8016, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.58, 0.00, 0.00, 0.25, 0.00, 0.6244, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.24, 0.00, 0.00, 0.25, 0.00, 0.2309, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.66, 0.00, 0.00, 0.25, 0.00, 0.6130, 0.0000, 0.3333, 0.0000
0.0, 0.50, 0.12, 0.25, 0.00, 0.00, 0.00, 0.3008, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.62, 0.25, 0.00, 0.00, 0.00, 0.7187, 0.0000, 0.3333, 0.0000
0.5, 0.50, 0.96, 0.00, 0.00, 0.25, 0.00, 0.8813, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.94, 0.25, 0.00, 0.00, 0.00, 0.9203, 0.3333, 0.0000, 0.0000
0.0, 0.25, 0.56, 0.00, 0.25, 0.00, 0.00, 0.6130, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.54, 0.00, 0.00, 0.25, 0.00, 0.5122, 0.0000, 0.3333, 0.0000
0.0, 0.25, 0.58, 0.25, 0.00, 0.00, 0.00, 0.7041, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.22, 0.25, 0.00, 0.00, 0.00, 0.3984, 0.3333, 0.0000, 0.0000
0.0, 0.75, 0.78, 0.00, 0.00, 0.25, 0.00, 0.7967, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.04, 0.25, 0.00, 0.00, 0.00, 0.1366, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.34, 0.25, 0.00, 0.00, 0.00, 0.3756, 0.0000, 0.3333, 0.0000
0.0, 0.75, 0.86, 0.00, 0.00, 0.25, 0.00, 0.7593, 0.0000, 0.0000, 0.3333
0.0, 0.25, 0.26, 0.00, 0.00, 0.25, 0.00, 0.2764, 0.0000, 0.3333, 0.0000
0.5, 0.25, 0.00, 0.25, 0.00, 0.00, 0.00, 0.0081, 0.0000, 0.0000, 0.3333
0.5, 0.50, 0.16, 0.00, 0.00, 0.25, 0.00, 0.1447, 0.0000, 0.0000, 0.3333
0.0, 0.50, 0.20, 0.25, 0.00, 0.00, 0.00, 0.2618, 0.0000, 0.0000, 0.3333
0.0, 0.75, 0.82, 0.00, 0.00, 0.25, 0.00, 0.7984, 0.0000, 0.0000, 0.3333
This entry was posted in JavaScript, Machine Learning. Bookmark the permalink.

1 Response to Implementing k-Means Clustering From Scratch Using JavaScript

  1. Vignes Anbah's avatar Vignes Anbah says:

    recoding because “it did not feel right”
    Ahh this is how Leonardo da Vinci must have thought!
    Thank you for your work

Comments are closed.