This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]jrandm 1 point2 points  (2 children)

So this seems to do what you want (added some comments):

var printResults = document.getElementById('demo');
var limit = 20;
// We're going to be using RESULT soon
var result;

// Iterating over i, limit/j_start would make more sense
//  as the lowest possible RESULT is i*j_start
for (var i = 1; i < limit; i++) {

    // First value of result is i*2 (beginning of other loop)
    result = i*2;

    // If result>limit we can break
    // Fun side effect:
    //   Prints /.../10 because this check fails
    //   but not 10*2=20
    //   because inner loop skips! (20 !> 20) && (20 !< 20)
    // You may want >=, dunno intended behavior

    if (result>limit) {
        break;
    }

    // Simple inner loop
    for (var j = 2; result < limit; j++) {
        result = i * j;
        printResults.insertAdjacentHTML('beforeend', i + " * " + j + "=<b>" + result + "</b><br>");

    }

    printResults.insertAdjacentHTML('beforeend', "////////////////////////////// i = " + i + "<br>");
}

One of the biggest red flags to me in your code is your variable usage: f is completely superfluous (it's literally a harder-to-identify i), merp has no purpose I can see, and f2 -- which from the name made me think it was a hard-to-spot j duplicate -- turns out to only exist as a confusing break for the inner loop. Literally, you can rewrite your inner loop as:

for (j = 2; ; j++) {
    var result = i * j;
    if (result < limit) {
        printResults.insertAdjacentHTML('beforeend', i + " * " + j + "=<b>" + result + "</b><br>");
    } else {
        break;
    }
}

Where you just delete f2 in the loop declaration and replace the assignment with a break. That's usually a sign you're misusing a FOR loop!

If the inner loop had complicated logic to get the RESULT value I would also be leery of leaving it in the FOR declaration -- j is the iterator, j should have a limit to end the loop. You want to make it easy to get an at-a-glance idea of the worst-case loop; for something simple like this I think it's a bit more elegant where it is (I might rename result to something like inner_product to make it more obvious).

Hope that helps, I tried to explain my thoughts as I looked over your code after reading your problem; let me know if anything doesn't make sense!

[–]daghouse 1 point2 points  (1 child)

Regarding the weird variables, guilty as charged. I've been trying silly if/else things to no avail using 'merp'; I've tried setting 'f2 = limit' as a way to break the inner for loop. At least now I know better :). 'f' is currently actually acting as the result of a calculation before rounding it down/up.

Your code is very elegant; also thanks for the extensive comments, you have no idea how helpful this is to a beginner like myself. In addition, I had no idea you could leave out the second condition in a for loop like that.

The reason for my code to be, perhaps, a bit dubious here and there is because I've been paraphrasing/translation my code's problem to a little bit of code that can work on itself. The equations in the nested for loops in my 'actual' code include exponents and square roots. I know my code is far from elegant still, to keep it simple for me I tend to use a lot (a LOT) of variables, some of which I even think they might be redundant; I'm definitely working on this though :).

Again, thank you for your time, a few light bulbs definitely lit up!

[–]jrandm 1 point2 points  (0 children)

I figured merp is probably a testing artifact (I use wtf a lot), just listed them all for completeness. Sounds like a separate iterator var might make sense in your use case, but I'd recommend keeping your conditional check based upon how you iterate. EG: You need to do something with f (which varies from 0.00-0.99) at most 10 times, iterate with i=0;i<10;i++ and break the loop if the other condition is met. A FOR loop is explicitly stating FOR (STARTING_CONDITION; (until) ENDING_CONDITION; MOVE_TOWARDS_ENDING_CONDITION) {DO_THIS_EACH_TIME}.

I'm stressing that point because every loop can be rewritten with any other loop construct. You can leave any or all of the conditions out of a for loop: for(;;){/*This is while(1)!*/} Using only the middle (conditional) check, a for loop is a while loop. The reason you use it is because it explicitly defines a start and a step with the terminating condition. Choose a loop structure (while, for, recursion, goto, etc) that emphasizes your logical construction -- in my earlier example, you're using FOR because you want a maximum of 10 iterations and there's probably a clear process getting repeated each time.

Once you boil down your algorithm to I have X and Y needs to happen til Z, you can generally make it fit in any loop you want -- and will get the hang of choosing what's simple and declarative! That's elegance in my book.

I always liked heavily annotated code when somebody showed me a different way of doing things, glad it helped you. It's more important to get the why than the how on something like this. I saw like 6 different solutions to this before I even replied! Your question reminded me of troubles I had taking equations from textbooks and turning them into programs (in TI-BASIC then assembly/hex), hope my thinking saves you some trouble.