-
-
Notifications
You must be signed in to change notification settings - Fork 654
Add Concept Exercise for 'randomness': Captain's Log #2683
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
Changes from 14 commits
5f5dee3
784ab06
839ff5d
9660cf4
aeaa04e
fe7da9a
365d8cc
580e1a9
77af0d8
f2a7ef8
91e048f
5ba9ac2
1de010d
c334b74
b9d179f
06a5d05
87ef708
a84402b
a249a06
ef7aa46
5fbe8cf
9a07643
eac6873
d9adf15
b068bfc
fb945a5
f03e1e7
47f5e27
b3cd46f
d2436ae
6d25bfb
9c2a849
3779474
855ccd2
fe381c7
173333d
f946ae5
0cdd9ac
ac1d8da
2d17cba
88e02f2
8c7d877
4d943eb
8bdd28b
65b9982
a786e47
e15e862
8e45315
10f181e
4c3e747
1fd3f14
eebe50a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| { | ||
| "authors": [ | ||
| "SneakyMallard" | ||
| ], | ||
| "contributors": [], | ||
| "forked-from": ["java/captains-log"], | ||
| "concept": [ | ||
| { | ||
| "uuid": "need-to-generate", | ||
| "slug": "captains-log", | ||
| "name": "Captain's Log", | ||
| "concepts": ["randomness"], | ||
| "prerequisites": ["numbers", "arithmetic-operators"] | ||
| } | ||
| ], | ||
| "files": { | ||
| "solution": ["captains-log.js"], | ||
| "test": ["captains-log.spec.js"], | ||
| "exemplar": [".meta/exemplar.js"] | ||
| }, | ||
| "blurb": "Learn about randomness and the Math.random() function while helping Mary generate stardates and starship registry numbers for her Star Trek roleplay." | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Design | ||
|
|
||
| ## Goal | ||
|
|
||
| The goal of this exercise is to teach the student how to generate psuedorandom numbers in JavaScript. | ||
|
|
||
| ## Learning objectives | ||
|
|
||
| - Know how to generate a random number with `Math.random()` | ||
| - Know how to generate a random number in a range. | ||
| - Know how to generate a random integer. | ||
|
|
||
| ## Out of scope | ||
|
|
||
| - Details of pseudorandom number generation in general. | ||
| - Different algorithms for pseudorandom number generation. | ||
|
|
||
|
|
||
| ## Concepts | ||
|
|
||
| The Concepts this exercise unlocks are: | ||
|
|
||
| - `randomness`: Know of the `Math.random()` function and know how to use it to generate random numbers. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - `numbers`: Know how numbers work in JavaScript. Know some number methods. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /// <reference path="./global.d.ts" /> | ||
SleeplessByte marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // @ts-check | ||
|
|
||
| /** | ||
| * Generates a random starship registry number. | ||
| * | ||
| * @returns {string} the generated registry number. | ||
| */ | ||
| export function randomShipRegistryNumber() { | ||
| return "NCC-"+Math.floor(1000 + Math.random()*9000) | ||
| } | ||
|
|
||
| /** | ||
| * Generates a random stardate. | ||
| * | ||
| * @returns {number} a stardate between 41000 (inclusive) and 42000 (exclusive). | ||
| */ | ||
| export function randomStardate() { | ||
| return 41000 + Math.random() * 1000 | ||
| } | ||
|
|
||
| /** | ||
| * Generates a random planet class. | ||
| * | ||
| * @returns {string} a one-letter planet class. | ||
| */ | ||
| export function randomPlanetClass() { | ||
| const planetClasses = ['D', 'H', 'J', 'K', 'L', 'M', 'N', 'R', 'T', 'Y'] | ||
| return planetClasses[Math.floor(Math.random() * 10)] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /// <reference path="./global.d.ts" /> | ||
SleeplessByte marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // @ts-check | ||
|
|
||
| /** | ||
| * Generates a random starship registry number. | ||
| * | ||
| * @returns {string} the generated registry number. | ||
| */ | ||
| export function randomShipRegistryNumber() { | ||
| throw new Error("Please remove this line and implement the randomShipRegistryNumber() function"); | ||
| } | ||
|
|
||
| /** | ||
| * Generates a random stardate. | ||
| * | ||
| * @returns {number} a stardate between 41000 (inclusive) and 42000 (exclusive). | ||
| */ | ||
| export function randomStardate() { | ||
| throw new Error("Please remove this line and implement the randomStardate() function"); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Generates a random planet class. | ||
| * | ||
| * @returns {string} a one-letter planet class. | ||
| */ | ||
| export function randomPlanetClass() { | ||
| throw new Error("Please remove this line and implement the randomStardate() function"); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import { describe, expect, test } from '@jest/globals'; | ||
| import { randomShipRegistryNumber, randomStardate, randomPlanetClass } from './captains-log'; | ||
| describe('randomShipRegistryNumber',() => { | ||
| test('registry numbers are valid',() => { | ||
| for (let i=0;i<4; i++){ | ||
| expect(randomShipRegistryNumber()).toMatch(/NCC-[1-9][0-9]{3}/)) | ||
Cool-Katt marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| }); | ||
| test('returns a random registry number',() => { | ||
| expect(randomShipRegistryNumber()).not.toEqual(randomShipRegistryNumber()) | ||
| }); | ||
| }); | ||
| function loadDie(...values) { | ||
| const originalRandom = Math.random() | ||
|
|
||
| Math.random = function loadedDie { | ||
| if (values.length === 0) { | ||
| return originalRandom(); | ||
| } | ||
| return values.shift(); | ||
| } | ||
| return () => { | ||
| Math.random = originalRandom; | ||
| } | ||
| } | ||
| describe('randomStardate',() => { | ||
| test('stardate is between 41000 and 42000',() => { | ||
| const restore = loadDie( | ||
| 0, 0, 0, 0, 0, 0, | ||
| 1, 1, 1, 1, 1, 1, | ||
| 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 | ||
| ); | ||
SleeplessByte marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // 6 * 0, 6 * 1, 6 * 0.5 and everything else random | ||
|
|
||
| for (let i = 0; i < 10_000; i++) { | ||
| const starDate = randomStardate() | ||
| expect(starDate).toBeGreaterThanOrEqual(41_000); | ||
| expect(starDate).toBeLessThan(42_000); | ||
| } | ||
| restore(); | ||
| } | ||
| } | ||
| describe('randomPlanetClass', () => { | ||
| test('planet classes are valid', () => { | ||
| const planetClasses = ['D', 'H', 'J', 'K', 'L', 'M', 'N', 'R', 'T', 'Y']; | ||
| for (let i=0;i<4; i++){ | ||
| expect(planetClasses).toContain(randomPlanetClass()) | ||
| } | ||
| }); | ||
|
||
| test('returns a random planet class',() => { | ||
| expect(randomPlanetClass()).not.toEqual(randomPlanetClass()) | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Hints | ||
|
|
||
| ## 1. Generate a random starship registry number | ||
| - To generate a random number in the range _min_ (inclusive) to _max_ (exclusive) you can use the snippet `min + Math.random()*(max - min)`. | ||
| - There is a [built in function][floor] for turning a floating point number into an integer. | ||
| ## 2.Generate a random stardate | ||
| - To generate a random number in the range _min_ (inclusive) to _max_ (exclusive) you can use the snippet `min + Math.random()*(max - min)`. | ||
| ## 3. Generate a random planet | ||
| - You can use a randomly generated integer as an array index. | ||
|
|
||
| [floor]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| ## Instructions | ||
|
|
||
| Mary is a big fan of the TV series Star Trek: The Next Generation. She often plays pen-and-paper role playing games, where she and her friends pretend to be the crew of the Starship Enterprise. Mary's character is Captain Picard, which means she has to keep the captain's log. She loves the creative part of the game, but doesn't like to generate random data on the spot. | ||
|
|
||
| Help Mary by creating random generators for data commonly appearing in the captain's log. | ||
| ### 1. Generate a random starship registry number | ||
|
|
||
| Enterprise (registry number NCC-1701) is not the only starship flying around! When it rendezvous with another starship, Mary needs to log the registry number of that starship. | ||
|
|
||
| Registry numbers start with the prefix "NCC-" and then use a number from 1000 to 9999 (both inclusive). | ||
|
|
||
| Implement the randomShipRegistryNumber() function that returns a random starship registry number. | ||
| ```javascript | ||
| randomShipRegistryNumber() | ||
| // => "NCC-1947" | ||
| ``` | ||
| ### 2. Generate a random stardate | ||
|
|
||
| What's the use of a log if it doesn't include dates? | ||
|
|
||
| A stardate is a floating point number. The adventures of the Starship Enterprise from the first season of The Next Generation take place between the stardates 41000.0 and 42000.0. The "4" stands for the 24th century, the "1" for the first season. | ||
|
|
||
| Implement the function randomStardate that returns a floating point number between 41000.0 (inclusive) and 42000.0 (exclusive). | ||
|
|
||
| ```javascript | ||
| randomStardate() | ||
| // => 41458.15721310934 | ||
| ``` | ||
| ### 3. Generate a random planet | ||
|
|
||
| The Starship Enterprise encounters many planets in its travels. Planets in the Star Trek universe are split into categories based on their properties. For example, Earth is a class M planet. All possible planetary classes are: D, H, J, K, L, M, N, R, T, and Y. | ||
|
|
||
| Implement the randomPlanetClassfunction. It should return one of the planetary classes at random. | ||
| ```javascript | ||
| randomPlanetClass() | ||
| // => "K" | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Introduction | ||
|
|
||
| Many programs need (apparently) random values to simulate real-world events. | ||
|
|
||
| Common, familiar examples include: | ||
|
|
||
| - A coin toss: a random value from ('H', 'T'). | ||
| - The roll of a die: a random integer from 1 to 6. | ||
| - Shuffling a deck of cards: a random ordering of a card list. | ||
| - The creation of trees and bushes in a 3-D graphics simulation. | ||
|
|
||
| Generating truly random values with a computer is a [surprisingly difficult technical challenge][why-randomness-is-hard], so you may see these results referred to as "pseudorandom". | ||
| ## Generating random numbers | ||
| In Javascript, you can generate psuedorandom numbers using the [`Math.random()`][Math.random] function. | ||
| It will return a psuedorandom floating-point number between 0 (inclusive), and 1 (exclusive). | ||
|
|
||
| To get a random number between _min_ (inclusive) and _max_ (exclusive) you can use a function something like this: | ||
| ```javascript | ||
| function getRandomInRange(min, max) { | ||
| return min + Math.random() * (max - min) ; | ||
| } | ||
| getRandomInRange(4, 10) | ||
| // => 5.72 | ||
| ``` | ||
| ## Generating random integers | ||
| To generate a random integer, you can use `Math.floor()` or `Math.ceil()` to turn a randomly generated number into an integer. | ||
| ~~~~exercism/caution | ||
|
|
||
| The `Math.random()` function should NOT be used for security and cryptographic applications!! | ||
|
|
||
| Instead, you can use the Web Crypto API, which provides various cryptographic functions. | ||
| ~~~~ | ||
|
|
||
| [why-randomness-is-hard]: https://www.malwarebytes.com/blog/news/2013/09/in-computers-are-random-numbers-really-random | ||
| [Math.random]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random |
Uh oh!
There was an error while loading. Please reload this page.