Refactoring JavaScript (Swtich & Function) - javascript

I'm a beginner at coding, and I'm studying JS. I'd like to know how to write a function inside a switch in this code below (if possible), turning the code smaller.
I tried to place the funtion for each operation inside of the switch, but it never worked.
Help me to improve my code. Thank you!
//Calculator of Basic Operations
function addition(a, b) {
return (a + b);
}
function subtraction(a, b) {
return (a - b);
}
function multiplication(a, b) {
return (a * b);
}
function division(a, b) {
return (a / b);
}
console.log('Choose the number for the operation you want to use.');
console.log('1 - Addition');
console.log('2 - Subtraction');
console.log('3 - Multiplication');
console.log('4 - Division');
let calcAB = prompt('Operation: ');
switch (calcAB) {
case '1':
a = Number(prompt('Enter the value for A: '));
b = Number(prompt('Enter the value for B: '));
console.log(`The addition result is "${addition(a, b)}"`);
break;
case '2':
a = Number(prompt('Enter the value for A: '));
b = Number(prompt('Enter the value for B: '));
console.log(`The subtraction result is "${subtraction(a, b)}"`);
break;
case '3':
a = Number(prompt('Enter the value for A: '));
b = Number(prompt('Enter the value for B: '));
console.log(`The multiplication result is "${multiplication(a, b)}"`);
break;
case '4':
a = Number(prompt('Enter the value for A (dividend): '));
b = Number(prompt('Enter the value for B (divisor): '));
console.log(`The division result is "${division(a, b)}"`);
break;
}

The only things that change between the cases are
The function called
The name of the operation called
The (dividend) (divisor) for /
I'd use an array for the functions and operator names instead - for example, [0] will refer to (a, b) => a + b, so that way you just have to subtract 1 from the number chosen by the user to get to the function. To get a and b, interpolate (dividend) (divisor) only if the case is 4 - but it can all be done at once.
const fns = [
[(a, b) => a + b, 'addition'],
[(a, b) => a - b, 'subtraction'],
[(a, b) => a * b, 'multiplication'],
[(a, b) => a / b, 'division']
];
const op = prompt('Operation: ');
const item = fns[op - 1];
if (!item) {
throw new Error('Invalid');
}
const a = Number(prompt(`Enter the value for A${op === '4' ? ' (dividend)' : ''}: `));
const b = Number(prompt(`Enter the value for b${op === '4' ? ' (divisor)' : ''}: `));
console.log(`The ${item[1]} result is ${item[0](a, b)}`);

Don't make your code complex in order to make it smaller, it makes it more confusing and misses the point, which is to make you understand the syntax and what you are doing

Related

Calculator - issue with multiple digit / operators operations

Newbie here, I am stuck with my Calculator project and cannot continue. There's something wrong with my code an cannot figure out what.
So the issue involves operations on multiple digit numbers (e.g. 22) as well as multiplying / dividing after summing / deducting.
Previously I was struggling with multiple operations in general, but it seems to be now working (with 1 digit numbers only though). Whenever I insert, e.g. 23, the function right away assigns 23 to both first and second operands and gives me 46.
The same thing happens when I use an operator in the 2nd operation which is different than the one used in the first operation (e.g if I use sum operator twice and then deduct, my result will be zero as the result gets assigned to both operands and continues with the operation).
Could someone advise what is the issue with this code? I think it's because of "operand1" variable. The expected behavior would be for the function to stop after each click, but then as soon as the operand1 value changes to "empty" again, the code continues. I tried to override this but nothing I come up with works, I feel like I'm missing something basic.
Thanks in advance!
let add = (a, b) => a + b;
let subtract = (a, b) => a - b;
let multiply = (a, b) => a * b;
let divide = (a, b) => a / b;
function operate(operator, a, b) {
if (operator === '+') {
return add(a, b);
} else if (operator === '-') {
return subtract(a, b);
} else if (operator === '*') {
return multiply(a, b);
} else { return divide(a, b); }
};
const display = document.querySelector("h1"); // display
const numButtons = document.querySelectorAll(".num"); // 0 - 9
const operateButtons = document.querySelectorAll(".operator"); // +, -, *, /
const equals = document.querySelector('#equals') // =
const clearBtn = document.querySelector('#clear'); // AC
let displayValue = []; // add clicked numbers to array
let displayNumbers; // joined array
let operations = ['a','operator','b'];
let operand1 = "empty"; // value that shows if 1st num has already been selected
numButtons.forEach((button) => {
button.addEventListener('click', function() {
displayValue.push(this.innerText);
displayNumbers = displayValue.join("");
display.textContent = displayNumbers;
operateButtons.forEach((button) => {
button.addEventListener('click', function insertOperand() {
if(operand1 === "empty") {
operations[0] = Number(displayNumbers);
operations[1] = this.textContent;
displayValue = [];
operand1 = "inserted";
} else if (operand1 === "inserted") {
operations[2] = Number(displayNumbers);
result = operate(operations[1],operations[0],operations[2]);
display.textContent = result;
displayNumbers = result;
displayValue = [];
operand1 = "empty";
button.removeEventListener('click',insertOperand);
}
});
});
});
});

