# Wintermate's solution

## to Triangle in the MIPS Assembly Track

Published at Feb 03 2019 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

Determine if a triangle is equilateral, isosceles, or scalene.

An equilateral triangle has all three sides the same length.
An isosceles triangle has at least two sides the same length. (It is sometimes specified as having exactly two sides the same length, but for the purposes of this exercise we'll say at least two.)
A scalene triangle has all sides of different lengths.

## Note

For a shape to be a triangle at all, all sides have to be of length > 0, and the sum of the lengths of any two sides must be greater than or equal to the length of the third side. See Triangle Inequality.

## Dig Deeper

The case where the sum of the lengths of two sides equals that of the third is known as a degenerate triangle - it has zero area and looks like a single line. Feel free to add your own code/tests to check for degenerate triangles.## Source

The Ruby Koans triangle project, parts 1 & 2 http://rubykoans.com

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### runner.mips

``````#
# 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"``````
``````.global triangle

.text

triangle:
# preload invalid state for validity checks
li \$v0, 3

# test if valid: Sides > 0
blez \$a0, _done
blez \$a1, _done
blez \$a2, _done

# test if valid: triangle inequality
add \$t0, \$a0, \$a1  # \$t0 = (\$a0 + \$a1 + \$a2 + 1) div 2 => half the sum rounded up.
add \$t0, \$t0, \$a2  #  \$a0, \$a1, \$a2 must all be less than this.
sra \$t0, \$t0, 1
bge \$a0, \$t0, _done
bge \$a1, \$t0, _done
bge \$a2, \$t0, _done

# Actual calculation:
seq \$v0, \$a0, \$a1  # \$v0 := \$(a0 == \$a1)
seq \$t0, \$a0, \$a2  # if \$a0 == \$a2 add 1 to \$v0.
bnez \$v0, _done    # If either of these was true, we're done:
# 2 sides equal => all sides equal => equilateral
# 1 side equal  => isosceles
seq \$v0, \$a1, \$a2  # Otherwise: triangle is isosceles iff \$a1 == \$a2
_done:
jr \$ra``````