Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save biancadanforth/574b5745553a1b93cff70699c9d5a11f to your computer and use it in GitHub Desktop.
Save biancadanforth/574b5745553a1b93cff70699c9d5a11f to your computer and use it in GitHub Desktop.
Algorithms Coursera Part III Programming Assignment 2.js
/* eslint-env node */
/* eslint-disable object-property-newline */
/**
* -------------------------- Part 1 -----------------------------
*/
/**
* In this programming problem and the next you'll code up the clustering
* algorithm from lecture for computing a max-spacing k-clustering.
*
* Download the text file below (clustering1.txt).
* (too large to copy in a gist: https://d18ky98rnyall9.cloudfront.net/_fe8d0202cd20a808db6a4d5d06be62f4_clustering1.txt?Expires=1552262400&Signature=LBSww0uBFDiF9-t4C~W-UWeq0eWUQxWb5Xg8wyQMAVKIbbZ62iXVMk05LiLWAusZ77zowkGNRjucYcWnRzcQhXG1O1E~XBW0OItQhjNlQtlR5ooCNKJJBljtXEN-NZke9kJW3QVjUaQZ6eC60rAENgNSEHjbng3Swf3FOEx~vRM_&Key-Pair-Id=APKAJLTNE6QMUY6HBC5A)
*
* This file describes a distance function (equivalently, a complete graph
* with edge costs). It has the following format:
*
* [number_of_nodes]
* [edge 1 node 1] [edge 1 node 2] [edge 1 cost]
* [edge 2 node 1] [edge 2 node 2] [edge 2 cost]
* ...
*
* There is one edge (i,j) for each choice of 1 ≤ i < j ≤ n where n is the
* number of nodes.
*
* For example, the third line of the file is "1 3 5250", indicating that
* the distance between nodes 1 and 3 (equivalently, the cost of the edge
* (1,3)) is 5250. You can assume that distances are positive, but you should
* NOT assume that they are distinct.
*
* Your task in this problem is to run the clustering algorithm from lecture
* on this data set, where the target number k of clusters is set to 4.
* What is the maximum spacing of a 4-clustering?
*
* ADVICE: If you're not getting the correct answer, try debugging your
* algorithm using some small test cases. And then post them to the discussion
* forum!
*
* Test cases from:
* https://github.com/beaunus/stanford-algs/tree/master/testCases/course3/assignment2Clustering/question1
*
* Clarification on what is meant by maximum spacing: this is the MINIMUM
* distance between the closest two separated nodes (i.e. after we have
* out k clusters, what is the minimum distance between any two nodes in
* different clusters). It is known as the "maximum spacing", as we want
* to maximize this minimum value and keep the clusters as far apart as possible.
*/
/**
* -------------------------- FILE I/O -----------------------------
*/
const fs = require("fs");
const edgesList = [];
// Map of node => list of incident edges to that node (array of
// {node, distance} objects)
const nodeVsIncidentEdges = new Map();
let numNodes;
/**
* Parse the text file and store it as an Array of objects of the form:
* [
* {p, q, distance},
* ...
* ]
*/
(function getInput() {
const data = fs.readFileSync("clustering1.txt", "utf8");
const rows = data.split("\n");
for (let row of rows) {
// Don't include the first row, which is the total number of nodes
if (row === rows[0]) {
numNodes = Number(row);
continue;
}
// Get rid of empty row at EOF
if (row === "") {
continue;
}
// Remove excess white space at the end of the line
row = row.trim();
// Break each row into a tuple of integers
row = row.split(" ");
const [p, q, distance] = [
Number(row[0]), Number(row[1]), Number(row[2])
];
// I don't need to de-dupe, since the assignment says: "There is one
// edge (i,j) for each choice of 1 ≤ i < j ≤ n where n is the number
// of nodes." i.e. if I get a (1, 348) I will not find a (348, 1)
// in the text file.
edgesList.push({
p,
q,
distance,
});
if (nodeVsIncidentEdges.has(p)) {
nodeVsIncidentEdges.get(p).push({node: q, distance});
} else {
nodeVsIncidentEdges.set(p, [{node: q, distance}]);
}
if (nodeVsIncidentEdges.has(q)) {
nodeVsIncidentEdges.get(q).push({node: p, distance});
} else {
nodeVsIncidentEdges.set(q, [{node: p, distance}]);
}
}
}());
// console.log(nodeVsIncidentEdges);
// Sort distances from biggest to smallest, since we will ultimately be fusing
// together the closest separated pairs of nodes, and Array.pop is more
// efficient than Array.shift to get the next min-distance edge to process.
edgesList.sort((a, b) => {
return b.distance - a.distance;
});
// Maintain map of cluster ID => list of nodes; needed for fusing two clusters
// together
const clusterIdVsNodesList = new Map();
// Maintain map of node => clusterID to see if p and q are separate
const nodeVsClusterId = new Map();
for (let i = 1; i <= numNodes; i++) {
clusterIdVsNodesList.set(i, [i]);
nodeVsClusterId.set(i, i);
}
/**
* -------------------- Single-Link Clustering Algorithm -----------------------
*/
// NOTE: TRY USING CHROME DEVTOOLS DEBUGGER:
// https://medium.com/@paul_irish/debugging-node-js-nightlies-with-chrome-devtools-7c4a1b95ae27
/**
* k = 4
* Pseudocode for Part 1
* 1. Initialize each point to its own cluster
* 2. While # clusters > k (stop before the final k - 1 edge additions)
* - Take the closest pair of separated nodes p, q, and...(how to break ties?)
* - separated means the pair are not in the same cluster already
* - Fuse them into the same cluster
*/
function getMaxSpacingForKClustering(k = 4) {
let numClusters = numNodes;
// Cluster nodes until there are k clusters
while (numClusters > k) {
for (let i = 0; i < edgesList.length; i++) {
// Get the next closest pair of points, p and q
const {p, q} = edgesList.pop();
// Find which cluster they are in
const pClusterId = nodeVsClusterId.get(p);
const qClusterId = nodeVsClusterId.get(q);
// Fuse q's into p's cluster if they're not in the same cluster
if (pClusterId !== qClusterId) {
const nodesInPCluster = clusterIdVsNodesList.get(pClusterId);
const nodesInQCluster = clusterIdVsNodesList.get(qClusterId);
for (const node of nodesInQCluster) {
nodeVsClusterId.set(node, pClusterId);
}
clusterIdVsNodesList.set(
pClusterId, nodesInPCluster.concat(nodesInQCluster)
);
clusterIdVsNodesList.delete(qClusterId);
numClusters--;
break;
}
}
}
// Get max spacing between nodes in different clusters (really the
// minimum distance between any two nodes in different clusters)
let maxSpacing = +Infinity;
for (const nodesList of Array.from(clusterIdVsNodesList.values())) {
for (const nodeMember of nodesList) {
// get incident edges
const incidentEdges = nodeVsIncidentEdges.get(nodeMember);
for (const {node, distance} of incidentEdges) {
if (!nodesList.includes(node) && distance < maxSpacing) {
// nodes are in separate clusters, and we have a new max spacing
maxSpacing = distance;
}
}
}
}
return maxSpacing;
}
console.log("maxSpacing: ", getMaxSpacingForKClustering());
// Solutions:
// testCase1.txt: 21
// testCase2.txt: 218
// testCase3.txt: 1245
// clustering1.txt: 106
/* eslint-env node */
/* eslint-disable object-property-newline */
/**
* -------------------------- Part 2 -----------------------------
*/
/**
* In this question your task is again to run the clustering algorithm
* from lecture, but on a MUCH bigger graph. So big, in fact, that the
* distances (i.e., edge costs) are only defined implicitly, rather than
* being provided as an explicit list.
*
* The data set is below (clustering_big.txt).
*
* The format is:
* [# of nodes] [# of bits for each node's label]
* [first bit of node 1] ... [last bit of node 1]
* [first bit of node 2] ... [last bit of node 2]
* ...
*
* For example, the third line of the file
* "0 1 1 0 0 1 1 0 0 1 0 1 1 1 1 1 1 0 1 0 1 1 0 1" denotes the 24 bits
* associated with node #2.
*
* The distance between two nodes u and v in this problem is defined as
* the Hamming distance--- the number of differing bits --- between the two
* nodes' labels. For example, the Hamming distance between the 24-bit label
* of node #2 above and the label
* "0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1" is 3 (since they differ
* in the 3rd, 7th, and 21st bits).
*
* The question is: what is the largest value of k such that there is a
* k-clustering with spacing at least 3? That is, how many clusters are
* needed to ensure that no pair of nodes with all but 2 bits in common get
* split into different clusters?
*
* NOTE: The graph implicitly defined by the data file is so big that you
* probably can't write it out explicitly, let alone sort the edges by cost.
* So you will have to be a little creative to complete this part of the
* question. For example, is there some way you can identify the smallest
* distances without explicitly looking at every pair of nodes?
*
* Approach by another student: https://www.coursera.org/learn/algorithms-greedy/discussions/weeks/2/threads/OctNCeS_Eeao1BJzfLTSbg/replies/czz9DuUrEeaikxICfuhamA
*
* Test cases from:
* https://github.com/beaunus/stanford-algs/tree/master/testCases/course3/assignment2Clustering/question2
*
* Clarification on what is meant by maximum spacing: this is the MINIMUM
* distance between the closest two separated nodes (i.e. after we have
* out k clusters, what is the minimum distance between any two nodes in
* different clusters). It is known as the "maximum spacing", as we want
* to maximize this minimum value and keep the clusters as far apart as possible.
*/
/**
* -------------------------- FILE I/O -----------------------------
*/
const fs = require("fs");
let numNodes;
let numBits;
const codeVsDistances = new Map();
// "code" here refers to the 24-bit string representing each node; there can
// be multiple nodes with the same code, so map is a string => Array.integer
const codeVsNodesList = new Map();
// Maintain map of cluster ID => list of nodes; needed for fusing two clusters
// together
const clusterIdVsNodesList = new Map();
// Maintain map of node => clusterID to see if p and q are separate
const nodeVsClusterId = new Map();
const codesList = [];
/**
* Parse the text file.
*
* For each vertex, generate and store all Hamming distances that are 0, 1 and 2
* units apart. There is only 1 code point that is 0 units apart (which is the
* same code as the vertex), 24C1 = 24 possible code points that are 1 unit apart
* and there are 24C2 = 276 possible code points that are 2 units apart for each
* vertex.
* This will take the form of a hash table (Map, `codeVsDistances`) of
* vertex => Array.array, where the 0th element array is the list of values that
* are 0 units apart, the 1st element array is the list of values that are 1
* unit apart, and the 2nd element in the array is the list of values that are
* 2 units apart.
*
* Also, put all vertexes along with their assigned code into a hash table. Use
* the code as the hash table key, with the vertex number as the value - note
* that some codes are not unique (i.e. more than one vertex can be associated
* with the same code), so each key in the hash table will have to potentially
* hold more than one vertex - we will use this hash table later to look up the
* vertex number(s) given the corresponding Hamming code in O(1) time.
* This will take the form of a hash table (Map, `codeVsNodesList`) of
* string => Array.integer, where the key is the 24-bit string representing each
* node and the value is a list of node #s with the same string code.
*/
(function getInput() {
const data = fs.readFileSync("clustering_big.txt", "utf8");
const rows = data.split("\n");
let nodeNum = 1;
for (let row of rows) {
// Don't include the first row, which is the total number of nodes
if (row === rows[0]) {
[numNodes, numBits] = row.split(" ");
[numNodes, numBits] = [Number(numNodes), Number(numBits)];
continue;
}
// Get rid of empty row at EOF
if (row === "") {
continue;
}
// Remove excess white space at the end of the line
row = row.trim();
// Remove spaces in between digits
row = row.replace(/\s/g, "");
// Generate and store all Hamming distances that are 0, 1 and 2 units apart
const listZeroUnitsApart = [row]; // Only 1 node label 0 units apart, itself
const listOneUnitsApart = []; // 24 choose 1 node (24) labels 1 unit apart
for (let i = 0; i < numBits; i++) {
const replacement = row[i] === "0" ? "1" : "0";
const variant = row.slice(0, i) + replacement
+ row.slice(i + replacement.length);
listOneUnitsApart.push(variant);
}
const listTwoUnitsApart = []; // 24 choose 2 node (276) labels 2 units apart
for (let j = 0; j < numBits; j++) {
for (let k = 0; k < numBits; k++) {
if (k === j) continue; // We have to change two different bits
const jReplacement = row[j] === "0" ? "1" : "0";
const kReplacement = row[k] === "0" ? "1" : "0";
let variant = row.slice(0, j) + jReplacement
+ row.slice(j + jReplacement.length);
variant = variant.slice(0, k) + kReplacement
+ variant.slice(k + kReplacement.length);
if (!(listTwoUnitsApart.includes(variant))) {
listTwoUnitsApart.push(variant);
}
}
}
codeVsDistances.set(row, [
listZeroUnitsApart,
listOneUnitsApart,
listTwoUnitsApart,
]);
if (codeVsNodesList.has(row)) {
codeVsNodesList.get(row).push(nodeNum);
} else {
codeVsNodesList.set(row, [nodeNum]);
}
// All nodes start out in their own cluster
clusterIdVsNodesList.set(nodeNum, new Set([nodeNum]));
nodeVsClusterId.set(nodeNum, nodeNum);
codesList.push(row);
nodeNum++;
}
}());
// console.log(codeVsDistances);
// console.log(codeVsNodesList);
// console.log(clusterIdVsNodesList);
// console.log(codesList);
/**
* -------------------- Clustering Algorithm -----------------------
*/
// NOTE: TRY USING CHROME DEVTOOLS DEBUGGER:
// https://medium.com/@paul_irish/debugging-node-js-nightlies-with-chrome-devtools-7c4a1b95ae27
/**
* Pseudocode for Part 2
* For each vertex (200K iterations):
* For each code that is 0 units apart from
* this vertex: (1 iteration - there is only one such code
* which is the same code as that of the vertex itself)
* - Use the code to index into the hash table and
* get the corresponding vertexes if they exist.
* - Add these 2 vertexes to a cluster.
*
* For each vertex (200K iterations):
* For each code that is 1 unit apart from
* this vertex: (24 iterations)
* - Use the code to index into the hash table and
* get the corresponding vertexes if they exist.
* - Add these 2 vertexes to a cluster.
*
*For each vertex (200K iterations):
* For each code that is 2 units apart from
* this vertex: (276 iterations)
* - Use the code to index into the hash table and
* get the corresponding vertexes if they exist.
* - Add these 2 vertexes to a cluster.
*
*You are now left with clusters that are at least 3 units apart.
*
* Explanation of pseudocode:
* In the first loop, we are essentially clustering all vertexes
* that are a distance of 0 units apart, in the second loop and
* third loop we are clustering vertexes that are 1 unit apart,
* and 2 units apart respectively (this is similar to sorting by
* edge weights and then combining the vertexes into clusters).
* The above code can be made much more compact - I have split up
* the three main loops for readability.
*
* The time complexity of the above is 200k + (200k * 24)
* + (200k * 276) = 200k * 301 = O(301n) iterations, plus for each
* iteration, we have to fix up the leader pointers of the smaller
* cluster - which gives us a final complexity of O(301nlog n).
* The space complexity is about O(301n).
*/
function updateClusters(node, potentialMatchingCodes) {
for (const potentialMatchingCode of potentialMatchingCodes) {
const potentialMatchingNodes = codeVsNodesList.get(potentialMatchingCode);
if (potentialMatchingNodes) {
const matchingNodes = potentialMatchingNodes; // rename for accuracy
for (const matchingNode of matchingNodes) {
const nodeClusterId = nodeVsClusterId.get(node);
const matchingNodeClusterId = nodeVsClusterId.get(matchingNode);
if (nodeClusterId !== matchingNodeClusterId) {
// Nodes are in separate clusters, fuse their cluster's together
// (fuse the smaller one into the bigger one)
const nodeClusterSize = clusterIdVsNodesList.get(nodeClusterId).size;
const matchingNodeClusterSize = clusterIdVsNodesList.get(matchingNodeClusterId).size;
if (nodeClusterSize >= matchingNodeClusterSize) {
// node's cluster absorbs matching node's cluster
const nodesToUpdate = clusterIdVsNodesList.get(matchingNodeClusterId);
for (const nodeToUpdate of nodesToUpdate) {
nodeVsClusterId.set(nodeToUpdate, nodeClusterId);
clusterIdVsNodesList.delete(matchingNodeClusterId);
clusterIdVsNodesList.get(nodeClusterId).add(nodeToUpdate);
}
} else {
// matching node's cluster absorbs node's cluster
const nodesToUpdate = clusterIdVsNodesList.get(nodeClusterId);
for (const nodeToUpdate of nodesToUpdate) {
nodeVsClusterId.set(nodeToUpdate, matchingNodeClusterId);
clusterIdVsNodesList.delete(nodeClusterId);
clusterIdVsNodesList.get(matchingNodeClusterId).add(nodeToUpdate);
}
}
}
}
}
}
}
function getNumClusters() {
// Clustering all vertices that are a distance of 0 units apart
for (const nodesList of Array.from(codeVsNodesList.values())) {
if (nodesList.length > 1) {
// The first entry will be our leader node <=> clusterId
const clusterId = nodesList[0];
// Fuse all of these nodes into the same cluster and update bookkeeping
for (const node of nodesList) {
// Don't overwrite the leader node's entry
if (node === nodesList[0]) continue;
clusterIdVsNodesList.get(clusterId).add(node);
const oldClusterId = nodeVsClusterId.get(node);
clusterIdVsNodesList.delete(oldClusterId);
nodeVsClusterId.set(node, clusterId);
}
}
}
// Clustering all vertices that are a distance of 1 units apart
let node = 1;
for (const code of codesList) {
const potentialMatchingCodes = codeVsDistances.get(code)[1];
updateClusters(node, potentialMatchingCodes);
node++;
}
// Clustering all vertices that are a distance of 2 units apart
node = 1;
for (const code of codesList) {
const potentialMatchingCodes = codeVsDistances.get(code)[2];
updateClusters(node, potentialMatchingCodes);
node++;
}
return Array.from(clusterIdVsNodesList.keys()).length;
}
console.log(getNumClusters());
// Solutions:
// testCase1.txt: 11
// testCase2.txt: 15
// clustering_big.txt: 6118 (took 10 minutes && had to increase V8 memory in node with `node --max-old-space-size=8192 <path/to/file>`)
8
1 2 32
1 3 46
1 4 50
1 5 57
1 6 57
1 7 32
1 8 51
2 3 50
2 4 35
2 5 1
2 6 17
2 7 56
2 8 19
3 4 21
3 5 22
3 6 42
3 7 29
3 8 44
4 5 27
4 6 38
4 7 25
4 8 18
5 6 6
5 7 53
5 8 9
6 7 27
6 8 22
7 8 46
64
1 2 908
1 3 2580
1 4 2040
1 5 1102
1 6 1736
1 7 517
1 8 624
1 9 703
1 10 231
1 11 3516
1 12 570
1 13 2298
1 14 2407
1 15 4009
1 16 3105
1 17 2090
1 18 3914
1 19 2085
1 20 501
1 21 2176
1 22 4071
1 23 12
1 24 1223
1 25 372
1 26 1487
1 27 2974
1 28 1338
1 29 2486
1 30 2959
1 31 3478
1 32 2460
1 33 2706
1 34 2562
1 35 3976
1 36 3885
1 37 456
1 38 539
1 39 2810
1 40 269
1 41 2773
1 42 2595
1 43 3268
1 44 3115
1 45 1014
1 46 1611
1 47 3078
1 48 4060
1 49 518
1 50 2302
1 51 2295
1 52 1499
1 53 3111
1 54 3232
1 55 3351
1 56 2365
1 57 2090
1 58 2812
1 59 3855
1 60 1762
1 61 3621
1 62 2660
1 63 1176
1 64 643
2 3 724
2 4 1240
2 5 775
2 6 2918
2 7 782
2 8 4076
2 9 4028
2 10 3548
2 11 1689
2 12 1115
2 13 2926
2 14 800
2 15 372
2 16 3971
2 17 3387
2 18 1372
2 19 3244
2 20 2021
2 21 2352
2 22 2414
2 23 2067
2 24 1762
2 25 2939
2 26 392
2 27 1799
2 28 1761
2 29 1408
2 30 3897
2 31 4080
2 32 354
2 33 1142
2 34 1776
2 35 3327
2 36 703
2 37 2152
2 38 695
2 39 623
2 40 2230
2 41 1185
2 42 2644
2 43 1335
2 44 3242
2 45 2458
2 46 2497
2 47 1222
2 48 1015
2 49 263
2 50 1312
2 51 3037
2 52 401
2 53 851
2 54 1986
2 55 738
2 56 2647
2 57 1462
2 58 3372
2 59 1492
2 60 2562
2 61 2557
2 62 3205
2 63 3689
2 64 3309
3 4 3535
3 5 1926
3 6 3240
3 7 1789
3 8 1329
3 9 1107
3 10 348
3 11 2466
3 12 3078
3 13 1078
3 14 1490
3 15 3145
3 16 3348
3 17 43
3 18 3628
3 19 1776
3 20 4008
3 21 2388
3 22 2416
3 23 141
3 24 461
3 25 1135
3 26 1132
3 27 4001
3 28 407
3 29 4049
3 30 417
3 31 1095
3 32 1385
3 33 1646
3 34 1269
3 35 2761
3 36 2016
3 37 2669
3 38 1568
3 39 3758
3 40 1118
3 41 371
3 42 1159
3 43 1543
3 44 2291
3 45 794
3 46 770
3 47 424
3 48 3060
3 49 3216
3 50 1554
3 51 134
3 52 386
3 53 2130
3 54 613
3 55 1002
3 56 2570
3 57 2314
3 58 3617
3 59 1052
3 60 1763
3 61 203
3 62 3652
3 63 3467
3 64 1049
4 5 1405
4 6 2474
4 7 1931
4 8 3750
4 9 3462
4 10 550
4 11 372
4 12 2166
4 13 977
4 14 290
4 15 3651
4 16 2232
4 17 1037
4 18 2662
4 19 2081
4 20 2101
4 21 3851
4 22 3002
4 23 2827
4 24 1860
4 25 2195
4 26 3247
4 27 355
4 28 555
4 29 835
4 30 2339
4 31 841
4 32 4028
4 33 1370
4 34 3541
4 35 1544
4 36 3603
4 37 3492
4 38 1457
4 39 2812
4 40 1036
4 41 2816
4 42 3599
4 43 1381
4 44 747
4 45 1583
4 46 4042
4 47 1385
4 48 1553
4 49 2538
4 50 774
4 51 3810
4 52 4093
4 53 334
4 54 28
4 55 228
4 56 3202
4 57 2789
4 58 1338
4 59 3160
4 60 543
4 61 3788
4 62 943
4 63 3640
4 64 2093
5 6 2317
5 7 1905
5 8 3911
5 9 4007
5 10 395
5 11 2434
5 12 1042
5 13 3801
5 14 2708
5 15 307
5 16 2409
5 17 1317
5 18 117
5 19 1734
5 20 438
5 21 3728
5 22 509
5 23 1023
5 24 1072
5 25 3000
5 26 3954
5 27 1669
5 28 1405
5 29 2243
5 30 3657
5 31 2262
5 32 3650
5 33 113
5 34 3840
5 35 3741
5 36 3300
5 37 2945
5 38 1520
5 39 895
5 40 1548
5 41 316
5 42 1564
5 43 1423
5 44 3513
5 45 1510
5 46 3399
5 47 1985
5 48 1058
5 49 1558
5 50 3792
5 51 374
5 52 17
5 53 3803
5 54 1035
5 55 1027
5 56 721
5 57 3639
5 58 1030
5 59 341
5 60 3298
5 61 4092
5 62 699
5 63 3804
5 64 1854
6 7 3847
6 8 270
6 9 884
6 10 3336
6 11 3151
6 12 3832
6 13 2020
6 14 1542
6 15 3053
6 16 1127
6 17 301
6 18 3670
6 19 1099
6 20 981
6 21 1107
6 22 1253
6 23 71
6 24 1937
6 25 2681
6 26 3084
6 27 3376
6 28 1158
6 29 2432
6 30 3832
6 31 1694
6 32 663
6 33 224
6 34 3074
6 35 2870
6 36 3979
6 37 512
6 38 1937
6 39 2429
6 40 746
6 41 3443
6 42 988
6 43 2083
6 44 1742
6 45 3143
6 46 2734
6 47 3687
6 48 1595
6 49 1839
6 50 1179
6 51 1690
6 52 2303
6 53 320
6 54 1306
6 55 2647
6 56 3504
6 57 132
6 58 718
6 59 2208
6 60 3339
6 61 1678
6 62 3897
6 63 3494
6 64 2744
7 8 1129
7 9 1181
7 10 1851
7 11 3319
7 12 1769
7 13 3499
7 14 2603
7 15 3543
7 16 2825
7 17 564
7 18 3327
7 19 2973
7 20 2535
7 21 1575
7 22 3218
7 23 353
7 24 1679
7 25 3443
7 26 1016
7 27 3938
7 28 2177
7 29 3908
7 30 662
7 31 27
7 32 1894
7 33 73
7 34 2632
7 35 3470
7 36 140
7 37 2028
7 38 2621
7 39 2032
7 40 201
7 41 3649
7 42 3972
7 43 2688
7 44 1460
7 45 1566
7 46 962
7 47 2411
7 48 3953
7 49 138
7 50 422
7 51 2536
7 52 2422
7 53 346
7 54 1133
7 55 1301
7 56 2851
7 57 433
7 58 3776
7 59 3751
7 60 3102
7 61 2372
7 62 1196
7 63 2326
7 64 3150
8 9 3361
8 10 3450
8 11 1050
8 12 3213
8 13 494
8 14 3741
8 15 137
8 16 3998
8 17 2283
8 18 3300
8 19 799
8 20 108
8 21 1324
8 22 322
8 23 1481
8 24 3679
8 25 3530
8 26 3005
8 27 407
8 28 2030
8 29 2945
8 30 3370
8 31 1568
8 32 1068
8 33 1511
8 34 3191
8 35 3961
8 36 2967
8 37 3853
8 38 1629
8 39 1790
8 40 2107
8 41 2837
8 42 2783
8 43 3105
8 44 2694
8 45 93
8 46 3110
8 47 785
8 48 156
8 49 3702
8 50 3437
8 51 3458
8 52 3410
8 53 3224
8 54 3503
8 55 1905
8 56 1391
8 57 2565
8 58 42
8 59 1656
8 60 573
8 61 380
8 62 292
8 63 842
8 64 2409
9 10 589
9 11 1369
9 12 366
9 13 744
9 14 3646
9 15 2302
9 16 966
9 17 2809
9 18 2535
9 19 3794
9 20 3796
9 21 3970
9 22 3893
9 23 3186
9 24 3706
9 25 1767
9 26 2999
9 27 3553
9 28 965
9 29 3284
9 30 3689
9 31 3731
9 32 3209
9 33 4048
9 34 3394
9 35 3666
9 36 2306
9 37 1918
9 38 1608
9 39 2682
9 40 2693
9 41 1752
9 42 1274
9 43 511
9 44 3064
9 45 1448
9 46 637
9 47 2288
9 48 1615
9 49 2726
9 50 797
9 51 321
9 52 2739
9 53 3449
9 54 3798
9 55 4088
9 56 2323
9 57 1703
9 58 685
9 59 3043
9 60 1763
9 61 816
9 62 218
9 63 679
9 64 1871
10 11 1880
10 12 2480
10 13 2468
10 14 2134
10 15 3137
10 16 3947
10 17 148
10 18 142
10 19 589
10 20 1199
10 21 3931
10 22 3823
10 23 900
10 24 2308
10 25 1435
10 26 2015
10 27 909
10 28 2920
10 29 2501
10 30 3271
10 31 3252
10 32 1388
10 33 3691
10 34 191
10 35 2579
10 36 2233
10 37 1925
10 38 66
10 39 2347
10 40 1935
10 41 3523
10 42 210
10 43 2182
10 44 3885
10 45 3560
10 46 2173
10 47 2615
10 48 2574
10 49 446
10 50 3821
10 51 2742
10 52 1798
10 53 3687
10 54 542
10 55 1428
10 56 2191
10 57 4092
10 58 1811
10 59 3153
10 60 3616
10 61 2790
10 62 972
10 63 1937
10 64 3683
11 12 1067
11 13 2978
11 14 3721
11 15 1364
11 16 1286
11 17 2914
11 18 2750
11 19 3759
11 20 732
11 21 1187
11 22 3196
11 23 2256
11 24 2293
11 25 591
11 26 2959
11 27 1580
11 28 2899
11 29 1946
11 30 3006
11 31 3470
11 32 1580
11 33 2208
11 34 2559
11 35 189
11 36 401
11 37 3924
11 38 1352
11 39 3919
11 40 3336
11 41 3245
11 42 1684
11 43 2958
11 44 1110
11 45 587
11 46 2403
11 47 1191
11 48 4023
11 49 4014
11 50 1685
11 51 3333
11 52 2769
11 53 908
11 54 226
11 55 225
11 56 3890
11 57 1
11 58 931
11 59 2358
11 60 4083
11 61 1984
11 62 1489
11 63 574
11 64 53
12 13 1206
12 14 4091
12 15 1073
12 16 836
12 17 3294
12 18 1484
12 19 1764
12 20 748
12 21 1785
12 22 2904
12 23 3395
12 24 3492
12 25 2837
12 26 1811
12 27 709
12 28 2417
12 29 1471
12 30 3884
12 31 475
12 32 2047
12 33 1950
12 34 719
12 35 1317
12 36 825
12 37 3208
12 38 3164
12 39 1910
12 40 1218
12 41 831
12 42 4080
12 43 817
12 44 2372
12 45 2052
12 46 2915
12 47 3505
12 48 3511
12 49 3352
12 50 1486
12 51 865
12 52 2675
12 53 2016
12 54 3995
12 55 1370
12 56 1665
12 57 62
12 58 2374
12 59 1992
12 60 2846
12 61 1819
12 62 1113
12 63 393
12 64 2125
13 14 2773
13 15 2425
13 16 979
13 17 1152
13 18 1724
13 19 3554
13 20 1760
13 21 2591
13 22 1836
13 23 3012
13 24 486
13 25 123
13 26 2527
13 27 3778
13 28 7
13 29 2198
13 30 3200
13 31 3478
13 32 3831
13 33 2705
13 34 633
13 35 1521
13 36 456
13 37 2618
13 38 2695
13 39 1373
13 40 1754
13 41 3292
13 42 3507
13 43 909
13 44 3127
13 45 1835
13 46 2138
13 47 1087
13 48 226
13 49 491
13 50 509
13 51 1596
13 52 646
13 53 1637
13 54 48
13 55 837
13 56 986
13 57 2740
13 58 925
13 59 1886
13 60 2977
13 61 2488
13 62 1164
13 63 683
13 64 2328
14 15 992
14 16 2405
14 17 3381
14 18 3726
14 19 1083
14 20 3235
14 21 2501
14 22 124
14 23 2252
14 24 832
14 25 483
14 26 2139
14 27 8
14 28 3080
14 29 3071
14 30 3720
14 31 2745
14 32 3655
14 33 1850
14 34 245
14 35 1230
14 36 3562
14 37 3376
14 38 3847
14 39 2554
14 40 375
14 41 2918
14 42 3056
14 43 269
14 44 2407
14 45 3298
14 46 1821
14 47 2966
14 48 1642
14 49 1577
14 50 39
14 51 1913
14 52 383
14 53 1554
14 54 3821
14 55 113
14 56 2881
14 57 918
14 58 2855
14 59 2216
14 60 3826
14 61 174
14 62 2034
14 63 832
14 64 1538
15 16 1707
15 17 722
15 18 451
15 19 1761
15 20 399
15 21 1359
15 22 4086
15 23 370
15 24 248
15 25 3705
15 26 2880
15 27 1450
15 28 1255
15 29 3957
15 30 3334
15 31 2044
15 32 408
15 33 2340
15 34 3542
15 35 575
15 36 2709
15 37 663
15 38 3815
15 39 1392
15 40 3420
15 41 3696
15 42 3046
15 43 2514
15 44 1995
15 45 29
15 46 3672
15 47 518
15 48 2627
15 49 1592
15 50 3586
15 51 1619
15 52 1045
15 53 3652
15 54 2612
15 55 3921
15 56 2959
15 57 2391
15 58 1348
15 59 1359
15 60 1450
15 61 229
15 62 2936
15 63 2865
15 64 824
16 17 3473
16 18 3955
16 19 2999
16 20 2648
16 21 3133
16 22 3464
16 23 2849
16 24 986
16 25 2426
16 26 1985
16 27 2262
16 28 1976
16 29 3196
16 30 3018
16 31 3031
16 32 3160
16 33 1421
16 34 3511
16 35 1638
16 36 1211
16 37 1817
16 38 1612
16 39 2035
16 40 3206
16 41 2418
16 42 3527
16 43 15
16 44 2431
16 45 4075
16 46 3718
16 47 3458
16 48 1806
16 49 1497
16 50 638
16 51 2308
16 52 2603
16 53 800
16 54 2374
16 55 694
16 56 1701
16 57 1423
16 58 3632
16 59 3629
16 60 3752
16 61 3631
16 62 4021
16 63 3920
16 64 3074
17 18 29
17 19 2841
17 20 2593
17 21 2559
17 22 2196
17 23 781
17 24 1440
17 25 3375
17 26 1388
17 27 2840
17 28 3618
17 29 1358
17 30 3340
17 31 3879
17 32 233
17 33 233
17 34 3166
17 35 574
17 36 1505
17 37 2627
17 38 3357
17 39 3334
17 40 4080
17 41 1472
17 42 3646
17 43 2483
17 44 1122
17 45 498
17 46 2582
17 47 3339
17 48 539
17 49 641
17 50 227
17 51 3925
17 52 409
17 53 549
17 54 973
17 55 326
17 56 3695
17 57 1069
17 58 1648
17 59 2906
17 60 2161
17 61 1734
17 62 2986
17 63 1173
17 64 1240
18 19 273
18 20 338
18 21 2922
18 22 3289
18 23 2673
18 24 3571
18 25 1260
18 26 1203
18 27 937
18 28 2330
18 29 2001
18 30 2100
18 31 2177
18 32 2502
18 33 4043
18 34 3888
18 35 1514
18 36 1566
18 37 228
18 38 745
18 39 3033
18 40 2506
18 41 2518
18 42 2527
18 43 2360
18 44 594
18 45 3295
18 46 2338
18 47 3756
18 48 1317
18 49 306
18 50 804
18 51 1270
18 52 2514
18 53 2905
18 54 3915
18 55 2395
18 56 3735
18 57 3811
18 58 1231
18 59 638
18 60 1267
18 61 3107
18 62 1822
18 63 1708
18 64 3881
19 20 1220
19 21 3572
19 22 2326
19 23 1605
19 24 3118
19 25 1764
19 26 2341
19 27 1242
19 28 677
19 29 1150
19 30 2808
19 31 2807
19 32 2407
19 33 648
19 34 2211
19 35 45
19 36 3710
19 37 445
19 38 498
19 39 1721
19 40 228
19 41 1235
19 42 3601
19 43 3019
19 44 3787
19 45 3768
19 46 1663
19 47 3814
19 48 2440
19 49 833
19 50 3389
19 51 2231
19 52 1137
19 53 3175
19 54 1545
19 55 3365
19 56 1074
19 57 3471
19 58 2973
19 59 1272
19 60 1325
19 61 3863
19 62 3824
19 63 1949
19 64 3721
20 21 3860
20 22 94
20 23 2782
20 24 2033
20 25 3741
20 26 3127
20 27 3034
20 28 210
20 29 784
20 30 3321
20 31 3485
20 32 1891
20 33 2662
20 34 2452
20 35 3882
20 36 1777
20 37 2496
20 38 3032
20 39 2468
20 40 2856
20 41 3718
20 42 910
20 43 3045
20 44 3862
20 45 3875
20 46 2608
20 47 2751
20 48 1496
20 49 3335
20 50 518
20 51 116
20 52 519
20 53 1591
20 54 2856
20 55 1370
20 56 3072
20 57 2766
20 58 1583
20 59 3576
20 60 1382
20 61 3375
20 62 3272
20 63 650
20 64 3292
21 22 2433
21 23 43
21 24 3651
21 25 620
21 26 1433
21 27 620
21 28 2008
21 29 1574
21 30 839
21 31 3782
21 32 3095
21 33 1576
21 34 2453
21 35 3362
21 36 1974
21 37 3555
21 38 65
21 39 3619
21 40 3797
21 41 2111
21 42 673
21 43 2310
21 44 421
21 45 1161
21 46 3395
21 47 2411
21 48 3132
21 49 3873
21 50 3021
21 51 316
21 52 1693
21 53 3239
21 54 2473
21 55 1438
21 56 3041
21 57 3824
21 58 3076
21 59 1801
21 60 890
21 61 140
21 62 3367
21 63 2744
21 64 1539
22 23 3251
22 24 3708
22 25 2312
22 26 603
22 27 620
22 28 2972
22 29 4038
22 30 1358
22 31 1609
22 32 3783
22 33 1456
22 34 214
22 35 3596
22 36 2011
22 37 4022
22 38 637
22 39 2067
22 40 1935
22 41 1481
22 42 1505
22 43 2639
22 44 2482
22 45 1429
22 46 1261
22 47 2461
22 48 2371
22 49 1573
22 50 4027
22 51 3724
22 52 2452
22 53 2175
22 54 1869
22 55 3
22 56 3959
22 57 1576
22 58 2193
22 59 3619
22 60 3421
22 61 1752
22 62 262
22 63 1191
22 64 2807
23 24 1567
23 25 203
23 26 232
23 27 1584
23 28 1408
23 29 2802
23 30 229
23 31 1424
23 32 2702
23 33 2204
23 34 1386
23 35 3988
23 36 371
23 37 4047
23 38 2179
23 39 3287
23 40 1302
23 41 2944
23 42 1443
23 43 3309
23 44 3516
23 45 1458
23 46 3412
23 47 1604
23 48 1400
23 49 2263
23 50 1686
23 51 2283
23 52 2409
23 53 386
23 54 1102
23 55 2812
23 56 1156
23 57 2560
23 58 703
23 59 1586
23 60 243
23 61 375
23 62 2973
23 63 954
23 64 2190
24 25 3354
24 26 853
24 27 1344
24 28 3691
24 29 300
24 30 683
24 31 1966
24 32 1170
24 33 3688
24 34 1386
24 35 61
24 36 2040
24 37 6
24 38 1863
24 39 346
24 40 2830
24 41 3396
24 42 503
24 43 2332
24 44 2014
24 45 3543
24 46 1737
24 47 2848
24 48 3196
24 49 3019
24 50 2556
24 51 2198
24 52 1763
24 53 1428
24 54 661
24 55 2916
24 56 3668
24 57 619
24 58 3601
24 59 1808
24 60 641
24 61 2548
24 62 1466
24 63 3014
24 64 3568
25 26 3028
25 27 1139
25 28 1449
25 29 3628
25 30 3066
25 31 3265
25 32 1133
25 33 588
25 34 1969
25 35 2642
25 36 2340
25 37 109
25 38 130
25 39 115
25 40 2772
25 41 580
25 42 2388
25 43 1105
25 44 2539
25 45 2168
25 46 1592
25 47 3290
25 48 1369
25 49 3451
25 50 2728
25 51 2176
25 52 613
25 53 868
25 54 2130
25 55 76
25 56 562
25 57 1180
25 58 1363
25 59 2830
25 60 3918
25 61 3416
25 62 1854
25 63 3013
25 64 2213
26 27 2424
26 28 2436
26 29 1490
26 30 929
26 31 3088
26 32 1890
26 33 1100
26 34 702
26 35 3897
26 36 3389
26 37 3447
26 38 3222
26 39 3355
26 40 2163
26 41 3435
26 42 814
26 43 2151
26 44 2667
26 45 1960
26 46 1066
26 47 1883
26 48 2667
26 49 1869
26 50 2991
26 51 3415
26 52 133
26 53 3728
26 54 2244
26 55 358
26 56 826
26 57 2408
26 58 793
26 59 2757
26 60 793
26 61 2190
26 62 382
26 63 3523
26 64 2123
27 28 1478
27 29 3353
27 30 876
27 31 1357
27 32 1813
27 33 1671
27 34 3667
27 35 2885
27 36 466
27 37 434
27 38 1803
27 39 3017
27 40 3390
27 41 215
27 42 64
27 43 1527
27 44 318
27 45 120
27 46 900
27 47 2023
27 48 1847
27 49 2534
27 50 3391
27 51 654
27 52 3691
27 53 1466
27 54 75
27 55 3
27 56 15
27 57 1878
27 58 3411
27 59 3994
27 60 4072
27 61 545
27 62 3614
27 63 259
27 64 809
28 29 1835
28 30 2796
28 31 1641
28 32 1470
28 33 1013
28 34 3803
28 35 283
28 36 1976
28 37 1594
28 38 3358
28 39 3980
28 40 3025
28 41 1394
28 42 3166
28 43 767
28 44 1717
28 45 1435
28 46 1891
28 47 2253
28 48 324
28 49 3558
28 50 2258
28 51 2381
28 52 2376
28 53 1556
28 54 2896
28 55 4060
28 56 1497
28 57 1675
28 58 3271
28 59 1811
28 60 3502
28 61 2835
28 62 2688
28 63 2523
28 64 2557
29 30 2932
29 31 1483
29 32 3686
29 33 3084
29 34 2376
29 35 1303
29 36 1219
29 37 2639
29 38 1531
29 39 2374
29 40 1456
29 41 1345
29 42 2072
29 43 895
29 44 3333
29 45 1612
29 46 3138
29 47 2412
29 48 406
29 49 874
29 50 1984
29 51 370
29 52 3688
29 53 3936
29 54 3812
29 55 1916
29 56 3478
29 57 470
29 58 1088
29 59 3725
29 60 1798
29 61 2292
29 62 3058
29 63 1727
29 64 3581
30 31 1039
30 32 705
30 33 3274
30 34 569
30 35 2196
30 36 3624
30 37 3424
30 38 2931
30 39 3111
30 40 1352
30 41 1570
30 42 4
30 43 2574
30 44 3856
30 45 2068
30 46 3488
30 47 2925
30 48 3312
30 49 3538
30 50 444
30 51 109
30 52 3513
30 53 857
30 54 2637
30 55 2418
30 56 1723
30 57 1202
30 58 3635
30 59 2512
30 60 202
30 61 1657
30 62 1330
30 63 2924
30 64 2397
31 32 2294
31 33 1567
31 34 1428
31 35 1900
31 36 2269
31 37 3112
31 38 2837
31 39 404
31 40 1851
31 41 2917
31 42 3433
31 43 1702
31 44 1689
31 45 600
31 46 2634
31 47 395
31 48 563
31 49 1923
31 50 320
31 51 426
31 52 3538
31 53 1106
31 54 3761
31 55 3045
31 56 934
31 57 1977
31 58 2939
31 59 2607
31 60 1124
31 61 2821
31 62 157
31 63 4010
31 64 2272
32 33 2488
32 34 2733
32 35 1873
32 36 3538
32 37 1555
32 38 2322
32 39 3032
32 40 865
32 41 3537
32 42 2336
32 43 1012
32 44 3693
32 45 3225
32 46 2547
32 47 2938
32 48 488
32 49 2239
32 50 166
32 51 1645
32 52 1839
32 53 2601
32 54 661
32 55 3131
32 56 86
32 57 4063
32 58 473
32 59 2280
32 60 506
32 61 2592
32 62 3218
32 63 2821
32 64 3354
33 34 3921
33 35 3194
33 36 1406
33 37 1870
33 38 2418
33 39 1545
33 40 418
33 41 471
33 42 2537
33 43 1422
33 44 3133
33 45 767
33 46 523
33 47 438
33 48 993
33 49 1754
33 50 1135
33 51 3696
33 52 1862
33 53 344
33 54 2336
33 55 3897
33 56 3659
33 57 2195
33 58 207
33 59 670
33 60 1614
33 61 1516
33 62 166
33 63 3093
33 64 2136
34 35 777
34 36 3568
34 37 1598
34 38 2155
34 39 3804
34 40 1310
34 41 3705
34 42 566
34 43 1398
34 44 2994
34 45 2626
34 46 2122
34 47 577
34 48 345
34 49 2995
34 50 534
34 51 3607
34 52 4086
34 53 695
34 54 2705
34 55 3307
34 56 949
34 57 304
34 58 193
34 59 3345
34 60 2556
34 61 3857
34 62 1540
34 63 2425
34 64 3997
35 36 1044
35 37 571
35 38 3898
35 39 2200
35 40 1059
35 41 1049
35 42 667
35 43 1153
35 44 3225
35 45 1930
35 46 919
35 47 2040
35 48 1646
35 49 1168
35 50 1377
35 51 870
35 52 3051
35 53 3942
35 54 617
35 55 931
35 56 326
35 57 749
35 58 3264
35 59 1262
35 60 1040
35 61 2876
35 62 1081
35 63 2946
35 64 2929
36 37 3436
36 38 2192
36 39 2119
36 40 1194
36 41 412
36 42 3380
36 43 3288
36 44 3653
36 45 1098
36 46 609
36 47 1977
36 48 3139
36 49 1292
36 50 735
36 51 2860
36 52 3120
36 53 18
36 54 4076
36 55 3566
36 56 3888
36 57 2096
36 58 1875
36 59 1710
36 60 2632
36 61 2703
36 62 2610
36 63 888
36 64 3270
37 38 776
37 39 2106
37 40 968
37 41 1801
37 42 3117
37 43 1941
37 44 2193
37 45 2998
37 46 2082
37 47 2532
37 48 2392
37 49 1857
37 50 2664
37 51 1577
37 52 1661
37 53 3850
37 54 3375
37 55 2614
37 56 1174
37 57 1698
37 58 3014
37 59 1180
37 60 536
37 61 4020
37 62 2958
37 63 2737
37 64 3673
38 39 3236
38 40 2942
38 41 1845
38 42 3403
38 43 3064
38 44 3215
38 45 2178
38 46 75
38 47 2962
38 48 1160
38 49 3514
38 50 3351
38 51 981
38 52 790
38 53 2736
38 54 1876
38 55 3327
38 56 406
38 57 757
38 58 623
38 59 1323
38 60 3009
38 61 3598
38 62 2222
38 63 3631
38 64 2159
39 40 4059
39 41 3108
39 42 2041
39 43 2435
39 44 660
39 45 710
39 46 1370
39 47 3613
39 48 2057
39 49 4083
39 50 3764
39 51 2717
39 52 484
39 53 3019
39 54 2570
39 55 3584
39 56 4043
39 57 2324
39 58 1727
39 59 3610
39 60 465
39 61 1170
39 62 3690
39 63 3575
39 64 3429
40 41 2109
40 42 3558
40 43 3918
40 44 2966
40 45 3192
40 46 2268
40 47 18
40 48 1355
40 49 3195
40 50 1394
40 51 326
40 52 3288
40 53 2505
40 54 3254
40 55 2543
40 56 3543
40 57 253
40 58 2244
40 59 984
40 60 2075
40 61 597
40 62 4046
40 63 3392
40 64 3605
41 42 3717
41 43 2939
41 44 3285
41 45 682
41 46 2564
41 47 342
41 48 3440
41 49 2376
41 50 909
41 51 605
41 52 2502
41 53 2887
41 54 383
41 55 221
41 56 2769
41 57 2221
41 58 1463
41 59 563
41 60 2256
41 61 3099
41 62 695
41 63 527
41 64 726
42 43 3629
42 44 917
42 45 2236
42 46 193
42 47 509
42 48 2745
42 49 3071
42 50 3331
42 51 2954
42 52 1798
42 53 2255
42 54 2543
42 55 345
42 56 2861
42 57 2600
42 58 896
42 59 2846
42 60 1783
42 61 2093
42 62 1982
42 63 1724
42 64 1494
43 44 1356
43 45 4012
43 46 488
43 47 85
43 48 1715
43 49 2065
43 50 1111
43 51 1373
43 52 1099
43 53 4044
43 54 2414
43 55 3132
43 56 55
43 57 2830
43 58 2303
43 59 887
43 60 2315
43 61 2467
43 62 1517
43 63 1074
43 64 3020
44 45 3401
44 46 1715
44 47 1659
44 48 3003
44 49 1324
44 50 3936
44 51 2946
44 52 2566
44 53 3860
44 54 626
44 55 3134
44 56 3001
44 57 2995
44 58 1969
44 59 1281
44 60 1901
44 61 28
44 62 3592
44 63 3425
44 64 1135
45 46 1097
45 47 3843
45 48 4016
45 49 1243
45 50 1652
45 51 2392
45 52 3405
45 53 1923
45 54 3924
45 55 1074
45 56 3880
45 57 3792
45 58 1570
45 59 3043
45 60 1545
45 61 3644
45 62 3005
45 63 2559
45 64 1370
46 47 2578
46 48 3360
46 49 2781
46 50 3841
46 51 2716
46 52 1244
46 53 454
46 54 3591
46 55 3092
46 56 1115
46 57 2075
46 58 3112
46 59 1030
46 60 2244
46 61 1447
46 62 3123
46 63 191
46 64 796
47 48 3115
47 49 1652
47 50 1140
47 51 3220
47 52 3628
47 53 2697
47 54 41
47 55 1483
47 56 1341
47 57 185
47 58 3167
47 59 3866
47 60 3930
47 61 3440
47 62 3573
47 63 2852
47 64 1364
48 49 1138
48 50 606
48 51 4017
48 52 126
48 53 1015
48 54 1853
48 55 2102
48 56 1803
48 57 4012
48 58 3966
48 59 1196
48 60 1289
48 61 1910
48 62 2629
48 63 830
48 64 2542
49 50 2439
49 51 3847
49 52 2248
49 53 1158
49 54 730
49 55 1074
49 56 2655
49 57 1443
49 58 427
49 59 747
49 60 3754
49 61 2567
49 62 194
49 63 2847
49 64 2972
50 51 3940
50 52 2545
50 53 3771
50 54 276
50 55 4030
50 56 572
50 57 3253
50 58 451
50 59 1359
50 60 3770
50 61 945
50 62 3233
50 63 1833
50 64 3127
51 52 601
51 53 3574
51 54 3413
51 55 1269
51 56 891
51 57 2343
51 58 195
51 59 3182
51 60 2777
51 61 2732
51 62 658
51 63 3617
51 64 3333
52 53 3479
52 54 106
52 55 3989
52 56 1562
52 57 1970
52 58 2524
52 59 1859
52 60 641
52 61 660
52 62 3056
52 63 877
52 64 2108
53 54 3619
53 55 2641
53 56 252
53 57 421
53 58 2926
53 59 982
53 60 3243
53 61 1874
53 62 2918
53 63 3093
53 64 848
54 55 2204
54 56 356
54 57 2728
54 58 3417
54 59 198
54 60 3212
54 61 1533
54 62 3164
54 63 146
54 64 4061
55 56 776
55 57 2801
55 58 2966
55 59 2598
55 60 2025
55 61 3451
55 62 1781
55 63 2865
55 64 601
56 57 2175
56 58 1818
56 59 2544
56 60 554
56 61 1633
56 62 1162
56 63 3367
56 64 3157
57 58 982
57 59 2032
57 60 1722
57 61 3978
57 62 1915
57 63 1260
57 64 2510
58 59 30
58 60 2510
58 61 1302
58 62 347
58 63 363
58 64 2980
59 60 403
59 61 366
59 62 944
59 63 3065
59 64 186
60 61 1799
60 62 3557
60 63 239
60 64 3070
61 62 2961
61 63 1432
61 64 1952
62 63 3583
62 64 3420
63 64 2249
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment