-
Notifications
You must be signed in to change notification settings - Fork 0
/
Project6.cpp
489 lines (449 loc) · 15.7 KB
/
Project6.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
/*
* Project6.c
* Recursion
* Fall 2017
* Jost Luebbe
* jl64249
* My TA
* Tues/Thurs 11-12:30
*
*
*/
#include <stdio.h>
#include <stdint.h>
#include "MazeParams.h"
#include "Recursion.h"
/* return the smallest of the elements in array x[]
* there are n elements in x[] (x[0].. x[n-1])
*/
int minIt(int x[], int n) {
int lowest = x[0];
int i;
for(i=1;i<n;i++){
if(x[i]<lowest){
lowest = x[i];
}
}
return lowest;
}
/* return the smallest of the elements in array x[]
* there are n elements in x[] (x[0].. x[n-1])
* solve the problem recursively and
* use an "n-1" type of decomposition
*/
int minRec1(int x[], int n) {
if(n==1)
return x[0];
int next = minRec1(x, n-1);
return (x[n-1] < next)? x[n-1] : next;
}
/*
* return the smallest of the elements in array x[]
* there are n elements in x[] (x[0].. x[n-1])
* n may be either odd or even
* solve the problem recursively and
* use an "n / 2" type of decomposition
*/
int minRec2(int x[], int n) {
if(n==1){
return x[0];
}
else if(n==0){
return x[0];
}
else{
int s1 = minRec2(x, n/2);
int s2 = minRec2(x + (n/2), n/2);
return (s1<s2)? s1: s2;
}
}
/*
* calculate and return the square root of x.
* The other two parameters are estimates of the square root.
* low_guess is smaller than the actual square root, and high_guess
* is larger than the actual square root.
* Searching for the square root can be done much like searching
* for a name in a phone book.
*
* Since you can't calculate a square root exactly, for this problem
* you're required to calculate the answer to 15 decimal digits of
* accuracy.
*/
double sqrtIt(double x, double low_guess, double high_guess) {
double my_guess = 0;
double add_val = 1;
while(true){
while(my_guess*my_guess<high_guess){
my_guess+=add_val;
}
if(my_guess*my_guess==x){
return my_guess;
}
if(my_guess*my_guess>low_guess){
my_guess -= add_val;
add_val /= 10;
}
if(add_val < .000000000000001){
return my_guess;
}
}
}
/*
* calculate and return the square root of x.
* The other two parameters are estimates of the square root.
* low_guess is smaller than the actual square root, and high_guess
* is larger than the actual square root.
* Searching for the square root can be done much like searching
* for a name in a phone book.
*
* Since you can't calculate a square root exactly, for this problem
* you're required to calculate the answer to 15 decimal digits of
* accuracy.
*/
double sqrtRec(double x, double low_guess, double high_guess) {
double half = (low_guess+high_guess)/2;
if(half*half == x || high_guess-low_guess<.000000000000001){
return half;
}
if(half*half > x){
return sqrtRec(x, low_guess, half);
}
return sqrtRec(x, half, high_guess);
}
/*
* using only recursion, write a string comparison function
* return -1 if str1 is less than str2
* return 0 if the two strings are equal
* return +1 if str1 is greater than str2
* when comparing strings, use the ASCII value to compare each character
* (i.e., that means 'A' is less than 'a' since it's ASCII value is smaller)
* The string str1 is less than str2 if either
* str1[0] < str2[0]
* or there exists a k such that str1[k] < str2[k] and
* for all j < k str1[j] == str2[j]
* and k is less than the length of str1 and str2
*/
int strCompare(char* str1, char* str2) {
if(*str1==0 && *str2==0){
return 0;
}
if(*str1 < *str2){
return -1;
}
if(*str1 > *str2){
return 1;
}
else{
return strCompare(str1+1, str2+1);
}
}
/*
* if c is not a letter return -1
* if c is a letter, return the position of c in the alphabet
* where 'A' (and 'a') are position 1 and 'Z' (and 'z') are position 26
*
* This code is rather ugly as I'm exploiting some detailed knowledge of the ASCII table
*/
int whatLetter(char c) {
if (c < 'A') { return -1; }
if (c > 'z') { return -1; }
if (c > 'Z' && c < 'a') { return -1; }
return c & ~32 - 64;
}
/*
* same as before, only this time
* ignore anything that is not a letter
* ignore the case (upper case, lower case)
* So, strCompare2("Hello", "hello") should return 0 (they're the same)
* strCompare2("The plane!", "theater") should return 1 since "theplane" is larger than "theater"
* once again, you can only use recursion, no loops
*/
int strCompare2(char* str1, char* str2) {
if(*str1==0 && *str2==0){
return 0;
}
if(whatLetter(*str1)<0){
return strCompare2(str1+1, str2);
}
if(whatLetter(*str2)<0){
return strCompare2(str1, str2+1);
}
if(whatLetter(*str1) < whatLetter(*str2)){
return -1;
}
if(whatLetter(*str1) > whatLetter(*str2)){
return 1;
}
else{
return strCompare2(str1+1, str2+1);
}
}
/*
* the two dimensional array maze[MATRIX_SIZE][MATRIX_SIZE] contains a maze
* Each square is (initially) either a 1 or a zero. Each 1 represents a wall
* (you cannot walk through walls, so you can't go into any square where the
* value is 1). Each 0 represents an open space.
*
* Write an recursive solution to find your way out of the maze
* Your starting point is at row and col. (params to this function)
* Your exit point is somewhere in the last row (which is: MATRIX_SIZE - 1)
*
* There is a relatively easy recursive solution to this problem, the trick is
* to think of the solution in the following terms:
* "In which direction(s) can I go and find a way out of this maze?"
* In some cases, you may find yourself in a spot in the maze that there's
* no way out (at least, not without backtracking). In that case, you'd return "false"
* since the maze has no solution. In most cases, there's one or more ways out
* from where you are now. Your key question is simply, "what is the first step I need to take"
*
* If you considered going "north", and you had a function that could tell you whether
* it was possible to get out of the maze starting at the square to the north of your
* current position, then you could use this function to determine if you can get out by
* going north first. Similarly, you could consider going south, east or west, and (recursively)
* determine if the maze can be solved from any of those locations.
*
* With that hint, the base case should be pretty obvious. In fact,
* I'd suggest you consider the possibility that the base case is "Yup, I'm already at
* the exit!"
*
* There is one tricky part to this decomposition. You need to make certain
* that the problem is getting smaller. The "bigness" or "smallness" of this
* problem is the number of squares that have not yet been tested. Each time
* you test an adjacent square (making a recursive call to decide if there is a
* path to the exit through that square), you'll be reducing the number of squares
* that have not yet been tested. Eventually, you must have tested all the
* squares and so you'll have to have found a way to the exit.
*
* The easy way to deal with the tricky part is to leave "bread crumbs" behind.
* Before you recursively check any (or all) of your neighbors to see if you
* can find the exit from there -- drop a bread crumb in your current square.
* Then, don't ever check to see if you can find the exit using a square
* with a breadcrumb in it (backtracking into that square would be silly).
*
* If you're trying to see if you can find an exit from some square, and all
* the adjacent squares are either walls, or have bread crumbs in them, then
* you already know the answer -- "you can't get to the exit from here".
* Pick up your bread crumb and return false.
*
* You can set the value of the current square to "2" to indicate that a bread
* crumb has been dropped. Set the square back to 0 when you want to pick
* the bread crumb back up.
* be sure not to change any of the squares that are 1 (the walls).
*
* for partial credit, you can leave all your bread crumbs on the floor.
* for full credit, you must pick up all the bread crumbs EXCEPT those
* along a path to the exit.
*/
int solveMazeRec(int row, int col) {
if(row > MATRIX_SIZE || col > MATRIX_SIZE){
return false;
}
if(row == MATRIX_SIZE){
return true;
}
if(maze[row][col]==1 || maze[row][col]==2){
return false;
}
maze[row][col]= 2;
if(solveMazeRec(row+1, col)==true){
return true;
}
if(solveMazeRec(row, col+1)==true){
return true;
}
if(solveMazeRec(row-1, col)==true){
return true;
}
if(solveMazeRec(row, col-1)==true){
return true;
}
maze[row][col] = 0;
return false;
}
/**********************
* adjacentCell and isOK are functions provided to help you write
* solveMazeIt()
*/
/*
* OK, we're currently at maze[row][col] and we're considering moving
* in direction dir.
* Set trow and tcol (local variables inside the calling function)
* to the row and column that we would move to IF we moved in
* that direction
*
* For example, there are two good ways to use this function.
* 1. to actually move one step in a direction use:
* adjacentCell(row, col, dir, &row, &col);
* That will set row and col to new values. The new values will
* be one square away from the old values.
*
* 2. to set trow and tcol to a square that is adjacent to row and col use:
* adjacentCell(row, col, dir, &trow, &tcol);
* That will not change row and col, but will change trow and tcol.
* This is useful if you aren't sure if you can actually move in this
* direction yet (e.g., maze[trow][tcol] may be a wall!). So, you set
* trow and tcol, and then check to see if it's OK to move there
*/
void adjacentCell(int row, int col, int dir, int* trow, int* tcol) {
*trow = row;
*tcol = col;
switch(dir) {
case 0: // UP
*trow = *trow - 1;
break;
case 1: // RIGHT
*tcol = *tcol + 1;
break;
case 2: // DOWN
*trow = *trow + 1;
break;
case 3: // LEFT
*tcol = *tcol - 1;
break;
}
}
/*
* return false if there is a wall in the square for row and col
* return true if it's not a wall.
*/
int isOK(int row, int col) {
return (row > 0 && row < MATRIX_SIZE
&& col > 0 && col < MATRIX_SIZE
&& maze[row][col] != 1);
}
/*
* return the value of the direction that is one turn to the right
*/
int turnRight(int dir) {
return (dir + 1) % 4;
}
/*
* return the value of the direction that is one turn to the left
*/
int turnLeft(int dir) {
return (dir + 3) % 4;
}
/*
* the two dimensional array maze[MATRIX_SIZE][MATRIX_SIZE] contains a maze
* Each square is (initially) either a 1 or a zero. Each 1 represents a wall
* (you cannot walk through walls, so you can't go into any square where the value
* is 1). Each 0 represents an open space.
*
* write an iterative solution to find your way out of the maze
* Your starting point is at row and col. (params to this function)
* Your exit point is somewhere in the last row (which is: MATRIX_SIZE - 1)
* The maze can be solved by following the right hand wall. In fact, there
* is exactly one path between any two points in the maze (well, between any two
* points that are not walls).
*
* The algorithm is not too bad, although it is certainly not trivial
* Initially, you'll be headed DOWN (direction 2)
* Each iteration do one of the following. Note that only one of two cases
* can possibly apply (the properties of the maze guarantee that).
* case 1: you can move in the current direction
* In this case, you should take one step in the current direction
* and then turn right.
* case 2: you cannot move in the current direction
* If there's a wall directly in front of you, then to follow the right
* hand wall, you'd need to turn left (placing your hand on the wall that
* used to be directly in front of you). So, if you discover this case
* then turn left. Don't move, just turn left.
* If you were walking down a straight corridor (with walls on both sides)
* then you'd alternate case 1 and case 2. On the first iteration, you'd
* take a step, and then turn right (case 1). This causes you to walk
* one position down the hallway but then turn to face the wall.
* On the next iteration, you'll be facing the wall, so you can't walk
* forward and therefore (case 2) you'll turn left. On the third iteration
* you'll be able to walk down the hallway again.
*
* If you follow those two cases, then you'll eventually find your way out
* of the maze. To confirm that you're making it out, leave a "bread crumb"
* behind each square along the path to the exit.
* For partial credit, place a bread crumb in every square you visit.
* For full credit, pick up all the breadcrumbs when you backtrack.
* Backtracking is when you go back to a square you've already been before.
* If the square you're about to step into has a breadcrumb, then pick up
* the bread crumb in the square you're at now.
* You indicate "bread crumbs" by setting the square equal to "2"
*/
void solveMazeIt(int row, int col) {
int dir = 2; // 0 is up, 1 is right, 2 is down, 3 is left.
maze[row][col] = 2; // drop a bread crumb in the starting square
while (row < MATRIX_SIZE - 1) { // the exit is the only open square
// in the last row
/* the rest of this loop is yours */
}
}
/*
* using recursion, with no loops or globals, write a function that calculates the optimal
* (fewest total coins) change for a given amount of money. Return a Martian struct that indicates
* this optimal collection of coins.
*/
Martian change(int cents) {
Martian m1 = {0,0,0};
Martian m2 = {0,0,0};
Martian temp;
if(cents>11){
m1.dodeks++;
temp = change(cents-12);
m1.dodeks += temp.dodeks;
m1.nicks = temp.nicks;
m1.pennies = temp.pennies;
}
else{
m1.nicks = cents/5;
m1.pennies = cents%5;
}
m2.nicks = cents/5;
m2.pennies = cents%5;
if((m1.dodeks+m1.nicks+m1.pennies)<(m2.dodeks+m2.nicks+m2.pennies)){
return m1;
}
return m2;
}
/*
* Same as before, except the more general version where the coins have values
* a cents and b cents, with a and b being algebraic. For the original problem,
* a is the constant 5 (nick_value = 5 cents) and b is the constant 12
* (dodek_value = 12 cents).
* If you've really mastered thinking recursively, then this version of the
* martian change problem is just as easy as the concrete version
*/
Martian change(int cents, int nick_val, int dodek_val) {
Martian m1 = {0,0,0};
Martian m2 = {0,0,0};
Martian temp;
if(cents > (dodek_val-1)){
m1.dodeks++;
temp = change(cents-dodek_val, nick_val, dodek_val);
m1.dodeks += temp.dodeks;
m1.nicks = temp.nicks;
m1.pennies = temp.pennies;
}
else{
m1.nicks = cents/nick_val;
m1.pennies = cents%nick_val;
}
m2.nicks = cents/nick_val;
m2.pennies = cents%nick_val;
if((m1.dodeks+m1.nicks+m1.pennies)<(m2.dodeks+m2.nicks+m2.pennies)){
return m1;
}
return m2;
}
/*
* without using recursion, solve the Martian change problem described above.
* it's not too bad for the specific case of nick_value = 5 and dodek_value = 12
*/
Martian changeIt(int cents) {
return Martian{}; // delete this line, it's broken. Then write the function properly!
}
/*
* However, I don't have a solution for the general case. In fact, I consider
* the general problem to "challenging" (i.e, an exercise in futility).
* But, if you like banging your head against the wall for zero credit
* this is the problem for you!
*/
Martian changeIt(int cents, int nick_value, int dodek_value) {
return Martian{}; // delete this line, it's broken. Then write the function properly!
}