-1

I am working on this kata https://www.codewars.com/kata/count-9-s-from-1-to-n/train/javascript

and i have written this code for it, but its not working. This question is similar to this one Count the number of occurrences of 0's in integers from 1 to N but it is different because searching for 9's is practically very different to searching for 0's. think part of the problem with this code is that it takes too long to run... any advice appreciated!

function has9(n) {

  var nine = [];

  var ninearr = n.toString().split('');

  for (var j = 0; j < ninearr.length; j++) {
    if (ninearr[j] == '9') {

      nine.push(ninearr[j]);
    }
  }
  return nine.length;
}

function number9(n) {
  var arr = [];
  var arrnew = [];

  for (var i = 0; i <= n; i++) {
    arr.push(i);
  }

  for (var l = 0; l < arr.length; l++) {
    arrnew.push(has9(l));

  }

  var sum = arrnew.reduce((a, b) => a + b, 0);
  return sum;
}
JJJ
  • 32,902
  • 20
  • 89
  • 102
E.Moon
  • 5
  • 5
  • no reason to split and loop over the string, just use indexOf on the string. – epascarello Oct 25 '17 at 12:30
  • but won't `indexOf` find only the first 9? – Jeremy Thille Oct 25 '17 at 12:32
  • It's completely unnecessary to build an array just to iterate from 0 to array length. Similarly a bit silly to build an array only for the purpose of returning its length. – JJJ Oct 25 '17 at 12:33
  • 1
    Too long to run. Part of these katas is finding an efficient algorithm. Checking each character from every string of digits in the numbers 1-N probably won’t be quick enough. Hint, there are the same number of 9s between 1-100 as between 101-200. – James Oct 25 '17 at 12:38
  • thanks for the hint, I have re written the code in accordance to this hint - but still having problems. will you have a look at it (below) - thanks – E.Moon Oct 25 '17 at 16:49

4 Answers4

0

Why not a regex based solution? (Too slow as well?)

const count9s = num => num.toString().match(/9/g).length

console.log(count9s(19716541879)) // 2
console.log(count9s(919191919191919)) // 8
console.log(count9s(999)) // 3
console.log(count9s(999999)) // 6
Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63
0

=== UPDATE ===

I just solved your kata using

function number9Helper(num) {
    var pow = Math.floor(Math.log10(num));
    var round = Math.pow(10, pow);
    var times = Math.floor(num / round);
    var rest = Math.abs(num - (round * times));
    var res = pow * (round==10 ? 1 : round / 10) * times;
    if (num.toString()[0] == '9') res += rest;
    if (rest < 9) return res;
    else return res + number9Helper(rest);
}
function number9(num) {
    var res = number9Helper(num);
    res = res + (num.toString().split('9').length-1);
    return res;
}

== Function below works but is slow ===

So, could something like this work for you:

for (var nines=0, i=1; i<=n; i++) nines += i.toString().split('9').length-1;

Basically, there are many way to achieve what you need, in the end it all depends how do you want to approach it.

You can test it with

function nines(n) {
  for (var nines=0, i=1; i<=n; i++) nines += i.toString().split('9').length-1;
  return nines;
}
dkasipovic
  • 5,930
  • 1
  • 19
  • 25
0

I have taken the above hint and completely re written the code, which I now feel should work, and it does for most inputs, but codewars is saying it fails on some of them. any ideas why?

 function nines(n){

  if(n>=100){
    var q= Math.floor(n/100);
    var nq= q * 20;
    var r = (n%100);
    var s = Math.floor(r/9);
    if (r<=90){
      return s + nq;
      }
    if (r == 99){
      return 20 + nq;
      }
    if (90 < r < 100 && r!= 99){
     var t = (r-90);
     return nq + s + t;
     }
     }

 if (n<100){

  if (n<=90){
    var a = Math.floor(n/9);
    return a ;
  }
  if (n == 99){
    return 20
  }
  if (90 < n < 100 && n!= 99){
    var c = (n-90);
    return 10 + c;
  }

 }
 }
E.Moon
  • 5
  • 5
0

function number9(n) {
  if (n < 8) {
    return 0
  };
  if (n === 9) {
    return 1
  };
  if (n > 10) {
    let str = ''
    for (let i = 9; i <= n; i++) {
      str += String(i)
    }
    return str.match(/[9]/g).length
  }
}