Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions modules/90-loops/100-while/en/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

Modify the method `printNumbers()` so that it prints the numbers in reverse order. For this you need to go from the upper bound to the lower one. That is, the counter has to be initialized with the maximum value, and in the body of the loop it has to be decreased down to the lower bound.

An example of a call and the output:

```java
printNumbers(4);
```

```text
4
3
2
1
finished!
```
119 changes: 119 additions & 0 deletions modules/90-loops/100-while/en/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
The programs we write while studying are becoming more and more complex and voluminous. They are still very far from real programs, where the number of lines of code is measured in tens and hundreds of thousands, but the current complexity is already able to make people without experience tense up.

Starting with this lesson, we move on to one of the most complex basic topics in programming — **loops**.

Any applied programs serve very pragmatic goals. They help to manage employees, finances, and in the end they entertain. Despite the differences, all these programs execute the algorithms built into them, which are very similar to each other.

An **algorithm** is a sequence of actions or instructions that leads us to some expected result. This description fits any program, but by algorithms something more specific is usually meant.

Imagine that we have a book and we want to find some specific phrase inside it. We remember the phrase itself, but we do not know which page it is on. How do we find the needed page?

Check notice on line 9 in modules/90-loops/100-while/en/README.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] modules/90-loops/100-while/en/README.md#L9

Use a comma before ‘and’ if it connects two independent clauses (unless they are closely connected and short). (COMMA_COMPOUND_SENTENCE[1]) Suggestions: `, and` URL: https://languagetool.org/insights/post/types-of-sentences/#compound-sentence Rule: https://community.languagetool.org/rule/show/COMMA_COMPOUND_SENTENCE?lang=en-US&subId=1 Category: PUNCTUATION
Raw output
modules/90-loops/100-while/en/README.md:9:25: Use a comma before ‘and’ if it connects two independent clauses (unless they are closely connected and short). (COMMA_COMPOUND_SENTENCE[1])
 Suggestions: `, and`
 URL: https://languagetool.org/insights/post/types-of-sentences/#compound-sentence 
 Rule: https://community.languagetool.org/rule/show/COMMA_COMPOUND_SENTENCE?lang=en-US&subId=1
 Category: PUNCTUATION

The simplest and longest way is to look through the book sequentially until we find the needed page. In the worst case we will have to look through all the pages, but we will get the result anyway.

Exactly this process is called an **algorithm**. It includes going through the pages and logical checks of whether we have found the phrase or not. The number of pages we will have to look at is not known in advance, but the process of looking itself repeats from time to time in a completely identical way.

Loops are exactly what is needed for performing repeating actions. Every such repetition is called an **iteration**.

Suppose we want to write a method. It has to print to the screen all the numbers from 1 to the number that we specified through the parameters:

```java
App.printNumbers(3);
// 1
// 2
// 3
```

It is impossible to implement this method with the means already studied, because the number of prints to the screen is not known in advance. But with loops this will not be a problem at all:

```java
public static void printNumbers(int lastNumber) {
// i is a shortening of index (the ordinal number)
// By common agreement it is used in many languages as the loop counter
var i = 1;

while (i <= lastNumber) {
System.out.println(i);
i = i + 1;
}
System.out.println("finished!");
}

App.printNumbers(3);
```

```text
1
2
3
finished!
```

The `while` loop is used in the code of the method. It consists of three elements:

* The **keyword** `while`. Despite the similarity to method calls, this is not a method call
* The **predicate** — the condition that is specified in parentheses after `while` and is evaluated on every iteration
* The **body of the loop** — a block of code in curly braces, analogous to the block of code in a method. All the constants or variables defined inside this block will be visible only inside this block

The construct reads like this: "do what is specified in the body of the loop while the condition `i <= lastNumber` is true". Let's take apart the work of this code for the call `App.printNumbers(3)`:

```java
// i is initialized
var i = 1;

// The predicate returns true, so the body of the loop is executed
while (1 <= 3)
// System.out.println(1);
// i = 1 + 1;

// The body of the loop has ended, so a return to the beginning happens
while (2 <= 3)
// System.out.println(2);
// i = 2 + 1;

// The body of the loop has ended, so a return to the beginning happens
while (3 <= 3)
// System.out.println(3);
// i = 3 + 1;

// The predicate returns false, so the execution moves past the loop
while (4 <= 3)

// System.out.println("finished!");
// At this stage i equals 4, but we do not need it anymore
// The method finishes
```

