240 lines
6.6 KiB
JavaScript
240 lines
6.6 KiB
JavaScript
|
/**
|
||
|
* JavaScript Exercise 1
|
||
|
* vim: set ts=2 sw=2 et tw=80:
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @param {number[]} a - The array of numbers.
|
||
|
* @param {number} c - The scalar multiplier.
|
||
|
* @return {number[]} An array computed by multiplying each element of the
|
||
|
* input array `a` with the input scalar value `c`.
|
||
|
*/
|
||
|
function scalar_product(a, c) {
|
||
|
if (!Array.isArray(a)) return undefined;
|
||
|
if (!c && c != 0) return a;
|
||
|
return a.map(e => e * c);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {number[]} a - The first array of numbers.
|
||
|
* @param {number[]} b - The second array of numbers.
|
||
|
* @return {number} A value computed by summing the products of each pair
|
||
|
* of elements of its input arrays `a`, `b` in the same position.
|
||
|
*/
|
||
|
function inner_product(a, b) {
|
||
|
if (a.length != b.length) return undefined;
|
||
|
return a.map((e, i) => e * b[i]).reduce((a, e) => a + e, 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {*[]} a - The array.
|
||
|
* @param {function} mapfn - The function for the map step.
|
||
|
* @param {function} [reducefn= function(x,y) { return x+y; }] - The
|
||
|
* function for the reduce step.
|
||
|
* @param {string} [seed=""] - The accumulator for the reduce step.
|
||
|
* @return {*} The reduced value after the map and reduce steps.
|
||
|
*/
|
||
|
function mapReduce(a, mapfn, reducefn, seed = "") {
|
||
|
if (!Array.isArray(a)) return undefined;
|
||
|
if (typeof mapfn != 'function') return undefined;
|
||
|
reducefn = reducefn || ((x, y) => x + y);
|
||
|
|
||
|
for (let i = 0; i < a.length; i++) {
|
||
|
seed = reducefn(seed, mapfn(a[i]));
|
||
|
}
|
||
|
return seed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {number[]} a - The first sorted array of numbers.
|
||
|
* @param {number[]} b - The second sorted array of numbers.
|
||
|
* @return {number[]} A sorted array with all the elements from
|
||
|
* both `a` and `b`.
|
||
|
*/
|
||
|
function mergeSortedArrays(a, b) {
|
||
|
const m = new Array(a.length + b.length);
|
||
|
let ac = a.length - 1, bc = b.length - 1, i = ac + bc + 1;
|
||
|
|
||
|
while (i >= 0) {
|
||
|
if (ac < 0 || b[bc] > a[ac]) m[i--] = b[bc--];
|
||
|
else m[i--] = a[ac--];
|
||
|
}
|
||
|
|
||
|
return m;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {integer} x - The first integer.
|
||
|
* @param {integer} y - The second integer.
|
||
|
* @param {integer} [step=1] - The value to add at each step.
|
||
|
* @return {integer[]} An array containing numbers x, x+step, … last, where:
|
||
|
* - last equals x + n*step for some n,
|
||
|
* - last <= y < last + step if step > 0 and
|
||
|
* - last + step < y <= last if step < 0.
|
||
|
*/
|
||
|
function range(x, y, step = 1) {
|
||
|
if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(step)
|
||
|
|| step == 0) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
console.log(x, y, step);
|
||
|
if ((x > y && step > 0) || (x < y && step < 0)) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
const a = [];
|
||
|
|
||
|
while (x < y) {
|
||
|
a.push(x);
|
||
|
x += step;
|
||
|
}
|
||
|
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {*[]} a - The array to flatten.
|
||
|
* @return {*[]} A flattened array.
|
||
|
*/
|
||
|
function flatten(arr) {
|
||
|
if (!Array.isArray(arr)) {
|
||
|
return arr;
|
||
|
}
|
||
|
|
||
|
const a = [];
|
||
|
arr.forEach(e => {
|
||
|
e = flatten(e); Array.isArray(e) ? a.push(...e) : a.push(e); });
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {integer} [line_size=72] - The line size.
|
||
|
* @return {function} A function that takes a string as an argument
|
||
|
* and returns an array of strings where:
|
||
|
* a. each string length is no more than `line_size` and
|
||
|
* b. doesn't contain line breaks, tabs, double spaces and initial/trailing
|
||
|
* white spaces.
|
||
|
*/
|
||
|
function mkPrettyPrinter(line_size = 72) {
|
||
|
if (!Number.isFinite(line_size)) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
return (s) => {
|
||
|
if (typeof s !== 'string') {
|
||
|
return undefined;
|
||
|
}
|
||
|
s = s.replace('\n', ' ').trim().replace(/\s+/g, ' ');
|
||
|
|
||
|
const a = [];
|
||
|
let i = -1;
|
||
|
const words = s.split(' ');
|
||
|
for (const word of words) {
|
||
|
if (i == -1 || a[i].length + 1 + word.length > line_size) {
|
||
|
a[++i] = word;
|
||
|
} else {
|
||
|
a[i] += ' ' + word;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return a;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {integer} line_size - The line size.
|
||
|
* @param {integer} [level=0] level - The indentation level.
|
||
|
* @return {function} A function twith the following behavior:
|
||
|
* - If called with an integer `n`, change the indentation level by
|
||
|
* adding `n`to the current indentation level.
|
||
|
* - If called with `true`, return the current indentation level.
|
||
|
* - If called with a string:
|
||
|
* - break it into lines with length (after adding the indentation)
|
||
|
* no more than `line_size`,
|
||
|
* - add spaces in front of each line according to the current
|
||
|
* indentation level and
|
||
|
* - store the resulting lines internally.
|
||
|
* - [optional] If called with an array of strings, create an
|
||
|
* bullet list (using `*`) taking current indentation level into
|
||
|
* account. Also, each element should be properly broken into lines and indented.
|
||
|
* - If called with no arguments, produce an array with the lines stored so far.
|
||
|
* Internal storage must be emptied. Indentation level must not be changed.
|
||
|
*/
|
||
|
function mkIndenter(line_size, level=0) {
|
||
|
if (!Number.isFinite(line_size) || !Number.isFinite(level)) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
let state = [];
|
||
|
return (param) => {
|
||
|
if (Number.isInteger(param)) {
|
||
|
level += param;
|
||
|
} else if (param === true) {
|
||
|
return level;
|
||
|
} else if (typeof param === 'string') {
|
||
|
console.log(param);
|
||
|
|
||
|
let words = mkPrettyPrinter(line_size - level)(param);
|
||
|
words = words.map(e => ' ' * level + e);
|
||
|
state.push(...words);
|
||
|
|
||
|
console.log(line_size, level, param, state);
|
||
|
} else if (Array.isArray(param)) {
|
||
|
for (const e of param) {
|
||
|
if (typeof e !== 'string') {
|
||
|
return;
|
||
|
}
|
||
|
const words = mkPrettyPrinter(line_size - level - 2)(param);
|
||
|
state.push('* ' + words[0]);
|
||
|
|
||
|
for (let i = 1; i < words.length; i++) {
|
||
|
state.push(' ' + words[i]);
|
||
|
}
|
||
|
}
|
||
|
} else if (param === void(0)) {
|
||
|
const a = state;
|
||
|
state = [];
|
||
|
return a;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* JavaScript Exercise 2
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Calculates the number of occurrences of letters in a given string
|
||
|
* @param {string} a - The input string.
|
||
|
* @return {number[]} An array indexed by the letter characters found in the string.
|
||
|
*/
|
||
|
function letter_frequency(s) {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Displays the output of the letter frequency analysis in an HTML table
|
||
|
* generated within the `dom` element passed as parameter
|
||
|
* @param {number[]} a - The array indexed by the letter characters as returned
|
||
|
* from `letter_frequency()`.
|
||
|
* @param {Object} dom - The DOM element that will contain the resulting table.
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
function display_letter_frequency(a, dom) {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Links the provided input text field in the test page with the table.
|
||
|
* @param {Object} inputEl - The DOM object of the input element in test.html.
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
function online_frequency_analysis(inputEl) {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* JavaScript Exercise 3
|
||
|
*/
|
||
|
function clock(){
|
||
|
|
||
|
}
|