Writing a calculator function - in the most functional programming way(javascript)

I am trying out a task from codewars and wanted to write in a functional programming way in javascript. I have some questions regarding my functions and how the code can be written in a better way.
The task itself is to build a calculator function. It will accept an input in the format:
'..... + ...'
The calculator must split the string by the middle character signifying the operation and then the two string that are left will be the two values. In the example above first value will be 5 and the second 3. Once this is done, depending on the operator, do the action - either addition, multiplication etc.
Here is my code:
function dotCalculator(equation) {
function returnSymbol(input) {
if (input.includes(' + ')) {
return ' + ';
} else if (input.includes(' - ')) {
return ' - ';
} else if (input.includes(' * ')) {
return ' * ';
} else if (input.includes(' / ')) {
return ' / ';
}
}
let symbolOf = returnSymbol;
let result = equation.split(symbolOf(equation)).map(x => x.length);
// Array.prototype.add = function(){
// return this[0] + this[1];
// }
}
I know my code is not done yet. I am trying to understand how to properly finish it having the functional programming way of thinking in mind. Maybe prototypal inheritance would a bit overkill. I am looking for some ideas from anyone who would lend a hand. I tried writing a more complex reduce after
let arrMine = equation.split(symbolOf(equation)).map((x) => x.length);
but it seemed way too messy. Any help would be greatly appreciated.
I'm very much a functional programming noob, the pipe function being here is probably kind of gratuitous and I might have taken the ..... + ... example overly literally, but here's an attempt:
const arith = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => a / b,
};
const pipe = (...fns) => (arg) => fns.reduce((res, fn) => fn(res), arg);
const get_input_elements = (input) => input.split(' ');
const get_number = (dots) => dots.length;
const get_numbers = ([str_a, op, str_b]) =>
[get_number(str_a), op, get_number(str_b)];
const apply_arith = ([a, op, b]) => arith[op](a, b);
const calc = pipe(
get_input_elements,
get_numbers,
apply_arith
);
console.log(calc('..... + ...'));
console.log(calc('..... - ...'));
console.log(calc('...... / ..'));
In this example are functional programs that can evaluate simple arithmetic -- adding, subtracting, multiplying, or dividing two numbers.
Details are commented in example below
Note: prefix any negative number being passed into calc() with an underscore _ instead of a hyphen -
// Utility function
const log = data => console.log(JSON.stringify(data));
// Arithmetic functions
const sum = (a, b) => (+a) + (+b);
const dif = (a, b) => a - b;
const pro = (a, b) => a * b;
const quo = (a, b) => a / b;
/**
* Calculate a simple formula a+b, a-b, a*b, or a/b.
* #param {string} formula - Pattern:
* "numberOPERANDnumber" ex. "5+5"
* Use an underscore to prefix negative numbers.
* #returns {number} Result of formula
*/
const calc = formula => {
// Declare variables
let result, f, a, b, op;
/*
Convert string into an array of strings.
[number, operand, number]
Replace any _ with - (see #param)
*/
f = formula.split(/([+\-*/])/)
.map(ab => ab.replace('_', '-'));
/*
Convert string of numbers into real numbers.
*/
a = parseFloat(f[0]);
b = parseFloat(f[2]);
op = f[1];
/*
Check if >a< and >b< are real numbers and if the input string was split
into 3 strings.
*/
if (Number.isNaN(a) || Number.isNaN(b) || f.length != 3) {
return;
}
// >op< determines the method of resolving the formula
switch (op) {
case '+':
result = sum(a, b);
break;
case '-':
result = dif(a, b);
break;
case '*':
result = pro(a, b);
break;
case '/':
result = quo(a, b);
break;
default:
return;
}
return result;
};
log(calc('5+5'));
log(calc('_10-7')); // That's a -10 (see #param)
log(calc('5*9'));
log(calc('51/3'));

compare math equations prior to evaluation javascript

I'm running through algebra and attempting to create a JavaScript tester function which compares two equations and determines if they are considered associative properties. In other words, if I group (a + b) + c vs. a + (b + c) the result will be the same. Multiplication and addition only.
Up to this point, I've attempted to build a simple function that resolves whether the final value is equal to the compared equation value. What I would like is if I was able to compare both equations without their parenthesis. Thinking I need to look up regular expressions... but looking for a little help on direction.
let a = 1,
b = 2,
c = 3,
number1 = (a * b) * c,
number2 = a * (b * c);
function isAssociative(num1, num2) {
let answer = num1 === num2;
return `Are ${num1} and ${num2} associative... ${answer}`;
}
console.log(isAssociative(number1, number2));
Currently, this results in, 'Are 6 and 6 associative... true'. This is what I want, but if I changed the second argument to a static 6 when calling the function... then this is not an associative combo and I would like it to return false.
You can use Mathjs and the simplify method:
console.clear();
term_a = 'a + ( b + c )'
term_b = '( a + b ) + c';
tree_a = math.simplify(term_a);
tree_b = math.simplify(term_b);
console.log(term_a, tree_a.equals(tree_b) ? 'equals' : 'differs from', term_b);
term_a = 'a + ( b + c + d )'
term_b = '( a + b ) + c';
tree_a = math.simplify(term_a);
tree_b = math.simplify(term_b);
console.log(term_a, tree_a.equals(tree_b) ? 'equals' : 'differs from', term_b);
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.4.2/math.min.js"></script>
I found an answer I'm satisfied with.
let number1 = prompt('Enter an equation').toString().replace(/[^0-9,+,*]+/g,''),
number2 = prompt('Enter equation 2').toString().replace(/[^0-9,+,*]+/g,'');
function isAssociative (num1, num2) {
if (num1 === num2) {
return eval(num1) === eval(num2);
} else {
return false;
}
}
alert(isAssociative(number1, number2));
I could wait for the numbers to enter the function as a string, check for parenthesis first to verify it even qualifies... if parenthesis exist, then I could execute the regEx code and if they don't exist return 'not associative' at that point. For now, this works as well as I want it to.

How do I add two numbers in JavaScript "without using `+` or `-` operators"?

I know an alternative to using the + sign for addition is to do something like this:
int add(int a, int b)
{
if(b == 0)
return sum;
sum = a ^ b;
carry = (a & b) << 1;
return add(sum,carry);
}
But I have two problems:
This is C++, not JavaScript. Is this supported in JavaScript?
It's obvious the whole trick is in ^ & <<, but I don't know how to start looking for them in JavaScript, because I don't know what they are called.
What should I be googling for even?
I tried to write this in JavaScript ... but seems I miss something
var getSum = function(a, b) {
return (a ^ b, (a & b) << 1)
};
We will use bitwise operators and will use recursion.
We use this method when we have a few low resources. Read more about when to use this method!
var getSum = function(a, b) {
if (b == 0) {
return a;
} else {
return getSum(a ^ b, (a & b) << 1)
}
};
ECMAScript 6 one-liner solution as suggested by #PatrickRoberts:
const getSum = (a,b) => b ? getSum(a ^ b, (a & b) << 1) : a;
Another solutions:
2- Arrays technique Array.prototype.fill()
const getSum = (a, b) => {
const firstArr = new Array(a).fill(true);
const secondArr = new Array(b).fill(true);
return firstArr.concat(secondArr).length
}
3- workaround to use plus sign without writing it:
const getSum = (a, b) => eval(''.concat(a).concat(String.fromCharCode(0x2B)).concat(b));
Well ok i am answering to the question as clearly described in the header. No + and no - operations right..? Yet... not with bitwise but with pure math should be a valid answer i suppose.
var x = 1,
y = 2,
sum = Math.log2(2**x * 2**y);
console.log(sum);
const add = (a, b) => new Function('a', 'b', `return ${a} ${String.fromCharCode(43)} ${b}`)(a, b);
We can implement same using while loop. We have to shift the carry to left and add it to binary sum of numbers till there will no carry. (As we follows the practice in addition of decimals.)
function getSum(a, b){
while(b!=0){
var carry = a&b; //calculate if is there any carry we need to add
a = a^b; // a is used to hold the sum
b = carry<<1; //b is used to hold left shift carry
}
return a;
}
document.write(getSum(7, 5))
It's possible to use arrays structures to perform a sum operation.
function getSum(a, b){
return Array(a).concat(Array(b)).length / 100;
}
Each input is coerced to an array, for instance, an input of value 5 would be coerced to an array of 5 elements. After coercing both inputs, the arrays are joined into a single array. The length of the final array is returned, by dividing to 100 to deal with the sum of decimal values.
Now, let's try to be defensive about invalid input cases, such as strings or falsy values.
const DEFAULT_NUMBER_VALUE = 0;
const DEFAULT_PRECISION = 100;
function parseAddInput(input){
if (!input) {
return DEFAULT_NUMBER_VALUE;
}
if (typeof input === 'string'){
input = parseInt(input);
}
const roundedNumber = Math.round(input * (10 * DEFAULT_PRECISION));
return roundedNumber;
}
function getSum(a, b){
return Array(
parseAddInput(a)
).concat(
Array(parseAddInput(b))
).length / 100;
}
function add(number1, number2){
return getSum(number1, number2);
}
The same approach as #PatrickRoberts suggested, but without recursion:
const add = (a, b) => {
let c;
while (a !== 0) {
c = b & a;
b = b ^ a;
c = c << 1;
a = c;
}
return b;
};

Turn array into comma separated grammatically correct sentence

If I have an array in Javascript that looks like
searchComponents = ['element1', 'element2', 'element3'];
What is the necessary logic to turn it into a sentence like:
"element1, element2, and element3"
Likewise, if there are only two elements it should read like:
"element1 and element2"
and so on and so forth. I am stuck.
One easy solution:
function arrayToSentence (arr) {
var last = arr.pop();
return arr.join(', ') + ' and ' + last;
}
console.log(arrayToSentence(['one','two','three']));
JS Fiddle demo.
And a slightly more complex/ridiculous solution (because who doesn't like silly, occasionally...):
function arrayToSentence (arr) {
var len = arr.length;
return arr.reduce(function(a,b,c){
return a + (c - 1 === length ? ', ' : ' and ') + b;
});
}
console.log(arrayToSentence(['one','two','three']));
JS Fiddle demo.
References:
Array.prototype.join().
Array.prototype.pop().
Array.prototype.reduce().
function toSentence(arr) {
return arr.slice(0, -2).join(', ') +
(arr.slice(0, -2).length ? ', ' : '') +
arr.slice(-2).join(' and ');
}
usage
toSentence([1])
1
toSentence([1, 2])
1 and 2
toSentence([1, 2, 3])
1, 2 and 3
toSentence([1, 2, 3, 4, 5, 6])
1, 2, 3, 4, 5 and 6
Here's a one liner:
const arrayToSentence = (a) => [a.slice(0, -1).join(', '), a.pop()].filter(w => w !== '').join(' and ');
console.log(arrayToSentence(['foo', 'bar', 'baz']));
console.log(arrayToSentence(['foo', 'bar']));
console.log(arrayToSentence(['foo']));
console.log(arrayToSentence([]));
Late answer, but this is my attempt at it. Relatively simple, immutable arguments, and works for 0-N items.
const toListSentence = (arr) => arr.length < 3 ?
arr.join(' and ') :
`${arr.slice(0, -1).join(', ')}, and ${arr[arr.length - 1]}`;
console.log(toListSentence([]));
console.log(toListSentence(['apple']));
console.log(toListSentence(['apple', 'banana']));
console.log(toListSentence(['apple', 'banana', 'peach']));
Try my compound-subject library:
https://github.com/adamshaylor/compound-subject
It includes controls over what character to delimit with (e.g. commas versus semicolons) as well as whether to delimit all the subjects (i.e. the “Oxford comma”).
More ES6/7 version without mutation:
function buildSentence (arr = []) {
if (arr.length === 0) {
return '';
}
if (arr.length === 1) {
return arr[0];
}
const newArr = [...arr];
const last = newArr.pop();
return newArr.join(', ') + ' and ' + last;
}
buildSentence([]);
buildSentence(['a']);
buildSentence(['a', 'b']);
buildSentence(['a', 'b', 'c']);
Here's a typed version that utilizes lodash functions:
Codesandbox: https://codesandbox.io/s/strange-architecture-z1854?file=/src/App.js
import { concat, first, join, last, slice } from 'lodash'
function joinOxford (list: string[]): string {
switch (list.length) {
case 1: return first(list)
case 2: return `${first(list)} and ${last(list)}`
default: return join(concat(slice(list, 0, -1), [`and ${last(list)}`]), ', ')
}
}
Usage:
joinOxford(['Alona'])
// Alona
joinOxford(['Alona', 'Loyce'])
// Alona and Loyce
joinOxford(['Alona', 'Loyce', 'Mikel'])
// Alona, Loyce, and Mikel
joinOxford(['Alona', 'Loyce', 'Mikel', 'Carrie'])
// Alona, Loyce, Mikel, and Carrie
joinOxford(['Alona', 'Loyce', 'Mikel', 'Carrie', 'Josie'])
// Alona, Loyce, Mikel, Carrie, and Josie
How's this...
function parseArray(arr) {
var s=arr.toString();
var c=s.lastIndexOf(",");
if(c!=-1) s=(s.substr(0,c)+" and "+s.substr(c+1)).replace(/,/g,", ");
return s[0].toUpperCase()+s.substr(1)+".";
}
console.log(parseArray(["one", "two","three","four","five"]));
console.log(parseArray(["one", "two"]));
console.log(parseArray(["one"]));
Output is:
One, two, three, four and five.
One and two.
One.
Grammatically correct?

Categories

Resources