The most important thing in a loop is the ending of its work, that is, **exiting the loop**. The process that the loop generates must stop in the end. The responsibility for stopping lies entirely on the programmer.

Usually the task comes down to introducing a variable called the **loop counter**. It works on the following principle:

* First the counter is initialized, that is, an initial value is set for it. In the example above the counter is the instruction `var i = 1`, executed before entering the loop
* Then the condition of the loop checks whether the counter has reached its limit value.
* In the end the counter changes its value `i = i + 1`

At this point beginners make the most mistakes. Let's imagine that the check in the predicate is written incorrectly in the code. This can lead to an **infinite loop** — a situation in which the loop works endlessly and the program never stops.

In that case you have to terminate it forcibly:

```java
public static void printNumbers(int lastNumber) {
var i = 1;

// This loop will never stop
// and will always print one and the same value
while (i <= lastNumber) {
System.out.println(i);
}
System.out.println("finished!");
}
```

In some cases infinite loops are useful. We do not consider such cases here, but it is useful to see what this code looks like:

```java
while (true) {
// We do something
}
```

Let's sum up. When are loops really needed, and when can you do without them? It is impossible to do without loops when the algorithm of solving the task requires repeating some actions, and the number of these operations is not known in advance. That is how it was in the example with the book that we looked at in the beginning of the lesson.
5 changes: 5 additions & 0 deletions modules/90-loops/100-while/en/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
name: The While loop
definitions:
- name: The While loop
description: an instruction for repeating code while some condition is satisfied.
2 changes: 1 addition & 1 deletion modules/90-loops/100-while/es/data.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: Ciclo While
definitions:
- name: Bucle While
- name: Ciclo While
description: >-
una instrucción para repetir un bloque de código mientras se cumple una
determinada condición.
8 changes: 8 additions & 0 deletions modules/90-loops/150-aggregation-numbers/en/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

Implement the method `multiplyNumbersFromRange()`, which multiplies the numbers in the specified range including the bounds of the range. An example of a call:

```java
App.multiplyNumbersFromRange(1, 5); // 1 * 2 * 3 * 4 * 5 = 120
App.multiplyNumbersFromRange(2, 3); // 2 * 3 = 6
App.multiplyNumbersFromRange(6, 6); // 6
```
85 changes: 85 additions & 0 deletions modules/90-loops/150-aggregation-numbers/en/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
In programming there is a separate class of tasks that cannot do without loops — it is called **data aggregation**.

Such tasks include finding:

* The maximum value
* The minimum value
* The sum
* The arithmetic mean

Their main feature is that the result depends on the whole set of data. To calculate the sum you need to add up **all** the numbers; to calculate the maximum you need to compare **all** the numbers.

Everyone who works with numbers is well familiar with this topic. For example, accountants or marketers often work with such tasks in spreadsheets like Microsoft Excel or Google Sheets.

Let's take apart the simplest example — finding the sum of a set of numbers. Let's implement a function that adds up the numbers in the specified range, including the bounds.

In this case a **range** is a series of numbers from some beginning to a certain end. For example, the range `[1, 10]` includes all the integers from 1 to 10:

```java
App.sumNumbersFromRange(5, 7); // 5 + 6 + 7 = 18
App.sumNumbersFromRange(1, 2); // 1 + 2 = 3

// The range [1, 1] with the same beginning and end is also a range
// It includes one number — the bound of the range itself
App.sumNumbersFromRange(1, 1); // 1
App.sumNumbersFromRange(100, 100); // 100
```

To implement this code we will need a loop. We choose a loop exactly because adding numbers is an iterative process. It repeats for every number, and the number of iterations depends on the size of the range.

To understand the topic better, try to answer the questions:

* What value should the counter be initialized with?
* How will it change?
* When must the loop stop?

And now look at the code below:

```java
public static int sumNumbersFromRange(int start, int finish) {
// Technically you can change start, but input arguments should be left at their original value
// This makes the code simpler to analyze
var i = start;
var sum = 0; // Initializing the sum

while (i <= finish) { // We move to the end of the range
sum = sum + i; // We count the sum for every number
i = i + 1; // We move on to the next number in the range
}

// We return the resulting value
return sum;
}
```

The general structure of the loop here is standard:

* The counter, which is initialized with the starting value of the range
* The loop itself with the stopping condition when the end of the range is reached
* Changing the counter at the end of the body of the loop

The number of iterations in such a loop equals `finish - start + 1`. For example, 3 iterations are needed to count the range from 5 to 7:

```md
7 - 5 + 1 = 3
```

The main differences from ordinary processing are related to the logic of calculating the result. In aggregation tasks there is always some variable that stores inside itself the result of the loop's work. In the code above it is `sum`.

On every iteration of the loop it changes, the next number in the range gets added: `sum = sum + i`. The whole process looks like this:

```java
// For the call sumNumbersFromRange(2, 5);
var sum = 0;
sum = sum + 2; // 2
sum = sum + 3; // 5
sum = sum + 4; // 9
sum = sum + 5; // 14
// 14 is the result of adding the numbers in the range [2, 5]
```

In mathematics there is the notion of the **neutral element of an operation**. An operation with such an element does not change the value the operation is performed on:

* In addition any number plus zero gives the number itself
* In subtraction it is the same
* Even concatenation has a neutral element — it is the empty string: `"" + "one"` will be `"one"`
3 changes: 3 additions & 0 deletions modules/90-loops/150-aggregation-numbers/en/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
name: Data aggregation (Numbers)
tips: []
8 changes: 8 additions & 0 deletions modules/90-loops/200-aggregation-strings/en/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

Implement the method `joinNumbersFromRange()`, which joins all the numbers from a range into a string:

```java
App.joinNumbersFromRange(1, 1); // "1"
App.joinNumbersFromRange(2, 3); // "23"
App.joinNumbersFromRange(5, 10); // "5678910"
```
61 changes: 61 additions & 0 deletions modules/90-loops/200-aggregation-strings/en/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Aggregation is applied not only to numbers, but also to strings. By string aggregation we mean tasks in which it is not known in advance what the strings contain and what size they are.

In aggregation the string is formed dynamically. Imagine a method that repeats a string the specified number of times. Java has ready-made means for this, but here we will look at how such a repetition is arranged inside:

```java
App.repeat("hexlet", 3); // "hexlethexlethexlet"
```

The principle of this method's work is quite simple. In a loop the string grows the specified number of times:

```java
public static String repeat(String text, int times) {
// The neutral element for strings is the empty string
var result = "";
var i = 1;

while (i <= times) {
// Every time we add the string to the result

Check notice on line 18 in modules/90-loops/200-aggregation-strings/en/README.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] modules/90-loops/200-aggregation-strings/en/README.md#L18

Possible typo: you repeated a word (ENGLISH_WORD_REPEAT_RULE) Suggestions: `result` Rule: https://community.languagetool.org/rule/show/ENGLISH_WORD_REPEAT_RULE?lang=en-US Category: MISC
Raw output
modules/90-loops/200-aggregation-strings/en/README.md:18:47: Possible typo: you repeated a word (ENGLISH_WORD_REPEAT_RULE)
 Suggestions: `result`
 Rule: https://community.languagetool.org/rule/show/ENGLISH_WORD_REPEAT_RULE?lang=en-US
 Category: MISC
result = result + text;
i = i + 1;
}

return result;
}
```

Let's describe the execution of this code step by step:

```java
// For the call repeat("hexlet", 3);
var result = "";
result = result + "hexlet"; // "hexlet"
result = result + "hexlet"; // "hexlethexlet"
result = result + "hexlet"; // "hexlethexlethexlet"
```

Visually the process of growing the string looks like this:

```text
repeat("hexlet", 3):

i=1: result = "" + "hexlet" = "hexlet"
i=2: result = "hexlet" + "hexlet" = "hexlethexlet"
i=3: result = "hexlethexlet" + "hexlet" = "hexlethexlethexlet"
└── the result
```

Two variables work here at once. The counter `i` controls the number of repetitions and stops the loop when the repetitions have reached `times`. The variable `result` stores the accumulated string and gives it to the calling code after the loop.

## The neutral element

For the growing to work, a starting value is needed. For strings the **empty string** `""` serves as it.

It is called the neutral element, because in concatenation it does not change anything:

```java
System.out.println("" + "abc"); // => abc
System.out.println("abc" + ""); // => abc
```

That is why the empty string always stands at the beginning in string aggregation. The loop starts the growing from it, and then on every iteration adds the next piece to the result.
10 changes: 10 additions & 0 deletions modules/90-loops/200-aggregation-strings/en/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: Data aggregation (Strings)
tips:
- |
[Iteration](https://en.wikipedia.org/wiki/Iteration)
definitions:
- name: Aggregation
description: >-
Accumulating the result during the iterations and working with it after the
loop.
Loading
Loading