-
Notifications
You must be signed in to change notification settings - Fork 0
/
checkedwords.js
99 lines (86 loc) · 3.35 KB
/
checkedwords.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* This Node program reads text from standard input, computes the frequency
* of each letter in that text, and displays a histogram of the most
* frequently used characters. It requires Node 12 or higher to run.
*
* In a Unix-type environment you can invoke the program like this:
* node charfreq.js < corpus.txt
*/
// This class extends Map so that the get() method returns the specified
// value instead of null when the key is not in the map
class DefaultMap extends Map {
constructor(defaultValue) {
super(); // Invoke superclass constructor
this.defaultValue = defaultValue; // Remember the default value
}
get(key) {
if (this.has(key)) {
// If the key is already in the map
return super.get(key); // return its value from superclass.
} else {
return this.defaultValue; // Otherwise return the default value
}
}
}
// This class computes and displays letter frequency histograms
class Histogram {
constructor() {
this.letterCounts = new DefaultMap(0); // Map from letters to counts
this.totalLetters = 0; // How many letters in all
}
// This function updates the histogram with the letters of text.
add(text) {
// Remove whitespace from the text, and convert to upper case
text = text.replace(/\s/g, "").toUpperCase();
// Now loop through the characters of the text
for (let character of text) {
let count = this.letterCounts.get(character); // Get old count
this.letterCounts.set(character, count + 1); // Increment it
this.totalLetters++;
}
}
// Convert the histogram to a string that displays an ASCII graphic
toString() {
// Convert the Map to an array of [key,value] arrays
let entries = [...this.letterCounts];
// Sort the array by count, then alphabetically
entries.sort((a, b) => {
// A function to define sort order.
if (a[1] === b[1]) {
// If the counts are the same
return a[0] < b[0] ? -1 : 1; // sort alphabetically.
} else {
// If the counts differ
return b[1] - a[1]; // sort by largest count.
}
});
// Convert the counts to percentages
for (let entry of entries) {
entry[1] = (entry[1] / this.totalLetters) * 100;
}
// Drop any entries less than 1%
entries = entries.filter((entry) => entry[1] >= 1);
// Now convert each entry to a line of text
let lines = entries.map(
([l, n]) => `${l}: ${"#".repeat(Math.round(n))} ${n.toFixed(2)}%`
);
// And return the concatenated lines, separated by newline characters.
return lines.join("\n");
}
}
// This async (Promise-returning) function creates a Histogram object,
// asynchronously reads chunks of text from standard input, and adds those chunks to
// the histogram. When it reaches the end of the stream, it returns this histogram
async function histogramFromStdin() {
process.stdin.setEncoding("utf-8"); // Read Unicode strings, not bytes
let histogram = new Histogram();
for await (let chunk of process.stdin) {
histogram.add(chunk);
}
return histogram;
}
// This one final line of code is the main body of the program.
// It makes a Histogram object from standard input, then prints the histogram.
histogramFromStdin().then((histogram) => {
console.log(histogram.toString());
});