Skip to content

Commit

Permalink
Merge pull request #8 from exercism/more-exercises
Browse files Browse the repository at this point in the history
Add isogram and triangle
  • Loading branch information
ozan committed Aug 20, 2016
2 parents 3b0364e + b8536f8 commit 426717a
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 1 deletion.
4 changes: 3 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"trinary",
"hexadecimal",
"leap",
"hamming"
"hamming",
"isogram",
"triangle"
],
"deprecated": [

Expand Down
48 changes: 48 additions & 0 deletions exercises/isogram/example.mips
Original file line number Diff line number Diff line change
@@ -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
97 changes: 97 additions & 0 deletions exercises/isogram/runner.mips
Original file line number Diff line number Diff line change
@@ -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"
61 changes: 61 additions & 0 deletions exercises/triangle/example.mips
Original file line number Diff line number Diff line change
@@ -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
100 changes: 100 additions & 0 deletions exercises/triangle/runner.mips
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 426717a

Please sign in to comment.