Skip to content

Instantly share code, notes, and snippets.

@bmershon
Last active March 16, 2017 03:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bmershon/7938f064dc2202364cdd52acbd24805d to your computer and use it in GitHub Desktop.
Save bmershon/7938f064dc2202364cdd52acbd24805d to your computer and use it in GitHub Desktop.
Multiplicative Group
border: no
license: MIT

The orders of every element of the multiplicative group of remainders modulo 11.

<!DOCTYPE html>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<body></body>
<script>
let n = 11;
let worker = new Worker("worker.js");
worker.onmessage = function(event) {
switch (event.data.type) {
case "end": return ended(event.data);
}
};
worker.postMessage({'n': n});
function ended(data) {
let matrix = data.matrix,
orders = data.orders;
// Add group elements down the left side of the table.
matrix = matrix.map((row, i) => {
return [i + 1].concat(row).concat([orders[i]]);
});
// Add group elements as top row.
matrix.unshift(d3.range(0, n + 1));
// Top left corner is empty.
matrix[0][0] = "";
// Top right corner is empty.
matrix[0][n] = "order";
let tr = d3.select("body")
.style("font-family", "helvetica")
.append("table")
.style("text-align", "center")
.selectAll("tr")
.data(matrix)
.enter().append("tr");
let td = tr.selectAll("td")
.data(d => d)
.enter().append("td")
.attr("width", "40px")
.attr("height", "40px")
.style("font-size", "24px")
.style("font-weight", (d, i) => {
switch(i) {
case 0: // Left-most column.
return "normal";
break;
case n: // Right-most column
return "bolder";
break;
default: // All other entries.
return "lighter";
break;
}
})
.style("color", (d, i) => {
return (i === n) ? "rgb(240, 0, 0)" : null;
})
.text(d => d);
// Style the top row.
d3.selectAll("tr").filter((d, i) => i === 0)
.selectAll("td")
.style("color", "normal");
}
</script>
onmessage = function(event) {
let n = event.data.n,
matrix = multiplicative_matrix(n),
orders = matrix.map((d, i) => {
return order(v(i), matrix);
});
postMessage({
"type": "end",
"matrix": matrix,
"orders": orders
});
}
// The value correction for a zero-based index system.
function v(index) { return index + 1; }
// Returns a square matrix[row][column] with n - 1 rows,
// each of which is a permutation of remainders modulo n.
// The first row corresponds to the element 1; the last row
// corresponds to the element n - 1.
function multiplicative_matrix(n) {
let matrix = [];
for (let i = 0; i < n - 1; i++) {
matrix.push(permutation(v(i), n));
}
return matrix;
}
// Returns an array representing a permutation of remainders modulo n.
function permutation(a, n) {
let row = new Array(n - 1);
for (i = 0; i < n - 1; i++) {
row[i] = v(i);
}
return row.map((d) => {
return (a * d) % n;
});
}
// Precondition: The matrix representing the modular multiplication
// table must have been constructed for a prime value n (e.g. 17).
// Returns the order of the group element a, using the matrix
// a to iteratively look up the result of successively applying a.
function order(a, matrix) {
let count = 1,
n = matrix[0][matrix.length - 1] + 1,
current = a;
while (current !== 1) {
// Zero-based index; subtract one from actual value.
current = matrix[current - 1][a - 1] % n;
count++;
}
return count;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment