Skip to content

Commit

Permalink
Verifier for Reading Problems
Browse files Browse the repository at this point in the history
  • Loading branch information
Granjow committed Oct 19, 2015
1 parent 11a2bed commit b9b7079
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ to solve various types of problems. More exercises will be added. Current progre
Create a Graph data structure which manages the vertices and edges
from the previous exercise.

Reading Problems ————————————·
Reading Problems ————————————·—————————————————·————
Read large graphs from files.

Under Siege —————————————————·
Expand Down
5 changes: 4 additions & 1 deletion exercises/ex0-intro/intro.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ var path = require( 'path' ),
verify = require( 'adventure-verify' ),
tools = require( '../../library/tools' );

exports.problem = tools.mdProblem( path.join( __dirname, 'problem-intro.md' ), 'problem-intro.pdf' );
exports.problem = tools.mdProblem( {
mdSource: path.join( __dirname, 'problem-intro.md' ),
pdfName: 'problem-intro.pdf'
} );
exports.solution = tools.mdSolution( path.join( __dirname, 'solution-intro.js' ) );

exports.verify = verify( { modeReset: true }, function checker( args, t ) {
Expand Down
5 changes: 4 additions & 1 deletion exercises/ex1-vertices-edges/vertices-edges.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ var path = require( 'path' ),
verify = require( 'adventure-verify' ),
tools = require( '../../library/tools' );

exports.problem = tools.mdProblem( path.join( __dirname, 'problem-vertices-edges.md' ), 'problem-vertices-edges.pdf' );
exports.problem = tools.mdProblem( {
mdSource: path.join( __dirname, 'problem-vertices-edges.md' ),
pdfName: 'problem-vertices-edges.pdf'
} );
exports.solution = tools.mdSolution( path.join( __dirname, 'solution-vertices-edges.js' ) );

exports.verify = verify( { modeReset: true }, function checker( args, t ) {
Expand Down
5 changes: 4 additions & 1 deletion exercises/ex2-graph-structure/graph-structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ var path = require( 'path' ),
verify = require( 'adventure-verify' ),
tools = require( '../../library/tools' );

exports.problem = tools.mdProblem( path.join( __dirname, 'problem-graph-structure.md' ), 'problem-graph-structure.pdf' );
exports.problem = tools.mdProblem( {
mdSource: path.join( __dirname, 'problem-graph-structure.md' ),
pdfName: 'problem-graph-structure.pdf'
} );

exports.solution = tools.mdSolution( path.join( __dirname, 'solution-graph-structure.js' ) );

Expand Down
19 changes: 15 additions & 4 deletions exercises/ex3-reading-problems/problem-reading-problems.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ You will be provided input files of the following form:
1 a

Each input file contains a list of vertices and a list of edges. The lists are separated by an empty line.
There is always at least one vertex.

You should use the functionality provided by Node.js for reading files. See the literature for details.

Expand All @@ -31,15 +32,25 @@ You should use the functionality provided by Node.js for reading files. See the
Export a function `readGraph` which takes the file name of the input file, reads it into a graph and returns this object.
For example, the following code should be supported:

var graph = readGraph( 'graph1.in' );
readGraph( 'graph1.in', function() {
var neighbours = graph.neighbours( 'A' );
// Would return an array containing the vertices [ a, 1, is-it-42 ] for the example graph above.
} );


var neighbours = graph.neighbours( 'A' );
// Would return an array containing the vertices [ a, 1, is-it-42 ] for the example graph above.

You can re-use code from the previous exercise, and you may use the following template:

function readGraph() {

/**
* Read a graph from a file.
* @param {String} inFilePath Absolute path to the input file
* @param {function(graph: Graph)} callback Callback function, called when Graph is read.
*/
function readGraph( inFilePath, callback ) {
// Your code here
// When your graph is read, call
// callback( yourGraphObject );
}
module.exports = readGraph;

Expand Down
57 changes: 57 additions & 0 deletions exercises/ex3-reading-problems/reading-problems.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
var path = require( 'path' ),
verify = require( 'adventure-verify' ),
tools = require( '../../library/tools' );

exports.problem = function () {
return tools.mdProblem( {
mdSource: path.join( __dirname, 'problem-reading-problems.md' ),
pdfName: 'problem-reading-problems.pdf',
sampleSource: path.join( __dirname, 'samples' ),
sampleDest: 'samples-reading-problems'
} );
};

exports.solution = tools.mdSolution( path.join( __dirname, 'solution-reading-problems.js' ) );

exports.verify = verify( { modeReset: true }, function checker( args, t ) {
var reader = require( path.resolve( args[ 0 ] ) ),
verifier = require( './solution-reading-problems' ),
sorter = function ( a, b ) {
return a.id.localeCompare( b.id );
},
inFile = path.join( __dirname, 'samples', 'sample1.in' );

console.log( 'Testing against ' + inFile );

reader( inFile, function ( testGraph ) {
verifier( inFile, function ( verifierGraph ) {
var verticesFound = { c: 0, total: 0 },
correctNbs = { c: 0, total: 0 };
verifierGraph._vertices.forEach( function ( v ) {
verticesFound.total++;
if ( testGraph.v( v.id ) ) {
verticesFound.c++;
var verifiedNeighbours = v.neighbours().sort( sorter ),
testNeighbours = testGraph.v( v.id ).neighbours().sort( sorter );

correctNbs.total++;
if ( testNeighbours.length === verifiedNeighbours.length ) {
if ( verifiedNeighbours.every( function ( el, ix ) {
return el.id == testNeighbours[ ix ].id;
} ) ) {
correctNbs.c++;
}
}
}
} );

t.equal( verticesFound.c, verticesFound.total, 'Correct vertices' );
t.equal( correctNbs.c, correctNbs.total, 'Vertices with correct neighbours' );

t.end();

} );
} );


} );
9 changes: 9 additions & 0 deletions exercises/ex3-reading-problems/samples/sample1.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
A
a
1
is-it-42

A a
A 1
A is-it-42
1 a
127 changes: 127 additions & 0 deletions exercises/ex3-reading-problems/solution-reading-problems.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
var fs = require( 'fs' ),
readline = require( 'readline' );

/**
* Vertex in a graph
* @param {*} id This vertex's ID
* @returns {Vertex}
*/
var Vertex = function ( id ) {

this.id = id;
this._edges = [];

return this;
};
Vertex.prototype = {
neighbours: function () {
return this._edges.map( function ( edge ) {
return edge.vTo;
} );
},
addEdge: function ( edge ) {
this._edges.push( edge );
}
};

/**
* Directed edge in a graph
* @param {Vertex} vFrom Source vertex
* @param {Vertex} vTo Target vertex
* @returns {Edge}
*/
var Edge = function ( vFrom, vTo ) {

/** @type {Vertex} */
this.vFrom = vFrom;
/** @type {Vertex} */
this.vTo = vTo;

this.vFrom.addEdge( this );

return this;
};

/**
* Graph containing edges and vertices
* @param vertices
* @param edges
* @constructor
*/
var Graph = function ( vertices, edges ) {

/**
* We use a ES6 Map for storing vertices. Maps have the advantage over objects that
* they can be iterated over with forEach.
* @type {Map.<Vertex>}
*/
this._vertices = new Map();

/**
* If you do not know why we don't just use `this` in the forEach loop, read this article:
* http://javascriptplayground.com/blog/2012/04/javascript-variable-scope-this/
*/
var me = this;

// Read and store all vertices
vertices.forEach( function ( id ) {
me._vertices.set( id, new Vertex( id ) );
} );

// Create the edges
edges.forEach( function ( pair ) {
var idFrom = pair[ 0 ],
idTo = pair[ 1 ];
new Edge( me.v( idFrom ), me.v( idTo ) );
} );

};
Graph.prototype = {
/**
* Retrieve a vertex identified by the given ID.
* @param id Vertex ID
* @returns {Vertex}
*/
v: function ( id ) {
return this._vertices.get( id );
}
};

/**
* Read a graph from a file.
* @param {String} inFilePath Absolute path to the input file
* @param {function(graph: Graph)} callback Callback function, called when Graph is read.
*/
function readGraph( inFilePath, callback ) {

var vertices = [],
edges = [],
verticesRead = false;

readline.createInterface( {
input: fs.createReadStream( inFilePath )
} ).on( 'line', function ( line ) {
if ( verticesRead ) {
var edge = line.split( ' ' );
if ( edge.length == 2 ) {
console.log( 'Edge: ', edge );
edges.push( edge );
} else {
console.log( 'No edge: ', line );
}
} else {
if ( line.length == 0 ) {
console.log( 'All vertices read.' );
verticesRead = true;
} else {
console.log( 'Vertex: ', line );
vertices.push( line );
}
}
} ).on( 'close', function () {
console.log( 'Read.' );
callback( new Graph( vertices, edges ) );
} );
}

module.exports = readGraph;
49 changes: 45 additions & 4 deletions library/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,56 @@ var fs = require( 'fs' ),

module.exports = {};

module.exports.mdProblem = function ( mdFile, outPdfFile ) {
function copySamples( fromDir, toDir ) {

if ( fs.existsSync ) {
if ( !fs.existsSync( toDir ) ) {
fs.mkdirSync( toDir );
}
}
if ( fs.accessSync ) {
try {
fs.accessSync( toDir );
} catch ( e ) {
fs.mkdirSync( toDir );
}
}
fs.readdir( fromDir, function ( err, files ) {
var messages = 'Creating some sample .in files for you ...';
if ( err ) throw err;
files.filter( function ( name ) {
return name.substr( -3 ) === '.in';
} ).map( function ( name ) {
return {
fromPath: path.join( fromDir, name ),
toPath: path.join( toDir, name )
};
} ).forEach( function ( data ) {
messages += '\n* Creating `' + data.toPath + '`';
fs.createReadStream( data.fromPath ).pipe( fs.createWriteStream( data.toPath ) );
} );
console.log( md( messages ) );
} );
}

/**
*
* @param {{mdSource:string, pdfName:string, sampleSource:string=, sampleDest:string=}} opts
* @returns {Function}
*/
module.exports.mdProblem = function ( opts ) {
return function () {
var out = path.resolve( outPdfFile );

markdownpdf().from( mdFile ).to( out, function () {
if ( opts.sampleSource && opts.sampleDest ) {
copySamples( opts.sampleSource, opts.sampleDest );
}

var out = path.resolve( opts.pdfName );
markdownpdf().from( opts.mdSource ).to( out, function () {
console.log( md( 'Created `' + out + '` -- if you prefer to read this problem as PDF' ) );
} );

return md( fs.readFileSync( mdFile, { encoding: 'utf8' } ) );
return md( fs.readFileSync( opts.mdSource, { encoding: 'utf8' } ) );
}
};
module.exports.mdSolution = function ( solutionFile ) {
Expand Down
3 changes: 3 additions & 0 deletions runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@ shop.add( 'Vertices and Edges', function () {
shop.add( 'Graph Structure', function () {
return require( './exercises/ex2-graph-structure/graph-structure' );
} );
shop.add( 'Reading Problems', function () {
return require( './exercises/ex3-reading-problems/reading-problems' );
} );

shop.execute( process.argv.slice( 2 ) );

0 comments on commit b9b7079

Please sign in to comment.