-
-
Notifications
You must be signed in to change notification settings - Fork 666
bird-watcher: add "for loop" concept #1775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
925250c
bird-watcher: Initial commit
sachinmk27 e8b40a1
Apply suggestions from code review
andrerfcsantos 8b42d70
Add exemplar and tests
andrerfcsantos c905869
Tweak concept
andrerfcsantos df475b8
Make gocritic happy
andrerfcsantos e092a89
Mark exercise as beta
andrerfcsantos cfe838d
Apply suggestions from code review
andrerfcsantos 7a796e0
Manual changes for suggestions on code review
andrerfcsantos d123682
Update test
andrerfcsantos c398f71
Update examples
andrerfcsantos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"blurb": "Execute the same piece of code several times", | ||
"authors": [ | ||
"sachinmk27", | ||
"andrerfcsantos" | ||
], | ||
"contributors": [] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# About | ||
|
||
## General syntax | ||
|
||
The for loop is one of the most commonly used statements to repeatedly execute some logic. In Go it consists of the `for` keyword, a header and a code block that contains the body of the loop wrapped in curly brackets. The header consists of 3 components separated by semicolons `;`: init, condition and post. | ||
|
||
```go | ||
for init; condition; post { | ||
// loop body - code that is executed repeatedly as long as the condition is true | ||
} | ||
``` | ||
|
||
- The **init** component is some code that runs only once before the loop starts. | ||
- The **condition** component must be some expression that evaluates to a boolean and controls when the loop should stop. The code inside the loop will run as long as this condition evaluates to true. As soon as this expression evaluates to false, no more iterations of the loop will run. | ||
- The **post** component is some code that will run at the end of each iteration. | ||
|
||
**Note:** Unlike other languages, there are no parentheses `()` surrounding the three components of the header. In fact, inserting such parenthesis is a compilation error. However, the braces `{ }` surrounding the loop body are always required. | ||
|
||
## For Loops - An example | ||
|
||
The init component usually sets up a counter variable, the condition checks whether the loop should be continued or stopped and the post component usually increments the counter at the end of each repetition. | ||
|
||
```go | ||
for i := 1; i < 10; i++ { | ||
fmt.Println(i) | ||
} | ||
``` | ||
|
||
This loop will print the numbers from `1` to `9` (including `9`). | ||
Defining the step is often done using an increment or decrement statement, as shown in the example above. | ||
|
||
## Optional components of the header | ||
|
||
The init and post components of the header are optional: | ||
|
||
```go | ||
var sum = 1 | ||
for sum < 1000 { | ||
sum += sum | ||
} | ||
fmt.Println(sum) | ||
// Output: 1024 | ||
``` | ||
|
||
By omitting the init and post component in a for loop like shown above, you create a while loop in Go. | ||
There is no `while` keyword. | ||
This is an example of Go's principle that concepts should be orthogonal. Since there is already a concept to achieve the behavior of a while loop, namely the for loop, `while` was not added as an additional concept. | ||
|
||
## Break and Continue | ||
|
||
Inside a loop body you can use the `break` keyword to stop the execution of the loop entirely: | ||
|
||
```go | ||
for n := 0; n <= 5; n++ { | ||
if n == 3 { | ||
break | ||
} | ||
fmt.Println(n) | ||
} | ||
// Output: | ||
// 0 | ||
// 1 | ||
// 2 | ||
``` | ||
|
||
In contrast, the keyword `continue` only stops the execution of the current iteration and continues with the next one: | ||
|
||
```go | ||
for n := 0; n <= 5; n++ { | ||
if n%2 == 0 { | ||
continue | ||
} | ||
fmt.Println(n) | ||
} | ||
// Output: | ||
// 1 | ||
// 3 | ||
// 5 | ||
``` | ||
## Infinite for loop | ||
|
||
The condition part of the loop header is also optional. In fact, you can write a loop with no header: | ||
|
||
```go | ||
for { | ||
// Endless loop... | ||
} | ||
``` | ||
|
||
This loop will only ever finish if the program exits or has a `break` in its body. | ||
|
||
## Labels and goto | ||
|
||
When we use `break`, Go will stop running the most inner loop. Similarly, when we use `continue`, Go will run the next iteration of the most inner loop. | ||
|
||
However, this is not always desirable. We can use labels together with `break` and `continue` to specifcy exactly from which loop we want to exit or continue, respectively. | ||
|
||
In this example we are creating a label `OuterLoop`, that will refer to the most outter loop. In the most inner loop, to say that we want exit from the most outter loop, we then use `break` followed by the name of the label of the most outter loop: | ||
|
||
```go | ||
OuterLoop: | ||
for i := 0; i < 10; i++ { | ||
for j := 0; j < 10; j++ { | ||
// ... | ||
break OuterLoop | ||
} | ||
} | ||
``` | ||
|
||
Using labels with `continue` would also work, in which case, Go would continue in the next iteration of the loop referenced by the label. | ||
|
||
Go also has a `goto` keyword that works in a similar way and allows us to jump to from a piece of code to another labeled piece of code. | ||
|
||
**Warning:** Even though Go allows to jump to a piece of code marked with a label, using this feature of the language can easily make the code very hard to read. For this reason, using labels is often not recommended. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Introduction | ||
|
||
|
||
## General syntax | ||
andrerfcsantos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The for loop is one of the most commonly used statements to repeatedly execute some logic. In Go it consists of the `for` keyword, a header and a code block that contains the body of the loop wrapped in curly brackets. The header consists of 3 components separated by semicolons `;`: init, condition and post. | ||
|
||
```go | ||
for init; condition; post { | ||
// loop body - code that is executed repeatedly as long as the condition is true | ||
} | ||
``` | ||
|
||
- The **init** component is some code that runs only once before the loop starts. | ||
- The **condition** component must be some expression that evaluates to a boolean and controls when the loop should stop. The code inside the loop will run as long as this condition evaluates to true. As soon as this expression evaluates to false, no more iterations of the loop will run. | ||
- The **post** component is some code that will run at the end of each iteration. | ||
|
||
**Note:** Unlike other languages, there are no parentheses `()` surrounding the three components of the header. In fact, inserting such parenthesis is a compilation error. However, the braces `{ }` surrounding the loop body are always required. | ||
|
||
## For Loops - An example | ||
|
||
The init component usually sets up a counter variable, the condition checks whether the loop should be continued or stopped and the post component usually increments the counter at the end of each repetition. | ||
|
||
```go | ||
for i := 1; i < 10; i++ { | ||
fmt.Println(i) | ||
} | ||
``` | ||
|
||
This loop will print the numbers from `1` to `9` (including `9`). | ||
Defining the step is often done using an increment or decrement statement, as shown in the example above. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[ | ||
{ | ||
"url": "https://tour.golang.org/flowcontrol/1", | ||
"description": "Tour of Go: For" | ||
}, | ||
{ | ||
"url": "https://gobyexample.com/for", | ||
"description": "Go by Example: For" | ||
}, | ||
{ | ||
"url": "https://yourbasic.org/golang/for-loop/", | ||
"description": "Article: 5 basic for loop patterns" | ||
} | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Hints | ||
|
||
## 1. Determine the total number of birds that you counted so far | ||
|
||
- Refer to the exercise introduction for an example how to use a for loop to iterate over a slice. | ||
- Use a helper variable to store the total count and increase that variable as you go through the slice. | ||
- Think about the correct initial value for that helper variable. | ||
|
||
## 2. Calculate the number of visiting birds in a specific week | ||
|
||
- This task is similar to the first one, you can copy your code as a starting point. | ||
- Think about which indexes in the slice you would need to take into account for week number 1 and 2, respectively. | ||
- Now find a general way to calculate the first and the last index that should be considered. | ||
- With that you can set up the for loop to only iterate over the relevant section of the slice. | ||
|
||
## 3. Fix a counting mistake | ||
|
||
- Again you need to set up a for loop to iterate over the whole bird count slice. | ||
- This time you only need to visit every second entry in the slice. | ||
- Change the step so the counter variable is increased accordingly after each iteration. | ||
- In the body of the for loop you can use the increment operator to change the value of an element in a slice in-place. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Instructions | ||
|
||
You are an avid bird watcher that keeps track of how many birds have visited your garden. | ||
Usually you use a tally in a notebook to count the birds, but to better work with your data, you've digitalized the bird counts for the past weeks. | ||
|
||
## 1. Determine the total number of birds that you counted so far | ||
|
||
Let us start analyzing the data by getting a high level view. | ||
Find out how many birds you counted in total since you started your logs. | ||
|
||
Implement a function `TotalBirdCount` that accepts a slice of `int`s that contains the bird count per day. | ||
It should return the total number of birds that you counted. | ||
|
||
```go | ||
birdsPerDay := []int{2, 5, 0, 7, 4, 1, 3, 0, 2, 5, 0, 1, 3, 1} | ||
TotalBirdCount(birdsPerDay) | ||
// => 34 | ||
``` | ||
|
||
## 2. Calculate the number of visiting birds in a specific week | ||
|
||
Now that you got a general feel for your bird count numbers, you want to make a more fine-grained analysis. | ||
|
||
Implement a function `BirdsInWeek` that accepts a slice of bird counts per day and a week number. | ||
|
||
It returns the total number of birds that you counted in that specific week. | ||
You can assume weeks are always tracked completely. | ||
|
||
```go | ||
birdsPerDay := []int{2, 5, 0, 7, 4, 1, 3, 0, 2, 5, 0, 1, 3, 1} | ||
BirdsInWeek(birdsPerDay, 2) | ||
// => 12 | ||
``` | ||
|
||
## 3. Fix a counting mistake | ||
|
||
You realized that all the time you were trying to keep track of the birds, there was one bird that was hiding in a far corner of the garden. | ||
|
||
You figured out that this bird always spent every second day in your garden. | ||
|
||
You do not know exactly where it was in between those days but definitely not in your garden. | ||
|
||
Your bird watcher intuition also tells you that the bird was in your garden on the first day that you tracked in your list. | ||
|
||
Given this new information, write a function `FixBirdCountLog` that takes a slice of birds counted per day as an argument and returns the slice after correcting the counting mistake. | ||
|
||
```go | ||
birdsPerDay := []int{2, 5, 0, 7, 4, 1} | ||
FixBirdCountLog(birdsPerDay) | ||
// => [3 5 1 7 5 1] | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Introduction | ||
|
||
## General syntax | ||
|
||
The for loop is one of the most commonly used statements to repeatedly execute some logic. In Go it consists of the `for` keyword, a header and a code block that contains the body of the loop wrapped in curly brackets. The header consists of 3 components separated by semicolons `;`: init, condition and post. | ||
|
||
```go | ||
for init; condition; post { | ||
// loop body - code that is executed repeatedly as long as the condition is true | ||
} | ||
``` | ||
|
||
- The **init** component is some code that runs only once before the loop starts. | ||
- The **condition** component must be some expression that evaluates to a boolean and controls when the loop should stop. The code inside the loop will run as long as this condition evaluates to true. As soon as this expression evaluates to false, no more iterations of the loop will run. | ||
- The **post** component is some code that will run at the end of each iteration. | ||
|
||
**Note:** Unlike other languages, there are no parentheses `()` surrounding the three components of the header. In fact, inserting such parenthesis is a compilation error. However, the braces `{ }` surrounding the loop body are always required. | ||
|
||
## For Loops - An example | ||
|
||
The init component usually sets up a counter variable, the condition checks whether the loop should be continued or stopped and the post component usually increments the counter at the end of each repetition. | ||
|
||
```go | ||
for i := 1; i < 10; i++ { | ||
fmt.Println(i) | ||
} | ||
``` | ||
|
||
This loop will print the numbers from `1` to `9` (including `9`). | ||
Defining the step is often done using an increment or decrement statement, as shown in the example above. | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"blurb": "Count the birds in your garden with for loops.", | ||
"authors": [ | ||
"sachinmk27" | ||
], | ||
"contributors": [ | ||
"andrerfcsantos" | ||
], | ||
"files": { | ||
"solution": [ | ||
"bird_watcher.go" | ||
], | ||
"test": [ | ||
"bird_watcher_test.go" | ||
], | ||
"exemplar": [ | ||
".meta/exemplar.go" | ||
] | ||
}, | ||
"forked_from": [ | ||
"javascript/bird-watcher" | ||
] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package birdwatcher | ||
|
||
// TotalBirdCount return the total bird count by summing | ||
// the individual day's counts. | ||
func TotalBirdCount(birdsPerDay []int) int { | ||
count := 0 | ||
for i := 0; i < len(birdsPerDay); i++ { | ||
count += birdsPerDay[i] | ||
} | ||
return count | ||
} | ||
|
||
// BirdsInWeek returns the total bird count by summing | ||
// only the items belonging to the given week. | ||
func BirdsInWeek(birdsPerDay []int, week int) int { | ||
count := 0 | ||
startOfWeek := (week - 1) * 7 | ||
endOfWeek := startOfWeek + 7 | ||
for i := startOfWeek; i < endOfWeek; i++ { | ||
count += birdsPerDay[i] | ||
} | ||
return count | ||
} | ||
|
||
// FixBirdCountLog returns the bird counts after correcting | ||
// the bird counts for alternate days. | ||
func FixBirdCountLog(birdsPerDay []int) []int { | ||
for i := 0; i < len(birdsPerDay); i += 2 { | ||
birdsPerDay[i]++ | ||
} | ||
return birdsPerDay | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package birdwatcher | ||
|
||
// TotalBirdCount return the total bird count by summing | ||
// the individual day's counts. | ||
func TotalBirdCount(birdsPerDay []int) int { | ||
panic("Please implement the TotalBirdCount() function") | ||
} | ||
|
||
// BirdsInWeek returns the total bird count by summing | ||
// only the items belonging to the given week. | ||
func BirdsInWeek(birdsPerDay []int, week int) int { | ||
panic("Please implement the BirdsInWeek() function") | ||
} | ||
|
||
// FixBirdCountLog returns the bird counts after correcting | ||
// the bird counts for alternate days. | ||
func FixBirdCountLog(birdsPerDay []int) []int { | ||
panic("Please implement the FixBirdCountLog() function") | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.