mirror of https://github.com/coolaj86/fizzbuzz.git
mock census parser for cs 142
This commit is contained in:
parent
6a5f859101
commit
86e3d5f76b
|
@ -0,0 +1,59 @@
|
|||
CS 142 Mid-Term 2 (Fall 2010)
|
||||
====
|
||||
|
||||
**Mock Census Parser**
|
||||
|
||||
Must read a file via HTTP or on the local filesystem.
|
||||
|
||||
(The file has ostensibly just passed validation and needs no further error-checking)
|
||||
|
||||
The file contains three newline-delimited directives per block and one EOF directive.
|
||||
|
||||
Each directive has a number of space-delimited attributes.
|
||||
|
||||
The directives appear in this order:
|
||||
|
||||
* `Head` - this must be the start of the block. Represents the head of household
|
||||
* name - first name of the individual
|
||||
* gender
|
||||
* eye_color
|
||||
* hair_color
|
||||
* height - feet as a float
|
||||
|
||||
* `Depedent` - 0 or many may exist. Represents children, spouse, etc
|
||||
* name
|
||||
* gender
|
||||
* age - 'minor' or 'adult'
|
||||
* height
|
||||
|
||||
* `End` - must close the block before the next 'Head'
|
||||
|
||||
* `SUPER-END` - a special end-of-file (EOF) marker
|
||||
* `end` MUST precede `SUPER-END`
|
||||
|
||||
Example Data File
|
||||
====
|
||||
|
||||
Head Kevin M brown brown 6.15
|
||||
Dependent Dagmar F adult 5.9
|
||||
Dependent Dorkus M minor 5.7
|
||||
End
|
||||
Head Eve F blue brown 5.5
|
||||
Dependent Adam M adult 6.2
|
||||
Dependent Fred M minor 6.1
|
||||
Dependent Fredwenda F adult 5.3
|
||||
End
|
||||
Head Pentultimus M brown brown 6
|
||||
End
|
||||
Head Beautisha F green red 5.7
|
||||
Dependent Bodacious M minor 4.0
|
||||
End
|
||||
SUPER-END
|
||||
|
||||
Variations from the Spec
|
||||
====
|
||||
|
||||
My implementation is written in JavaScript (which is like LISP, not at all like Java).
|
||||
I take advantage of some JavaScript-isms.
|
||||
|
||||
In my implementation I also handle `#` comments as well as some extremely minimalistic error-checking.
|
|
@ -0,0 +1,9 @@
|
|||
# invalid
|
||||
node mock-census.js
|
||||
node mock-census.js files:///path/to/file
|
||||
node mock-census.js httpss://domain.tld/resource
|
||||
# valid
|
||||
node mock-census.js /path/to/file
|
||||
node mock-census.js file:///path/to/file
|
||||
node mock-census.js http://domain.tld/resource
|
||||
node mock-census.js https://domain.tld/resource
|
|
@ -0,0 +1,191 @@
|
|||
// TODO parse streaming
|
||||
"use strict";
|
||||
(function (undefined) {
|
||||
var fs = require('fs'),
|
||||
url = require('url'),
|
||||
ahr = require('ahr'),
|
||||
stream,
|
||||
node = process.argv[0],
|
||||
self = process.argv[1],
|
||||
fulluri = process.argv[2],
|
||||
uri;
|
||||
|
||||
self = self.substr(self.lastIndexOf('/') + 1);
|
||||
|
||||
require('remedial');
|
||||
|
||||
function usage() {
|
||||
console.log("Usage: node {self}".supplant({self: self}) +
|
||||
" file:///path/to/file | http://path/to/file");
|
||||
}
|
||||
|
||||
|
||||
// Head, and Dependent "Classes"
|
||||
function Comment(lines) {
|
||||
while (true) {
|
||||
line = lines.shift();
|
||||
if (undefined === line || null === line) {
|
||||
throw new Error("Expected 'Dependent' or 'end' but reach end-of-file");
|
||||
}
|
||||
if (!line.match(/\s*#/)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
function Dependent(lines) {
|
||||
var line, dep;
|
||||
line = Comment(lines);
|
||||
|
||||
if (line.match(/^Dependent\s*/)) {
|
||||
parts = line.split(/\s+/);
|
||||
dep = {
|
||||
// no error checking in spec
|
||||
name: parts[1],
|
||||
gender: parts[2],
|
||||
age: parts[3],
|
||||
height: parseInt(parts[4], 10),
|
||||
};
|
||||
} else if (line.match(/^End\s*/)) {
|
||||
return false;
|
||||
} else {
|
||||
throw new Error("Expected 'Dependent' or 'End' but saw\n " + line.substr(0,20));
|
||||
}
|
||||
return dep;
|
||||
}
|
||||
|
||||
function Head(lines) {
|
||||
var line, head, parts, dep;
|
||||
line = Comment(lines);
|
||||
|
||||
if (line.match(/^Head\s*/)) {
|
||||
parts = line.split(/\s+/);
|
||||
head = {
|
||||
// no error checking in spec
|
||||
name: parts[1],
|
||||
gender: parts[2],
|
||||
eye_color: parts[3],
|
||||
hair_color: parts[4],
|
||||
height: parseInt(parts[5], 10),
|
||||
deps: []
|
||||
};
|
||||
while (dep = Dependent(lines)) {
|
||||
head.deps.push(dep);
|
||||
}
|
||||
} else if (line.match(/^SUPER-END\s*/)) {
|
||||
return false;
|
||||
} else {
|
||||
throw new Error("Expected 'Head' or 'SUPER-END' but saw\n " + line.substr(0,20));
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
function readFile(file) {
|
||||
var promise = require('futures').promise(),
|
||||
stream,
|
||||
data = new Buffer('');
|
||||
|
||||
stream = fs.createReadStream(file, { flags: 'r' });
|
||||
stream.on('error', function (err) {
|
||||
promise.fulfill(err, stream, data);
|
||||
});
|
||||
stream.on('data', function (chunk) {
|
||||
data += chunk;
|
||||
});
|
||||
stream.on('end', function () {
|
||||
promise.fulfill(undefined, stream, data);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Queries
|
||||
|
||||
// Average height of Heads of Household
|
||||
function query1(heads) {
|
||||
var heights = 0.0;
|
||||
heads.forEach(function (head) {
|
||||
heights += head.height;
|
||||
});
|
||||
console.log("Average Height of Heads of Household: " + (heights / heads.length));
|
||||
}
|
||||
|
||||
// What is the height of the tallest of all dependents?
|
||||
function query2(heads) {
|
||||
var max = 0.0;
|
||||
heads.forEach(function (head) {
|
||||
head.deps.forEach(function (dep) {
|
||||
max = Math.max(max, dep.height);
|
||||
});
|
||||
});
|
||||
console.log("Height of tallest Dependent: " + max);
|
||||
}
|
||||
|
||||
// The height of the shortest Dependent of a female Head of Household
|
||||
function query3(heads) {
|
||||
var min = Infinity;
|
||||
heads.forEach(function (head) {
|
||||
if ('F' !== head.gender) {
|
||||
return;
|
||||
}
|
||||
head.deps.forEach(function (dep) {
|
||||
min = Math.min(min, dep.height);
|
||||
});
|
||||
});
|
||||
console.log("Height of shortest Dependent of a Female-Headed Household: " + min);
|
||||
}
|
||||
|
||||
// Average height of male dependents of brown-haired male heads of houshold
|
||||
function query4(heads) {
|
||||
var heights = 0.0, count = 0;
|
||||
heads.forEach(function (head) {
|
||||
if ('m' !== head.gender && 'brown' !== head.hair_color) {
|
||||
return;
|
||||
}
|
||||
head.deps.forEach(function (dep) {
|
||||
count += 1;
|
||||
heights += dep.height;
|
||||
});
|
||||
});
|
||||
console.log("Average height of male dependent of brown-haired male Heads of Household: " + (heights / count));
|
||||
}
|
||||
|
||||
function parseData(err, x, data) {
|
||||
var lines = data.split('\n'),
|
||||
heads = [],
|
||||
curHead;
|
||||
|
||||
while (curHead = Head(lines)) {
|
||||
heads.push(curHead);
|
||||
}
|
||||
console.log(JSON.stringify(heads, null, ' '));
|
||||
query1(heads);
|
||||
query2(heads);
|
||||
query3(heads);
|
||||
query4(heads);
|
||||
return heads;
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (!fulluri) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
uri = url.parse(fulluri, true);
|
||||
if (!uri.protocol) {
|
||||
uri.protocol = '';
|
||||
}
|
||||
if ('file:' === uri.protocol || '' === uri.protocol) {
|
||||
readFile(uri.pathname).when(parseData);
|
||||
} else if (uri.protocol.match(/^http[s]?:$/)) {
|
||||
ahr.get(fulluri).when(parseData);
|
||||
} else {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
}());
|
|
@ -0,0 +1,19 @@
|
|||
#Head First Gender Eye-color Hair-color Height (exactly one per block)
|
||||
Head Kevin M brown brown 6.15
|
||||
#Dependent First Gender Age Height (0 or more per block)
|
||||
Dependent Dagmar F adult 5.9
|
||||
Dependent Dorkus M minor 5.7
|
||||
#End end-of-block
|
||||
End
|
||||
Head Eve F blue brown 5.5
|
||||
Dependent Adam M adult 6.2
|
||||
Dependent Fred M minor 6.1
|
||||
Dependent Fredwenda F adult 5.3
|
||||
End
|
||||
Head Pentultimus M brown brown 6
|
||||
End
|
||||
Head Beautisha F green red 5.7
|
||||
Dependent Bodacious M minor 4.0
|
||||
End
|
||||
#SUPER-END end-of-file
|
||||
SUPER-END
|
Loading…
Reference in New Issue