Files
.github
api-server
client
config
curriculum
__fixtures__
challenges
_meta
chinese
english
01-responsive-web-design
02-javascript-algorithms-and-data-structures
basic-algorithm-scripting
basic-data-structures
basic-javascript
basic-javascript-rpg-game
debugging
es6
functional-programming
functional-programming-spreadsheet
part-001.md
part-002.md
part-003.md
part-004.md
part-005.md
part-006.md
part-007.md
part-008.md
part-009.md
part-010.md
part-011.md
part-012.md
part-013.md
part-014.md
part-015.md
part-016.md
part-017.md
part-018.md
part-019.md
part-020.md
part-021.md
part-022.md
part-023.md
part-024.md
part-025.md
part-026.md
part-027.md
part-028.md
part-029.md
part-030.md
part-031.md
part-032.md
part-033.md
part-034.md
part-035.md
part-036.md
part-037.md
part-038.md
part-039.md
part-040.md
part-041.md
part-042.md
part-043.md
part-044.md
part-045.md
part-046.md
part-047.md
part-048.md
part-049.md
part-050.md
part-051.md
part-052.md
part-053.md
part-054.md
part-055.md
part-056.md
part-057.md
part-058.md
part-059.md
part-060.md
part-061.md
part-062.md
part-063.md
part-064.md
part-065.md
part-066.md
part-067.md
part-068.md
part-069.md
part-070.md
part-071.md
part-072.md
part-073.md
part-074.md
part-075.md
part-076.md
part-077.md
part-078.md
part-079.md
part-080.md
part-081.md
part-082.md
part-083.md
part-084.md
part-085.md
part-086.md
part-087.md
part-088.md
part-089.md
part-090.md
part-091.md
part-092.md
part-093.md
part-094.md
part-095.md
part-096.md
part-097.md
part-098.md
part-099.md
part-100.md
part-101.md
part-102.md
part-103.md
part-104.md
part-105.md
part-106.md
part-107.md
part-108.md
part-109.md
part-110.md
part-111.md
part-112.md
part-113.md
part-114.md
part-115.md
part-116.md
part-117.md
part-118.md
part-119.md
part-120.md
part-121.md
part-122.md
part-123.md
part-124.md
part-125.md
part-126.md
part-127.md
part-128.md
part-129.md
part-130.md
part-131.md
part-132.md
part-133.md
part-134.md
part-135.md
part-136.md
part-137.md
part-138.md
part-139.md
part-140.md
part-141.md
intermediate-algorithm-scripting
intermediate-javascript-calorie-counter
javascript-algorithms-and-data-structures-projects
object-oriented-programming
regular-expressions
03-front-end-libraries
04-data-visualization
05-apis-and-microservices
06-quality-assurance
07-scientific-computing-with-python
08-data-analysis-with-python
09-information-security
10-coding-interview-prep
11-machine-learning-with-python
12-certificates
schema
test
.babelrc
LICENSE.md
comment-dictionary.js
create-challenge-bundle.js
getChallenges.acceptance.test.js
getChallenges.js
getChallenges.test.js
gulpfile.js
lib.js
package-entry.js
package-lock.json
package.json
utils.js
cypress
docs
tools
utils
.editorconfig
.eslintignore
.eslintrc.json
.gitattributes
.gitignore
.gitpod.yml
.node-inspectorrc
.npmrc
.prettierignore
.prettierrc
.snyk
.vcmrc
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Dockerfile.tests
HoF.md
LICENSE.md
README.md
SECURITY.md
change_volumes_owner.sh
crowdin.yml
cypress-install.js
cypress.json
docker-compose-shared.yml
docker-compose.tests.yml
docker-compose.yml
jest.config.js
lerna.json
lighthouserc.js
package-lock.json
package.json
sample.env

325 lines
7.9 KiB
Markdown
Raw Normal View History

