0

I am transitioning a project from Python to Node.js - everything has been going fine up until this point. I have a function that is supposed to convert the amount of EXP someone has into a level. I have attempted to rewrite the working function from Python into Node.js but the functions return completely different answers and I can't figure out why.

Python:

def calculateLevel(exp):
    if exp < 83: return 1
    else:
        calcExp = 0
        for level in range(1, 1000):
            diff = int(level + 300 * math.pow(2, float(level)/7))
            calcExp += diff
            if exp < calcExp//4:
                break
        return level

Node.js:

const _ = require("underscore");
// ...
function calculateLevel(exp) {
    return new Promise((resolve, reject) => {
        if (exp < 83) resolve(1);
        else {
            var calcExp = 0;
            for (var i in _.range(1, 1000)) {
                calcExp += parseInt(i + 300 * Math.pow(2, i/7));
                if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }
            }
        }
    });
}

For example, calculateLevel(123456) in Python returns 51 (the correct answer), but await calculateLevel(123456); in Node.js returns 15 (the incorrect answer).

Clearly there is something wrong in the Node.js version, but I can't figure out what it is.

Any help is greatly appreciated. Thanks in advance.

2
  • your resolve(i) is not in the same block than your return level, maybe you need to get it out of the loop Commented Aug 21, 2018 at 15:03
  • @jonatjano I just tried this, but unfortunately it gives the same result. Commented Aug 21, 2018 at 15:06

4 Answers 4

2

In Python:

for i in range(1, 10)
   print(i)

Will create the sequence to 1 2 3 4 5 6 7 8 9

The for...in in JavaScript will iterate over the keys and not the values.

So for (var i in _.range(1, 1000)) { will always be 0 ... 999

Change it to for...of

function calculateLevel(exp) {
    return new Promise((resolve, reject) => {
        if (exp < 83) resolve(1);
        else {
            var calcExp = 0;
            for (var i of _.range(1, 999)) {
                calcExp += parseInt(i + 300 * Math.pow(2, i/7));
                if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }
            }
        }
    });
}

Beside that it is not clear why you use a Promise here because you do not have any async code here. So you can completely remove the Promise here.

const _ = require("underscore");
// ...
function calculateLevel(exp) {
  if (exp < 83) return 1;
  else {
      var calcExp = 0;
      for (var i of _.range(1, 1000)) {
          calcExp += parseInt(i + 300 * Math.pow(2, i/7));
          if (exp < Math.floor(calcExp/4)) {
              break;
          }
      }
      return i;
  }
}

console.log(calculateLevel(123456))
Sign up to request clarification or add additional context in comments.

2 Comments

This worked. Thanks for the answer! I'm new to Javascript, and most times I use a function, it returns undefined unless I use a promise or callback, and I find promises to be easier and cleaner than callbacks.
@L.Thompson updated the answer and added the same code without Promises and it works fine.
0
if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }

should be

if (exp < Math.floor(calcExp/4)) {
                        break;
                    }
resolve(i)

1 Comment

I just tested this but unfortunately it gives the same result.
0

I ran this code:

function calculateLevel(exp) {
    return new Promise((resolve, reject) => {
        if (exp < 83) resolve(1);
        else {
            var calcExp = 0;
            for (var i=1; i<1000; i++) {
                calcExp += parseInt(i + 300 * Math.pow(2, i/7));
                if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }
            }
        }
    }); }

console.log(calculateLevel(123456));

and it returned 51.

something else is probably causing the issue.

Comments

0

Just adding my opinion as you already have an accepted answer.

Although you convert a Python code block to Javascript, I feel you don't really have to use the same syntaxes and method names.

For an example, if we take the following code block in Python and JS;

Python:

def calculateLevel(exp):
    if exp < 83: return 1
    else:
        calcExp = 0
        for level in range(1, 1000):
            diff = int(level + 300 * math.pow(2, float(level)/7))
            calcExp += diff
            if exp < calcExp//4:
                break
        return level

Note: Here it uses for level in range(1, 1000):.

The same thing can be done by using a while loop as well. So it could look something like:

level = 0
while level <= 1000:
    diff = int(level + 300 * math.pow(2, float(level)/7))
    calcExp += diff
    if exp < calcExp//4:
        break
return level

But looping over a for in range() in Python is more efficient than using a while loop. If I run a simple benchmark, I could see the following results.

for in range() : 55 function calls in 0.000 seconds

while: 1650 function calls in 0.001 seconds

Although this is the case with Python, it's quite different in Javascript (and in your approach which uses underscore's range() function.) Although the function names look similar, it doesn't mean they have same performance as in Python.

In fact, looping over _.range() is much slower than looping over a while loop. If you look at some benchmark results, you would see something like this:

Using _.range(1, 1000): 67.67% slower

https://jsbench.me/b2jl4vvgnw/1

So with all that, I think it's better to write this using a while loop, and with a slight modification, I would write it as:

function calculateLevel(exp) {
    var level = 1;

    if (exp > 83){
        var calcExp = 0;
        while(level <= 1000){
            calcExp += parseInt(level + 300 * Math.pow(2, level/7));
            if (exp < Math.floor(calcExp/4))
                break;
            level++;
        }
    }
    return level;
}

Hope it helps!!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.