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
5 changes: 5 additions & 0 deletions concepts/randomness/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"blurb": "Generate pseudo-random integer and floating-point numbers.",
"authors": ["norbs57"],
"contributors": []
}
89 changes: 89 additions & 0 deletions concepts/randomness/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# About

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.
They are completely determined by an initial `seed` value.
By default, the package uses the number `1` as a seed.

In order to get a different sequence of random numbers, we need to set a different seed.
A simple approach is to seed with the current computer time.

```go
rand.Seed(time.Now().UnixNano())
```

Setting the seed must be done **before** calling any of the functions that generate random numbers.
We usually only need to set the seed once in our program.
From one seed we can generate many random numbers.

### Warning

If you don't call `rand.Seed`, then the package will produce the same sequence of random numbers each time your program runs!

As an example, consider the following program:

```go
package main

import (
"fmt"
"math/rand"
)

func main() {
// rand.Seed(time.Now().UnixNano())
a := rand.Intn(1000000)
b := rand.Intn(1000000)
c := rand.Intn(1000000)
fmt.Println(a, b, c)
}
```

Every time this program runs, it will produce the same output:

```text
498081 727887 131847
```

Once we uncomment the first line in the `main()` function, the output varies between different runs:

```text
817603 745216 422387

265737 21561 640434

708506 627509 363987
```

~~~~exercism/caution

The output produced by package `math/rand` might be easily predictable regardless of how it is seeded.
For random numbers suitable for security-sensitive work, you should use the [crypto/rand][cryptorand] package.

[mathrand]: https://pkg.go.dev/math/rand
[cryptorand]: https://pkg.go.dev/crypto/rand
47 changes: 47 additions & 0 deletions concepts/randomness/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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.
They are completely determined by an initial `seed` value.
By default, the package uses the integer `1` as a seed.

In order to get a different sequence of random numbers, we need to specify a different seed value.
A simple approach is to use the "current time":

```go
rand.Seed(time.Now().UnixNano())
```

Setting the seed must be done **before** calling any of the functions that generate random numbers.
We usually only need to set the seed once in our program.
From one seed we can generate many random numbers.

~~~~exercism/caution

If you don't call `rand.Seed`, then the package will produce the same sequence of random numbers each time your program runs!
~~~~
22 changes: 22 additions & 0 deletions concepts/randomness/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"url": "https://pkg.go.dev/math/rand",
"description": "Go standard library: package math/rand"
},
{
"url": "https://gobyexample.com/random-numbers",
"description": "Go by Example: random numbers"
},
{
"url": "https://golang.org/ref/spec#IncDec_statements",
"description": "Yourbasic.org: generate random numbers"
},
{
"url": "https://en.wikipedia.org/wiki/Randomness",
"description": "Wikipedia: randomness"
},
{
"url": "https://en.wikipedia.org/wiki/Random_see",
"description": "Wikipedia: random seed"
}
]
18 changes: 18 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,19 @@
"for-loops"
],
"status": "beta"
},
{
"slug": "animal-magic",
"name": "Animal magic",
"uuid": "71a1be49-daf1-4043-af6e-33cd44481bb5",
"concepts": [
"randomness"
],
"prerequisites": [
"arithmetic-operators",
"slices"
],
"status": "beta"
}
],
"practice": [
Expand Down Expand Up @@ -1984,6 +1997,11 @@
"slug": "range-iteration",
"uuid": "8f644992-59ec-4fff-8b40-36b5ed61404d"
},
{
"name": "Randomness",
"slug": "randomness",
"uuid": "5d354412-a87d-458b-af6c-fadfa58cfdc3"
},
{
"name": "Runes",
"slug": "runes",
Expand Down
26 changes: 26 additions & 0 deletions exercises/concept/animal-magic/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Hints

## General

This [article][gobyexample] gives a nice introduction to package `math/rand`.

## 1. Seed the random number generator.

See `rand.Seed` example in the instructions for this exercise.

## 2. Roll a die.

This [article][yourbasic] shows how to generate integers in a certain range.

## 3. Generate wand energy.

Function [rand.Float64][float64] returns a random `float64` number between 0.0 and 1.0.

## 4. 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
42 changes: 42 additions & 0 deletions exercises/concept/animal-magic/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 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. Seed the random number generator.

Implement a `SeedWithTime` function that seeds the `math.rand` package with the current computer time.

## 2. 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
```

## 3. 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
```

## 4. 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.
46 changes: 46 additions & 0 deletions exercises/concept/animal-magic/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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.
They are completely determined by an initial `seed` value.
By default, the package uses the integer `1` as a seed.

In order to get a different sequence of random numbers, we need to specify a different seed value.
A simple approach is to use the "current time":

```go
rand.Seed(time.Now().UnixNano())
```

Setting the seed must be done **before** calling any of the functions that generate random numbers.
We usually only need to set the seed once in our program.
From one seed we can generate many random numbers.

### Warning

If you don't call `rand.Seed`, then the package will produce the same sequence of random numbers each time your program runs!
10 changes: 10 additions & 0 deletions exercises/concept/animal-magic/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"blurb": "Learn how to work with pseudo-random numbers",
"authors": ["norbs57"],
"contributors": [],
"files": {
"solution": ["animal_magic.go"],
"test": ["animal_magic_test.go"],
"exemplar": [".meta/exemplar.go"]
}
}
35 changes: 35 additions & 0 deletions exercises/concept/animal-magic/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Design

## Goal

The goal of this exercise is to teach student the basics on how to work with pseudo-random numbers in Go.

## Learning objectives

- how to create pseudo random numbers with the math/rand package (float64 and int)
- what seeding is for and how/where to define the seed in the code
- that there are some helpers in the math/rand package line Shuffle and Perm
- when and how to create cryptographically secure random numbers with crypto/rand (does not have to be part of the exercise but would be good to mention in the concept to raise security awareness)

## Out of scope

- details of pseudo random number generation in general
- discussing the different algorithms for random number generation
- details on entropy sources etc

## Concepts

- `randomness`

## Prerequisites

- `numbers`
- `slices`

## Implementing

Here you can find the [Implementation Guide](https://github.com/exercism/v3/blob/master/languages/go/reference/implementing-a-concept-exercise.md).

## Help

If you have any questions while implementing the exercise, please post the questions as comments in this issue.
30 changes: 30 additions & 0 deletions exercises/concept/animal-magic/.meta/exemplar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package chance

import (
"math/rand"
"time"
)

// SeedWithTime seeds math/rand with the current computer time
func SeedWithTime() {
rand.Seed(time.Now().UnixNano())
}

// RollADie returns a random int between 1 and 20
func RollADie() int {
return 1 + rand.Intn(20)
}

// GenerateWandEnergy returns a random float64 f with 0.0 <= f < 12.0
func GenerateWandEnergy() float64 {
return 12.0 * rand.Float64()
}

// ShuffleAnimals returns a slice with eight animal strings in random order
func ShuffleAnimals() []string {
result := []string{"ant", "beaver", "cat", "dog", "elephant", "fox", "giraffe", "hedgehog"}
rand.Shuffle(len(result), func(i, j int) {
result[i], result[j] = result[j], result[i]
})
return result
}
Loading