done for the day

This commit is contained in:
Vitor Gonçalves 2024-02-15 21:12:53 -03:00
parent 66198b71fe
commit 381d7e61e8
Signed by: vitorg
GPG Key ID: B90BF113DF56EB41
16 changed files with 672 additions and 0 deletions

View File

@ -0,0 +1,27 @@
{
"authors": [
"norbs57"
],
"contributors": [
"junedev"
],
"files": {
"solution": [
"animal_magic.go"
],
"test": [
"animal_magic_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"icon": "roll-the-die",
"blurb": "Learn how to work with pseudo-random numbers",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"animal-magic","id":"a360aa7c4e38433097944355d348ce02","url":"https://exercism.org/tracks/go/exercises/animal-magic","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/animal-magic/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit animal_magic.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

24
go/animal-magic/HINTS.md Normal file
View File

@ -0,0 +1,24 @@
# Hints
## General
This [article][gobyexample] gives a nice introduction to package `math/rand`.
If you are working locally and use Go 1.19 or lower, make sure to seed your random number generator with the current time.
## 1. Roll a die.
This [article][yourbasic] shows how to generate integers in a certain range.
## 2. Generate wand energy.
Function [rand.Float64][float64] returns a random `float64` number between 0.0 and 1.0.
## 3. Shuffle a slice.
Create a slice with the eight animal strings, then call [rand.Shuffle][shuffle] to put it into a random order.
[gobyexample]: https://gobyexample.com/random-numbers
[yourbasic]: https://yourbasic.org/golang/generate-number-random-range
[shuffle]: https://pkg.go.dev/math/rand#Rand.Shuffle
[float64]: https://pkg.go.dev/math/rand#Float64

96
go/animal-magic/README.md Normal file
View File

@ -0,0 +1,96 @@
# Animal Magic
Welcome to Animal Magic on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
Package [math/rand][mathrand] provides support for generating pseudo-random numbers.
Here is how to generate a random integer between `0` and `99`:
```go
n := rand.Intn(100) // n is a random int, 0 <= n < 100
```
Function `rand.Float64` returns a random floating point number between `0.0` and `1.0`:
```go
f := rand.Float64() // f is a random float64, 0.0 <= f < 1.0
```
There is also support for shuffling a slice (or other data structures):
```go
x := []string{"a", "b", "c", "d", "e"}
// shuffling the slice put its elements into a random order
rand.Shuffle(len(x), func(i, j int) {
x[i], x[j] = x[j], x[i]
})
```
## Seeds
The number sequences generated by package `math/rand` are not truly random.
Given a specific "seed" value, the results are entirely deterministic.
In Go 1.20+ the seed is automatically picked at random so you will see a different sequence of random numbers each time you run your program.
In prior versions of Go, the seed was `1` by default.
So to get different sequences for various runs of the program, you had to manually seed the random number generator, e.g. with the current time, before retrieving any random numbers.
```go
rand.Seed(time.Now().UnixNano())
```
[mathrand]: https://pkg.go.dev/math/rand
## Instructions
Elaine is working on a new children's game that features animals and magic wands.
It is time to code functions for rolling a die, generating random wand energy and shuffling a slice.
## 1. Roll a die.
Implement a `RollADie` function.
This will be the traditional twenty-sided die with numbers 1 to 20.
```go
d := RollADie() // d will be assigned a random int, 1 <= d <= 20
```
## 2. Generate wand energy.
Implement a `GenerateWandEnergy` function.
The wand energy should be a random floating point number between 0.0 and 12.0.
```go
f := GenerateWandEnergy() // f will be assigned a random float64, 0.0 <= f < 12.0
```
## 3. Shuffle a slice.
The game features eight different animals:
- ant
- beaver
- cat
- dog
- elephant
- fox
- giraffe
- hedgehog
Write a function `ShuffleAnimals` that returns a slice with the eight animals in random order.
## Source
### Created by
- @norbs57
### Contributed to by
- @junedev

View File

@ -0,0 +1,29 @@
package chance
import (
"math/rand"
)
// RollADie returns a random int d with 1 <= d <= 20.
func RollADie() int {
x := rand.Intn(21)
if(x < 1) {
x = RollADie()
}
return x
}
// GenerateWandEnergy returns a random float64 f with 0.0 <= f < 12.0.
func GenerateWandEnergy() float64 {
return rand.Float64() * 12
}
// ShuffleAnimals returns a slice with all eight animal strings in random order.
func ShuffleAnimals() []string {
x := []string{"ant", "beaver", "cat", "dog", "elephant", "fox", "giraffe", "hedgehog"}
rand.Shuffle(len(x), func(i, j int) {
x[i], x[j] = x[j], x[i]
})
return x
}

View File

@ -0,0 +1,103 @@
//nolint:gosec // In the context of this exercise, it is fine to use math.Rand instead of crypto.Rand.
package chance
import (
"sort"
"testing"
)
func TestRollADie(t *testing.T) {
const tests = 100
var got int
foundDifferent := false
var last int
for i := 0; i < tests; i++ {
got = RollADie()
if got < 1 || got > 20 {
t.Fatalf("RollADie() out of range: %d", got)
}
if i > 0 && got != last {
foundDifferent = true
}
last = got
}
if !foundDifferent {
t.Errorf("RollADie() always generates the same number: %d", got)
}
}
func TestWandEnergy(t *testing.T) {
const tests = 200
const bucketSize float64 = 0.6
var got float64
foundDifferent := false
var last float64
numBuckets := int(12.0 / bucketSize)
buckets := make([]int, numBuckets)
for i := 0; i < tests; i++ {
got = GenerateWandEnergy()
if got < 0.0 || got >= 12.0 {
t.Fatalf("GenerateWandEnergy() out of range: %f", got)
}
if i > 0 && got != last {
foundDifferent = true
}
buckets[int(got/bucketSize)]++
last = got
}
if !foundDifferent {
t.Fatalf("GenerateWandEnergy() always generates the same number: %f", got)
}
var low, high float64
for i, v := range buckets {
if v == 0 {
low = float64(i) * bucketSize
high = float64(i+1) * bucketSize
break
}
}
if high != 0.0 {
t.Errorf("GenerateWandEnergy() results are not uniformly distributed. %.2f to %.2f should contain values.", low, high)
}
}
func TestShuffleAnimals(t *testing.T) {
const tests = 100
animals := []string{"ant", "beaver", "cat", "dog", "elephant", "fox", "giraffe", "hedgehog"}
foundDifferent := false
var last []string
var got []string
for i := 0; i < tests; i++ {
got = ShuffleAnimals()
gotSorted := make([]string, len(got))
copy(gotSorted, got)
sort.Strings(gotSorted)
if !slicesEqual(gotSorted, animals) {
t.Fatalf("ShuffleAnimals() returns incorrect slice: %v", got)
}
if i > 0 && !foundDifferent && !slicesEqual(last, got) {
foundDifferent = true
}
last = got
}
if !foundDifferent {
t.Errorf("ShuffleAnimals() always generates the same slice: %v", got)
}
}
func slicesEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
if len(a) == 0 {
return true
}
size := len(a)
for i := 0; i < size; i++ {
if a[i] != b[i] {
return false
}
}
return true
}

3
go/animal-magic/go.mod Normal file
View File

@ -0,0 +1,3 @@
module chance
go 1.18

View File

@ -0,0 +1,29 @@
{
"authors": [
"sachinmk27"
],
"contributors": [
"andrerfcsantos"
],
"files": {
"solution": [
"bird_watcher.go"
],
"test": [
"bird_watcher_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"forked_from": [
"javascript/bird-watcher"
],
"blurb": "Count the birds in your garden with for loops.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"bird-watcher","id":"4f0efc47e0744c5a9e1ea4eaf386b2e5","url":"https://exercism.org/tracks/go/exercises/bird-watcher","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/bird-watcher/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit bird_watcher.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

21
go/bird-watcher/HINTS.md Normal file
View File

@ -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.

98
go/bird-watcher/README.md Normal file
View File

@ -0,0 +1,98 @@
# Bird Watcher
Welcome to Bird Watcher on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## 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.
## 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]
```
## Source
### Created by
- @sachinmk27
### Contributed to by
- @andrerfcsantos

View File

@ -0,0 +1,33 @@
package birdwatcher
// TotalBirdCount return the total bird count by summing
// the individual day's counts.
func TotalBirdCount(birdsPerDay []int) int {
totalBirds := 0
for i := 0; i < len(birdsPerDay); i++ {
totalBirds = totalBirds + birdsPerDay[i]
}
return totalBirds
}
// BirdsInWeek returns the total bird count by summing
// only the items belonging to the given week.
func BirdsInWeek(birdsPerDay []int, week int) int {
var t int
for i := week * 7 - 7; i < week * 7; i++ {
t = t + birdsPerDay[i]
}
return t
}
// 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++ {
if (i % 2 == 0) {
birdsPerDay[i]++
}
}
return birdsPerDay
}

View File

@ -0,0 +1,122 @@
package birdwatcher
import (
"reflect"
"testing"
)
// testRunnerTaskID=1
func TestTotalBirdCount(t *testing.T) {
tests := []struct {
name string
birdCounts []int
want int
}{
{
name: "calculates the correct total number of birds",
birdCounts: []int{9, 0, 8, 4, 5, 1, 3},
want: 30,
},
{
name: "works for a short bird count list",
birdCounts: []int{2},
want: 2,
},
{
name: "works for a long bird count list",
birdCounts: []int{2, 8, 4, 1, 3, 5, 0, 4, 1, 6, 0, 3, 0, 1, 5, 4, 1, 1, 2, 6},
want: 57,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TotalBirdCount(tt.birdCounts); got != tt.want {
t.Errorf("TotalBirdCount(%v) = %v; want %v", tt.birdCounts, got, tt.want)
}
})
}
}
// testRunnerTaskID=2
func TestBirdsInWeek(t *testing.T) {
tests := []struct {
name string
birdCounts []int
week int
want int
}{
{
name: "calculates the number of birds in the first week",
birdCounts: []int{3, 0, 5, 1, 0, 4, 1, 0, 3, 4, 3, 0, 8, 0},
week: 1,
want: 14,
},
{
name: "calculates the number of birds for a week in the middle of the log",
birdCounts: []int{4, 7, 3, 2, 1, 1, 2, 0, 2, 3, 2, 7, 1, 3, 0, 6, 5, 3, 7, 2, 3},
week: 2,
want: 18,
},
{
name: "works when there is only one week",
birdCounts: []int{3, 0, 3, 3, 2, 1, 0},
week: 1,
want: 12,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := BirdsInWeek(tt.birdCounts, tt.week); got != tt.want {
t.Errorf("BirdsInWeek(%v) = %v; want %v", tt.birdCounts, got, tt.want)
}
})
}
}
// testRunnerTaskID=3
func TestFixBirdCount(t *testing.T) {
tests := []struct {
name string
birdCounts []int
week int
want []int
}{
{
name: "returns a bird count list with the corrected values",
birdCounts: []int{3, 0, 5, 1, 0, 4, 1, 0, 3, 4, 3, 0},
want: []int{4, 0, 6, 1, 1, 4, 2, 0, 4, 4, 4, 0},
},
{
name: "works for a short bird count list",
birdCounts: []int{4, 2},
want: []int{5, 2},
},
{
name: "works for a long bird count list",
birdCounts: []int{2, 8, 4, 1, 3, 5, 0, 4, 1, 6, 0, 3, 0, 1, 5, 4, 1, 1, 2, 6},
want: []int{3, 8, 5, 1, 4, 5, 1, 4, 2, 6, 1, 3, 1, 1, 6, 4, 2, 1, 3, 6},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input := make([]int, len(tt.birdCounts))
copy(input, tt.birdCounts)
if got := FixBirdCountLog(tt.birdCounts); !reflect.DeepEqual(tt.want, got) {
t.Errorf("FixBirdCountLog(%v) = %v; want %v", input, got, tt.want)
}
})
}
}
// testRunnerTaskID=3
func TestFixBirdCountDoesNotCreateNewSlice(t *testing.T) {
counts := []int{4, 0, 6, 1, 1, 4, 2, 0, 4, 4, 4, 0}
got := FixBirdCountLog(counts)
if reflect.ValueOf(got).Pointer() != reflect.ValueOf(counts).Pointer() {
t.Error("it looks like that you are creating a new slice in the function FixBirdCountLog - " +
"please make sure you are modifying the slice passed as argument")
}
}

3
go/bird-watcher/go.mod Normal file
View File

@ -0,0 +1,3 @@
module birdwatcher
go 1.18