1

I have array contains strings. I have to read the words one by one and output words which has any character in it appearing exactly two times. But my code also show 3 or more same character also. How can I output the words which only character appearing two times ? For example not showing : "aaaa" or "aaab"

const words = [
  "asdf",
  "fdas",
  "asds",
  "d fm",
  "dfaa",
  "aaaa",
  "aabb",
  "aaabb"
];

function checkString(text,index){
    if((text.length - index) == 0 ){ //stop condition
        return false; 
    }else{
        return checkString(text,index + 1) 
        || text.substr(0, index).indexOf(text[index])!=-1;
    }
}

// example Data to test

for(var idx in words){
    var txt = words[idx];
  
  if(checkString(txt,0)) {
    console.log(txt);
  }
  
}
const words = [
  "asdf",
  "fdas",
  "asds",
  "d fm",
  "dfaa",
  "aaaa",
  "aabb",
  "aaabb"
];

/*
Output have to be :
asds
dfaa
aabb
aaabb
*/
Ruslan Bairamovi
  • 378
  • 3
  • 22

7 Answers7

2

const words = [ "asdf", "fdas", "asds", "d fm", "dfaa", "aaaa", "aabb", "aaabb" ];

function checkString(text) {
  //create a map to store the frequency of characters
  let map = new Map();
  for(let ch of text){
    if(map.has(ch)){
      map.set(ch, map.get(ch)+1);
    }else{
      map.set(ch, 1);
    }
  }
  
  //now check if frequency of any character is equal to 2
  return [...map.values()].some(x => x == 2);
}

// example Data to test

for (let txt of words) {
  if (checkString(txt)) {
    console.log(txt);
  }
}
Harsh Saini
  • 598
  • 4
  • 13
2

You can build an object mapping letters in your input string to its occurrences in it, then filter the letters based on whether they appear twice:

const checkString = (inputString) => {
  // Build an empty object
  const occurrences = {};
  for (let char of inputString) {
    // For each character in the input string, add one to its occurrence count
    // If it has never appeared until now, occurrences[char] + 1 will evaluate
    // to NaN, and Nan || 1 is 1
    occurrences[char] = occurrences[char] + 1 || 1;
  }

  // Get the characters appearing in the string
  const charsInInputString = Object.keys(occurrences);
  // Extract only the characters appearing exactly twice
  const charsAppearingTwice = charsInInputString.filter(
    (char) => occurrences[char] === 2
  );
  // Return true if there is at least one such character
  return charsAppearingTwice.length > 0;
};

Your final array of correct words would then be words.filter(checkString).

If you want to format the words to display as a single string, with a space separator, you can use the .join method:

const checkedWords = words.filter(checkString).join(" "); // = asds dfaa aabb aaabb
1

A better way to do it is to write a function that takes a string and counts how many of each character it contains, and then check if there's a character that appears exactly two times.

Something along the lines of

function checkString(text){
    const charAppearances = {};
    text.split('').forEach( character => {
       charAppearances[character] = (charAppearances[character] || 0) + 1
   })
    return Object.values(charAppearances).includes(2);
}

The purpose of charAppearances is to count how many times a character appears, so for example for the string 'asdf' it will be {a: 1, s: 1, d:1, f:1}

The forEach section iterates over the characters of the string and updates the count of the current character (The charAppearances[character] = (charAppearances[character] || 0) + 1 means "If character exists in charAppearances, add 1 to it, otherwise add 1 to 0, which will result 1)

Ron B.
  • 1,502
  • 2
  • 7
1

This is a good chance to think in terms of decomposition. A function that counts chars can be written with reduce (citation). One that determines whether a string contains any pair is just a narrower question about the first. Filtering based on that is simple, so...

function countsOfCharsIn(string) {
  return [...string].reduce((a, e) => { a[e] = a[e] ? a[e] + 1 : 1; return a }, {}); 
}

function stringHasAPairOfChars(string) {
  return Object.values(countsOfCharsIn(string)).includes(2)
}

function stringsWithPairs(array) {
  return array.filter(stringHasAPairOfChars);
}

const words = [
  "asdf",
  "fdas",
  "asds",
  "d fm",
  "dfaa",
  "aaaa",
  "aabb",
  "aaabb"
];

console.log(stringsWithPairs(words));
danh
  • 62,181
  • 10
  • 95
  • 136
1

How about the following implementations? I thought that you wanted to exclude "aaabb" since 'a' appears three times even though 'b' appears two times. But your comment at the end of the code includes "aaabb". In that case the following implementations suffice.

const words = [
  "asdf",
  "fdas",
  "asds",
  "d fm",
  "dfaa",
  "aaaa",
  "aabb",
  "aaabb"
];

function isAppearingTwoTimes(word) {
  const [...chars] = word; // split chars into the array
  const set = new Set(chars);

  if (set.size === word.length)
    return false; // all the chars are unique

  return Array.from(set.values()).reduce((accum, ch) => {
    // if found two appearing characters, you don't have to count anymore
    if (accum) return true;
    // counts how many times 'ch' appears in the word 'chars'
    const nums = chars.reduce((counter, c) =>
      c === ch ? counter + 1 : counter, 0);

    return nums === 2 || accum;
  }, false);

}

// test the code
words.forEach(e => {
  if (isAppearingTwoTimes(e)) console.log(e);
});
waterloos
  • 410
  • 2
  • 7
1

Your approach was so close! Only thing you need to change was, instead of take a subString, just .split() all the string in a char array and use the .reduce() method to count the number of times a char appears in the array:

text.split("").reduce((a, char) => char === text[index] ? ++a : a, 0) === 2;

Try it here

const words = [
  "afsd",
  "fdas",
  "asds",
  "d fm",
  "dfaa",
  "aaaa",
  "aabb",
  "aaabb"
];

function checkString(text,index){
    if((text.length - index) == 0 ){ //stop condition
        return false; 
    }else{
        return checkString(text,index + 1) 
        || text.split("").reduce((a, char) => char === text[index] ? ++a : a, 0) === 2;
    }
}

// example Data to test

for(var idx in words){
    var txt = words[idx];
  
  if(checkString(txt,0)) {
    console.log(txt);
  }
  
}

Plus

  • Instead of using recursion, you can use a while() loop with this method:

const words = [
  "afsd",
  "fdas",
  "asds",
  "d fm",
  "dfaa",
  "aaaa",
  "aabb",
  "aaabb"
];



// example Data to test

for (var idx in words) {
  var txt = words[idx];

  let state = false,
    thisChar = 0;
    
  while (!state && thisChar < txt.length) {
    txt.split("").reduce((a, char) => char === txt[thisChar] ? ++a : a, 0) === 2 
    && (state = true);
    thisChar++;
  }
  
  if (state) console.log(txt);
}
AlexSp3
  • 2,201
  • 2
  • 7
  • 24
0
process.stdin.resume();
process.stdin.setEncoding('utf8');

process.stdin.on('data', function(input) {
    lines = input.split("\n");

    lines.forEach(processLine => {
        const a = checkInput(processLine);
        if(a)
    console.log(processLine);
      });
        
        
    });
function checkInput(text){
    const charAppearances = {};
    text.split('').forEach( character => {
       charAppearances[character] = (charAppearances[character] || 0) + 1;
   });
    return Object.values(charAppearances).includes(2);
}
Abhishek Gupta
  • 230
  • 2
  • 12