Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
77
Task/Stem-and-leaf-plot/JavaScript/stem-and-leaf-plot-1.js
Normal file
77
Task/Stem-and-leaf-plot/JavaScript/stem-and-leaf-plot-1.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
|
||||
<title>stem and leaf plot</title>
|
||||
<script type='text/javascript'>
|
||||
|
||||
function has_property(obj, propname) {
|
||||
return typeof(obj[propname]) === "undefined" ? false : true;
|
||||
}
|
||||
|
||||
function compare_numbers(a, b) {return a-b;}
|
||||
|
||||
function stemplot(data, target) {
|
||||
var stem_data = {};
|
||||
var all_stems = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var stem = Math.floor(data[i] / 10);
|
||||
var leaf = Math.round(data[i] % 10);
|
||||
if (has_property(stem_data, stem)) {
|
||||
stem_data[stem].push(leaf);
|
||||
} else {
|
||||
stem_data[stem] = [leaf];
|
||||
all_stems.push(stem);
|
||||
}
|
||||
}
|
||||
all_stems.sort(compare_numbers);
|
||||
|
||||
var min_stem = all_stems[0];
|
||||
var max_stem = all_stems[all_stems.length - 1];
|
||||
|
||||
var table = document.createElement('table');
|
||||
for (var stem = min_stem; stem <= max_stem; stem++) {
|
||||
var row = document.createElement('tr');
|
||||
var label = document.createElement('th');
|
||||
row.appendChild(label);
|
||||
label.appendChild(document.createTextNode(stem));
|
||||
if (has_property(stem_data, stem)) {
|
||||
stem_data[stem].sort(compare_numbers);
|
||||
for (var i = 0; i < stem_data[stem].length; i++) {
|
||||
var cell = document.createElement('td');
|
||||
cell.appendChild(document.createTextNode(stem_data[stem][i]));
|
||||
row.appendChild(cell);
|
||||
}
|
||||
}
|
||||
table.appendChild(row);
|
||||
}
|
||||
target.appendChild(table);
|
||||
}
|
||||
|
||||
</script>
|
||||
<style type='text/css'>
|
||||
body {font-family: monospace;}
|
||||
table {border-collapse: collapse;}
|
||||
th {border-right: 1px solid black; text-align: right;}
|
||||
td {text-align: right;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="target"></div>
|
||||
|
||||
<script type='text/javascript'>
|
||||
|
||||
var data = [
|
||||
12,127,28,42,39,113,42,18,44,118,44,37,113,124,37,48,127,36,29,31,125,139,131,
|
||||
115,105,132,104,123,35,113,122,42,117,119,58,109,23,105,63,27,44,105,99,41,128,
|
||||
121,116,125,32,61,37,127,29,113,121,58,114,126,53,114,96,25,109,7,31,141,46,13,
|
||||
27,43,117,116,27,7,68,40,31,115,124,42,128,52,71,118,117,38,27,106,33,117,116,
|
||||
111,40,119,47,105,57,122,109,124,115,43,120,43,27,27,18,28,48,125,107,114,34,
|
||||
133,45,120,30,127,31,116,146
|
||||
];
|
||||
stemplot(data, document.getElementById('target'));
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
211
Task/Stem-and-leaf-plot/JavaScript/stem-and-leaf-plot-2.js
Normal file
211
Task/Stem-and-leaf-plot/JavaScript/stem-and-leaf-plot-2.js
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
(() => {
|
||||
// main :: IO String
|
||||
const main = () => {
|
||||
|
||||
// Strings derived from integers,
|
||||
// and split into [(initial string, final character)] tuples.
|
||||
|
||||
// xs :: [(String, Char)]
|
||||
const xs = map(n => fanArrow(init, last)(n.toString()), [
|
||||
12, 127, 28, 42, 39, 113, 42, 18, 44, 118, 44, 37, 113, 124,
|
||||
37, 48, 127, 36, 29, 31, 125, 139, 131, 115, 105, 132, 104,
|
||||
123, 35, 113, 122, 42, 117, 119, 58, 109, 23, 105, 63, 27,
|
||||
44, 105, 99, 41, 128, 121, 116, 125, 32, 61, 37, 127, 29, 113,
|
||||
121, 58, 114, 126, 53, 114, 96, 25, 109, 7, 31, 141, 46, 13, 27,
|
||||
43, 117, 116, 27, 7, 68, 40, 31, 115, 124, 42, 128, 52, 71, 118,
|
||||
117, 38, 27, 106, 33, 117, 116, 111, 40, 119, 47, 105, 57, 122,
|
||||
109, 124, 115, 43, 120, 43, 27, 27, 18, 28, 48, 125, 107, 114,
|
||||
34, 133, 45, 120, 30, 127, 31, 116, 146
|
||||
]);
|
||||
|
||||
// Re-reading the initial strings as Ints
|
||||
// (empty strings read as 0),
|
||||
|
||||
// ns :: [(Int, Char)]
|
||||
const ns = map(x => {
|
||||
const s = fst(x);
|
||||
return Tuple(s.length > 0 ? (
|
||||
parseInt(s, 10)
|
||||
) : 0, snd(x));
|
||||
}, xs);
|
||||
|
||||
// and sorting and grouping by these initial Ints,
|
||||
// interpreting them as data-collection bins.
|
||||
|
||||
// bins :: [[(Int, Char)]]
|
||||
const bins =
|
||||
groupBy(
|
||||
(a, b) => a[0] === b[0],
|
||||
sortBy(mappendComparing([
|
||||
[fst, true],
|
||||
[snd, true]
|
||||
]), ns)
|
||||
);
|
||||
|
||||
// Forming bars by the ordered accumulation of
|
||||
// final characters in each bin,
|
||||
|
||||
// bars :: [(Int, String)]
|
||||
const bars = map(
|
||||
fanArrow(
|
||||
x => fst(x[0]),
|
||||
x => map(snd, x)
|
||||
),
|
||||
bins
|
||||
);
|
||||
|
||||
// and obtaining a complete series, with empty bars
|
||||
// interpolated for any missing integers.
|
||||
|
||||
// series :: [(Int, String)]
|
||||
const series = concat(mapAccumL(
|
||||
(a, x) => {
|
||||
const n = x[0];
|
||||
return a !== n ? (
|
||||
Tuple(1 + n,
|
||||
map(i => Tuple(i, []),
|
||||
enumFromToInt(a, n - 1)
|
||||
)
|
||||
.concat([x])
|
||||
)
|
||||
) : Tuple(1 + a, [x]);
|
||||
}, 7, bars
|
||||
)[1]);
|
||||
|
||||
// Assembling the series as a list of strings with
|
||||
// right-justified indices,
|
||||
|
||||
// plotLines :: [String]
|
||||
const plotLines = foldr(
|
||||
(x, a) => cons(concat([
|
||||
justifyRight(2, ' ', x[0].toString()),
|
||||
' | ',
|
||||
unwords(x[1])
|
||||
]), a), [],
|
||||
series
|
||||
);
|
||||
|
||||
// and passing these over to IO as a single
|
||||
// newline-delimited string.
|
||||
|
||||
return unlines(plotLines);
|
||||
};
|
||||
|
||||
// GENERIC FUNCTIONS -----------------------------------------------------
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = (a, b) => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b
|
||||
});
|
||||
|
||||
// compare :: a -> a -> Ordering
|
||||
const compare = (a, b) => a < b ? -1 : (a > b ? 1 : 0);
|
||||
|
||||
// concat :: [[a]] -> [a]
|
||||
// concat :: [String] -> String
|
||||
const concat = xs =>
|
||||
xs.length > 0 ? (() => {
|
||||
const unit = typeof xs[0] === 'string' ? '' : [];
|
||||
return unit.concat.apply(unit, xs);
|
||||
})() : [];
|
||||
|
||||
// cons :: a -> [a] -> [a]
|
||||
const cons = (x, xs) => [x, ...xs];
|
||||
|
||||
// enumFromToInt :: Int -> Int -> [Int]
|
||||
const enumFromToInt = (m, n) =>
|
||||
n >= m ? Array.from({
|
||||
length: Math.floor(n - m) + 1
|
||||
}, (_, i) => m + i) : [];
|
||||
|
||||
// Compose a function from a simple value to a tuple of
|
||||
// the separate outputs of two different functions
|
||||
// fanArrow (&&&) :: (a -> b) -> (a -> c) -> (a -> (b, c))
|
||||
const fanArrow = (f, g) => x => Tuple(f(x), g(x));
|
||||
|
||||
// flip :: (a -> b -> c) -> b -> a -> c
|
||||
const flip = f => (a, b) => f.apply(null, [b, a]);
|
||||
|
||||
// Note that that the Haskell signature of foldr is different from that of
|
||||
// foldl - the positions of accumulator and current value are reversed
|
||||
// foldr :: (a -> b -> b) -> b -> [a] -> b
|
||||
const foldr = (f, a, xs) => xs.reduceRight(flip(f), a);
|
||||
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl => tpl.type !== 'Tuple' ? undefined : tpl[0];
|
||||
|
||||
// Typical usage: groupBy(on(eq, f), xs)
|
||||
// groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
|
||||
const groupBy = (f, xs) => {
|
||||
const dct = xs.slice(1)
|
||||
.reduce((a, x) => {
|
||||
const h = a.active.length > 0 ? a.active[0] : undefined;
|
||||
return h !== undefined && f(h, x) ? {
|
||||
active: a.active.concat([x]),
|
||||
sofar: a.sofar
|
||||
} : {
|
||||
active: [x],
|
||||
sofar: a.sofar.concat([a.active])
|
||||
};
|
||||
}, {
|
||||
active: xs.length > 0 ? [xs[0]] : [],
|
||||
sofar: []
|
||||
});
|
||||
return dct.sofar.concat(dct.active.length > 0 ? [dct.active] : []);
|
||||
};
|
||||
|
||||
// init :: [a] -> [a]
|
||||
const init = xs => xs.length > 0 ? xs.slice(0, -1) : undefined;
|
||||
|
||||
// justifyRight :: Int -> Char -> String -> String
|
||||
const justifyRight = (n, cFiller, strText) =>
|
||||
n > strText.length ? (
|
||||
(cFiller.repeat(n) + strText)
|
||||
.slice(-n)
|
||||
) : strText;
|
||||
|
||||
// last :: [a] -> a
|
||||
const last = xs => xs.length ? xs.slice(-1)[0] : undefined;
|
||||
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = (f, xs) => xs.map(f);
|
||||
|
||||
// mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
|
||||
const mapAccumL = (f, acc, xs) =>
|
||||
xs.reduce((a, x, i) => {
|
||||
const pair = f(a[0], x, i);
|
||||
return Tuple(pair[0], a[1].concat(pair[1]));
|
||||
}, Tuple(acc, []));
|
||||
|
||||
// mappendComparing :: [((a -> b), Bool)] -> (a -> a -> Ordering)
|
||||
const mappendComparing = fboolPairs =>
|
||||
(x, y) => fboolPairs.reduce(
|
||||
(ordr, fb) => {
|
||||
const f = fb[0];
|
||||
return ordr !== 0 ? (
|
||||
ordr
|
||||
) : fb[1] ? (
|
||||
compare(f(x), f(y))
|
||||
) : compare(f(y), f(x));
|
||||
}, 0
|
||||
);
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => tpl.type !== 'Tuple' ? undefined : tpl[1];
|
||||
|
||||
// sortBy :: (a -> a -> Ordering) -> [a] -> [a]
|
||||
const sortBy = (f, xs) =>
|
||||
xs.slice()
|
||||
.sort(f);
|
||||
|
||||
// unlines :: [String] -> String
|
||||
const unlines = xs => xs.join('\n');
|
||||
|
||||
// unwords :: [String] -> String
|
||||
const unwords = xs => xs.join(' ');
|
||||
|
||||
// MAIN ------------------------------------------------------------------
|
||||
return main();
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue