If you've ever played craps, some of these numbers might look familiar.
I'm just starting out with Javascript so it probably shows. Here's where I'm at
This logic assumes a 10 count roll. Starting with iteration number 1, if the combined value of 'myRoll' is found inside the 'point' array, that first found number needs to be the established 'point' (pointNumber).
For example, (if 'myRoll' === 6) then 6 should be the 'pointNumber'.
I want to output the message 'Frontline winner!' if the first 'pointNumber' (in this case, 6)
gets randomly chosen again.
const point = [4, 5, 6, 8, 9, 10]
let pointNumber = 0
const n = 10
for (let i = 1; i <= n; i++) {
let dice1 = Math.floor(Math.random() * 6) + 1;
let dice2 = Math.floor(Math.random() * 6) + 1;
let myRoll = dice1 + dice2
if (point.includes(myRoll)) {
pointNumber = myRoll
}
console.log('Roll:' + i + ' Dice: ' + myRoll + ' Point:' + pointNumber)
}
This what the output currently looks like:
Roll:1 Dice: 6 Point:6
Roll:2 Dice: 9 Point:9
Roll:3 Dice: 10 Point:10
Roll:4 Dice: 10 Point:10
Roll:5 Dice: 6 Point:6
Roll:6 Dice: 5 Point:5
Roll:7 Dice: 6 Point:6
Roll:8 Dice: 7 Point:6
Roll:9 Dice: 8 Point:8
Roll:10 Dice: 11 Point:8
Here is how it should be displayed:
Roll:1 Dice: 6 Point:6
Roll:2 Dice: 9 Point:6
Roll:3 Dice: 10 Point:6
Roll:4 Dice: 10 Point:6
Roll:5 Dice: 6 Frontline winner!
Roll:6 Dice: 5 Point:5
Roll:7 Dice: 6 Point:5
Roll:8 Dice: 7 seven out
Roll:9 Dice: 8 Point:8
Roll:10 Dice: 11 Point:8
Notice how the 'dice' matched the 'point' on roll 5, resulting in a "Frontline winner"
And on the next role the 'point' is re-established again, until it is met (or a 7 is dealt).
This is just a fun personal exercise I am working on. Any help would be great!
UPDATE Okay, I got the logic to work exactly how it should. Some of the wording needs to be tweaked to be more cohesive with craps terminology and I'm sure there are many ways to improve this code, but at least it's a start:
//const { point, craps, come_out, bigRed, Yo } = require('./checkRoll')
const point = [4,5,6,8,9,10]
let NonpointNumberArr = []
let pointNumberArr = []
let pointNumber = 0
const n = 10
let isPointWinner = false
let isSeven = false
for (let i=1; i<= n; i++) {
let text = [`Roll: ${i}`]
let dice1 = Math.floor(Math.random() * 6) + 1;
let dice2 = Math.floor(Math.random() * 6) + 1;
let myRoll = []
myRoll[i] = dice1 + dice2
text.push(`Dice: ${myRoll[i]}`)
if(myRoll[i] === 7) {
text.push(`seven out`)
isSeven = true
isPointWinner = false
NonpointNumberArr.push(myRoll[i])
pointNumber = 0
pointNumberArr = []
} else {
if (!point.includes(myRoll[i])){
isPointWinner = false
text.push(`Point: ${pointNumber}`)
NonpointNumberArr.push(myRoll[i])
}}
if (point.includes(myRoll[i])){
pointNumberArr.push(myRoll[i])
if (myRoll[i] === pointNumber) {
text.push(`frontline winner!`)
pointNumber = 0
pointNumberArr = []
} else {
pointNumber = pointNumberArr[0]
text.push(`Point: ${pointNumber}`)
}
}
isSeven = false
console.log(text.join(' '))
}
// console.log(`\npoint number ${pointNumber}`)
// console.log(`\npoint numbers: ${pointNumberArr}`)
// console.log(`\nNon point numbers: ${NonpointNumberArr}`)
Something like this?
const point = [4, 5, 6, 8, 9, 10]
let pointNumber = 0, n = 10, pointArr = [];
for (let i = 1; i <= n; i++) {
let text = [`Roll: ${i}`]
let dice1 = Math.floor(Math.random() * 6) + 1;
let dice2 = Math.floor(Math.random() * 6) + 1;
let myRoll = dice1 + dice2
text.push(`Dice: ${myRoll}`)
if (myRoll === 7) {
pointArr = [];
text.push(`seven out`)
} else {
if (point.includes(myRoll)) {
pointNumber = myRoll;
text.push(`Point: ${pointNumber}`)
if (pointArr.includes(pointNumber)) text.push(`Frontline winner!`)
pointArr.push(myRoll);
}
else text.push(`Point: 0`)
}
console.log(text.join(' '))
}
const point = [4,5,6,8,9,10]
let pointNumberArr = []
let myRoll = []
let pointNumber = 0
const n = 10
for (let i=1; i<= n; i++) {
let text = [`Roll: ${i}`]
let dice1 = Math.floor(Math.random() * 6) + 1;
let dice2 = Math.floor(Math.random() * 6) + 1;
myRoll[i] = dice1 + dice2
text.push(`Dice: ${myRoll[i]}`)
if(myRoll[i] === 7) {
text.push(`seven out`)
pointNumber = 0
pointNumberArr = []
} else {
if (!point.includes(myRoll[i])){
text.push(`Point: ${pointNumber}`)
}}
if (point.includes(myRoll[i])){
pointNumberArr.push(myRoll[i])
if (myRoll[i] === pointNumber) {
text.push(`frontline winner!`)
pointNumber = 0
pointNumberArr = []
} else {
pointNumber = pointNumberArr[0]
text.push(`Point: ${pointNumber}`)
}
}
console.log(text.join(' '))
}
Related
Having the following input string: 923857614
This is represented into a matrix like this:
9 2 3
8 5 7
6 1 4
Having a moving sequence like this: 423692, this means that we start in point 4, we move to 2, then to 3, then to 6, then to 9 and finally to 2.
It must be computed the length of the road. At beginning it starts from 0, if the next step is adjacent to the current one, add 1, if it isn't adjacent, add 2.
How I tried to do it:
function computeRoadLength(keypad, movingSequence) {
// build the matrix
const arr = [[keypad[0], keypad[1], keypad[2]],
[keypad[3], keypad[4], keypad[5]],
[keypad[6], keypad[7], keypad[8]]];
let roadLength = 0;
for (i = 0; i < movingSequence.length; i++) {
// some way to compute the distance here
if (arr[i] > arr[i+1]) roadLength = roadLength + 1;
if (arr[i] < arr[i+1]) roadLength = roadLength + 2;
}
return roadLength;
}
computeRoadLength(923857614, 423692); // 2 + 1 + 2 + 2 + 1 = 8, should return 8
You could take a different approach by using an object of positions of all keypad values and take the absolute delta of the positions.
For adding to movingSequence add one or max two.
function computeRoadLength(keypad, movingSequence) {
const positions = {};
for (let i = 0; i < keypad.length; i++) {
positions[keypad[i]] = [Math.floor(i / 3), i % 3];
}
let roadLength = 0,
last = positions[movingSequence[0]];
for (let i = 1; i < movingSequence.length; i++) {
const
item = positions[movingSequence[i]],
sum = Math.abs(last[0] - item[0]) + Math.abs(last[1] - item[1]);
roadLength += Math.min(sum, 2);
last = item;
}
return roadLength;
}
console.log(computeRoadLength('923857614', '423692')); // 2 + 1 + 2 + 2 + 1 = 8
function SingleDigits(num) {
function makeDigits(num) {
let value = 1
let arr = String(num)
for(let i = 0 ; i < arr.length; i++){
value = value * Number(arr[i])
}
return value;
}
value += "";
while(1>=value.length){
let result = 1;
result = result
}
I'm going to do it until I make a single digit..
num = 786
7 * 8 * 6 -> 336
3 * 3 * 6 -> 54
5 * 4 -> 20
2 * 0 -> 0
like that.. how can i setting ?? or , my direction is right ?
You can use recursion to keep on going until the total equals 0.
eg.
function digits(num) {
const nums = num.toString().
split('').map(Number);
const total = nums.reduce(
(a,v) => a * v);
console.log(
nums.join(' * ') +
" => " + total);
if (total > 9)
digits(total);
}
digits(786);
Use recursion. The function can be pretty simple using a reducer to calculate the products.
const singleDigit = num => {
const nums = [...`${num}`];
const product = nums.reduce( (acc, val) => acc * +val, 1);
console.log(`${nums.join(" * ")} -> ${product}`);
return product <= 9 ? product : singleDigit(product);
}
console.log(singleDigit(4328));
You Should use recursive strategy.
function SingleDigits(num) {
if (parseInt(num / 10) > 0) {
let t = 1;
while (num > 0) {
t *= num % 10;
num = parseInt(num / 10);
}
console.log(t);
SingleDigits(t);
}
}
SingleDigits(786);
I am not sure why you have to use string here. You can do the following,
function SingleDigits(num) {
if(num <= 9) {
return num;
}
let res = 1;
while(num) {
res = res * (num % 10);
num = parseInt(num / 10);
}
if(res <= 9) {
return res;
}
return SingleDigits(res);
}
console.log(SingleDigits(786));
Does anyone have an idea how to make these 3 colored squares move around the perimeter of the board, and not like now, i.e. in lines? (lines 57-78) https://codepen.io/diana-larussa/pen/ExgpXzo
function timer() {
ttl--
divElement = document.querySelectorAll('div')
divElement[nr_boxu].style.backgroundColor = "#6d5dfc"
divElement[nr_boxu].value = 0
nr_boxu = nr_boxu + 1
divElement[nr_boxu].style.backgroundColor = "#F25270"
divElement[nr_boxu+1].style.backgroundColor = "#F25270"
divElement[nr_boxu+2].style.backgroundColor = "#F25270"
spanTimer.innerHTML = "TIME: " + ttl
//if (nr_boxu>gridDOMElement.value-4) stop()
/*if (divElement[nr_boxu] == gridDOMElement.value - 4) {
divElement[gridDOMElement.value + 1].style.backgroundColor = "#F25270"
}*/
if (ttl == 0) stop()
}
I think for each grid size it is possible to generate perimeter sequence of indices and timer() function could pick 4 of those indices to update.
For example, in this grid 5x4:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
perimeter array would be: [0, 1, 2, 3, 4, 9, 14, 19, 18, 17, 16, 15, 10, 5] (indices highlighted in bold)
timer function will pick 4 indices out of the array, for example [0, 1, 2, 3] at the start and will colour element at index 0 with #6d5dfc and 1, 2, 3 with #F25270.
It will later follow around the perimeter, for example picking 4 elements: [2, 3, 4, 9] and colouring element 2 with #6d5dfc and 3, 4, 9 with #F25270 (need to be careful when reaching end of array).
nr_boxu seems to be incremented starting from 0 on every timer() call.
It can be used to pick 4 elements from perimeter array starting from 0 till the end of array.
The following formula - nr_boxu % perimeter.length uses remainder operator to keep iterating from 0 till perimeter.length - 1.
perimeter and timer can be built like this:
function getPerimeter(cols, rows) {
let res = [];
// top line: 0, 1, 2, 3, 4
for (let i = 0; i < cols; i++) {
res.push(i);
}
// right line: 9, 14
for (let i = 1; i < rows - 1; i++) {
res.push(cols * (i + 1) - 1);
}
// bottom line: 19, 18, 17, 16, 15
for (let i = 0; i < cols; i++) {
res.push(cols * rows - 1 - i);
}
// left line: 10, 15
for (let i = rows - 2; i > 0; i--) {
res.push(i * cols);
}
return res;
}
let perimeter = getPerimeter(numOfColumns, numOfRows);
function timer() {
ttl--
const ind1 = perimeter[nr_boxu % perimeter.length];
const ind2 = perimeter[(nr_boxu + 1) % perimeter.length];
const ind3 = perimeter[(nr_boxu + 2) % perimeter.length];
const ind4 = perimeter[(nr_boxu + 3) % perimeter.length];
divElement = document.querySelectorAll('div')
divElement[ind1].style.backgroundColor = "#6d5dfc"
divElement[ind1].value = 0
nr_boxu = nr_boxu + 1
divElement[ind2].style.backgroundColor = "#F25270"
divElement[ind3].style.backgroundColor = "#F25270"
divElement[ind4].style.backgroundColor = "#F25270"
spanTimer.innerHTML = "TIME: " + ttl
//if (nr_boxu>gridDOMElement.value-4) stop()
/*if (divElement[nr_boxu] == gridDOMElement.value - 4) {
divElement[gridDOMElement.value + 1].style.backgroundColor = "#F25270"
}*/
if (ttl == 0) stop()
}
I'm given a number and I need to find the sum of the multiples of 3 and 5 below the number.
For example:
20 => 78 = 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18
My code works, but not for numbers greater than 1,000,000 (I tested it for 100,000 - it gives the result with 2sec delay). So, it should be optimized. Could someone help me? Why is my code slow? Thanks.
My logic is as follows:
add multiples to an array
filter duplicate values
sum all values
my code:
function sumOfMultiples(number) {
let numberBelow = number - 1;
let numberOfThrees = Math.floor(numberBelow / 3);
let numberOfFives = Math.floor(numberBelow / 5);
let multiples = [];
let multipleOfThree = 0;
let multipleOfFive = 0;
for (var i = 0; i < numberOfThrees; i++) {
multiples.push(multipleOfThree += 3);
}
for (var j = 0; j < numberOfFives; j++) {
multiples.push(multipleOfFive += 5);
}
return multiples
.filter((item, index) => multiples.indexOf(item) === index)
.reduce((a, b) => a + b);
}
You can also do this without using any loops.
For example if N is 1000, the sum of all multiples of 3 under 1000 is 3 + 6 + 9 ..... 999 => 3( 1 + 2 + 3 .... 333)
Similarly for 5, sum is 5(1 + 2 + 3 .... 200). But we have to subtract common multiples like 15, 30, 45 (multiples of 15)
And sum of first N natural numbers is N*(N+1)/2;
Putting all of this together
// Returns sum of first N natural numbers
const sumN = N => N*(N+1)/2;
// Returns number of multiples of a below N
const noOfMulitples = (N, a) => Math.floor((N-1)/a);
function sumOfMulitples(N) {
const n3 = noOfMulitples(N, 3); // Number of multiples of 3 under N
const n5 = noOfMulitples(N, 5); // Number of multiples of 5 under N
const n15 = noOfMulitples(N, 15); // Number of multiples of 3 & 5 under N
return 3*sumN(n3) + 5*sumN(n5) - 15*sumN(n15);
}
You can just run a loop from 1 to number, and use the modulo operator % to check if i divides 3 or 5:
function sumOfMultiples(number) {
var result = 0;
for (var i = 0; i < number; i++) {
if (i % 5 == 0 || i % 3 == 0) {
result += i;
}
}
return result;
}
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
You can do that just using a single loop.
function sumOfMultiples(number) {
let sum = 0;
for(let i = 1; i < number; i++){
if(i % 3 === 0 || i % 5 === 0){
sum += i;
}
}
return sum;
}
console.time('t');
console.log(sumOfMultiples(100000))
console.timeEnd('t')
You can do something like this
Set the difference equal to 5 - 3
Start loop with current as 0, keep looping until current is less than number,
Add 3 to current in every iteration,
Add difference to current and check if it is divisible by 5 only and less than number, than add it final result,
Add current to final result
function sumOfMultiples(number) {
let num = 0;
let difference = 5 - 3
let current = 0
while(current < number){
current += 3
let temp = current + difference
if((temp % 5 === 0) && (temp %3 !== 0) && temp < number ){
num += temp
}
difference += 2
if(current < number){
num += current
}
}
return num
}
console.log(sumOfMultiples(20))
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
you can do something like this
function multiplesOfFiveAndThree(){
let sum = 0;
for(let i = 1; i < 1000; i++) {
if (i % 3 === 0 || i % 5 === 0) sum += i;
}
return sum;
}
console.log(multiplesOfFiveAndThree());
My problem is I have a number for example 17; I also have three other constant numbers: 2, 5, 7;
I need to find all possible combinations which make the specific number 17 or any other number;
5 + 5 + 7 = 17 (1 combination)
5 + 5 + 5 + 2 = 17 (2 combinations)
2 + 2 + 2 + 2 + 2 + 7 = 17 (3 combinations)
2 + 2 + 2 + 2 + 2 + 2 + 5 = 17 (4 combinations)
So the answer is 4.
I created my script which working correctly with the number 17 but wrong with bigger numbers as 20 or 30. How to make it working with all numbers ?
const seek = 30;
const firstNum = 2;
const secondNum = 5;
const thirdNum = 7;
let combinations = 0;
const maxDivisor = Math.round(seek / 2);
for (let i = 1; i <= maxDivisor; i += 1) {
if (secondNum * i + thirdNum === seek) {
combinations++
} else if (secondNum * i + firstNum === seek) {
combinations++
} else if (firstNum * i + secondNum === seek) {
combinations++
} else if (firstNum * i + thirdNum === seek) {
combinations++
} else if (thirdNum * i + firstNum === seek || thirdNum * i + secondNum === 0) {
combinations++
} else if (firstNum + secondNum + thirdNum === seek) {
combinations++
} else if (firstNum * i === seek || thirdNum * i === seek || secondNum * i === seek) {
combinations++
}
}
console.log(combinations);
Simple solution is to first calculate max multipliers for each number and then keep summing all the possible combinations.
/** LOGIC **/
function getCombinations(inputNumber, pieceNumbers) {
const combinations = []
const initial = maxes(inputNumber, pieceNumbers);
let divs = initial;
const sum = createSum(pieceNumbers);
while (!allZeros(divs)) {
if (sum(divs) === inputNumber) {
combinations.push(divs);
}
divs = decrement(divs, initial);
}
return combinations;
}
/**
* returns max multiplier for each number
* that is less than input number
* ie. for [2, 5] and input 17
* you get [8 (17 / 2); 3 (17 / 5)]
*/
function maxes(inputNumber, pieceNumbers) {
return pieceNumbers.map((num, i) =>
inputNumber / num | 0
)
}
/**
* decrements list of numbers till it contains only zeros
* if we have divs [2, 0] and initial [2, 5] the result
* will be [1, 5]
*/
function decrement(divs, initial) {
const arr = divs.slice();
let i = arr.length;
while (i--) {
if (arr[i] > 0) {
return [...arr.slice(0, i), arr[i] - 1, ...initial.slice(i + 1)];
}
}
}
function allZeros(divs) {
return divs.every(div => div === 0);
}
function createSum(pieceNumbers) {
return (divs) => divs.reduce((acc, itm, i) => acc + itm * pieceNumbers[i], 0);
}
function toPrint(combinations, pieceNumbers) {
const printable = combinations.map(nums =>
nums.map(
(n, i) => Array(n).fill(pieceNumbers[i]).join(" + ")
)
.filter(x => x)
.join(" + ")
).join("\n");
return printable;
}
/** VIEW **/
const addPieceEl = document.querySelector(".js-add-piece-number");
const removePieceEl = document.querySelector(".js-remove-piece-number");
const calculateEl = document.querySelector(".js-calculate");
const displayEl = document.querySelector(".js-display-result");
addPieceEl.addEventListener("click", () => {
addPieceEl.insertAdjacentHTML("beforebegin", ` <input type="number" class="js-piece-number number" value="7" /> `)
})
removePieceEl.addEventListener("click", () => {
addPieceEl.previousElementSibling.remove()
})
calculateEl.addEventListener("click", () => {
const inputNumber = Number(document.querySelector(".js-input-number").value);
const pieceNumbers = Array.from(document.querySelectorAll(".js-piece-number")).map(el => Number(el.value))
const combinations = getCombinations(inputNumber, pieceNumbers);
const total = `There are ${combinations.length} combinations for ${inputNumber} with ${pieceNumbers.join(", ")}:\n`;
displayEl.textContent = total + toPrint(combinations, pieceNumbers);
});
.number {
width: 30px;
}
Input Number: <input type="number" class="js-input-number number" value="17"/>
<br/>
<br/>
Piece Numbers:
<input type="number" class="js-piece-number number" value="2"/>
<input type="number" class="js-piece-number number" value="5"/>
<input type="number" class="js-piece-number number" value="7"/>
<button class="js-add-piece-number">+</button>
<button class="js-remove-piece-number">-</button>
<br/>
<br/>
<button class="js-calculate">calculate</button>
<pre class="js-display-result"/>
You can test all combinations
const n = 30;
console.log('Number to reach: n = ' + n);
const k = [7, 5, 2];
console.log('Numbers to use: k = ' + k);
console.log('n can be wrote: n = a*k[0] + b*k[1] + c*k[2]');
console.log('Let\'s found all combinations of [a, b, c]');
let t = [];
for (let a = 0; n >= a*k[0]; a++)
for (let b = 0; n >= a*k[0] + b*k[1]; b++)
for (let c = 0; n >= a*k[0] + b*k[1] + c*k[2]; c++)
if (n == a*k[0] + b*k[1] + c*k[2])
t.push([a, b, c]);
console.log('Number of combinations: ' + t.length);
for (let i = 0; i < t.length; i++)
console.log(
n + ' = ' + new Array()
.concat(new Array(t[i][0]).fill(k[0]).join(' + '))
.concat(new Array(t[i][1]).fill(k[1]).join(' + '))
.concat(new Array(t[i][2]).fill(k[2]).join(' + '))
.filter(e => e.length > 0)
.join(' + ')
);
I am assuming you only want solutions that are unique in the sense that 2+5 and 5+2 aren't unique.
Using recursion you can create an algorithm that can solve this problem for every number and every list of constants.
const seek = 17;
const numbs = [2,5,7];
const minNum = Math.min(...numbs);
let numberOfCombinations = 0;
seekCombinations(seek, numbs);
function seekCombinations (toSeek, numbs) {
for (let i = 0; i < numbs.length; i++) {
let newToSeek = toSeek - numbs[i];
if (newToSeek === 0) { //you found a combination
numberOfCombinations++;
} else if (newToSeek >= minNum) { //The new number to seek can still form a combination
//remove numbers from your list of constants that are smaller then then the number that is already in your current combination so you'll only get unique solutions.
let index = numbs.indexOf(numbs[i]);
let newNumbs = numbs.slice(index, numbs.length);
//recursively call seekCombinations
seekCombinations (newToSeek, newNumbs, currentCombination)
}
}
}
so whats the question?
whats wrong with your script or how to do it?
in case you missed it,
multiplying the number with i doesnt solve this problem. because:
30 = 2 + 2 + 5 + 7 + 7 + 7
30 = 2 + 2 + 2 + 5 + 5 + 7 + 7
any number of one of those 3 constants can appear there.
these cases are not covered by your script