I am trying to write a card counting function in javascript. Each card is assigned a value according to the table below. When the count is positive, the player should bet high. When the count is zero or negative, the player should bet low.
(i) if cards are 2, 3, 4, 5, 6 then count change =(+1);
(ii) if cards are 7,8,9 then count change =0;
(iii)if cards are 10, 'J', 'Q', 'K', 'A', then count change = (-1);
Here is my function:
var count = 0;
function cc(card) {
{
case 2:
case 3:
case 4:
case 5:
case 6:
return count++;
case 7:
case 8:
case 9:
return count;
case 10:
case 'J':
case 'Q':
case 'K':
case 'A':
return count--;
}
}
cc(2); cc(3); cc(7); cc('K'); cc('A');
From the last line of the code, I was anticipating to get a '0', but instead it gives me a '1'. Can anyone enlightens me on this?
Notice that the expression count++ (or count--) returns the counter before the update (and updates it as a side effect).
If you want to return the counter after updating you should use the ++ (or --) before the counter.
For example, if the count is 1 -
If you return count++ then 1 will be returned and as a side effect count will increase to 2.
If you return ++count then count will first increase and then be returned so 2 will be returned.
var count = 0;
function cc(card) {
if (card >= 2 && card <= 6) {
count += 1
}
else if (card >= 7 && card <= 9) {
count += 0
} else {
count -= 1
}
return count <= 0 ? `${count} Hold` : `${count} Bet`;
}
Related
I'm doing this exercise where you have to calculate the number of limes needed to get the juice.
It needs a switch statement inside which takes out the first element of the "limes" array, (and that works flawlessly). Until i add the condition to count down the wedges: even if in the cases is specified to subtract a determined amount, at every iteration it seems to ignore it and never meeting the needed condition to break the switch statement
here's the code
function limesToCut(wedgesNeeded, limes) {
let limesNeeded = 0
while(limes.length != 0 || wedgesNeeded > 0 ) {
switch (limes[0]) {
case 'small':
limes.shift()
limesNeeded += 1
wedgesNeeded -= 6
break;
case 'medium':
limes.shift()
limesNeeded += 1
wedgesNeeded -= 8
break;
case 'large':
limes.shift()
limesNeeded += 1
wedgesNeeded -= 10
break;
default:
break
}
}
console.log(limesNeeded)
}
//test cases
console.log("case 1")
limesToCut(4, ['medium', 'small'])
console.log("case 2")
limesToCut(80,['small','large','large','medium','small','large','large',])
console.log("case 3")
limesToCut(0, ['small', 'large', 'medium'])
console.log("case 4")
limesToCut(10, [])
where did i go wrong? it seems to not be working even when i exclude the other condition from the loop
quoting #James in the comments:
It's because for some of your test cases, limes.length != 0 || wedgesNeeded > 0 is always true, so it gets stuck in a loop. Consider the case where you need 80 wedges but only have 7 limes which could yield 70 wedges tops (if they were all the largest size). So there are no limes left but wedgesNeeded > 0, so it loops and loops.
The below function is working as expected except case noticed in a comment, namely, for each number:
if the number is divisible by three I want to log out the word fizz instead of that number
if the number is divisible by five I want to log out the word buzz instead of that number.
And if a number is divisible by both 3 and 5 I want to log out the word fizzbuzz instead of that number.
Example - 1
const FizzBuzz = (num) => {
for (let i = 1; i <= num; i++) {
const foo = 0;
switch (foo) {
case (i % 3 || i % 5): console.log('fizzbuzz');
// expect in this case should be work with logical operator '&&': (i % 3 && i % 5)
break;
case i % 3: console.log('fizz');
break;
case i % 5: console.log('buzz');
break;
default: console.log(i);
}
}
}
FizzBuzz(20)
This is how I know - With switch-case statement preferable use:
Example 2
switch(true) {
case (i % 3 === 0 && i % 5 === 0): console.log('fizzbuzz');
break;
// etc...
}
But with the instance of code above (Example 1: where switch(foo) doesn't have the constant value like true), it looks more flexible and readable.
And in "Example 1", as I understood, the operator || works like operator && and vice versa.
The "Example 1" works perfectly as result. But I can't understand Why. Primarily my question is - Why the logical operator OR behave as an operator AND in this example??
Thnx in advance.
The issue is that you're switching on foo, and foo is 0, so case <expression> will run when <expression> evaluates to 0.
So, case i % 3 runs when expected, because you want the i % 3 case to run when that evaluates to 0. Same for i % 5. But
case (i % 3 || i % 5)
, when i is a multiple of 15, resolves to
case (15 % 3 || 15 % 5)
->
case (0 || 0)
Because 0 is falsey, the || will mean that both 15 % 3 and 15 % 5 must be 0 for the case there to resolve to 0 (and thus match foo's 0).
If you used &&, then the && expression will evaluate to the first falsey value, rather than requiring both %s to resolve to 0, eg when i is 3:
case (3 % 3 && 3 % 5)
->
case (0 && 2)
->
case 0
which then matches foo's 0, despite the fact that only one of the conditions in the && resolved to 0.
It's extremely unintuitive. Don't use switch here. If you had to use switch, I'd highly recommend setting foo to true instead, and using === 0 tests:
const FizzBuzz = (num) => {
for (let i = 1; i <= num; i++) {
const foo = true;
switch (foo) {
case i % 3 === 0 && i % 5 === 0:
console.log('fizzbuzz');
break;
case i % 3 === 0:
console.log('fizz');
break;
case i % 5 === 0:
console.log('buzz');
break;
default:
console.log(i);
}
}
}
FizzBuzz(20)
The code in Example 1 works because you switch on the variable foo which is set to 0.
The code in the first case is evaluated to 0:
15 % 3 || 15 % 5 = 0
This value gets compared to foo which is 0 and so the JS code enters the first case.
In JavaScript logical OR operators always return the first "truthy" value.
'foo' || 'bar' = 'foo'
false || 'bar' = 'bar'
The card function has been explained multiple times, and I understand it. For those who do not know it: my function receives a card parameter, which can be a number or a string. I then increment or decrement the global count variable according to the card's value 2,3,4,5,6 increments, 7,8,9 keeps it at 0, while 10, J, Q, K, A decrements it. My function then returns a string with the current count and the string "Bet" if the count is positive, or "Hold" if it is negative.
So I understand how the function is done, and FreeCodeCamp accepted my solution as technically it meets their conditions. But have a question regarding this function:
var count = 0;
function cc(card) {
if (card >= 2 && card <= 6) {
count++;
} else if (card >= 7 && card <= 9) {
count += 0;
} else {
count--;
}
if (count <= 0) {
return count + " Hold";
} else {
return count + " Bet";
}
}
console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('A'));
As I can see, the first condition is fairly simple and easy to define, so is the else if. In the third case, there are both numbers and strings involved. Does this not mean that when I put ANY string into cc, it will decrement? As anything that is not between 2 and 6, or 7 and 9, will automatically decrement? Even if the user inputs something that is not a card or is not a value from the list?
I understand that there is a list of predefined card values and names, but nevertheless, is there any better way to condition my statement to make sure that my condition will ONLY run IF the card is either 10, J, Q, K or A, and not any other value?
You can change your current else, to return and error message or just return immediately in case of the input being a non-valid card, and add another else-if to check for 10 through Ace:
if (card >= 2 && card <= 6) {
count++;
} else if (card>=7 && card <=9) {
count+= 0;
} else if (card === 10 || card === 'J' || card === 'Q' || card === 'K' || card === 'A'){
count--;
}else {
//Either just return or alert an error message and return
}
There are a number of ways you could deal with this situation. You could initially parse the input, and say assign 'J' to 11, 'Q' to 12, 'K' to 13 and 'A' to 1 (if you need to distinguish), or just a common number to that category. Everything else is an invalid input and you return immediately/post an error message. Something like:
var count = 0;
function cc(card) {
if (card == 'J' || card == 'Q' || card == 'K' || card == 'A')
card = 11;
if (card >= 2 && card <= 6) {
count++;
} else if (card>=7 && card <=9) {
count+= 0;
} else if (card >= 10 && card <= 11) {
count--; // to keep structure cleaner we use dummy 11 value
} else
//error message
if (count <= 0) {
return count + " Hold";
} else {
return count + " Bet";
}
}
cc(2); cc(3); cc(7); cc('K'); cc('A');
Also, you need to make sure to handle lower case and upper case values for the picture cards.
Define a set of allowed values and check if the value you are given is within that set using .includes(). For example:
var count = 0;
function cc(card) {
// Only change code below this line
const up = [2,3,4,5,6];
const no = [7,8,9];
const down = [10, "J", "Q", "K", "A"];
if(up.includes(card))count++;
if(down.includes(card))count--;
const str = count > 0 ? "Bet" : "Hold";
return `${count} ${str}`;
// Only change code above this line
}
// Add/remove calls to test your function.
// Note: Only the last will display
cc(2); cc(3); cc(7); cc('K'); cc('A');
Bear in mind this is type sensitive.
Another possibility is something like the following, which explicitly lists the changes for each card:
const counter = () => {
let count = 0
let values = {2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 0, 8: 0,
9: 0, 10: -1, J: -1, Q: -1, K: -1, A: -1}
return (card) => {
const change = values[card] || 0 // no change if card is, say, 'XYZ' or 'Joker'
count += change
return count <= 0 ? 'Hold' : 'Bet'
}
}
const cc = counter();
console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('A'));
For a list as short as thirteen values, I think this sort of explicit list is cleaner.
This also encapsulates the count variable in a closure. I find that cleaner than a global variable.
Where the comment talks about jokers, you might want some more robust error-handling:
if (!(card in values)) {throw 'Bad card'}
const change = values[card]
You could use a regular expression at the very top of your function to skip all the conditionals and return a handy message if the argument passed in doesn't match a valid card:
// Check if card is valid
var cardRegex = /^(10|[2-9AJQK])$/i;
if (!cardRegex.test(card)) {
return "Invalid Card";
}
So, in the context of your code, it would look like:
var count = 0;
function cc(card) {
// Check if card is valid
var cardRegex = /^(10|[2-9AJQK])$/i;
if (!cardRegex.test(card)) {
return "Invalid Card";
}
if (card >= 2 && card <= 6) {
count++;
} else if (card >= 7 && card <= 9) {
count += 0;
} else {
count--;
}
if (count <= 0) {
return count + " Hold";
} else {
return count + " Bet";
}
}
// Valid inputs
console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('a'));
// Invalid inputs
console.log(cc('e'));
console.log(cc('L'));
console.log(cc(0));
My solution for Basic JavaScript: Counting Cards
function cc(card) {
// Only change code below this line
if(card >= 2 && card <= 6) {
count++;
} else if (card === 10 ||card === 'J' || card === 'Q' || card === 'K' || card === 'A') {
count = count - 1;
}
if (count > 0) {
return count + ' Bet';
}
return count + ' Hold';
// Only change code above this line
}
My solution, based on what we learned so far.
Maybe it isnĀ“t the best, but it also works.
var count = 0;
function cc(card) {
// Only change code below this line
switch(card){
case 2:
case 3:
case 4:
case 5:
case 6:
count++;
break
case 7:
case 8:
case 9:
count = count;
break
case 10:
case 'J':
case 'Q':
case 'K':
case 'A':
count--;
break;
}
if (count <=0) {
return count + ' Hold';
}
else {
return count + ' Bet'
}
// Only change code above this line
}
console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('A'));
let count = 0;
function cc(card) {
switch (card) {
case 2:
case 3:
case 4:
case 5:
case 6:
count++;
break;
case 10:
case 'J':
case 'Q':
case 'K':
case 'A':
count--;
}
if (count > 0) {
return count + " Bet";
} else {
return count + " Hold";
}
}
I have the following code displaying an image based on gamma values of the gyroscope. My first shot at it was to write a switch statement but having used object literals before I thought this could be a cleaner alternative. Is there any way to do this with the following code? Or any other cleaner solution?
switch (true) {
case (gamma <= -28):
view360.goToItem(0);
break;
case (gamma <= -24):
view360.goToItem(1);
break;
case (gamma <= -20):
view360.goToItem(2);
break;
case (gamma <= -16):
view360.goToItem(3);
break;
case (gamma <= -12):
view360.goToItem(4);
break;
case (gamma <= -8):
view360.goToItem(5);
break;
case (gamma <= -4):
view360.goToItem(6);
break;
case (gamma <= 0):
view360.goToItem(7);
break;
case (gamma <= 4):
view360.goToItem(8);
break;
case (gamma <= 8):
view360.goToItem(9);
break;
case (gamma <= 12):
view360.goToItem(10);
break;
case (gamma <= 16):
view360.goToItem(11);
break;
case (gamma <= 20):
view360.goToItem(12);
break;
case (gamma <= 24):
view360.goToItem(13);
break;
default:
view360.goToItem(13);
}
Your indexes are a function of the gamma, so you should write it as a function that captures that relationship. It looks like the relationship is simply (28 + gamma) / 4 with an additional check gamma is greater than 60. Since you are using inequalities to capture the in-between values, you need to divide by 31 and take the floor. This will allow both 3 and 4 to return 8 for example. So this should match your switches:
function getIndex(g) {
return g > 60 ? 13 : Math.floor((31 + g) / 4)
}
view360.goToItem(getIndex(gamma))
Not in this case, because you're using <= rather than =. Your whole method here would be better expressed with if and else - switch(true) is not really a switch.
Here's a switch you could convert to an object literal:
switch ( val ) {
case 'a': return 'hello';
case 'b': return 'goodbye';
}
Could be:
return { a: 'hello', b: 'goodbye' }[ val ];
Because the result of your switch (the argument to goToItem) is sequential (0, 1, 2...) you could use an array for this.
var gammaValues = [ -28, -24, -20, -16 /* etc */ ];
var idx = gammaValues.findIndex( value => gamma <= value );
if ( index !== -1 ) view360.goToItem( idx );
May be using map can help
const mapBreakpointToItem = {
-28: 0,
-24: 1,
...
};
Object.keys(mapBreakpointToItem).some((breakpoint) => {
if (gamma <= breakpoint) {
const item = mapBreakpointToItem[breakpoint];
view360.goToItem(item);
return true;
}
return false;
});
Or you can use math Math.floor((gamma + 31) / 4 for mapping breakpoints and items, but if something is changed its easier to change map object.
I'm currently taking the code academy course on Javascript and I'm stuck on the FizzBuzz task. I need to count from 1-20 and if the number is divisible by 3 print fizz, by 5 print buzz, by both print fizzbuzz, else just print the number. I was able to do it with if/ else if statements, but I wanted to try it with switch statements, and cannot get it. My console just logs the default and prints 1-20. Any suggestions?
for (var x = 0; x<=20; x++){
switch(x){
case x%3==0:
console.log("Fizz");
break;
case x%5===0:
console.log("Buzz");
break;
case x%5===0 && x%3==0:
console.log("FizzBuzz");
break;
default:
console.log(x);
break;
};
};
Switch matches the x in switch(x){ to the result of evaluating the case expressions. since all your cases will result in true /false there is no match and hence default is executed always.
now using switch for your problem is not recommended because in case of too many expressions there may be multiple true outputs thus giving us unexpected results. But if you are hell bent on it :
for (var x = 0; x <= 20; x++) {
switch (true) {
case (x % 5 === 0 && x % 3 === 0):
console.log("FizzBuzz");
break;
case x % 3 === 0:
console.log("Fizz");
break;
case x % 5 === 0:
console.log("Buzz");
break;
default:
console.log(x);
break;
}
}
I thought switch too,but no need.
for (var n = 1; n <= 100; n++) {
var output = "";
if (n % 3 == 0)
output = "Fizz";
if (n % 5 == 0)
output += "Buzz";
console.log(output || n);
}
Switch statement checks if the situation given in the cases matches the switch expression. What your code does is to compare whether x divided by 3 or 5 is equal to x which is always false and therefore the default is always executed. If you really want to use a switch statement here is one way you can do.
for (var i=1; i<=30; i++){
switch(0){
case (i % 15):
console.log("fizzbuzz");
break;
case (i % 3):
console.log("fizz");
break;
case (i % 5):
console.log("buzz");
break;
default:
console.log(i);
}
}
Not to too my own horn but this is much cleaner:
var numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for (var i = 1; i <= numbers.length; i++) {
if (i % 15 === 0) {
console.log("FizzBuzz");
} else if (i % 5 === 0) {
console.log("Buzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else {
console.log(i);
}
};
The switch(true) part of this statement helped me. I was trying to do a switch statement for fizzbuzz. My solution incorporates the coding style of Rosettacodes - general solution. Most significantly the use of force typing to shorten the primary conditionals. I thought, it was valuable enough to post:
var fizzBuzzSwitch = function() {
for (var i =0; i < 101; i++){
switch(true) {
case ( !(i % 3) && !(i % 5) ):
console.log('FizzBuzz');
break;
case ( !(i % 3) ):
console.log('Fizz');
break;
case ( !(i % 5) ):
console.log('Buzz');
break;
default:
console.log(i);
}
}
}
Here's what made it clear for me, might help :
It's a misinterpretation of what switch (x){} means.
It doesn't mean : "whenever whatever I put inbetween those brackets is true, when the value of x changes."
It means : "whenever x EQUALS what I put between those brackets"
So, in our case, x NEVER equals x%3===0 or any of the other cases, that doesn't even mean anything. x just equals x all the time. That's why the machine just ignores the instruction. You are not redefining x with the switch function. And what you put inbetween the brackets describes x and x only, not anything related to x.
In short :
With if/else you can describe any condition.
With switch you can only describe the different values taken by the variable x.
Here's a solution incorporating #CarLuvr88's answer and a switch on 0:
let fizzBuzz = function(min, max){
for(let i = min; i <= max; i++){
switch(0){
case i % 15 : console.log('FizzBuzz'); break;
case i % 3 : console.log('Fizz'); break;
case i % 5 : console.log('Buzz'); break;
default : console.log(i); break;
}
}
}
fizzBuzz(1,20)
We can use a function to find a multiple of any number and declare two variables to identify these multiples so that if you want to change the multiples you only need to change at max 2 lines of code
function isMultiple(num, mod) {
return num % mod === 0;
}
let a = 3;
let b = 5;
for(i=0;i<=100;i++){
switch(true){
case isMultiple(i,a) && isMultiple(i,b):
console.log("FizzBuzz")
case isMultiple(i,a):
console.log("Fizz");
case isMultiple(i,b):
console.log("Buzz");
default:
console.log(i);
}
}