-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnumnec.js
136 lines (122 loc) · 4.66 KB
/
numnec.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Returns an array consisting of of all and only the number necklaces in specified base, in ascending order.
function allNecklaces( base ) {
var pairs = [],
necklaces = [],
lengths = [];
// Initialize the pairs 2d array.
for ( var i = 0; i < base; i++ ) {
pairs[i] = [];
}
// Initialize the lengths array for special case of (0)
//lengths[1] = 1;
// For each possible pair in base base,
for ( var i = 0; i < base; i++ ) {
for ( var j = 0; j < base; j++ ) {
// If we haven't seen this pair in any necklace yet,
if ( ! pairs[i][j] ) {
var n = [ i, j ],
k = 2;
// Create a number necklace starting with this pair.
do {
// Current element is the sum of previous two elements mod base.
n[k] = (n[k-2] + n[k-1]) % base;
// Mark the current pair as 'seen'.
pairs[ n[k-2] ][ n[k-1] ] = 1;
k++;
// Continue to add elements to the necklace until we're back where we started.
} while ( ! ( n[k-2] == i && n[k-1] == j ) );
// Pop off the last two elements for savings.
n.pop();
n.pop();
// Push created necklace onto the necklaces array.
necklaces.push( n );
// Update lengths array.
if ( lengths[ n.length ] ) {
lengths[ n.length ]++;
}
else {
lengths[ n.length ] = 1;
}
}
}
}
// Sort necklaces by period
necklaces.sort( (a, b) => a.length - b.length );
return { necklaces: necklaces, lengths: lengths };
}
// Override the default toString method on arrays to output custom HTML. 1234567890
Array.prototype.toString = function() {
var s = '';
let digitColors = {
0: '#aaaaaa',
1: '#5a6f9c',
2: '#75a1ff',
3: '#44ab82',
4: '#cca1a1',
5: '#a5d1a5',
6: '#dbdba2',
7: '#a44ecc',
8: '#a3a3a3',
9: '#c2a44a'
};
for ( var i = 0; i < this.length; i++ ) {
let beadColor = digitColors[ this[i] % 10 ];
s += "<span class='bead-wrapper'><span class='bead' style='background-color: " + beadColor + "'>" + this[i] + "</span></span>";
}
return s;
}
// Polyfill to return current time with microsecond accuracy for Chrome and Firefox and millisecond accuracy for Safari.
function currentTime() {
return 'performance' in window ? performance.now() : new Date().getTime()
}
// Write all number necklaces for a given base to the HTML document.
function displayAllNecklaces( b ) {
// time before calculating the necklaces
var startTime = currentTime(),
necklacesAndLengths = allNecklaces( b ),
// necklaces is the array of all necklaces of base b, in ascending order
necklaces = necklacesAndLengths.necklaces,
// lengths is a array giving the number of necklaces of each given length
lengths = necklacesAndLengths.lengths,
// time after calculating the necklaces
endTime = currentTime(),
// Table header
h = "<table id='results-table'><tr><th colspan='2'>All " + necklaces.length + " number " +
( necklaces.length != 1 ? "necklaces" : "necklace" ) + " for modulus " + b + ":</th></tr>";
// Print the summary
h += "<tr><td colspan='2'>";
for ( var i = 0; i < lengths.length; i++) {
if ( lengths[i] >= 0 ) {
h += lengths[i] + ( lengths[i] != 1 ? " necklaces" : " necklace" ) + " of period " + i + "<br>\n";
}
}
h += "</td></tr>";
// For each necklace in the necklaces array,
for ( var i = 0; i < necklaces.length; i++) {
var n = necklaces[i];
// Write the necklace length and beads to the HTML document.
h += "<tr><td>" + n.length + "</td><td>" + n + "</td></tr>\n";
}
// Write the table footer including time elapsed.
h += "<tr><td colspan='2'>Time elapsed: " + ( Math.round( ( endTime - startTime ) * 1000 ) / 1000 ) + "ms.\n";
h += "</table>\n"
// Set the results selement's innerHTML to our table.
document.getElementById( 'results' ).innerHTML = h;
}
// When page is loaded,
window.onload = function() {
// Set the submit function for the form.
document.getElementById( 'num-nec-form' ).onsubmit = function() {
// b is the value of the text input element 'base'
var b = document.getElementById( 'base').value - 0;
// If b is a positive integer,
if ( b % 1 === 0 && b > 0 ) {
// Calculate all necklaces of base b.
displayAllNecklaces( b );
}
else {
// Otherwise throw up an alert message.
alert( "Please enter a positive integer." );
}
}
}