---
id: 5d7925395888767e9304c082
title: Part 119
challengeType: 0
---
## Description
<section id='description'>
The `reduce` method takes a function with an accumulator and the current value. The accumulator is initially set to the value at index 0.
The `reduce` method then goes through each element of the array after that, passing in the element as the current value and the result of the last call as the accumulator.
For example, here's how to multiply all the value in an array:
```js
[2, 3, 4].reduce((a, x) => a * x); // 24
```
Using `reduce`, add a function `sum` to `spreadsheetFunctions`, which sums all values in the array passed to it.
</section>
## Instructions
<section id='instructions'>
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: See description above for instructions.
testString: assert(spreadsheetFunctions.sum([10,5,1,3]) === 19 && code.includes("reduce"));
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
const infixToFunction = {
"+": (x, y) => x + y,
"-": (x, y) => x - y,
"*": (x, y) => x * y,
"/": (x, y) => x / y
};
const infixEval = (str, regex) =>
str.replace(regex, (_, arg1, fn, arg2) =>
infixToFunction[fn](parseFloat(arg1), parseFloat(arg2))
);
const highPrecedence = str => {
const regex = /([0-9.]+)([*\/])([0-9.]+)/;
const str2 = infixEval(str, regex);
return str === str2 ? str : highPrecedence(str2);
};
const isEven = num => num % 2 === 0;
const spreadsheetFunctions = {
"": x => x,
random: ([x, y]) => Math.floor(Math.random() * y + x),
increment: nums => nums.map(x => x + 1),
firsttwo: arr => arr.slice(0, 2),
lasttwo: arr => arr.slice(-2),
even: nums => nums.filter(isEven)
};
const applyFn = str => {
const noHigh = highPrecedence(str);
const infix = /([0-9.]+)([+-])([0-9.]+)/;
const str2 = infixEval(noHigh, infix);
const regex = /([a-z]*)\(([0-9., ]*)\)(?!.*\()/i;
const toNumberList = args => args.split(",").map(parseFloat);
const applyFunction = (fn, args) =>
spreadsheetFunctions[fn.toLowerCase()](toNumberList(args));
return str2.replace(
regex,
(match, fn, args) =>
spreadsheetFunctions.hasOwnProperty(fn.toLowerCase()) ? applyFunction(fn, args) : match
);
};
const range = (start, end) =>
start > end ? [] : [start].concat(range(start + 1, end));
const charRange = (start, end) =>
range(start.charCodeAt(0), end.charCodeAt(0)).map(x =>
String.fromCharCode(x)
);
const evalFormula = (x, cells) => {
const idToText = id => cells.find(cell => cell.id === id).value;
const rangeRegex = /([A-J])([1-9][0-9]?):([A-J])([1-9][0-9]?)/gi;
const rangeFromString = (n1, n2) => range(parseInt(n1), parseInt(n2));
const elemValue = n => c => idToText(c + n);
const addChars = c1 => c2 => n => charRange(c1, c2).map(elemValue(n));
const varRangeExpanded = x.replace(rangeRegex, (_, c1, n1, c2, n2) =>
rangeFromString(n1, n2).map(addChars(c1)(c2))
);
const varRegex = /[A-J][1-9][0-9]?/gi;
const varExpanded = varRangeExpanded.replace(
varRegex,
match => idToText(match.toUpperCase())
);
const functionExpanded = applyFn(varExpanded);
return functionExpanded === x
? functionExpanded
: evalFormula(functionExpanded, cells);
};
window.onload = () => {
const container = document.getElementById("container");
const createLabel = name => {
const label = document.createElement("div");
label.className = "label";
label.textContent = name;
container.appendChild(label);
};
const letters = charRange("A", "J");
letters.forEach(createLabel);
range(1, 99).forEach(x => {
createLabel(x);
letters.forEach(y => {
const input = document.createElement("input");
input.type = "text";
input.id = y + x;
input.onchange = update;
container.appendChild(input);
});
});
};
const update = event => {
const element = event.target;
const value = element.value.replace(/\s/g, "");
if (!value.includes(element.id) && value[0] === "=") {
element.value = evalFormula(
value.slice(1),
Array.from(document.getElementById("container").children)
);
}
};
</script>
```
</div>
### Before Test
<div id='html-setup'>
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Spreadsheet</title>
<style>
#container {
display: grid;
grid-template-columns: 50px repeat(10, 200px);
grid-template-rows: repeat(11, 30px);
}
.label {
background-color: lightgray;
text-align: center;
vertical-align: middle;
line-height: 30px;
}
</style>
</head>
<body>
<div id="container">
<div></div>
</div>
```
</div>
### After Test
<div id='html-teardown'>
```html
</body>
</html>
```
</div>
</section>
## Solution
<section id='solution'>
```html
<script>
const infixToFunction = {
"+": (x, y) => x + y,
"-": (x, y) => x - y,
"*": (x, y) => x * y,
"/": (x, y) => x / y
};
const infixEval = (str, regex) =>
str.replace(regex, (_, arg1, fn, arg2) =>
infixToFunction[fn](parseFloat(arg1), parseFloat(arg2))
);
const highPrecedence = str => {
const regex = /([0-9.]+)([*\/])([0-9.]+)/;
const str2 = infixEval(str, regex);
return str === str2 ? str : highPrecedence(str2);
};
const isEven = num => num % 2 === 0;
const spreadsheetFunctions = {
"": x => x,
random: ([x, y]) => Math.floor(Math.random() * y + x),
increment: nums => nums.map(x => x + 1),
firsttwo: arr => arr.slice(0, 2),
lasttwo: arr => arr.slice(-2),
even: nums => nums.filter(isEven),
sum: nums => nums.reduce((a, x) => a + x)
};
const applyFn = str => {
const noHigh = highPrecedence(str);
const infix = /([0-9.]+)([+-])([0-9.]+)/;
const str2 = infixEval(noHigh, infix);
const regex = /([a-z]*)\(([0-9., ]*)\)(?!.*\()/i;
const toNumberList = args => args.split(",").map(parseFloat);
const applyFunction = (fn, args) =>
spreadsheetFunctions[fn.toLowerCase()](toNumberList(args));
return str2.replace(
regex,
(match, fn, args) =>
spreadsheetFunctions.hasOwnProperty(fn.toLowerCase()) ? applyFunction(fn, args) : match
);
};
const range = (start, end) =>
start > end ? [] : [start].concat(range(start + 1, end));
const charRange = (start, end) =>
range(start.charCodeAt(0), end.charCodeAt(0)).map(x =>
String.fromCharCode(x)
);
const evalFormula = (x, cells) => {
const idToText = id => cells.find(cell => cell.id === id).value;
const rangeRegex = /([A-J])([1-9][0-9]?):([A-J])([1-9][0-9]?)/gi;
const rangeFromString = (n1, n2) => range(parseInt(n1), parseInt(n2));
const elemValue = n => c => idToText(c + n);
const addChars = c1 => c2 => n => charRange(c1, c2).map(elemValue(n));
const varRangeExpanded = x.replace(rangeRegex, (_, c1, n1, c2, n2) =>
rangeFromString(n1, n2).map(addChars(c1)(c2))
);
const varRegex = /[A-J][1-9][0-9]?/gi;
const varExpanded = varRangeExpanded.replace(
varRegex,
match => idToText(match.toUpperCase())
);
const functionExpanded = applyFn(varExpanded);
return functionExpanded === x
? functionExpanded
: evalFormula(functionExpanded, cells);
};
window.onload = () => {
const container = document.getElementById("container");
const createLabel = name => {
const label = document.createElement("div");
label.className = "label";
label.textContent = name;
container.appendChild(label);
};
const letters = charRange("A", "J");
letters.forEach(createLabel);
range(1, 99).forEach(x => {
createLabel(x);
letters.forEach(y => {
const input = document.createElement("input");
input.type = "text";
input.id = y + x;
input.onchange = update;
container.appendChild(input);
});
});
};
const update = event => {
const element = event.target;
const value = element.value.replace(/\s/g, "");
if (!value.includes(element.id) && value[0] === "=") {
element.value = evalFormula(
value.slice(1),
Array.from(document.getElementById("container").children)
);
}
};
</script>
```
</section>