Skip to content

Instantly share code, notes, and snippets.

@edrex
Created February 27, 2012 02:34
Show Gist options
  • Select an option

  • Save edrex/1920883 to your computer and use it in GitHub Desktop.

Select an option

Save edrex/1920883 to your computer and use it in GitHub Desktop.
Pascal's Triangle Congruence Mod p
<!DOCTYPE html>
<meta charset="utf-8">
<title>Pascal's Triangle Congruence Mod p</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/2.7.4/d3.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<style>
form#form {
font-size: small;
}
svg {
font: 10px sans-serif;
}
circle:hover {
cursor:crosshair;
fill: red ! important;
}
.pascal-text {
text-align: center;
}
.pascal-text div {
white-space: nowrap;
height: 5px;
}
.pascal-text div span {
display: inline-block;
width: 5px;
height: 5px;
margin: 0;
}
.axis path, .axis line {
fill: none;
stroke: #fff;
}
​}
</style>
<body>
<div style="float:right; text-align: right">
<form id='form'>
<p>
<label for="max">Maximum rows:</label>
<input type="number" value="64" min="1" max=500 id="n">
</p>
<p>
<label for="max">P (base for mod):</label>
<input type="number" value="11" min="1" max=500 id="p">
</p>
<input type="submit" id="generate">Generate!</input>
</form>
</div>
<script>
function pascals_triangle(n, mod) {
var T = [[1]];
var r=0
var f_no_mod = function(i) {return ((T[r-1][i-1]||0) + (T[r-1][i]||0))};
var f = mod ? function(i) { return f_no_mod(i) % mod } : f_no_mod;
while (r < n-1) {
r++
T.push(_.map(_.range(r+1), f));
}
return T;
}
// flatten positional information into each entry so they can lay themselves out
function mangle(T) {
var R = [];
for (var i=0; i<T.length; i++) {
for (var j=0; j<T[i].length; j++) {
R.push([i,j,T[i][j]]);
}
}
return R;
}
var colors = d3.interpolateHsl('rgb(0,255,0)', 'rgb(128, 0, 128)');
var body = d3.select('body')
function make_vis_text(n, p) {
body.selectAll('.pascal-text').remove()
var c = body.append('div')
.attr('class', 'pascal-text');
c.selectAll('div').remove();
var row = c.selectAll('div')
.data(pascals_triangle(n), function(n) {return n.length});
row.enter().append("div");
row.exit().remove();
var entry = row.selectAll('span')
.data(function(d) { return d; })
.enter().append("span")
//.text(function(d) { return d})
.style("background-color", function(v) {return colors((v%p)/p)});
}
function make_vis_svg(n, p) {
var canvas_size = 500
var n = Math.min(n, canvas_size-2);
var vis_size = (n/(n+2)) * canvas_size
var margin = (canvas_size - vis_size)/2
var scale = vis_size/n
var dy = Math.sin(Math.PI/3)
body.selectAll('.pascal-svg').remove()
var svg = d3.select("body").append("svg")
.attr("class", 'pascal-svg')
.attr("width", canvas_size)
.attr("height", canvas_size)
var vis = svg.append("g")
.attr("transform", "scale("+scale+","+scale+") translate("+(1+n/2)+",1.5) ")
var entry = vis.selectAll('circle')
.data(mangle(pascals_triangle(n, p)), function(n) {return n.length});
entry.enter().append("circle")
.style("fill", function(d) {return colors((d[2]%p)/p)})
.attr("r", 0.5)
.attr("cx", function(d){return d[1] - d[0]/2})
.attr("cy", function(d){return d[0]*dy})
.append("svg:title")
.text(function(d, i) { return "The value at row "+d[0]+" and column "+ d[1]+ " is "+d[2] });
}
function make_p_gen(p, g) {
return make_vis_svg(Math.pow(p,g),p)
}
function render() {
make_vis_svg(d3.select("#n").property("value"),
d3.select("#p").property("value"));
}
render();
var form = d3.select("#form")
.on("submit", function() {
render()
d3.event.preventDefault()
});
//make_p_gen(3,4);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment