Skip to content

Instantly share code, notes, and snippets.

@LGitHub-sprout
Last active June 29, 2023 15:28
Show Gist options
  • Save LGitHub-sprout/e692455d8b52344814142a4bc808aab2 to your computer and use it in GitHub Desktop.
Save LGitHub-sprout/e692455d8b52344814142a4bc808aab2 to your computer and use it in GitHub Desktop.
TOP Foundations Exercises #8-12
// https://www.theodinproject.com/lessons/foundations-fundamentals-part-5#assignment
// Calculator bits and pieces
// 1. The calculator functions
const add = (a, b) => a += b;
const subtract = (a, b) => a -= b;
const multiply = (a, b) => a *= b;
const divide = (a, b) => a /= b;
function operate(operator, num1, num2) { // still needs the operators
if (operator === '+') {
return add(num1, num2);
}
if (operator === '-') {
return subtract(num1, num2);
}
if (operator === '*') {
return multiply(num1, num2);
}
if (operator === '/') {
return divide(num1, num2);
}
return operator;
// takes an operator and 2 nums
// then calls one of the above functions on the nums.
};
// console.log(operate('+', 6, 4)); console.log(operate('-', 6, 1)); console.log(operate('*', 3, 4)); console.log(operate('/', 3, 4));
// Using a constructor
function Calculator(a, b, operator, element) {
this.a = 0;
this.b = 0;
this.operator = ['+', '-', '*', '/'];
this.add = function (a, b) { return a += b; };
// Display receives click/keypress value & shows on screen
// Also builds equation string for operations stack
// https://stackoverflow.com/questions/12731528/adding-event-listeners-in-constructor
// https://www.section.io/engineering-education/keyboard-events-in-javascript/#handling-keyboard-events-in-javascript
const display = document.querySelector('.calc-display-wrap'); // console.log(display)
display.textContent = 'poop';
// this.element = document.querySelector('.calc-display-wrap');
const self = this;
this.bar = function (event, element) {
// console.log(event);
// return event; // no need to return event?
};
// window.addEventListener('keypress', // keydown
// function (event, element) {
// display.textContent += `${event.key}`;
// // console.log(display); // this.element is undefined,
// // console.log(event.clientY, event.clientX); // event
// // event.preventDefault();
// // self.bar(event.clientX); // seems to do nothing
// }
// );
};
// const calc = new Calculator('.calc-display-wrap');
// calc; // works, but bar() doesn't do anything
// // Display receives click/keypress value & shows on screen
// // Also builds equation string for operations stack
// // https://stackoverflow.com/questions/12731528/adding-event-listeners-in-constructor
// this.element = document.querySelector('.calc-display-wrap');
// const self = this;
// this.bar = function (event, element) {
// // console.log(event);
// // return event; // no need ot return event?
// };
// this.element.addEventListener('click', // keydown
// function (event, element) {
// console.log(this.element); // undefined
// // self.bar(event.clientX);
// console.log(event.clientY, event.clientX); // event
// event.preventDefault();
// });
// };
// const calc = new Calculator('.calc-display-wrap');
// calc.bar(display);
// const calc = new Calculator();
// console.log(calc.add(21, 34)); // 55
// console.log(calc.operator.includes('*')); // true
// console.log(calc.operator.filter(o => o === '*').join()); // string
// console.log(calc.operator.find(e => e === '/')); // works
// https://www.geeksforgeeks.org/how-to-create-dynamic-length-array-with-numbers-and-sum-the-numbers-using-javascript/
// operate() using reduce()
let input = '1000 - 5000';
// would need display to a space after 1st num and operator
const getInputArray = function (str) {
return str.split(' '); // .map(Number);
};
// It makes sense to pull out the indiv nums and operator early
const operate2 = function () {
const inputArr = getInputArray(input); console.log(inputArr); // (3) ['699', '-', '9156987']
if (inputArr.includes('-')) {
// I need a variable for the operator to pass as param for display
// also need the actual arithmetic operator for expression
const operator = inputArr.indexOf('-'); console.log(operator)
return inputArr.toSpliced(operator, 1).reduce((acc, currVal, i, a) => {
//currVal -= acc; // 1000 wrong
acc -= currVal;
// currVal = +currVal;
console.log('value', currVal, acc)
// acc -= currVal; // Wrong! 0 - 1000 = -1000
return acc;
}); //, 0);
}
return getInputArray(input);
};
// console.log(operate2());
/*
Remember that I need vars for ea operand & operator for the display.
I have an array to loop over
if array contains includes specific operator
slice splice, then reduce?
*/
// Display
const display = document.querySelector('.calc-display-wrap'); // console.log(display)
const para = document.createElement('p');
// display.append(para); // .setAttribute('class', 'poop');
// const display = document.getElementsByClassName('display'); console.log(typeof Array.from(display));
display.setAttribute('style', 'border:solid 1px #7f7f7f; height:2em; text-align:center;');
// const key = document.querySelector('.key'); console.log(key); // works
function printToDisplay(e) {
// console.log(e.target.tagName, Array.from(e.target.classList).includes('display'));
// console.log('e', e.key, typeof e.key, e.currentTarget, e.target.tagName); // .key is the value, target is element?
// question is how to target the child of display-wrap
const str = e.key;
const code = e.code.charAt(0); // Numpad1 thru Numpad0
// console.log(typeof key, key, e.key, typeof str, e.type); // string, key value '1', '2', etc.
// console.log(e.code, str); // typeof object typeof e, e,
// overflow: hidden; https://stackoverflow.com/questions/1165497/how-to-prevent-text-from-overflowing-in-css
if (e.key === 'Clear') display.textContent = '';
// the problem is to add spaces to the operator
// console.log(str.split()); // string to array
if (code === 'N' && e.key !== 'Clear') display.textContent += str; // prints number to the display
if (e.key === 'Enter' || e.key === '=') display.textContent = calc.add(a, b); // works, but needs (a, b) vars
// if (key === 'Clear') display.textContent = str; // nope
// const key = document.querySelector(`div[data-key="${e.key}"]`);
};
document.addEventListener('keydown', printToDisplay); // document or window works
// 12. Find The Oldest
/* Some resources I found while working on this problem:
https://www.google.com/search?q=return+product+of+nested+objects+without+mutation+javascript&oq=return+product+of+nested+objects+without+mutation+javascript+&aqs=chrome..69i57.41064j0j7&sourceid=chrome&ie=UTF-8#ip=1
https://dev.to/krsgrnt/safely-copying-nested-objects-in-javascript-5fpi
https://www.amitmerchant.com/reduce-array-of-objects-to-an-object-in-javascript/#:~:text=reduce()%20method%2C%20we%20can,wanted%20as%20an%20end%20result.
https://www.redbitdev.com/post/using-array-reduce-with-objects
https://stackoverflow.com/questions/40025718/es6-finding-data-in-nested-arrays
*/
/*
@toby Pass obj properties as args
Given an object with possible fields
(yearOfBrith and yearOfDeath may or may not exist)
take the data and return an age.
Just one object, one function, no mutation, no reduce.
*/
const person = {
name: 'Toby',
// yearOfBirth: 1969,
yearOfDeath: 2088,
};
/*
Getting the idea: it's helper function that returns age, passes properties if missing.
Use getCurrentAge() to return ages for comparison in findTheOldes()
*/
const getCurrentAge = ({
yearOfBirth = new Date().getFullYear(),
yearOfDeath = new Date().getFullYear()
}) => yearOfDeath - yearOfBirth;
// console.log('tobys getCurrentAge', getCurrentAge(person)); // 119, 54 or 65 depending which props are missing.
// Odin Solution
// I want calcAge() to return the product of subtracting death from birth to get ea person's age.
// If 'death' doesn't exist, use the new Date() to get the current year.
// The findTheOldest() uses vars created using calcAge() to compare which person is eldest.
const calcAge = (death, birth) => {
if (!death) {
death = new Date().getFullYear();
}
return death - birth;
};
// console.log('calcAge', calcAge(null, 1966));
const findTheOldest2 = function (arr) {
// looking for oldest so name accumulator 'eldest'
return arr.reduce((eldest, currVal) => {
// use calcAge() to initialize
eldestAge = calcAge(eldest.yearOfDeath, eldest.yearOfBirth);
currValAge = calcAge(currVal.yearOfDeath, currVal.yearOfBirth)
// notice when compared like this: 'eldestAge > currValAge ? eldest : currVal' it doesn't work.
return eldestAge < currValAge ? currVal : eldest;
});
};
// My final working version.
const findTheOldest = function (arr, currY = new Date().getFullYear()) {
return arr.reduce((acc, currVal) => {
if ('yearOfDeath' in acc === false && currY - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth) return acc;
return acc = acc.yearOfDeath - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth ? acc : currVal;
});
};
// Duh! Just pass current year as an arg :|
const findTheOldest = function (arr, currY = new Date().getFullYear()) {
return arr.reduce((acc, currVal) => {
if ('yearOfDeath' in acc === false) {
if (currY - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth) return acc;
}
return acc = acc.yearOfDeath - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth ? acc : currVal;
});
};
// Using Object.assign() stops mutation
const findTheOldest = function (arr) {
return arr.reduce((acc, currVal) => {
if ('yearOfDeath' in acc === false) {
const target = { yearOfDeath: new Date().getFullYear() };
Object.assign(target, acc)
if (target.yearOfDeath - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth) return acc;
}
if (acc.yearOfDeath - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth) return acc;
return currVal;
});
};
// Passes tests but mutates array
const findTheOldest = function (arr) { // didn't work [{}, ...arr]
const currYear = new Date();
return arr.reduce((acc, currVal, index, theArr) => {
if ('yearOfDeath' in acc === false) {
acc['yearOfDeath'] = currYear.getFullYear();
}
if (acc.yearOfDeath - acc.yearOfBirth > currVal.yearOfDeath - currVal.yearOfBirth) {
if ('yearOfDeath' in acc === false) console.log('AFTER: caught it?', acc); // Nothing for 'true' 'false' or 'undefined'
return acc; // Removing return on 'acc' returns last item ('Jane')
}
return currVal;
});
}
// 11. Get The Titles
const getTheTitles = function (arr) {
return arr.reduce((acc, currentVal) => {
// console.log('currentVal', currentVal, typeof currentVal, Array.isArray(currentVal))
// console.log(currentVal.title, typeof currentVal.title)
acc.push(currentVal.title)
// for (title of currentVal.title) {
// acc.push(title)
// }
return acc;
}, []);
};
console.log('getTheTitles', getTheTitles(books)); // getTheTitles(books)).toEqual( ['Book','Book2'] )
// Fibonacci v.2
// https://www.freecodecamp.org/news/array-map-tutorial/
const oldArray = [33, 20, 10, 5];
const newArray = oldArray.map((currentVal, index, arr) => {
let nextItem = index + 1 < arr.length ? arr[index + 1] : 0
return currentVal - nextItem;
});
// console.log(newArray); // [13, 10, 5, 5]
const fibonacci2 = function (n) {
// Problem is how I'm constructing initial array
// const series = [...Array(n).keys()];
const series = [0, 1, 1, 2];
console.log('series', series);
const result = series.map((el, index, arr) => {
let nextItem = index + 1 < n ? arr[index + 1] : 0;
return el + nextItem; // wrong: doubles el
return el + arr[index]; // wrong: doubles el
// return el = arr[index] + arr[index + 1]; // wrong: add 2 to ea element
// return el + arr[nextItem]; // wrong: both nextItem and arr[nextItem] stil adds 2 to ea el
});
console.log('result', result);
return result[n]; // must subtract 1 to get last element
};
// console.log('fibonacci2', fibonacci2(6)); // (6) .tobe 8
// Fibonacci
// https://www.tutorialspoint.com/adding-two-values-at-a-time-from-an-array-javascript
const fibonacci = function(n) {
n = Number(n);
if (n < 0) return 'OOPS';
const arr = [0, 1];
for (let i = 0; i < n; i++) {
arr.push(arr[i] + arr[i + 1]);
}
return arr[n];
};
// // Palindromes v.2 & v.3 w RegEx examples
// const spaceRE = /\s+/g;
// const digitRE = /\d+/g;
// const alphaAZ = /([a-z])/g; // /([a-z])/g; /([a-z])\w+/g;
// punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]/g;
const palindromes = function (str) {
str = str.toLowerCase();
const extractedStr = str.match(/([a-z])/g);
const strMatch = [...extractedStr].join(''); // compare w strReverse for equality
// let strReverse = [];
let strReverse = '';
for (let i = extractedStr.length - 1; i >= 0; i--) {
strReverse += extractedStr[i];
}
// for (let i = extractedStr.length; i >= 0; i--) {
// strReverse.push(extractedStr[i]);
// }
// return strReverse = strReverse.join('') === strMatch ? true : false;
return strReverse = strReverse === strMatch ? true : false;
};
// Panindromes
const palindromes = function (str) {
const spaceRE = /\s+/g;
const digitRE = /\d+/g;
punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]/g;
const newStr = str.replace(spaceRE, '').replace(digitRE, '').replace(punctRE, '').toLowerCase();
const reverseStr = [...newStr].reverse().join('');
return newStr === reverseStr;
};
// Factorial https://www.thoughtco.com/why-does-zero-factorial-equal-one-3126598
// Khan Academy Factorial https://www.khanacademy.org/math/precalculus/x9e81a4f98389efdf:prob-comb/x9e81a4f98389efdf:combinatorics-precalc/v/factorial-and-counting-seat-arrangements
// console.log(5 * 4 * 3 * 2 * 1); // factorial 5 or 5! s/b 120
// TOP recursive example - no range or loop necessary
const factorial4 = function (num) {
if (num === 0) return 1;
return num * factorial4(num - 1);
};
console.log(factorial4(10)); // 120
// my factorial loop solution
const factorial3 = function (num) {
let product = 1;
for (let i = num; i > 0; i--) {
product *= i;
}
return product;
};
// console.log(factorial3(10)); // 3628800
/* range()
It seems I'll need to create a range for factorial.
But I need it to go from start to zero (or 1, I suppose).
Functional Programming Recursive Range Solution
https://dev.to/ycmjason/how-to-create-range-in-javascript-539i
*/
// function recursiveRange (start, end) {
// if (start === end) return [start];
// // recursive case
// return [start, ...recursiveRange(start + 1, end)];
// }
// console.log(recursiveRange(3, 13)); // [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
const loopRange = (start = 0) => {
const startArr = [start];
if (startArr.includes(0)) return 1;
let end = start - 1;
for (start; end > 0; end--) startArr.push(end);
const factorial = startArr.reduce((acc, currentVal) => {
// console.log(currentVal, start);
return start *= currentVal;
});
return factorial;
};
console.log('loopRange', loopRange(19)); // 5! = 120, 10! = 3628800
// raises one number to the power of another number
const power = function (num, pow) {
let total = 1;
for (let i = 1; i <= pow; i++) {
total *= num;
}
return total;
};
// console.log(7 * 7 * 7 * 7 * 7 * 7 * 7 * 7, 'manual 7pow8'); // 5764801
// console.log(power(7, 8), '7pow8'); // 5764801
const power3 = function (base, pow) {
return arr = [...Array(pow).fill(base)].reduce((acc, currentVal) => acc * currentVal);
};
console.log(power3(4, 3)); // 64
console.log(4 * 4 * 4); // 64
console.log(power3(6, 2)); // 36
console.log(power3(6, 9)); // 10077696
console.log(power3(7, 8)); // 5764801
console.log(7 * 7 * 7 * 7 * 7 * 7 * 7 * 7, 'manual 7 to power of 8'); // 5764801
const multiplyNums = [2, 4, 6, 8, 10, 12, 14]; // [2, 4, 6, 8, 10, 12, 14]
const multiply = [...multiplyNums].reduce((acc, nextNum) => {
return acc *= nextNum;
});
// console.log('multipy', multiply); // 645120
const sum = function (arr) {
return arr.reduce((acc, currentVal) => {
return acc += currentVal;
}, 0,
);
};
console.log(sum([1,3,5,7,9])); // 25
const sumNums = [1, 3, 5, 7, 9];
const sum = [...sumNums].reduce((acc, nextNum) => {
return acc += nextNum;
}, 0);
// console.log('sum', sum); // s/b 25
const sumLoop = (arr) => {
let total = 0;
for (let i = 0; i < arr.length; i++) {
// console.log(arr[i]);
// total = total + arr[i];
total += arr[i];
}
return total;
};
// console.log('sumLoop', sumLoop(sumNums)); // 25
const add = function (num1, ...theArgs) {
for (let num2 of theArgs) return num1 += num2;
};
// console.log(add(2, 6)); // 8
const subtract = function (num1, ...theArgs) { // ...theArgs is an array, therefore: loop
for (let num of theArgs) {
num1 -= num;
}
return num1;
};
// console.log(subtract(10, 4, 12, 11, 9, 6, 19, 4)); // 6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment