Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
honors project 1 and merge sort
- Loading branch information
Jerry Shi
committed
Feb 2, 2024
1 parent
9a9d5a7
commit a129644
Showing
5 changed files
with
335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Mergesort | ||
|
||
Here is a skeleton code for merge sort. | ||
|
||
The pseudocode for merge sort function is in a homework question. It | ||
needs minor changes if we want to support large arrays. | ||
|
||
The pseudocode for `array_merge` is below. This version uses a single loop and | ||
does not need `array_copy` function. | ||
|
||
|
||
```C | ||
// Merge sorted two arrays a1 and a2 into one array dst | ||
void array_merge(int dst[], int a1[], int n1, int a2[], int n2) | ||
{ | ||
int total = n1 + n2; | ||
|
||
// we maintain three indexes, one for each array | ||
int i1 = i2 = id = 0; | ||
|
||
while (id < total) { | ||
if ((i2 >= n2) || (i1 < n1 && a1[i1] < a2[i2])) { | ||
// Note that if i1 >= n1, control flow goes to the ELSE branch | ||
// copy an element from a1 to dst | ||
dst[id] = a1[i1]; | ||
i1 += 1; | ||
} else { | ||
// copy an element from a2 to dst | ||
dst[id] = a2[i2]; | ||
i2 += 1; | ||
} | ||
id += 1; | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# Merge Sort | ||
|
||
.data #data segment | ||
.align 2 | ||
buffer: .space 4096 #allocate space for 1K words | ||
|
||
.text # Code segment | ||
.globl main # declare main to be global | ||
main: | ||
# specify the size of the array, must be less than 1024 | ||
# la s1, buffer # address of the buffer | ||
lui s1, 0x10010 # hard code the address | ||
addi s2, x0, 200 # number of elements | ||
|
||
# call init_array() to initialize the array with random values | ||
addi a0, s1, 0 | ||
addi a1, s2, 0 | ||
jal ra, init_array | ||
|
||
# call merge_sort function with proper arguments | ||
# we must assume a0 and a1 are changed after function call | ||
addi a0, s1, 0 | ||
addi a1, s2, 0 | ||
jal ra, merge_sort | ||
|
||
# set a breakpoint here and examine the memory | ||
Exit: | ||
addi a7, x0, 10 | ||
ecall | ||
|
||
# void init_array(int p[], int n) | ||
# use pseudorandom numbers to fill out the array | ||
init_array: | ||
# we use pointers in this function | ||
# t0 is the starting address and | ||
# t1 is the word address right after the array | ||
addi t0, a0, 0 | ||
slli t1, a1, 2 | ||
add t1, t1, t0 # &p[n] | ||
|
||
# set the seed | ||
addi a0, x0, 0 | ||
lui a1, 0x3666 | ||
addi a7, x0, 40 | ||
ecall | ||
|
||
# syscall for rand() | ||
# 41 on randon integer | ||
# 42 for bounded values. upper bound is in a1 | ||
# a1 and a7 are not changed in the loop | ||
lui a1, 0x100 | ||
addi a7, x0, 42 | ||
|
||
beq zero, zero, ia_test | ||
ia_loop: | ||
addi a0, x0, 0 | ||
ecall # a1 and a7 are set before the loop | ||
sw a0, 0(t0) # save the random value | ||
addi t0, t0, 4 # move to the next word | ||
ia_test: | ||
bltu t0, t1, ia_loop | ||
|
||
jalr x0, ra, 0 | ||
|
||
####START_OF_MERGE_SORT and helper functions | ||
|
||
# array_merge(int da[], int a1[], int n1, int a2[], int n2) | ||
# merge sorted array a1 and a2 into array da | ||
# a1 has n1 words and a2 has n2 words | ||
array_merge: | ||
|
||
|
||
# void merge_sort(int p[], int n) | ||
# TODO | ||
merge_sort: | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
#define TRUE 1 | ||
#define FALSE 0 | ||
#define BOARDSIZE 8 | ||
#define EMPTY_CHAR '-' | ||
|
||
|
||
int difference(int i, int j) | ||
{ | ||
if (i < j) | ||
return j - i; | ||
else | ||
return i - j; | ||
} | ||
|
||
int is_valid(int a[], int row, int column) | ||
{ | ||
// check if any queen already placed threats board[row][column] | ||
for (int i = 0; i < row; i ++) { | ||
if ((column == a[i]) // column threat | ||
|| difference(i, row) == difference(a[i], column)) // diagonal threat | ||
return FALSE; | ||
} | ||
return TRUE; | ||
} | ||
|
||
void my_puts(int *s) | ||
{ | ||
int i; | ||
|
||
for (i = 0; s[i]; i ++) | ||
putchar(s[i]); | ||
putchar('\n'); | ||
} | ||
|
||
void process_solution(int a[], int k) | ||
{ | ||
// print the board | ||
int line[BOARDSIZE + 1]; | ||
|
||
for (int i = 0; i < BOARDSIZE; i ++) { | ||
line[i] = EMPTY_CHAR; | ||
} | ||
line[BOARDSIZE] = 0; | ||
|
||
for (int i = 0; i < BOARDSIZE; i ++) { | ||
line[a[i]] = '*'; | ||
my_puts(line); | ||
line[a[i]] = EMPTY_CHAR; | ||
} | ||
|
||
// no need to print the numbers in assembly code | ||
for (int i = 0; i < BOARDSIZE; i ++) { | ||
printf("%d ", a[i]); | ||
} | ||
putchar('\n'); | ||
} | ||
|
||
|
||
// k: number of queens already placed and k >= 0 | ||
int solve_8queens(int a[], int k) | ||
{ | ||
int counter = 0; | ||
|
||
if (k == BOARDSIZE) { | ||
// if all queens have already been placed ... | ||
process_solution(a, k); | ||
counter += 1; | ||
} | ||
else { | ||
// try row k. Rows 0 .. (k-1) already have a queen | ||
// Use j for columns | ||
for (int j = 0; j < BOARDSIZE; j ++) { | ||
if (is_valid(a, k, j)) { | ||
a[k] = j; | ||
counter += solve_8queens(a, k+1); | ||
if (counter ) { | ||
// terminate after the first solution | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
return counter; | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int a[BOARDSIZE] = {0}; /* location of queens. */ | ||
|
||
if (argc == 2) { | ||
int c = atoi(argv[1]); | ||
if (c < 0 || c >= BOARDSIZE) { | ||
printf("The position is not correct.\n"); | ||
return -1; | ||
} | ||
a[0] = c; | ||
} | ||
|
||
// int solution_counts[]={1, 0, 0, 2, 10, 4, 40, 92}; | ||
|
||
printf("Number of solutions=%d\n", solve_8queens(a, 1)); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Eight Queens | ||
|
||
Deadline: demo by Friday, 03/01/2024. Come to professors' office hours or make | ||
an appointment with Prof Shi or Prof Ding. | ||
|
||
The eight queens problem is a classic coding problem. The goal is to place | ||
eight chess queens on an 8×8 chessboard and no two queens threaten each | ||
other. The size of board may be adjusted. | ||
|
||
In this assignment, we write a RISC-V program to find a solution on an 8x8 | ||
board, when the location of the queen in the first row (row 0) is specified. | ||
One implementation in C is in "eightqueens.c". In this version, the program | ||
stops searching when the first solution is found. The location of the first | ||
queen defaults to column 0, but it can be specified at the command line. For | ||
example, the following command place the frist queen in row 0, column 1. | ||
|
||
./eightqueens 1 | ||
|
||
The skeleton code is in "eightqueens.s". Here are some differences in the | ||
assembly verson and some constraints. | ||
|
||
* Assume only two branch instructions, BEQ and BNE, are available. Do not use | ||
BLT, BGE, BLTU, or BGEU. Otherwise, you will have to rewirte your code | ||
later. | ||
|
||
* The location of the queen in row 0 is specifed by the first number in array | ||
`a`. We can change the number manually. Note that array `a` is on the | ||
stack. | ||
|
||
* In function `process_solution()`, there is no need to write the second loop | ||
to print decimal values. Once the program terminates, we can see the numbers | ||
in array `a` in data segment window. | ||
|
||
Also, pay attention to `line`. It is a local word array. | ||
|
||
`my_puts` function is provided in the skeleton code. | ||
|
||
## Testing | ||
|
||
The solutions found by the RISC-V program should be the same as the ones found | ||
by the C program. Here are some solutions from the C program. Note that the | ||
number of solutions is 1 because we terminate the search when the first | ||
solution is found. Compile the C program and compare the results for other | ||
initial setups. | ||
|
||
``` | ||
# ./eightqueens | ||
*------- | ||
----*--- | ||
-------* | ||
-----*-- | ||
--*----- | ||
------*- | ||
-*------ | ||
---*---- | ||
0 4 7 5 2 6 1 3 | ||
Number of solutions=1 | ||
# ./eightqueens 1 | ||
-*------ | ||
---*---- | ||
-----*-- | ||
-------* | ||
--*----- | ||
*------- | ||
------*- | ||
----*--- | ||
1 3 5 7 2 0 6 4 | ||
Number of solutions=1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# code | ||
.text | ||
.globl main | ||
main: | ||
|
||
# allocate space for array a from the stack | ||
# the numbers in the array are the location of the queen in each row. | ||
# we can place the queen in row 0 in a different column | ||
# by changing the first 0 below. | ||
|
||
addi sp, sp, -32 | ||
addi a0, sp, 0 # put a's address in a0 | ||
|
||
addi t0, x0, 0 # place a queen in column 0 in row 0 | ||
sw t0, 0(a0) | ||
|
||
addi a1, x0, 1 # number of queens already placed | ||
jal ra, solve_8queens | ||
|
||
beq x0, x0, exit | ||
|
||
# print a string stored in a word array, and a newline | ||
my_puts: | ||
addi a7, x0, 11 # system call printing a character | ||
addi t0, a0, 0 # copy a0 to t0, which is the address of the array | ||
mp_loop: | ||
lw a0, 0(t0) | ||
beq a0, x0, mp_exit | ||
ecall | ||
addi t0, t0, 4 | ||
beq x0, x0, mp_loop | ||
mp_exit: | ||
# print newline | ||
addi a0, x0, '\n' | ||
ecall | ||
jalr x0, ra, 0 | ||
|
||
####################### | ||
### put your code here | ||
solve_8queens: | ||
|
||
|
||
### End of your code | ||
####################### | ||
|
||
exit: | ||
# no need to do anything here |