From 596b93d3a1a553667cbf172c8e55087b09b5c7c6 Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Mon, 13 Jan 2025 20:11:33 +1100 Subject: [PATCH] Add house exercise --- config.json | 8 + exercises/practice/house/.docs/hints.md | 6 + .../house/.docs/instructions.append.md | 0 .../practice/house/.docs/instructions.md | 105 ++++++++++ exercises/practice/house/.meta/config.json | 19 ++ exercises/practice/house/.meta/example.mips | 62 ++++++ exercises/practice/house/.meta/tests.toml | 52 +++++ exercises/practice/house/impl.mips | 11 + exercises/practice/house/runner.mips | 194 ++++++++++++++++++ 9 files changed, 457 insertions(+) create mode 100644 exercises/practice/house/.docs/hints.md create mode 100644 exercises/practice/house/.docs/instructions.append.md create mode 100644 exercises/practice/house/.docs/instructions.md create mode 100644 exercises/practice/house/.meta/config.json create mode 100644 exercises/practice/house/.meta/example.mips create mode 100644 exercises/practice/house/.meta/tests.toml create mode 100644 exercises/practice/house/impl.mips create mode 100644 exercises/practice/house/runner.mips diff --git a/config.json b/config.json index 3b1430f..67be5c7 100644 --- a/config.json +++ b/config.json @@ -481,6 +481,14 @@ "prerequisites": [], "difficulty": 6 }, + { + "slug": "house", + "name": "House", + "uuid": "914f654d-2d0c-4d4b-8c42-bff8ebdac21c", + "practices": [], + "prerequisites": [], + "difficulty": 6 + }, { "slug": "knapsack", "name": "Knapsack", diff --git a/exercises/practice/house/.docs/hints.md b/exercises/practice/house/.docs/hints.md new file mode 100644 index 0000000..52d65b0 --- /dev/null +++ b/exercises/practice/house/.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/house/.docs/instructions.append.md b/exercises/practice/house/.docs/instructions.append.md new file mode 100644 index 0000000..e69de29 diff --git a/exercises/practice/house/.docs/instructions.md b/exercises/practice/house/.docs/instructions.md new file mode 100644 index 0000000..88928c5 --- /dev/null +++ b/exercises/practice/house/.docs/instructions.md @@ -0,0 +1,105 @@ +# Instructions + +Recite the nursery rhyme 'This is the House that Jack Built'. + +> [The] process of placing a phrase of clause within another phrase of clause is called embedding. +> It is through the processes of recursion and embedding that we are able to take a finite number of forms (words and phrases) and construct an infinite number of expressions. +> Furthermore, embedding also allows us to construct an infinitely long structure, in theory anyway. + +- [papyr.com][papyr] + +The nursery rhyme reads as follows: + +```text +This is the house that Jack built. + +This is the malt +that lay in the house that Jack built. + +This is the rat +that ate the malt +that lay in the house that Jack built. + +This is the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the maiden all forlorn +that milked the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the man all tattered and torn +that kissed the maiden all forlorn +that milked the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the priest all shaven and shorn +that married the man all tattered and torn +that kissed the maiden all forlorn +that milked the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the rooster that crowed in the morn +that woke the priest all shaven and shorn +that married the man all tattered and torn +that kissed the maiden all forlorn +that milked the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the farmer sowing his corn +that kept the rooster that crowed in the morn +that woke the priest all shaven and shorn +that married the man all tattered and torn +that kissed the maiden all forlorn +that milked the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. + +This is the horse and the hound and the horn +that belonged to the farmer sowing his corn +that kept the rooster that crowed in the morn +that woke the priest all shaven and shorn +that married the man all tattered and torn +that kissed the maiden all forlorn +that milked the cow with the crumpled horn +that tossed the dog +that worried the cat +that killed the rat +that ate the malt +that lay in the house that Jack built. +``` + +[papyr]: https://papyr.com/hypertextbooks/grammar/ph_noun.htm diff --git a/exercises/practice/house/.meta/config.json b/exercises/practice/house/.meta/config.json new file mode 100644 index 0000000..98a71fa --- /dev/null +++ b/exercises/practice/house/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "impl.mips" + ], + "test": [ + "runner.mips" + ], + "example": [ + ".meta/example.mips" + ] + }, + "blurb": "Output the nursery rhyme 'This is the House that Jack Built'.", + "source": "British nursery rhyme", + "source_url": "https://en.wikipedia.org/wiki/This_Is_The_House_That_Jack_Built" +} diff --git a/exercises/practice/house/.meta/example.mips b/exercises/practice/house/.meta/example.mips new file mode 100644 index 0000000..b542144 --- /dev/null +++ b/exercises/practice/house/.meta/example.mips @@ -0,0 +1,62 @@ +# | Register | Usage | Type | Description | +# | -------- | ------------ | ------- | ----------------------------- | +# | `$a0` | input | integer | start verse | +# | `$a1` | input | integer | end verse | +# | `$a2` | input/output | address | null-terminated output string | +# | `$t0` | temporary | byte | character being copied | +# | `$t3` | temporary | address | pointer into lyrics | +# | `$t5` | temporary | address | lyrics | +# | `$t6` | temporary | address | table | +# | `$t7` | temporary | word | "THIS" (4 ASCII bytes) | +# | `$t8` | temporary | word | " IS " (4 ASCII bytes) | + +.eqv THIS 0x73696854 # "This" +.eqv IS 0x20736920 # " is " + +.globl recite + +.data + +lyrics: .asciiz "This is the horse and the hound and the horn that belonged to the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n" + +table: + .word -1, 389, 368, 351, 331, 310, 267, 232, 190, 145, 99, 62, 8 + + +.text + +recite: + la $t5, lyrics + la $t6, table + li $t7, THIS + li $t8, IS + + sll $a0, $a0, 2 + sll $a1, $a1, 2 + add $a0, $t6, $a0 # pointer into table for current verse + add $a1, $t6, $a1 # pointer into table for end verse + +line: + usw $t7, 0($a2) # unaligned store word "This" + usw $t8, 4($a2) # unaligned store word " is " + add $a2, $a2, 8 + + lw $t3, 0($a0) + add $t3, $t5, $t3 + +copy_string: + # copy string from source $t3 to destination $a2 + lb $t0, 0($t3) # load source byte + sb $t0, 0($a2) # write byte to destination + addi $t3, $t3, 1 # increment souce pointer + addi $a2, $a2, 1 # increment destination pointer + bne $t0, $zero, copy_string # repeat until we have reached null terminator + + subi $a2, $a2, 1 # decrement destination pointer, + # ready to append other strings + + move $t1, $a0 + add $a0, $a0, 4 + bne $t1, $a1, line + + jr $ra diff --git a/exercises/practice/house/.meta/tests.toml b/exercises/practice/house/.meta/tests.toml new file mode 100644 index 0000000..da24dc3 --- /dev/null +++ b/exercises/practice/house/.meta/tests.toml @@ -0,0 +1,52 @@ +# 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. + +[28a540ff-f765-4348-9d57-ae33f25f41f2] +description = "verse one - the house that jack built" + +[ebc825ac-6e2b-4a5e-9afd-95732191c8da] +description = "verse two - the malt that lay" + +[1ed8bb0f-edb8-4bd1-b6d4-b64754fe4a60] +description = "verse three - the rat that ate" + +[64b0954e-8b7d-4d14-aad0-d3f6ce297a30] +description = "verse four - the cat that killed" + +[1e8d56bc-fe31-424d-9084-61e6111d2c82] +description = "verse five - the dog that worried" + +[6312dc6f-ab0a-40c9-8a55-8d4e582beac4] +description = "verse six - the cow with the crumpled horn" + +[68f76d18-6e19-4692-819c-5ff6a7f92feb] +description = "verse seven - the maiden all forlorn" + +[73872564-2004-4071-b51d-2e4326096747] +description = "verse eight - the man all tattered and torn" + +[0d53d743-66cb-4351-a173-82702f3338c9] +description = "verse nine - the priest all shaven and shorn" + +[452f24dc-8fd7-4a82-be1a-3b4839cfeb41] +description = "verse 10 - the rooster that crowed in the morn" + +[97176f20-2dd3-4646-ac72-cffced91ea26] +description = "verse 11 - the farmer sowing his corn" + +[09824c29-6aad-4dcd-ac98-f61374a6a8b7] +description = "verse 12 - the horse and the hound and the horn" + +[d2b980d3-7851-49e1-97ab-1524515ec200] +description = "multiple verses" + +[0311d1d0-e085-4f23-8ae7-92406fb3e803] +description = "full rhyme" diff --git a/exercises/practice/house/impl.mips b/exercises/practice/house/impl.mips new file mode 100644 index 0000000..df14541 --- /dev/null +++ b/exercises/practice/house/impl.mips @@ -0,0 +1,11 @@ +# | Register | Usage | Type | Description | +# | -------- | ------------ | ------- | ----------------------------- | +# | `$a0` | input | integer | start verse | +# | `$a1` | input | integer | end verse | +# | `$a2` | input/output | address | null-terminated output string | +# | `$t0-9` | temporary | any | for temporary storage | + +.globl recite + +recite: + jr $ra diff --git a/exercises/practice/house/runner.mips b/exercises/practice/house/runner.mips new file mode 100644 index 0000000..293c5ba --- /dev/null +++ b/exercises/practice/house/runner.mips @@ -0,0 +1,194 @@ +# +# Test recite with some examples +# +# a0 - start verse, for callee +# a1 - end verse, for callee +# a2 - pointer to output string, for callee +# s0 - num of tests left to run +# s1 - address of start verse +# s2 - address of end verse +# s3 - address of expected output string +# s4 - copy of output location +# s5 - copy of address of expected output + +.eqv BUFFER_SIZE 4000 + +.data + +# number of test cases +n: .word 14 +start_verses: .word + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 4, + 1 +end_verses: .word + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 8, + 12 +outs: .ascii + "This is the house that Jack built.\n\0", + + "This is the malt that lay in the house that Jack built.\n\0", + + "This is the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the horse and the hound and the horn that belonged to the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0", + + "This is the house that Jack built.\n", + "This is the malt that lay in the house that Jack built.\n", + "This is the rat that ate the malt that lay in the house that Jack built.\n", + "This is the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n", + "This is the horse and the hound and the horn that belonged to the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.\n\0" + +failmsg: .asciiz "failed for test input: (" +commamsg: .asciiz ", " +expectedmsg: .asciiz "). expected\n" +tobemsg: .asciiz "to be\n" +okmsg: .asciiz "all tests passed" + + +.text + +runner: + lw $s0, n + la $s1, start_verses + la $s2, end_verses + la $s3, outs + + li $v0, 9 # code for allocating heap memory + li $a0, BUFFER_SIZE # specify length of longest expected output + syscall + move $s4, $v0 # location of allocated memory + +run_test: + jal clear_output # zero out output location + + lw $a0, 0($s1) # load start verse + lw $a1, 0($s2) # load end verse + move $a2, $s4 # load output address + jal recite # call subroutine under test + + move $t0, $s4 # set a temporary pointer to allocated memory + move $s5, $s3 # copy pointer to current expected output string +scan: + lb $t3, 0($s3) # load one byte of the expectation + lb $t4, 0($t0) # load one byte of the actual + bne $t3, $t4, exit_fail # if the two differ, the test has failed + addi $s3, $s3, 1 # point to next expectation byte + addi $t0, $t0, 1 # point to next actual byte + bne $t3, $zero, scan # if one char (and therefore the other) was not null, loop + +done_scan: + addi $s1, $s1, 4 # point to next start verse word + addi $s2, $s2, 4 # point to next end verse word + 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, 0($s1) # load start verse + li $v0, 1 + syscall + + la $a0, commamsg + li $v0, 4 + syscall + + lw $a0, 0($s2) # load end verse + li $v0, 1 + syscall + + la $a0, expectedmsg + li $v0, 4 + syscall + + move $a0, $s4 # print actual that failed on + li $v0, 4 + syscall + + la $a0, tobemsg + li $v0, 4 + syscall + + move $a0, $s5 # print expected value that failed on + li $v0, 4 + syscall + + li $a0, 1 # set error code to 1 + li $v0, 17 # 17 is exit with error + syscall + +clear_output: + # zero out output by storing zeros + addi $t0, $s4, BUFFER_SIZE # pointer to end of output buffer + +clear: + subi $t0, $t0, 4 # decrement pointer + sw $zero, 0($t0) # store a 0 word + bne $t0, $s4, clear # repeat util we have reached the start of the buffer + jr $ra + +# # Include your implementation here if you wish to run this from the MARS GUI. +# .include "impl.mips"