3

So I have been learning javascript for two months now and I'm doing some precourse work and got stuck on this question. I know I need a for a loop. but I am completely lost and there doesn't seem to be a comparable problem anywhere to learn from. the problem is://Given a string, write a program that counts how many colors are used in that string. For the purposes of our challenge, let's say all the available colors are: blue, green, gray, red, black, and purple.

So here is the code I have so far

//declaring values and user input
const colors = ["blue", "green", "gray", "red", "black", "purple"];
const sillySentence = prompt("Tell me a colorful Rhyme: ");

//for loop to solve the problem



//start output
console.log("You Listed " + x + " colors in your rhyme.")
Harsha pps
  • 2,012
  • 2
  • 25
  • 35
Corey
  • 31
  • 1

7 Answers7

1

If a for loop is not a necessary requirement, here you have a different approach without one. If elements of color array have only letters you could use match() that returns an array of matches, to build the regex we convert the colors array into string and replace the , for | that means or in a regex so the result is something like /blue|green|gray/, then we count the length of the matches:

const colors = ["blue", "green", "gray", "red", "black", "purple"];

const sillySentence = prompt("Text: ");

var r = new RegExp(colors.toString().replace(/,/g, "|"), "g");

var found = (sillySentence.match(r) > 0) ? sillySentence.match(r).length : 0;

console.log(found);

This example won't work if we have , in the strings of colors.

Emeeus
  • 5,072
  • 2
  • 25
  • 37
  • 2
    This is probably the smartest answer right now. Please explain how match works. He is new to JS. Also, he need a forloop...even tho this is the smartest answer it's not a valid one –  Aug 27 '18 at 18:11
  • @TamoDev not for everyone : / , I've added an explanation – Emeeus Aug 27 '18 at 18:26
1

Here's a version using regular expressions. This code will only accept colors as words, e.g. bluegreen will not match anything.

Edit: now takes into account unique colors only.

const colors = ['blue', 'green', 'gray', 'red', 'black', 'purple'];
const sillySentence = prompt('Tell me a colorful Rhyme:');

const result = (sillySentence.match(
  new RegExp('(\\b' + colors.join('|') + '\\b)', 'g'))
    .filter((value, index, self) => self.indexOf(value) === index)
  || []).length;

console.log(result);

Explanation:

  • This builds a regexp of the form /\b(blue|green|red)\b/, which basically says: a word among blue, green and red (\b is the word boundary character, preventing thisisthebluecolor from matching blue).
  • It uses Array.join to build that regexp.
  • It uses String.match to test the input string against that regexp.
  • It uses Array.filter to remove duplicates (see this answer)
  • the || [] basically says: if the regexp doesn't match, consider the result of String.match an empty array (so that .length, the size of that result, will return 0).
Jeto
  • 14,596
  • 2
  • 32
  • 46
0

You can use something like this:

const colors = ["blue", "green", "gray", "red", "black", "purple"];
var sillySentence = prompt("Tell me a colorful Rhyme: ");
let x = 0;
if (sillySentence) {
    sillySentence = sillySentence.toLowerCase();
    for (let i = 0; i < colors.length; i++) {
        if (sillySentence.indexOf(colors[i]) >= 0) {
            x += 1;
        }
    }
}

//start output
console.log("You Listed " + x + " colors in your rhyme.");

It'll be best to loop through number of colors as they will be less than number of words of the rhyme and it will count unique colors only.

Sookie Singh
  • 1,543
  • 11
  • 17
  • This code is not working completely. it doesn't pass a the test case with multiple color words ex. red blue, return one instead of 2 –  Aug 27 '18 at 18:16
  • awesome. i tried to use .length but i messed it up somewhere and already deleted it from frustration. thanks guy! – Corey Aug 27 '18 at 18:18
0

Simple Solution

A Simple, but inefficient, solution is:

  • Lowercase the string
  • Split the string by spaces and punctuation.

Then you iterate through the words and try to find the colors. Example:

const colors = ["blue", "green", "gray", "red", "black", "purple"];
const sillySentence = prompt("Tell me a colorful Rhyme: ");

const colorCount = new Set();

const words = sillySentence.toLowerCase().split(/[\s,.:;]+/);
for (let i = 0; i < words.length; i++) {
  const word = words[i];
  if (colors.indexOf(word) >= 0) {
    colorCount.add(word);
  }
}

console.log(colorCount.size);

Efficient Solution

A more efficient solution is to populate a Set and use it to quickly lookup the colors:

const colors = ["blue", "green", "gray", "red", "black", "purple"];
const sillySentence = prompt("Tell me a colorful Rhyme: ");

const colorSet = new Set();
colors.forEach(color => colorSet.add(color));

const colorCount = new Set();

const words = sillySentence.toLowerCase().split(/[\s,.:;]+/);
for (let i = 0; i < words.length; i++) {
  const word = words[i];
  if (colorSet.has(word)) {    
    colorCount.add(word);
  }
}

console.log(colorCount.size);
HugoTeixeira
  • 4,674
  • 3
  • 22
  • 32
  • Your code doesn't pass all the test cases. Try blue red blue black and returns 2, instead of 3 –  Aug 27 '18 at 18:14
0

While this is not a correct answer because you are asking for a forloop I wanted to share another way to do things in JS since you are new into JS.

const colors = ["blue", "green", "gray", "red", "black", "purple"];
const sillySentence = prompt("Tell me a colorful Rhyme: ");

    let count = 0;
    sillySentence.split(' ').find((color)=> {
      if (colors.includes(color) !== -1) {
        count += 1;
      }
    });
    console.log("You Listed " + count + " colors in your rhyme.");
0

You also could just use regular expression group match (/(blue)/ for example) and simply count the length ... this way you do not have to worry about special characters, splitting to words etc.

Here is an example:

const colors = ["blue", "green", "gray", "red", "black", "purple"];
const rhyme = "I love blue, and red, but mostly blue!! and sometimes green! and red... NO gray!"

console.log(colors.reduce((r,c) => {
   let matches = rhyme.match(new RegExp(`(${c})`, 'gi'))
   return matches ? Object.assign(r, { [c]: matches.length }) : r
},{}))

Note: I wraped the whole thing in a reduce just so I can return an object with the counts etc but I am sure you get the picture.

Akrion
  • 18,117
  • 1
  • 34
  • 54
-1

Get the value of the prompt and split it into an array, then iterate that array and for each value in that array see if there exist a same element in colors array, if it is so then increase value of x by 1

const colors = ["blue", "green", "gray", "red", "black", "purple"];
const sillySentence = prompt("Tell me a colorful Rhyme: ");

let x = 0;
sillySentence.split(' ').forEach(function(item) {
  if (colors.indexOf(item) !== -1) {
    x += 1;
  }
});
console.log("You Listed " + x + " colors in your rhyme.")

Note: This program is not taking care of unique color in the prompt value. For example if any color appears twice , it will consider it as 2

brk
  • 48,835
  • 10
  • 56
  • 78
  • This code doesn't work. It also doesn't count if you put more than one color –  Aug 27 '18 at 18:09
  • @TamoDev which part does not work? Share that scenario – brk Aug 27 '18 at 18:16
  • nvm it works! Idk how gave you the -1 tho.. but this answer works pretty solid. Good job! –  Aug 27 '18 at 18:20