| Deadline | Friday, November 10, 11:59pm |
| Name on Marmoset | Q8 |
| To Submit |
practice.wlp4
|
The ultimate goal of the projects in this course is to write a compiler that translates a C-like programming language called WLP4 into MIPS assembly language. You can then translate the MIPS assembly into MIPS machine language with your assembler from Project 2, and run your programs!
The purpose of this question is to get you familiar with the features and limitations of WLP4, to help you better understand the
requirements of compilation. There will not be further WLP4 programming questions, but you will have to write your own WLP4 programs to test the components of your compiler!
WLP4 is similar to a small subset of C, but it uses
C++ style memory allocation (new/delete instead of malloc/free).
It only supports
The syntax of WLP4 is harshly restricted, which makes it more annoying to write, but easier to compile.
For example:
WLP4 Quick Introduction
int and int* variables,
basic arithmetic (addition, subtraction, multiplication, division, and modulo),
conditional statements (if/else)
and while loops with comparison-based tests,
a println statement for printing numbers,
memory allocation with new and delete,
and procedures that return an int value.
More detailed information about WLP4 is linked below:
Step 1.
Write a WLP4 procedure int abs(int n) { ... }
that computes the absolute
value of an integer. You do not need to properly handle the case
of -231 = -2147483648 (this integer has no
positive counterpart in 32-bit two's complement).
Step 2.
Write a WLP4 procedure int tieBreak(int a, int b) { ... }
which should be called with two distinct integers as parameters.
Step 3.
Write a WLP4 procedure
int wain(int *array, int size) { ... }
that takes a non-empty array of integers
in the range -241 to 241 (inclusive) as input and
returns the integer that occurs most frequently.
If there is a tie for the most frequent integer,
break the tie using the rule from the tieBreak
procedure.
The wain procedure is the WLP4 equivalent of main. It
must appear as the last procedure in the program, or a parsing error will occur.
For full marks, your program should run in linear time (in the size of the input array). A quadratic time solution using nested loops can get at most 50% of the marks.
Suppose the input array is [1, 2, 2, 3, 3, 3]. Your program should return 3.
Suppose the input array is [4, 4, 2, 4, 2, -3, 2, -3, -3].
There's a three way tie between 4, 2 and -3. Since 2 has the least absolute value,
your program should return 2.
Suppose the input array is [1, -1, 2, -2].
There's a four way tie between 1, -1, 2, and -2.
Among these, 1 and -1 tie for the smallest absolute value.
To break this tie, you choose the negative number, so you return -1.
Compile your program with
wlp4c.
This will produce MIPS machine code, which can be run directly with one of our MIPS emulators. Which emulator you use depends on whether the wain procedure takes two integer parameters, or a pointer (int*) and an integer.
For this question, you should test your program with
mips.array.
The array address in $1 corresponds to the first parameter of
wain
and the size in $2 corresponds to the second parameter.
The return value will be placed in $3.
wlp4c < practice.wlp4 > practice.mips mips.array practice.mips Enter length of array: 4 Enter array element 0: 3 Enter array element 1: 1 Enter array element 2: 2 Enter array element 3: 3 Running MIPS program. MIPS program completed normally. $01 = 0x00000fcc $02 = 0x00000004 $03 = 0x00000003 $04 = 0x00000004 ...Or more concisely:
mips.array <(wlp4c < practice.wlp4) <<< "4 3 1 2 3" Enter length of array: Enter array element 0: Enter array element 1: ... Running MIPS program. MIPS program completed normally. $01 = 0x00000fcc $02 = 0x00000004 $03 = 0x00000003 $04 = 0x00000004 ...
If you don't know how to find the most frequent element in an array in linear time,
it is a good problem to practice your skill at designing algorithms.
However, the main purpose of this question is not to practice algorithm design, but rather to get you familiar with the WLP4 language.
If you are having trouble with the algorithm design aspect, there are some hints below,
though we encourage you to try to solve the question without them.
Your first instinct might be to solve the problem with a hash table, but implementing a hash table in WLP4 would be extremely painful.
Instead, implement something similar but simpler.
Hash tables are useful when the keys are not integers, or when the number of keys are very large. In this problem, the keys are integers
that lie in a small range.
If the range of integers was 0 to 241, you could solve this problem using an array of size 242, where
Using an array that tracks the frequency of each integer, you can solve the problem with two loops:
Create a variable called
Allocate an array called
Initialize
Loop through the remaining elements of the input array. For each value Hint 1
Hint 2
array[i] stores the number of occurrences of number i. Modify this approach to work with the range -241 to 241.
Hint 3
Keep track of the current "winner" during the second loop, and call tieBreak whenever you find a new candidate for the "winner".
Hint 4 (Full Algorithm)
mostFrequent to store the most frequent number.
frequency of size 483, where frequency[i+241] will store the number of occurrences of number i. Initialize all the elements to zero.
mostFrequent to the first element of the input array.
i in the input array:
Return frequency[i+241] by 1.frequency[i+241] is greater than frequency[mostFrequent+241], set mostFrequent = i.frequency[i+241] is equal to frequency[mostFrequent+241], set mostFrequent = tieBreak(mostFrequent, i).mostFrequent.