diff --git a/config.json b/config.json index beaddb9..1ead9b9 100644 --- a/config.json +++ b/config.json @@ -10,7 +10,9 @@ "trinary", "hexadecimal", "leap", - "hamming" + "hamming", + "isogram", + "triangle" ], "deprecated": [ diff --git a/exercises/isogram/example.mips b/exercises/isogram/example.mips new file mode 100644 index 0000000..ee605b2 --- /dev/null +++ b/exercises/isogram/example.mips @@ -0,0 +1,48 @@ +# Determine if the given string is an isogram, meaning that the same character +# does not appear more than once. +# +# Strategy: use the bits of a single word to represent set of encountered letters +# +# $a0 - input, pointer to null-terminated string of chars 0-7 +# $v0 - output, boolean representing is or is not isogram +# $t0 - set of bits +# $t1 - an encountered character + +.globl is_isogram + +is_isogram: + li $t0, 0 # Reset set to 0. + +loop: + lb $t1, 0($a0) # Load a character, + beq $t1, $zero, true # if end of string, return true. + + addi $t2, $t1, -65 # If less than 'A'... + blt $t2, $zero, increment # continue to next letter. + + addi $t1, $t1, -97 # Find offset from 'a'. + blt $t1, $zero, downcase # If negative, presume upper case, so downcase + +consider_seen: + li $t3, 1 + sllv $t3, $t3, $t1 # Create bit mask + and $t4, $t0, $t3 # Apply to set. + bgt $t4, $zero, false # If char has been seen, return false. + + or $t0, $t0, $t3 # Otherwise flip bit for char + +increment: + addi $a0, $a0, 1 # Finally, increment the pointer + j loop # and loop. + +downcase: + addi $t1, $t1, 32 # Upper -> lower ascii value + j consider_seen + +false: + li $v0, 0 + jr $ra + +true: + li $v0, 1 + jr $ra diff --git a/exercises/isogram/runner.mips b/exercises/isogram/runner.mips new file mode 100644 index 0000000..76a692e --- /dev/null +++ b/exercises/isogram/runner.mips @@ -0,0 +1,97 @@ +# +# Test is_isogram with some examples +# +# s0 - num of tests left to run +# s1 - address of input word +# s2 - address of expected output word +# s3 - char byte +# s4 - output word +# +# is_isogram must: +# - be named is_isogram and declared as global +# - read input address of string from a0 +# - follow the convention of using the t0-9 registers for temporary storage +# - (if it uses s0-7 then it is responsible for pushing existing values to the stack then popping them back off before returning) +# - write boolean result to v0 + +.data + +# number of test cases +n: .word 8 +# input values (null terminated) & expected output values (word sized ints) +ins: .asciiz "duplicates", "eleven", "subdermatoglyphic", "Alphabet", "thumbscrew-japingly", "Hjelmqvist-Gryb-Zock-Pfund-Wax", "the quick brown fox", "Emily Jung Schwartzkopf" +outs: .word 1, 0, 1, 0, 1, 1, 0, 1 + +failmsg: .asciiz "failed for test input: " +expectedmsg: .asciiz ". expected " +tobemsg: .asciiz " to be " +okmsg: .asciiz "all tests passed" + + +.text + +runner: + lw $s0, n + la $s1, ins + la $s2, outs + +run_test: + move $a0, $s1 # move address of input str to a0 + jal is_isogram # call subroutine under test + move $v1, $v0 # move return value in v0 to v1 because we need v0 for syscall + + lw $s4, 0($s2) # read expected output from memory + bne $v1, $s4, exit_fail # if expected doesn't match actual, jump to fail + +scan: + addi $s1, $s1, 1 # move input address on byte forward + lb $s3, 0($s1) # load byte + beq $s3, $zero, done_scan # if char null, break loop + j scan # loop + +done_scan: + addi $s1, $s1, 1 # move input address on byte past null + + addi $s2, $s2, 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 + + move $a0, $s1 # print input that failed on + li $v0, 4 + syscall + + la $a0, expectedmsg + li $v0, 4 + syscall + + move $a0, $v1 # print actual that failed on + li $v0, 1 # 1 is print integer + syscall + + la $a0, tobemsg + li $v0, 4 + syscall + + move $a0, $s4 # print expected value that failed on + li $v0, 1 # 1 is print integer + syscall + + li $a0, 1 # set error code to 1 + li $v0, 17 # 17 is exit with error + syscall + +# # Include your implementation here if you wish to run this from the MARS GUI. +# .include "impl.mips" diff --git a/exercises/triangle/example.mips b/exercises/triangle/example.mips new file mode 100644 index 0000000..d21d103 --- /dev/null +++ b/exercises/triangle/example.mips @@ -0,0 +1,61 @@ +# +# Determine if triangle with given sides is invalid, equilateral, isoceles or scalene. +# +# Variables: +# +# $a0 - side a (int) +# $a1 - side b (int) +# $a2 - side c (int) +# $v0 - enum 0: scalene, 1: isoceles, 2: equilateral, 3: invalid +# $t0 - a == b +# $t1 - b == c +# $t5 - a == b && b == c (equilateral) +# $t6 - a == b || b == c (isoceles, if not above) + +.globl triangle + + +triangle: + bgt $a0, $a1, swap_ab + bgt $a1, $a2, swap_bc + j solve + +swap_ab: + move $t0, $a1 + move $a1, $a0 + move $a0, $t0 + j triangle + +swap_bc: + move $t0, $a2 + move $a2, $a1 + move $a1, $t0 + j triangle + +solve: + addu $t0, $a0, $a1 + bge $a2, $t0, invalid # invalid if violate triangle inequality + + seq $t0, $a0, $a1 # a == b + seq $t1, $a1, $a2 # b == c + + and $t5, $t0, $t1 + or $t6, $t0, $t1 + + bne $t5, $zero, equilateral + bne $t6, $zero, isoceles + + li $v0, 0 + jr $ra + +equilateral: + li $v0, 2 + jr $ra + +isoceles: + li $v0, 1 + jr $ra + +invalid: + li $v0, 3 + jr $ra diff --git a/exercises/triangle/runner.mips b/exercises/triangle/runner.mips new file mode 100644 index 0000000..4ebe912 --- /dev/null +++ b/exercises/triangle/runner.mips @@ -0,0 +1,100 @@ +# +# Test triange with some examples +# +# s0 - num of tests left to run +# s1 - address of side 1 +# s2 - address of side 2 +# s3 - address of side 3 +# s4 - address of expected output +# s5 - value of expected output +# +# triangle must: +# - be named triangle and declared as global +# - read input integers from a0, a1 and a2 +# - 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 result to v0 as: +# 0 - scalene +# 1 - isoceles +# 2 - equilateral +# 3 - invalid triangle + +.data + +n: .word 11 +as: .word 2, 10, 3, 4, 4, 3, 10, 5, 7, 1, 0 +bs: .word 2, 10, 4, 3, 7, 4, 11, 4, 3, 1, 0 +cs: .word 2, 10, 4, 4, 4, 5, 12, 2, 2, 3, 0 +outs: .word 2, 2, 1, 1, 1, 0, 0, 0, 3, 3, 3 + +failmsg: .asciiz "failed for test input: " +okmsg: .asciiz "all tests passed" +comma: .asciiz ", " + +.text + +runner: + lw $s0, n + la $s1, as + la $s2, bs + la $s3, cs + la $s4, outs + +run_test: + lw $a0, 0($s1) # load inputs into argument registers + lw $a1, 0($s2) + lw $a2, 0($s3) + + jal triangle # call subroutine under test + move $v1, $v0 # move return value in v0 to v1 because we need v0 for syscall + + lw $s5, 0($s4) # read expected output from memory + bne $v1, $s5, exit_fail # if expected doesn't match actual, jump to fail + + addi $s1, $s1, 4 # move to next word in as + addi $s2, $s2, 4 # move to next word in bs + addi $s3, $s3, 4 # move to next word in cs + addi $s4, $s4, 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, 0($s1) # set arg of syscall to input that failed the test + li $v0, 1 # 1 is print int + syscall + + la $a0, comma # put address of failmsg into a0 + li $v0, 4 # 4 is print string + syscall + + lw $a0, 0($s2) # set arg of syscall to input that failed the test + li $v0, 1 # 1 is print int + syscall + + la $a0, comma # put address of failmsg into a0 + li $v0, 4 # 4 is print string + syscall + + lw $a0, 0($s3) # set arg of syscall to input that failed the test + li $v0, 1 # 1 is print int + 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"