From f731b6daee8ff6a344d2e3921ad35c95b294baaa Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Sat, 18 May 2024 21:44:59 +1000 Subject: [PATCH 1/4] Add space-age exercise --- config.json | 8 ++ exercises/practice/space-age/.docs/hints.md | 6 + .../space-age/.docs/instructions.append.md | 14 ++ .../practice/space-age/.docs/instructions.md | 28 ++++ .../practice/space-age/.docs/introduction.md | 20 +++ .../practice/space-age/.meta/config.json | 19 +++ .../practice/space-age/.meta/example.mips | 41 ++++++ exercises/practice/space-age/.meta/tests.toml | 38 ++++++ exercises/practice/space-age/impl.mips | 13 ++ exercises/practice/space-age/runner.mips | 123 ++++++++++++++++++ 10 files changed, 310 insertions(+) create mode 100644 exercises/practice/space-age/.docs/hints.md create mode 100644 exercises/practice/space-age/.docs/instructions.append.md create mode 100644 exercises/practice/space-age/.docs/instructions.md create mode 100644 exercises/practice/space-age/.docs/introduction.md create mode 100644 exercises/practice/space-age/.meta/config.json create mode 100644 exercises/practice/space-age/.meta/example.mips create mode 100644 exercises/practice/space-age/.meta/tests.toml create mode 100644 exercises/practice/space-age/impl.mips create mode 100644 exercises/practice/space-age/runner.mips diff --git a/config.json b/config.json index 17f89b1..38d5363 100644 --- a/config.json +++ b/config.json @@ -162,6 +162,14 @@ "prerequisites": [], "difficulty": 4 }, + { + "slug": "space-age", + "name": "Space Age", + "uuid": "24c7e0dc-6c3e-405e-8449-c8da0100545d", + "practices": [], + "prerequisites": [], + "difficulty": 4 + }, { "slug": "atbash-cipher", "name": "Atbash Cipher", diff --git a/exercises/practice/space-age/.docs/hints.md b/exercises/practice/space-age/.docs/hints.md new file mode 100644 index 0000000..52d65b0 --- /dev/null +++ b/exercises/practice/space-age/.docs/hints.md @@ -0,0 +1,6 @@ +# Hints + +## General + +- The `$t0-9` registers can be used to temporarily store values +- The instructions specify which registers are used as input and output diff --git a/exercises/practice/space-age/.docs/instructions.append.md b/exercises/practice/space-age/.docs/instructions.append.md new file mode 100644 index 0000000..ae24b1a --- /dev/null +++ b/exercises/practice/space-age/.docs/instructions.append.md @@ -0,0 +1,14 @@ +# Instructions append + +## Output format + +Output the age in hundredths of a year. + +## Registers + +| Register | Usage | Type | Description | +| -------- | --------- | ------- | ----------------------------- | +| `$a0` | input | integer | planet (`0` = Mercury, `1` = Venus, `2` = Earth, `3` = Mars, `4` = Jupiter, `5` = Saturn, `6` = Uranus, `7` = Neptune) | +| `$a1` | input | integer | seconds | +| `$v0` | output | integer | age in hundredths of a year | +| `$t0-9` | temporary | any | used for temporary storage | diff --git a/exercises/practice/space-age/.docs/instructions.md b/exercises/practice/space-age/.docs/instructions.md new file mode 100644 index 0000000..f23b5e2 --- /dev/null +++ b/exercises/practice/space-age/.docs/instructions.md @@ -0,0 +1,28 @@ +# Instructions + +Given an age in seconds, calculate how old someone would be on a planet in our Solar System. + +One Earth year equals 365.25 Earth days, or 31,557,600 seconds. +If you were told someone was 1,000,000,000 seconds old, their age would be 31.69 Earth-years. + +For the other planets, you have to account for their orbital period in Earth Years: + +| Planet | Orbital period in Earth Years | +| ------- | ----------------------------- | +| Mercury | 0.2408467 | +| Venus | 0.61519726 | +| Earth | 1.0 | +| Mars | 1.8808158 | +| Jupiter | 11.862615 | +| Saturn | 29.447498 | +| Uranus | 84.016846 | +| Neptune | 164.79132 | + +~~~~exercism/note +The actual length of one complete orbit of the Earth around the sun is closer to 365.256 days (1 sidereal year). +The Gregorian calendar has, on average, 365.2425 days. +While not entirely accurate, 365.25 is the value used in this exercise. +See [Year on Wikipedia][year] for more ways to measure a year. + +[year]: https://en.wikipedia.org/wiki/Year#Summary +~~~~ diff --git a/exercises/practice/space-age/.docs/introduction.md b/exercises/practice/space-age/.docs/introduction.md new file mode 100644 index 0000000..014d788 --- /dev/null +++ b/exercises/practice/space-age/.docs/introduction.md @@ -0,0 +1,20 @@ +# Introduction + +The year is 2525 and you've just embarked on a journey to visit all planets in the Solar System (Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus and Neptune). +The first stop is Mercury, where customs require you to fill out a form (bureaucracy is apparently _not_ Earth-specific). +As you hand over the form to the customs officer, they scrutinize it and frown. +"Do you _really_ expect me to believe you're just 50 years old? +You must be closer to 200 years old!" + +Amused, you wait for the customs officer to start laughing, but they appear to be dead serious. +You realize that you've entered your age in _Earth years_, but the officer expected it in _Mercury years_! +As Mercury's orbital period around the sun is significantly shorter than Earth, you're actually a lot older in Mercury years. +After some quick calculations, you're able to provide your age in Mercury Years. +The customs officer smiles, satisfied, and waves you through. +You make a mental note to pre-calculate your planet-specific age _before_ future customs checks, to avoid such mix-ups. + +~~~~exercism/note +If you're wondering why Pluto didn't make the cut, go watch [this YouTube video][pluto-video]. + +[pluto-video]: https://www.youtube.com/watch?v=Z_2gbGXzFbs +~~~~ diff --git a/exercises/practice/space-age/.meta/config.json b/exercises/practice/space-age/.meta/config.json new file mode 100644 index 0000000..3563a84 --- /dev/null +++ b/exercises/practice/space-age/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "impl.mips" + ], + "test": [ + "runner.mips" + ], + "example": [ + ".meta/example.mips" + ] + }, + "blurb": "Given an age in seconds, calculate how old someone is in terms of a given planet's solar years.", + "source": "Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial.", + "source_url": "https://pine.fm/LearnToProgram/?Chapter=01" +} diff --git a/exercises/practice/space-age/.meta/example.mips b/exercises/practice/space-age/.meta/example.mips new file mode 100644 index 0000000..462bee2 --- /dev/null +++ b/exercises/practice/space-age/.meta/example.mips @@ -0,0 +1,41 @@ +# | Register | Usage | Type | Description | +# | -------- | --------- | ------- | ------------------------------------------ | +# | `$a0` | input | integer | planet (`0` = Mercury, `1` = Venus, | +# | | | | `2` = Earth, `3` = Mars, `4` = Jupiter, | +# | | | | `5` = Saturn, `6` = Uranus, `7` = Neptune) | +# | `$a1` | input | integer | seconds | +# | `$v0` | output | integer | age in hundredths of a year | +# | `$t0` | temporary | address | address of reciprocal of planet's period | +# | `$t1` | temporary | integer | reciprocal of planet's period | +# | `$t2` | temporary | integer | 0x8000, used to round up result | + +.globl age + +.data + +# reciprocal of the number of seconds in a year, scaled up by 100 * 2**48 +reciprocals: .word + 3703353120, # Mercury, + 1449844523, # Venus, + 891940378, # Earth, + 474230585, # Mars, + 75189187, # Jupiter, + 30289174, # Saturn, + 10616209, # Uranus, + 5412545 # Neptune + +.text + +age: + la $t0, reciprocals + sll $a0, $a0, 2 + add $t0, $t0, $a0 + lw $t1, 0($t0) # load reciprocal of the number of seconds in a year + multu $t1, $a1 + mfhi $v0 # scale down by 2**32 by discarding low bits + + ori $t2, $zero, 0x8000 + addu $v0, $v0, $t2 # scale down by 2**16, with rounding + srl $v0, $v0, 16 + + jr $ra diff --git a/exercises/practice/space-age/.meta/tests.toml b/exercises/practice/space-age/.meta/tests.toml new file mode 100644 index 0000000..a62017e --- /dev/null +++ b/exercises/practice/space-age/.meta/tests.toml @@ -0,0 +1,38 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[84f609af-5a91-4d68-90a3-9e32d8a5cd34] +description = "age on Earth" + +[ca20c4e9-6054-458c-9312-79679ffab40b] +description = "age on Mercury" + +[502c6529-fd1b-41d3-8fab-65e03082b024] +description = "age on Venus" + +[9ceadf5e-a0d5-4388-9d40-2c459227ceb8] +description = "age on Mars" + +[42927dc3-fe5e-4f76-a5b5-f737fc19bcde] +description = "age on Jupiter" + +[8469b332-7837-4ada-b27c-00ee043ebcad] +description = "age on Saturn" + +[999354c1-76f8-4bb5-a672-f317b6436743] +description = "age on Uranus" + +[80096d30-a0d4-4449-903e-a381178355d8] +description = "age on Neptune" + +[57b96e2a-1178-40b7-b34d-f3c9c34e4bf4] +description = "invalid planet causes error" +include = false diff --git a/exercises/practice/space-age/impl.mips b/exercises/practice/space-age/impl.mips new file mode 100644 index 0000000..e6e10c8 --- /dev/null +++ b/exercises/practice/space-age/impl.mips @@ -0,0 +1,13 @@ +# | Register | Usage | Type | Description | +# | -------- | --------- | ------- | ------------------------------------------ | +# | `$a0` | input | integer | planet (`0` = Mercury, `1` = Venus, | +# | | | | `2` = Earth, `3` = Mars, `4` = Jupiter, | +# | | | | `5` = Saturn, `6` = Uranus, `7` = Neptune) | +# | `$a1` | input | integer | seconds | +# | `$v0` | output | integer | age in hundredths of a year | +# | `$t0-9` | temporary | any | used for temporary storage | + +.globl age + +age: + jr $ra diff --git a/exercises/practice/space-age/runner.mips b/exercises/practice/space-age/runner.mips new file mode 100644 index 0000000..300151b --- /dev/null +++ b/exercises/practice/space-age/runner.mips @@ -0,0 +1,123 @@ +# +# Test age with some examples +# +# s0 - num of tests left to run +# s1 - address of planet input word +# s2 - address of seconds input word +# s3 - address of expected output word +# s4 - output word + +.data +# number of test cases +n: .word 8 +# input values (word sized ints) +planets: .word + 2, # Earth, + 0, # Mercury, + 1, # Venus, + 3, # Mars, + 4, # Jupiter, + 5, # Saturn, + 6, # Uranus, + 7 # Neptune +seconds: .word + 1000000000, + 2134835688, + 189839836, + 2129871239, + 901876382, + 2000000000, + 1210123456, + 1821023456 +# output values (word sized ints) +outs: .word + 3169, + 28088, + 978, + 3588, + 241, + 215, + 46, + 35 + +failmsg: .asciiz "failed for test input: (" +commamsg: .asciiz ", " +expectedmsg: .asciiz "). expected " +tobemsg: .asciiz " to be " +okmsg: .asciiz "all tests passed" + + +.text + +runner: + lw $s0, n + la $s1, planets + la $s2, seconds + la $s3, outs + j run_test + +run_test: + lw $a0, 0($s1) # move input planet number to a0 + lw $a1, 0($s2) # move input seconds number to a1 + jal age # call subroutine under test + move $v1, $v0 # move return value in v0 to v1 because we need v0 for syscall + + lw $s4, 0($s3) # read expected output from memory + bne $v1, $s4, exit_fail # if expected doesn't match actual, jump to fail + + addi $s1, $s1, 4 # move to next planet word in input + addi $s2, $s2, 4 # move to next seconds word in input + addi $s3, $s3, 4 # move to next word in output + + sub $s0, $s0, 1 # decrement num of tests left to run + bgt $s0, $zero, run_test # if more than zero tests to run, jump to run_test + +exit_ok: + la $a0, okmsg # put address of okmsg into a0 + li $v0, 4 # 4 is print string + syscall + + li $v0, 10 # 10 is exit with zero status (clean exit) + syscall + +exit_fail: + la $a0, failmsg # put address of failmsg into a0 + li $v0, 4 # 4 is print string + syscall + + lw $a0, ($s1) # print input that failed on + li $v0, 1 + syscall + + la $a0, commamsg + li $v0, 4 + syscall + + lw $a0, ($s2) + li $v0, 1 + syscall + + la $a0, expectedmsg + li $v0, 4 + syscall + + move $a0, $v1 # print actual that failed on + li $v0, 1 + syscall + + la $a0, tobemsg + li $v0, 4 + syscall + + move $a0, $s4 # print expected value that failed on + li $v0, 1 + syscall + + li $a0, 1 # set error code to 1 + li $v0, 17 # 17 is exit with error + syscall + + jr $ra + +# # Include your implementation here if you wish to run this from the MARS GUI. +# .include "impl.mips" From fb485dbc7d5087187bbcc47ffed4106e3624c0ca Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Sun, 19 May 2024 08:58:03 +1000 Subject: [PATCH 2/4] adjust two test cases, to permit less accurate solutions --- exercises/practice/space-age/runner.mips | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/space-age/runner.mips b/exercises/practice/space-age/runner.mips index 300151b..d4a0585 100644 --- a/exercises/practice/space-age/runner.mips +++ b/exercises/practice/space-age/runner.mips @@ -24,10 +24,10 @@ seconds: .word 1000000000, 2134835688, 189839836, - 2129871239, + 2129820540, 901876382, 2000000000, - 1210123456, + 1210792309, 1821023456 # output values (word sized ints) outs: .word From df89eb08e217f24767ec9d93959ec87fcfaf9ecc Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Sun, 19 May 2024 19:43:15 +1000 Subject: [PATCH 3/4] eqv --- exercises/practice/space-age/impl.mips | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/exercises/practice/space-age/impl.mips b/exercises/practice/space-age/impl.mips index e6e10c8..627579c 100644 --- a/exercises/practice/space-age/impl.mips +++ b/exercises/practice/space-age/impl.mips @@ -7,6 +7,15 @@ # | `$v0` | output | integer | age in hundredths of a year | # | `$t0-9` | temporary | any | used for temporary storage | +.eqv MERCURY 0 +.eqv VENUS 1 +.eqv EARTH 2 +.eqv MARS 3 +.eqv JUPITER 4 +.eqv SATURN 5 +.eqv URANUS 6 +.eqv NEPTUNE 7 + .globl age age: From f619df44725b9ef62491e608f8c8a02b47b9a37e Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Tue, 21 May 2024 18:26:32 +1000 Subject: [PATCH 4/4] hundredths example --- exercises/practice/space-age/.docs/instructions.append.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exercises/practice/space-age/.docs/instructions.append.md b/exercises/practice/space-age/.docs/instructions.append.md index ae24b1a..ecef952 100644 --- a/exercises/practice/space-age/.docs/instructions.append.md +++ b/exercises/practice/space-age/.docs/instructions.append.md @@ -4,6 +4,8 @@ Output the age in hundredths of a year. +For example, 100 × 1,000,000,000 ÷ 31,557,600 ≈ 3,169, so someone 1,000,000,000 seconds old is `3169` hundredths of an Earth-year old. + ## Registers | Register | Usage | Type | Description |