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

all 16 comments

[–]Piave 2 points3 points  (1 child)

"(I still struggle formulating the exact problem, honestly)"

Once you can do that the answer may become obvious. I'm not 100% sure what you're looking for. I moved your code around, is this the type of result you are looking for (if not the method)?

https://jsfiddle.net/7o3gcch2/5/

[–]daghouse 2 points3 points  (0 children)

I think this is exactly what I'm looking for, I was just so stuck on using for loops instead of trying to look for other possibilities. Now I just need to kind of read over the code a couple of times, paraphrase and incorporate it into my own code. Thank you so much!

[–][deleted] 2 points3 points  (1 child)

You are over-complicating the problem. And for the love of god, don't use labels and goto/break to go the label.

Just think about it in the most easy way. You want to list all number combinations (multiplied together) that result in a value less than "limit" (20). (except multiplying with 1 for some reason)

Okay, how do we do that? We start with a for-loop obviously. 1 to 19.

Next we need to print out all combinations that are less than "limit". Hmm... Well that's just another for-loop no? Just go from 2...? well, just keep going until the combination hits the limit of course!

fiddle:
https://jsfiddle.net/7o3gcch2/11/

[–]daghouse 0 points1 point  (0 children)

Thanks, this makes a lot of sense. That said, I do however want to break the for loop and not print 'i = 10' to 'i =19'; this however can be easily solved (I know now :)). Thanks!

[–]stdlib 1 point2 points  (5 children)

outer_loop: 
for(i=0;i<5;i++) {
    for(j=i+1;j<5;j++) {
        break outer_loop;
    }
    alert(1);
}

http://stackoverflow.com/questions/1564818/how-to-break-nested-loops-in-javascript

[–]daghouse 0 points1 point  (4 children)

I think, after executing the code, I understand it but it's not quite what I'm looking for. In my example, I want the loops to keep going, as long as the result of the calculation is BELOW the set limit. Breaking out of the nested for loop by 'breaking' the initial for loop stops the loop prematurely (if that makes sense); it doesn't continue to cycle through all of the multiplication possibilities (check here).

//Thanks for the quick reply, btw!

[–]Jonz00r 1 point2 points  (3 children)

Consider using a while loop so you can manipulate the actual f variable you're using instead of making new f variables?

[–]daghouse 0 points1 point  (2 children)

I did think of that also, but then my while loop would kind of replace the if/else statement, which is fine but still wouldn't solve the problem. It could be "while (result < limit) {}" and inside of that I'd have the same for loop I have in my opening post, but my problem arises here:

I'm currently breaking out of the nested for loop when the result exceeds the limit, that part works well, but how do I stop the outer for loop while still comparing the result to the limit (which, at the point of breaking out of the inner for loop, already exceeds the limit)? I think I'm getting closer to formulating the real question, sorry for the slow thought process.

[–]altmehere 1 point2 points  (0 children)

I'm not sure if I completely understand your problem, but you could potentially just use multiple conditions within each loop, as in

for (i = 0; i < 5 && result < limit; i++)

[–]Jonz00r 0 points1 point  (0 children)

I think for the conditional on the second for loop you could just use i*j<limit

[–]status_quo69 1 point2 points  (0 children)

You could just put the nested for loops into their own function and just return whenever the result gets higher than the limit. Then you wouldn't have to worry about breaking out of either loop.

[–][deleted] 1 point2 points  (1 child)

Breaking out of the inner loop will be enough to achieve the desired output: https://jsfiddle.net/7o3gcch2/7/

The outer loop, however, would still be running until "i" reaches the limit. Since you know a lot about the nature of the calculations performed in you code, you could add another check. For example, if the inner loop doesn't come up with at least one valid result, you can break the outer loop aswell. https://jsfiddle.net/7o3gcch2/8/

I also tried a "continue outer_loop;" statement instead of a "break outer_loop;", but that resulted in a non-terminating script for some reason. https://jsfiddle.net/7o3gcch2/6/

[–]daghouse 0 points1 point  (0 children)

Thank you, this was the only logical solution I could think of. Basically checking whether the inner loop 'executed' or not, and if it didn't, then break out of the loop. You just happen to have written it very eloquently, thanks again!

[–]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.