This commit is contained in:
Ilya Kantor 2017-03-24 17:28:37 +03:00
parent c9401b3104
commit 0fcf9f84fa
58 changed files with 673 additions and 643 deletions

View file

@ -10,7 +10,7 @@ while (i) {
Every loop iteration decreases `i` by `1`. The check `while(i)` stops the loop when `i = 0`.
Hence, the steps of the loop make the following sequence ("loop unrolled"):
Hence, the steps of the loop form the following sequence ("loop unrolled"):
```js
let i = 3;
@ -23,4 +23,3 @@ alert(i--) // shows 1, decreases i to 0
// done, while(i) check stops the loop
```

View file

@ -4,7 +4,7 @@ importance: 3
# Last loop value
What is be the last value alerted by this code? Why?
What is the last value alerted by this code? Why?
```js
let i = 3;
@ -13,4 +13,3 @@ while (i) {
alert( i-- );
}
```

View file

@ -11,7 +11,7 @@ The task demonstrates how postfix/prefix forms can lead to different results whe
Then follow `2,3,4…` -- the values show up one after another. The comparison always uses the incremented value, because `++` is before the variable.
Finally, `i=4` is incremented to `5`, the comparison `while(5 < 5)` fails and the loop stops. So `5` is not shown.
Finally, `i=4` is incremented to `5`, the comparison `while(5 < 5)` fails, and the loop stops. So `5` is not shown.
2. **From 1 to 5**
```js run
@ -28,4 +28,3 @@ The task demonstrates how postfix/prefix forms can lead to different results whe
Let's stop on `i=4`. The prefix form `++i` would increment it and use `5` in the comparison. But here we have the postfix form `i++`. So it increments `i` to `5`, but returns the old value. Hence the comparison is actually `while(4 < 5)` -- true, and the control goes on to `alert`.
The value `i=5` is the last one, because on the next step `while(5 < 5)` is false.

View file

@ -4,9 +4,9 @@ importance: 4
# Which values shows the while?
For every loop, scribe down which values it shows, in your opinion.
For every loop, write down which values it shows, in your opinion. And then compare with the answer.
And then compare with the answer.
Both loops `alert` same values or not?
1. The prefix form `++i`:
@ -20,4 +20,3 @@ And then compare with the answer.
let i = 0;
while (i++ < 5) alert( i );
```

View file

@ -8,7 +8,7 @@ for (let i = 0; i < 5; i++) alert( i );
That can be easily deducted from the algorithm of `for`:
1. Execute once `i=0` before everything.
1. Execute once `i=0` before everything (begin).
2. Check the condition `i<5`
3. If `true` -- execute the loop body `alert(i)`, and then `i++`

View file

@ -4,9 +4,9 @@ importance: 4
# Which values get shown by the "for" loop?
For each loop scribe down which values it is going to show.
For each loop write down which values it is going to show. Then compare with the answer.
Then compare with the answer.
Both loops `alert` same values or not?
1. The postfix form:
@ -18,4 +18,3 @@ Then compare with the answer.
```js
for (let i = 0; i < 5; ++i) alert( i );
```

View file

@ -10,6 +10,6 @@ do {
The loop `do..while` repeats while both checks are truthy:
1. The check for `num <= 100` -- that is, the entered value is still not greater than `100`.
2. The check for a truthiness of `num` checks that `num != null` and `num != ""` simultaneously.
2. The check `&& num` is false when `num` is `null` or a empty strig. Then the `while` loop stops too.
P.S. By the way, if `num` is `null` then `num <= 100` would return `false`, not `true`!
P.S. If `num` is `null` then `num <= 100` is `false`, so without the 2nd check the loop wouldn't stop if the user clicks CANCEL. Both checks are required.

View file

@ -4,11 +4,10 @@ importance: 5
# Repeat until the input is incorrect
Write a loop which prompts for a number greater than `100`. If the visitor enters another number -- ask him to repeat the input, and so on.
Write a loop which prompts for a number greater than `100`. If the visitor enters another number -- ask him to input again.
The loop must ask for a number until either the visitor enters a number greater than `100` or cancels the input/enters an empty line.
Here we can assume that the visitor only inputs numbers. There's no need to implement the special handling for a non-numeric input in this task.
Here we can assume that the visitor only inputs numbers. There's no need to implement a special handling for a non-numeric input in this task.
[demo]

View file

@ -13,8 +13,10 @@ For each i in the interval {
The code using a label:
```js run
let n = 10;
nextPrime:
for (let i = 2; i <= 10; i++) { // for each i...
for (let i = 2; i <= n; i++) { // for each i...
for (let j = 2; j < i; j++) { // look for a divisor..
if (i % j == 0) continue nextPrime; // not a prime, go next i
@ -24,5 +26,4 @@ for (let i = 2; i <= 10; i++) { // for each i...
}
```
Surely, there's a lot of space to opimize it. Like, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need change the approach and rely heavily on advanced maths and algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc.
There's a lot of space to opimize it. For instance, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need change the approach and rely on advanced maths and complex algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc.

View file

@ -4,15 +4,14 @@ importance: 3
# Output prime numbers
An integer number greater than `1` is called a [prime](https://en.wikipedia.org/wiki/Prime_number) if it cannot be not divided without a remainder by anything except `1` and itself.
An integer number greater than `1` is called a [prime](https://en.wikipedia.org/wiki/Prime_number) if it cannot be divided without a remainder by anything except `1` and itself.
In other words, `n>1` is a prime if the result of it's division by anything except `1` and `n` is not integer.
In other words, `n>1` is a prime if it can't be evenly divided by anything except `1` and `n`.
For example, `5` is a prime, because it cannot be divided without a remainder by `2`, `3` and `4`.
**Write the code which outputs prime numbers in the interval from `2` to `10`.**
**Write the code which outputs prime numbers in the interval from `2` to `n`.**
The result will be `2,3,5,7`.
P.S. The code should be easily modifiable for other intervals.
For `n=10` the result will be `2,3,5,7`.
P.S. The code should work for any `n`, not be hard-tuned for any fixed value.

View file

@ -14,7 +14,8 @@ The `while` loop has the following syntax:
```js
while (condition) {
// code ("loop body")
// code
// so-called "loop body"
}
```
@ -30,18 +31,18 @@ while (i < 3) { // shows 0, then 1, then 2
}
```
There's a special term *iteration* for each loop run. The loop in the example above makes 3 iterations.
A single execution of the loop body is called *an iteration*. The loop in the example above makes 3 iterations.
If there were no `i++` in the example above, the loop would repeat (in theory) forever, eating 100% CPU. In practice, the browser would show a message about a "hanging" script and let the user stop it.
If there were no `i++` in the example above, the loop would repeat (in theory) forever. In practice, the browser provides ways to stop such loops, and for server-side JavaScript we can kill the process.
The `while` converts `condition` to a logical value. It can be any expression, not just a comparison.
Any expression or a variable can be a loop condition, not just a comparison. They are evaluated and converted to boolean by `while`.
For instance, the shorter way to write `while (i!=0)` could be `while (i)`:
```js run
let i = 3;
*!*
while (i) { // when i becomes 0, the condition is falsy and the loop stops
while (i) { // when i becomes 0, the condition becomes falsy, and the loop stops
*/!*
alert( i );
i--;
@ -69,7 +70,7 @@ do {
} while (condition);
```
The loop will first execute the body and then check the condition.
The loop will first execute the body, then check the condition, and while it's truthy -- execute it again and again.
For example:
@ -81,11 +82,11 @@ do {
} while (i < 3);
```
This form of syntax is rarely used, because the ordinary `while` is more obvious. We don't need to scroll down the code looking for the condition.
This form of syntax is rarely used. Usually, if there's no special reason, the other form is preferred: `while(…) {…}`.
## The "for" loop
The `for` loop is actually the most often used one.
The `for` loop is the most often used one.
It looks like this:
@ -95,7 +96,7 @@ for (begin; condition; step) {
}
```
Let's see these parts in an example. For instance, the loop below runs `alert(i)` for `i` from `0` up to (but not including) `3`:
Let's learn the meaning of these parts by example. The loop below runs `alert(i)` for `i` from `0` up to (but not including) `3`:
```js run
for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2
@ -103,42 +104,45 @@ for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2
}
```
Let's examine the last example part-by-part:
Let's examine the `for` statement part by part:
| part | | |
|-------|----------|----------------------------------------------------------------------------|
| begin | `i=0` | Executes once upon entering the loop. |
| condition | `i<3`| Checked before every loop iteration, if fails the loop stops. |
| body | `alert(i)`| Runs again and again while the condition is truthy |
| step| `i++` | Executes after the body on each iteration, but before the condition check. |
| body | `alert(i)`| Runs again and again while the condition is truthy |
The general loop algorithm works like this:
```
Begin
Run begin
→ (if condition → run body and run step)
→ ... repeat while the condition is truthy
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ ...
```
If you are new to loops, then maybe it would help if you go back to the example and reproduce how it runs step-by-step on a piece of paper.
That's what exactly happens in our case:
Here's what exactly happens in our case:
```js
// for (let i = 0; i < 3; i++) alert(i)
// begin
// run begin
let i = 0
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// repeat while the condition is truthy
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// ...finish, because now i == 3
```
````smart header="Inline variable declaration"
Here the "counter" variable `i` is declared right in the the loop. That's called an "inline" variable declaration. Such variable is visible only inside the loop.
Here the "counter" variable `i` is declared right in the loop. That's called an "inline" variable declaration. Such variable is visible only inside the loop.
```js run
for (*!*let*/!* i = 0; i < 3; i++) {
@ -147,13 +151,15 @@ for (*!*let*/!* i = 0; i < 3; i++) {
alert(i); // error, no such variable
```
We can use an existing variable as well:
Instead of defining a variable, we can use an existing one:
```js run
let i = 0;
for (i = 0; i < 3; i++) { // use an existing variable
alert(i); // 0, 1, 2
}
alert(i); // 3, visible, because declared outside of the loop
```
@ -162,14 +168,14 @@ alert(i); // 3, visible, because declared outside of the loop
### Skipping parts
Any part of the `for` can be skipped.
Any part of `for` can be skipped.
For example, we can omit `begin` if we don't need to do anything at the loop start.
Like here:
```js run
let i = 0; // imagine we have i already declared and assigned
let i = 0; // we have i already declared and assigned
for (; i < 3; i++) { // no need for "begin"
alert( i ); // 0, 1, 2
@ -223,7 +229,7 @@ while (true) {
alert( 'Sum: ' + sum );
```
The `break` directive is activated in the line `(*)` if the user enters an empty line or cancels the input. It stops the loop immediately, passing the control to the first line after it's loop. Namely, `alert`.
The `break` directive is activated in the line `(*)` if the user enters an empty line or cancels the input. It stops the loop immediately, passing the control to the first line after the loop. Namely, `alert`.
The combination: "infinite loop + `break` as needed" is great for situations when the condition must be checked not in beginning/end of the loop, but in the middle. Or even in several places of the body.
@ -248,7 +254,7 @@ for (let i = 0; i < 10; i++) {
For even values of `i` the `continue` directive stops body execution, passing the control to the next iteration of `for` (with the next number). So the `alert` is only called for odd values.
````smart header="The directive `continue` helps to decrease nesting level"
A loop for odd-only values could look like this:
A loop that shows odd values could look like this:
```js
for (let i = 0; i < 10; i++) {
@ -268,7 +274,7 @@ But as a side-effect we got one more figure brackets nesting level. If the code
````warn header="No `break/continue` to the right side of '?'"
Please note that syntax constructs that are not expressions cannot be used in `'?'`. In particular, directives `break/continue` are disallowed there.
For example, if one we take this code:
For example, if we take this code:
```js
if (i > 5) {
@ -295,7 +301,7 @@ That's just another reason not to use a question mark operator `'?'` instead of
Sometimes we need to break out from multiple nested loops at once.
For example, in the code below we loop over `i` and `j` asking for values on coordinates `(i, j)` from `(0,0)` to `(3,3)`:
For example, in the code below we loop over `i` and `j` prompting for coordinates `(i, j)` from `(0,0)` to `(3,3)`:
```js run no-beautify
for (let i = 0; i < 3; i++) {
@ -312,7 +318,7 @@ for (let i = 0; i < 3; i++) {
alert('Done!');
```
Let's say we need a way to stop the process. Like if we user decides to cancel the input.
We need a way to stop the process if the user cancels the input.
The ordinary `break` after `input` would only break the inner loop. That's not sufficient. Labels come to the rescue.
@ -323,7 +329,7 @@ labelName: for(...) {
}
```
We can put the `labelName` after a break statement, and it will break out of the labelled loop.
The `break <labelName>` statement in the loop breaks out to the label.
Like here:
@ -354,7 +360,7 @@ outer:
for (let i = 0; i < 3; i++) { ... }
```
The `continue` directive can also be used with a label. In this case the execution would jump onto the next iteration of the labelled loop.
The `continue` directive can also be used with a label. In this case the execution jumps to the next iteration of the labelled loop.
````warn header="Labels are not a \"goto\""
Labels do not allow to jump into an arbitrary place of code.
@ -379,6 +385,6 @@ We covered 3 types of loops:
To make an "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive.
If we don't want to do anything more on this iteration and would like to forward on to the next one -- the `continue` directive does it.
If we don't want to do anything on the current iteration and would like to forward to the next one -- the `continue` directive does it.
`Break/continue` support labels before the loop. A label is the only way for `break/continue` to escape the nesting and go to the outer loop.