Skip to content

Commit

Permalink
feat: Add Grains (resolves #149) (#167)
Browse files Browse the repository at this point in the history
  • Loading branch information
keiravillekode authored Oct 13, 2023
1 parent 2d475e5 commit 77acf07
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
15 changes: 15 additions & 0 deletions exercises/practice/grains/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions exercises/practice/grains/.meta/config.json
Original file line number Diff line number Diff line change
@@ -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"
}
32 changes: 32 additions & 0 deletions exercises/practice/grains/.meta/example.mips
Original file line number Diff line number Diff line change
@@ -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

45 changes: 45 additions & 0 deletions exercises/practice/grains/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -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

Empty file.
115 changes: 115 additions & 0 deletions exercises/practice/grains/runner.mips
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 77acf07

Please sign in to comment.