From 95452f91fdf3bbad046789ea2a5e61d9a0fad459 Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Sat, 7 Oct 2023 19:08:30 +1100 Subject: [PATCH] feat: Add Grains (resolves #149) --- config.json | 8 ++ .../practice/grains/.docs/instructions.md | 15 +++ exercises/practice/grains/.meta/config.json | 19 +++ exercises/practice/grains/.meta/example.mips | 32 +++++ exercises/practice/grains/.meta/tests.toml | 45 +++++++ exercises/practice/grains/impl.mips | 0 exercises/practice/grains/runner.mips | 115 ++++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 exercises/practice/grains/.docs/instructions.md create mode 100644 exercises/practice/grains/.meta/config.json create mode 100644 exercises/practice/grains/.meta/example.mips create mode 100644 exercises/practice/grains/.meta/tests.toml create mode 100644 exercises/practice/grains/impl.mips create mode 100644 exercises/practice/grains/runner.mips diff --git a/config.json b/config.json index 8a96044..d9c1194 100644 --- a/config.json +++ b/config.json @@ -86,6 +86,14 @@ "difficulty": 3, "topics": [] }, + { + "slug": "grains", + "name": "Grains", + "uuid": "0a05186b-c395-40dc-b690-b1364978d7d3", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "triangle", "name": "Triangle", diff --git a/exercises/practice/grains/.docs/instructions.md b/exercises/practice/grains/.docs/instructions.md new file mode 100644 index 0000000..df479fc --- /dev/null +++ b/exercises/practice/grains/.docs/instructions.md @@ -0,0 +1,15 @@ +# Instructions + +Calculate the number of grains of wheat on a chessboard given that the number on each square doubles. + +There once was a wise servant who saved the life of a prince. +The king promised to pay whatever the servant could dream up. +Knowing that the king loved chess, the servant told the king he would like to have grains of wheat. +One grain on the first square of a chess board, with the number of grains doubling on each successive square. + +There are 64 squares on a chessboard (where square 1 has one grain, square 2 has two grains, and so on). + +Write code that shows: + +- how many grains were on a given square, and +- the total number of grains on the chessboard diff --git a/exercises/practice/grains/.meta/config.json b/exercises/practice/grains/.meta/config.json new file mode 100644 index 0000000..676e4b0 --- /dev/null +++ b/exercises/practice/grains/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "impl.mips" + ], + "test": [ + "runner.mips" + ], + "example": [ + ".meta/example.mips" + ] + }, + "blurb": "Calculate the number of grains of wheat on a chessboard given that the number on each square doubles.", + "source": "The CodeRanch Cattle Drive, Assignment 6", + "source_url": "https://coderanch.com/wiki/718824/Grains" +} diff --git a/exercises/practice/grains/.meta/example.mips b/exercises/practice/grains/.meta/example.mips new file mode 100644 index 0000000..269f045 --- /dev/null +++ b/exercises/practice/grains/.meta/example.mips @@ -0,0 +1,32 @@ +# Convert square to number of grains +# +# Strategy: shift 1 left by (the square number minus 1) +# +# $a0 - input, square number in the range 1..64 +# $v0 - low 32 bits of output +# $v1 - high 32 bits of output + +.globl square + +square: + move $v0, $zero + move $v1, $zero + li $t0, 1 + blt $a0, $t0, invalid_square + sub $a0, $a0, $t0 + li $t1, 32 + blt $a0, $t1, low + sub $a0, $a0, $t1 + blt $a0, $t1, high + +invalid_square: + jr $ra + +low: + sllv $v0, $t0, $a0 + jr $ra + +high: + sllv $v1, $t0, $a0 + jr $ra + diff --git a/exercises/practice/grains/.meta/tests.toml b/exercises/practice/grains/.meta/tests.toml new file mode 100644 index 0000000..d3d628c --- /dev/null +++ b/exercises/practice/grains/.meta/tests.toml @@ -0,0 +1,45 @@ +# 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. + +[9fbde8de-36b2-49de-baf2-cd42d6f28405] +description = "returns the number of grains on the square -> grains on square 1" + +[ee1f30c2-01d8-4298-b25d-c677331b5e6d] +description = "returns the number of grains on the square -> grains on square 2" + +[10f45584-2fc3-4875-8ec6-666065d1163b] +description = "returns the number of grains on the square -> grains on square 3" + +[a7cbe01b-36f4-4601-b053-c5f6ae055170] +description = "returns the number of grains on the square -> grains on square 4" + +[c50acc89-8535-44e4-918f-b848ad2817d4] +description = "returns the number of grains on the square -> grains on square 16" + +[acd81b46-c2ad-4951-b848-80d15ed5a04f] +description = "returns the number of grains on the square -> grains on square 32" + +[c73b470a-5efb-4d53-9ac6-c5f6487f227b] +description = "returns the number of grains on the square -> grains on square 64" + +[1d47d832-3e85-4974-9466-5bd35af484e3] +description = "returns the number of grains on the square -> square 0 raises an exception" + +[61974483-eeb2-465e-be54-ca5dde366453] +description = "returns the number of grains on the square -> negative square raises an exception" + +[a95e4374-f32c-45a7-a10d-ffec475c012f] +description = "returns the number of grains on the square -> square greater than 64 raises an exception" + +[6eb07385-3659-4b45-a6be-9dc474222750] +description = "returns the total number of grains on the board" +include = false + diff --git a/exercises/practice/grains/impl.mips b/exercises/practice/grains/impl.mips new file mode 100644 index 0000000..e69de29 diff --git a/exercises/practice/grains/runner.mips b/exercises/practice/grains/runner.mips new file mode 100644 index 0000000..db91680 --- /dev/null +++ b/exercises/practice/grains/runner.mips @@ -0,0 +1,115 @@ +# +# Test square with some examples +# +# s0 - num of tests left to run +# s1 - address of input word +# s2 - address of expected low output word +# s3 - address of expected high output word +# s4 - input word +# s5 - low output word +# s6 - high output word +# +# square must: +# - be named square and declared as global +# - read input integer from a0 +# - follow the convention of using the t0-9 registers for temporary storage +# - (if it wants to use s0-7 then it is responsible for pushing existing values to the stack then popping them back off before returning) +# - write low word of integer result to v0 +# - write high word of integer result to v1 + +.data + +n: .word 10 # number of test cases +ins: .word 1, 2, 3, 4, 16, 32, 64, 0, -1, 65 # input numbers +lows: .word 1, 2, 4, 8, 32768, 2147483648, 0, 0, 0, 0 # expected result (low word) +highs: .word 0, 0, 0, 0, 0, 0, 2147483648, 0, 0, 0 # expected result (high word) + +failmsg: .asciiz "failed for test input: " +expectedmsg: .asciiz ". expected " +commamsg: .asciiz ", " +tobemsg: .asciiz " to be " +okmsg: .asciiz "all tests passed" + + +.text + +runner: + lw $s0, n + la $s1, ins + la $s2, lows + la $s3, highs + +run_test: + lw $s4, 0($s1) # read input from memory + move $a0, $s4 # move it to a0 + jal square # call subroutine under test + move $s5, $v0 # move return value in v0 to s5 because we need v0 for syscall + move $s6, $v1 # move return value in v1 to s6 + + lw $t0, 0($s2) # read expected low output from memory + bne $t0, $s5, exit_fail # if expected doesn't match actual, jump to fail + lw $t1, 0($s3) # read expected high output from memory + bne $t1, $s6, exit_fail # if expected doesn't match actual, jump to fail + + addi $s1, $s1, 4 # move to next word in input + addi $s2, $s2, 4 # move to next low word in output + addi $s3, $s3, 4 # move to next high 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 + + move $a0, $s4 # set arg of syscall to input that failed the test + li $v0, 1 # 1 is print int + syscall + + la $a0, expectedmsg + li $v0, 4 + syscall + + move $a0, $s5 # print actual low that failed on + li $v0, 1 + syscall + + la $a0, commamsg + li $v0, 4 + syscall + + move $a0, $s6 # print actual high that failed on + li $v0, 1 + syscall + + la $a0, tobemsg + li $v0, 4 + syscall + + lw $a0, 0($s2) # print expected low value that failed on + li $v0, 1 + syscall + + la $a0, commamsg + li $v0, 4 + syscall + + lw $a0, 0($s3) # print expected high value that failed on + li $v0, 1 + syscall + + li $a0, 1 # set exit code to 1 + li $v0, 17 # terminate with the exit code in $a0 + syscall + +# # Include your implementation here if you wish to run this from the MARS GUI. +# .include "impl.mips" +