const genDataset = (n) => ( Array.from(Array(n).keys()) ); const genRandomset = (n) => { let ret = Array.from( Array(n-1).keys() ).map( x => n*Math.random() ); ret.sort(function(a, b) { return a - b; }); return [0].concat(ret); }; const genSines = (n) => ( Array.from( Array(n).keys() ).map(x => n*Math.sin(x*Math.PI/(2*(n-1)))) ); const Column = (props) => { const n = parseInt(props.n); const datasines = genSines(n); const [dataset, setDataset] = React.useState( genRandomset(n) ); const iterate = () => { // Burgi's step one let aux = [ dataset[n-1]/2 ]; for( const x of Array(n-2).keys() ){ aux.push( aux[aux.length - 1] + dataset[n-2-x]); } aux.reverse(); console.log( aux ); // Burgi's step two let newDataset = [ 0 ]; for( const x of aux ){ newDataset.push( newDataset[newDataset.length-1] + x ); } // Scale down let newColumn = newDataset.map( x => n*x/newDataset[n-1] ); console.log( newColumn ); setDataset( newColumn ); }; const margin = {top: 50, right: 50, bottom: 50, left: 50} , width = window.innerWidth - margin.left - margin.right , height = props.height - margin.top - margin.bottom; const xScale = d3.scaleLinear() .domain([0, n]) // input .range([0, width]); // output const yScale = d3.scaleLinear() .domain([0, n]) // input .range([height, 0]); // output const line = d3.line() .defined(d => !isNaN(d)) .x((d,i) => {return xScale(i);}) .y((d) => {return yScale(d);}); React.useEffect( () => { d3.selectAll("svg > *").remove(); let svg = d3.select("#chart") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(xScale)); svg.append("g") .attr("class", "y axis") .call(d3.axisLeft(yScale)); svg.append( "path" ) .datum(dataset) .attr("stroke-linejoin", "round") .attr("stroke-linecap", "round") .attr("class", "burgiLine") .attr("d", line); svg.append( "path" ) .datum( datasines ) .attr("stroke-linejoin", "round") .attr("stroke-linecap", "round") .attr("class", "burgiSine") .attr("d", line); svg.selectAll(".dot") .data(dataset) .enter().append("circle") // Uses the enter().append() method .attr("class", "dot") // Assign a class for styling .attr("cx", function(d, i) { return xScale(i); }) .attr("cy", function(d) { return yScale(d); }) .attr("r", 5) .on("mouseover", function(a, b, c) { console.log(a); this.attr('class', 'focus'); }) .on("mouseout", function() { }); }); return (

 Burgi's iterate transformation from a random initial set of values (yellow line) converges quickly to the sines (blue).

); }; const App = () => { return(
); }; ReactDOM.render( , document.getElementById('root') );