├── Assignment1 ├── life-extra.cpp ├── life.cpp └── mycolony.txt ├── Assignment2 ├── myinput.txt ├── ngrams.cpp ├── ngrams_extra.cpp ├── wordladder.cpp └── wordladder_extra.cpp ├── Assignment3 ├── fractals.cpp ├── grammarsolver.cpp └── mygrammar.txt ├── Assignment4 ├── Boggle.cpp ├── Boggle.h └── boggleplay.cpp ├── Assignment5 ├── HeapPatientQueue.cpp ├── HeapPatientQueue.h ├── LinkedListPatientQueue.cpp ├── LinkedListPatientQueue.h ├── VectorPatientQueue.cpp └── VectorPatientQueue.h ├── Assignment6 ├── encoding.cpp ├── mymap.cpp ├── mymap.h └── secretmessage.huf ├── Assignment7 ├── Trailblazer.cpp ├── map-custom.jpg ├── map-custom.txt └── trailblazerHandout.pdf └── README.md /Assignment1/life-extra.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * LIFE - EXTRA (CONTAINS EXTENSIONS) 3 | * This program is a console based simulation of "The Game of Life", which is indeed 4 | * a simulation for modelling the life cycle of bacteria using a two-dimensional grid 5 | * of cells. The game simulates the birth and death of future generations based on 6 | * an initial pattern and some simple rules. The code involves variables and fuctions 7 | * to model the game. The program also contains some extensions. Those extensions involve 8 | * random pattern generation and GUI. Random pattern generation code can be found in the 9 | * function named generateRandomGrid and GUI codes are added inside displayGrid, advanceGrid 10 | * and main functions. 11 | * @author EFE ACER 12 | * CS106B - Section Leader: Ryan Kurohara 13 | */ 14 | 15 | //necessary includes 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "console.h" 23 | #include "filelib.h" 24 | #include "grid.h" 25 | #include "gwindow.h" 26 | #include "simpio.h" 27 | #include "strlib.h" 28 | #include "lifegui.h" 29 | #include "random.h" //added it for the extensions 30 | using namespace std; 31 | 32 | //Constant declerations (for further changes) 33 | const string WELCOME_MESSAGE = "Welcome to the CS 106B Game of Life,\n" 34 | "a simulation of the lifecycle of a bacteria colony.\n" 35 | "Cells (X) live and die by the following rules:\n" 36 | "- A cell with 1 or fewer neighbors dies.\n" 37 | "- Locations with 2 neighbors remain stable.\n" 38 | "- Locations with 3 neighbors will create life.\n" 39 | "- A cell with 4 or more neighbors dies.\n\n"; 40 | const string PROMPT_FILE = "Grid input file name? "; 41 | const string RANDOM = "(type \"random\" to generate a random pattern) "; 42 | const string FILE_ERROR = "Unable to open that file. Try again.\n"; 43 | const string OPTIONS = "Should the simulation wrap around the grid (y/n)? "; 44 | const string MENU = "a)nimate, t)ick, q)uit? "; 45 | const string PROMPT_FRAME_NUMBER = "How many frames? "; 46 | const string ERROR = "Invalid choice; please try again.\n"; 47 | const int PAUSE = 50; 48 | 49 | //Function declerations 50 | void displayGrid(Grid &grid, LifeGUI &GUIgrid); 51 | void advanceGrid(Grid &grid, bool wrapping, LifeGUI &GUIgrid); 52 | int countNeighbours(Grid &grid, int row, int col, bool wrapping); 53 | void generateRandomGrid(Grid &grid, LifeGUI &GUIgrid); 54 | 55 | //main function of the program 56 | int main() { 57 | //Variables 58 | string file; 59 | ifstream stream; 60 | string row; 61 | string col; 62 | string toPut; 63 | string wrap; 64 | string choice; 65 | bool wrapAround; 66 | bool random; 67 | int frameNo; 68 | 69 | //Displaying the intro welcome message 70 | cout << WELCOME_MESSAGE; 71 | 72 | //Prompting a file and processing it 73 | random = false; 74 | do { 75 | file = getLine(PROMPT_FILE + RANDOM); 76 | if (file == "random") { //additional code for random world generation 77 | random = true; 78 | } 79 | else if (!isFile(file)) { 80 | cout << FILE_ERROR; 81 | } 82 | } while (!isFile(file) && file != "random"); 83 | LifeGUI GUIgrid; //Grid grid; 84 | Grid grid; 85 | if (random) { 86 | generateRandomGrid(grid, GUIgrid); 87 | } 88 | else { 89 | openFile(stream, file); 90 | //Constructing the grid, using the information in the file 91 | getline(stream, row); 92 | getline(stream, col); 93 | GUIgrid.resize(stringToInteger(row), stringToInteger(col)); 94 | grid.resize(stringToInteger(row), stringToInteger(col)); 95 | //filling the grid accordingly 96 | for (int r = 0; r < grid.numRows(); r++) { 97 | getline(stream, toPut); 98 | for (int c = 0; c < grid.numCols(); c++) { 99 | grid[r][c] = toPut[c]; 100 | } 101 | } 102 | } 103 | //Updating the grid and the menu options 104 | do { 105 | wrap = getLine(OPTIONS); 106 | if (!equalsIgnoreCase(wrap, "y") && !equalsIgnoreCase(wrap, "n")) { 107 | cout << ERROR; 108 | } 109 | } while (!equalsIgnoreCase(wrap, "y") && !equalsIgnoreCase(wrap, "n")); 110 | if (equalsIgnoreCase(wrap, "y")) { 111 | wrapAround = true; 112 | } 113 | else if (equalsIgnoreCase(wrap, "n")) { 114 | wrapAround = false; 115 | } 116 | displayGrid(grid, GUIgrid); 117 | do { 118 | choice = getLine(MENU); 119 | if (equalsIgnoreCase(choice, "a")) { 120 | //animating the pattern 121 | frameNo = getInteger(PROMPT_FRAME_NUMBER); 122 | for (int i = 0; i < frameNo; i++) { 123 | clearConsole(); 124 | advanceGrid(grid, wrapAround, GUIgrid); 125 | pause(PAUSE); 126 | } 127 | } 128 | else if (equalsIgnoreCase(choice, "t")) { 129 | advanceGrid(grid, wrapAround, GUIgrid); 130 | } 131 | else if (equalsIgnoreCase(choice, "q")) {} 132 | else { 133 | cout << ERROR; 134 | } 135 | } while (!equalsIgnoreCase(choice, "q")); 136 | 137 | //ending message 138 | cout << "Have a nice Life!" << endl; 139 | return 0; 140 | } 141 | 142 | /** 143 | * @brief displayGrid Prints the parametrized grid to the console, also displays the GUI 144 | * representation of the grid. 145 | * @param grid The grid that will be printed. 146 | * @param GUIgrid The GUI reference of the grid, which will be displayed. 147 | */ 148 | void displayGrid(Grid &grid, LifeGUI &GUIgrid) { 149 | for (int r = 0; r < grid.numRows(); r++) { 150 | for (int c = 0; c < grid.numCols(); c++) { 151 | cout << grid[r][c]; 152 | if (grid[r][c] == "X") { 153 | GUIgrid.drawCell(r, c, true); 154 | } 155 | else if (grid[r][c] == "-") { 156 | GUIgrid.drawCell(r, c, false); 157 | } 158 | } 159 | cout << endl; 160 | } 161 | } 162 | 163 | /** 164 | * @brief advanceGrid Advances the grid to the next generation based on a bunch of rules, prints it 165 | * to the console and displays it with a GUI. 166 | * @param grid The grid that will be advanced. 167 | * @param wrapping A bool type expression indicating whether the grid is wrapping around 168 | * itself or not. 169 | * @param GUIgrid The GUI reference of the grid, which will be updated to its' next generation. 170 | */ 171 | void advanceGrid(Grid &grid, bool wrapping, LifeGUI &GUIgrid) { 172 | Grid counts(grid.numRows(), grid.numCols()); 173 | for (int r = 0; r < grid.numRows(); r++) { 174 | for (int c = 0; c < grid.numCols(); c++) { 175 | counts[r][c] = countNeighbours(grid, r, c, wrapping); 176 | } 177 | } 178 | for (int r = 0; r < grid.numRows(); r++) { 179 | for (int c = 0; c < grid.numCols(); c++) { 180 | if (counts[r][c] <= 1 || counts[r][c] >= 4) { 181 | GUIgrid.drawCell(r, c, false); 182 | grid[r][c] = "-"; 183 | } 184 | else if (counts[r][c] == 3) { 185 | GUIgrid.drawCell(r, c, true); 186 | grid[r][c] = "X"; 187 | } 188 | } 189 | } 190 | displayGrid(grid, GUIgrid); 191 | } 192 | 193 | /** 194 | * @brief countNeighbours Counts the neighbour cells of a specified one. 195 | * @param grid The grid that contains the cells. 196 | * @param row The row number of the specified cell. 197 | * @param col The column number of the specified cell. 198 | * @param wrapping A bool type expression indicating whether the grid is wrapping around 199 | * itself or not. 200 | * @return The number of neighbours of the specified cell. 201 | */ 202 | int countNeighbours(Grid &grid, int row, int col, bool wrapping) { 203 | int count = 0; 204 | if (!wrapping) { 205 | for (int r = row - 1; r <= row + 1; r++) { 206 | for (int c = col - 1; c <= col + 1; c++) { 207 | if (row != r || col != c) { 208 | if (grid.inBounds(r, c)) { 209 | if (grid[r][c] == "X") { 210 | count++; 211 | } 212 | } 213 | } 214 | } 215 | } 216 | } 217 | else { 218 | int numRows = grid.numRows(); 219 | int numCols = grid.numCols(); 220 | for (int r = row - 1; r <= row + 1; r++) { 221 | for (int c = col - 1; c <= col + 1; c++) { 222 | if (row != r || col != c) { 223 | if (grid.inBounds(r, c)) { 224 | if (grid[r][c] == "X") { 225 | count++; 226 | } 227 | } 228 | else { 229 | if ((r == -1 || r == numRows) && (c == -1 || c == numCols)) { 230 | if (grid[(r + numRows) % numRows][(c + numCols) % numCols] == "X") { 231 | count++; 232 | } 233 | 234 | } 235 | else if (r == -1 || r == numRows) { 236 | if (grid[(r + numRows) % numRows][c] == "X") { 237 | count++; 238 | } 239 | } 240 | else if (c == -1 || c == numCols) { 241 | if (grid[r][(c + numCols) % numCols] == "X") { 242 | count++; 243 | } 244 | } 245 | } 246 | } 247 | } 248 | } 249 | } 250 | return count; 251 | } 252 | 253 | /** 254 | * @brief generateRandomGrid The function generates a randomly sized and randomly filled grid of 255 | * dead and living cells. This one is a part of extensions. 256 | * @param grid The referenced grid that will be randomly sized and filled. 257 | * @param GUIgrid The GUI reference of the grid that will be updated. 258 | */ 259 | void generateRandomGrid(Grid &grid, LifeGUI &GUIgrid) { 260 | int randomRow = randomInteger(1, 50); 261 | int randomCol = randomInteger(1, 50); 262 | GUIgrid.resize(randomRow, randomCol); 263 | grid.resize(randomRow, randomCol); 264 | int possibility = randomInteger(1, 20); //random possibility 265 | //placing the living cells to the grid 266 | for (int r = 0; r < grid.numRows(); r++) { 267 | for (int c = 0; c < grid.numCols(); c++) { 268 | if (randomInteger(1, 20) <= possibility) { //placing the living cells depending on the random 269 | GUIgrid.drawCell(r, c, true); //possibility 270 | grid[r][c] = "X"; 271 | } 272 | else { 273 | GUIgrid.drawCell(r, c, false); 274 | grid[r][c] = "-"; 275 | } 276 | } 277 | } 278 | } 279 | 280 | 281 | -------------------------------------------------------------------------------- /Assignment1/life.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This program is a console based simulation of "The Game of Life", which is indeed 3 | * a simulation for modelling the life cycle of bacteria using a two-dimensional grid 4 | * of cells. The game simulates the birth and death of future generations based on 5 | * an initial pattern and some simple rules. The code involves variables and fuctions 6 | * to model the game. 7 | * @author EFE ACER 8 | * CS106B - Section Leader: Ryan Kurohara 9 | */ 10 | 11 | //necessary includes 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "console.h" 19 | #include "filelib.h" 20 | #include "grid.h" 21 | #include "gwindow.h" 22 | #include "simpio.h" 23 | #include "strlib.h" 24 | #include "lifegui.h" 25 | using namespace std; 26 | 27 | //Constant declerations (for further changes) 28 | const string WELCOME_MESSAGE = "Welcome to the CS 106B Game of Life,\n" 29 | "a simulation of the lifecycle of a bacteria colony.\n" 30 | "Cells (X) live and die by the following rules:\n" 31 | "- A cell with 1 or fewer neighbors dies.\n" 32 | "- Locations with 2 neighbors remain stable.\n" 33 | "- Locations with 3 neighbors will create life.\n" 34 | "- A cell with 4 or more neighbors dies.\n\n"; 35 | const string PROMPT_FILE = "Grid input file name? "; 36 | const string FILE_ERROR = "Unable to open that file. Try again.\n"; 37 | const string OPTIONS = "Should the simulation wrap around the grid (y/n)? "; 38 | const string MENU = "a)nimate, t)ick, q)uit? "; 39 | const string PROMPT_FRAME_NUMBER = "How many frames? "; 40 | const string ERROR = "Invalid choice; please try again.\n"; 41 | const int PAUSE = 50; 42 | 43 | //Function declerations 44 | void displayGrid(Grid &grid); 45 | void advanceGrid(Grid &grid, bool wrapping); 46 | int countNeighbours(Grid &grid, int row, int col, bool wrapping); 47 | 48 | int main() { 49 | //Variables 50 | string file; 51 | ifstream stream; 52 | string row; 53 | string col; 54 | string toPut; 55 | string wrap; 56 | string choice; 57 | bool wrapAround; 58 | int frameNo; 59 | 60 | //Displaying the intro welcome message 61 | cout << WELCOME_MESSAGE; 62 | 63 | //Prompting a file and processing it 64 | do { 65 | file = getLine(PROMPT_FILE); 66 | if (!isFile(file)) { 67 | cout << FILE_ERROR; 68 | } 69 | } while (!isFile(file)); 70 | openFile(stream, file); 71 | //Constructing the grid, using the information in the file 72 | getline(stream, row); 73 | getline(stream, col); 74 | Grid grid(stringToInteger(row), stringToInteger(col)); 75 | //filling the grid accordingly 76 | for (int r = 0; r < grid.numRows(); r++) { 77 | getline(stream, toPut); 78 | for (int c = 0; c < grid.numCols(); c++) { 79 | grid[r][c] = toPut[c]; 80 | } 81 | } 82 | 83 | //Updating the grid and the menu options 84 | do { 85 | wrap = getLine(OPTIONS); 86 | if (!equalsIgnoreCase(wrap, "y") && !equalsIgnoreCase(wrap, "n")) { 87 | cout << ERROR; 88 | } 89 | } while (!equalsIgnoreCase(wrap, "y") && !equalsIgnoreCase(wrap, "n")); 90 | if (equalsIgnoreCase(wrap, "y")) { 91 | wrapAround = true; 92 | } 93 | else if (equalsIgnoreCase(wrap, "n")) { 94 | wrapAround = false; 95 | } 96 | displayGrid(grid); 97 | do { 98 | choice = getLine(MENU); 99 | if (equalsIgnoreCase(choice, "a")) { 100 | //animating the pattern 101 | frameNo = getInteger(PROMPT_FRAME_NUMBER); 102 | for (int i = 0; i < frameNo; i++) { 103 | clearConsole(); 104 | advanceGrid(grid, wrapAround); 105 | pause(PAUSE); 106 | } 107 | } 108 | else if (equalsIgnoreCase(choice, "t")) { 109 | advanceGrid(grid, wrapAround); 110 | } 111 | else if (equalsIgnoreCase(choice, "q")) {} 112 | else { 113 | cout << ERROR; 114 | } 115 | } while (!equalsIgnoreCase(choice, "q")); 116 | 117 | //ending message 118 | cout << "Have a nice Life!" << endl; 119 | return 0; 120 | } 121 | 122 | /** 123 | * @brief displayGrid Prints the parametrized grid to the console. 124 | * @param grid The grid that will be printed. 125 | */ 126 | void displayGrid(Grid &grid) { 127 | for (int r = 0; r < grid.numRows(); r++) { 128 | for (int c = 0; c < grid.numCols(); c++) { 129 | cout << grid[r][c]; 130 | } 131 | cout << endl; 132 | } 133 | } 134 | 135 | /** 136 | * @brief advanceGrid Advances the grid to the next generation based on a bunch of rules. 137 | * @param grid The grid that will be advanced. 138 | * @param wrapping A bool type expression indicating whether the grid is wrapping around 139 | * itself or not. 140 | */ 141 | void advanceGrid(Grid &grid, bool wrapping) { 142 | Grid counts(grid.numRows(), grid.numCols()); 143 | for (int r = 0; r < grid.numRows(); r++) { 144 | for (int c = 0; c < grid.numCols(); c++) { 145 | counts[r][c] = countNeighbours(grid, r, c, wrapping); 146 | } 147 | } 148 | for (int r = 0; r < grid.numRows(); r++) { 149 | for (int c = 0; c < grid.numCols(); c++) { 150 | if (counts[r][c] <= 1 || counts[r][c] >= 4) { 151 | grid.set(r, c, "-"); 152 | } 153 | else if (counts[r][c] == 3) { 154 | grid.set(r, c, "X"); 155 | } 156 | } 157 | } 158 | displayGrid(grid); 159 | } 160 | 161 | /** 162 | * @brief countNeighbours Counts the neighbour cells of a specified one. 163 | * @param grid The grid that contains the cells. 164 | * @param row The row number of the specified cell. 165 | * @param col The column number of the specified cell. 166 | * @param wrapping A bool type expression indicating whether the grid is wrapping around 167 | * itself or not. 168 | * @return The number of neighbours of the specified cell. 169 | */ 170 | int countNeighbours(Grid &grid, int row, int col, bool wrapping) { 171 | int count = 0; 172 | if (!wrapping) { 173 | for (int r = row - 1; r <= row + 1; r++) { 174 | for (int c = col - 1; c <= col + 1; c++) { 175 | if (row != r || col != c) { 176 | if (grid.inBounds(r, c)) { 177 | if (grid[r][c] == "X") { 178 | count++; 179 | } 180 | } 181 | } 182 | } 183 | } 184 | } 185 | else { 186 | int numRows = grid.numRows(); 187 | int numCols = grid.numCols(); 188 | for (int r = row - 1; r <= row + 1; r++) { 189 | for (int c = col - 1; c <= col + 1; c++) { 190 | if (row != r || col != c) { 191 | if (grid.inBounds(r, c)) { 192 | if (grid[r][c] == "X") { 193 | count++; 194 | } 195 | } 196 | else { 197 | if ((r == -1 || r == numRows) && (c == -1 || c == numCols)) { 198 | if (grid[(r + numRows) % numRows][(c + numCols) % numCols] == "X") { 199 | count++; 200 | } 201 | 202 | } 203 | else if (r == -1 || r == numRows) { 204 | if (grid[(r + numRows) % numRows][c] == "X") { 205 | count++; 206 | } 207 | } 208 | else if (c == -1 || c == numCols) { 209 | if (grid[r][(c + numCols) % numCols] == "X") { 210 | count++; 211 | } 212 | } 213 | } 214 | } 215 | } 216 | } 217 | } 218 | return count; 219 | } 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /Assignment1/mycolony.txt: -------------------------------------------------------------------------------- 1 | 10 2 | 20 3 | -------------------- 4 | ----X--------------- 5 | ---X-X-------X--X--- 6 | ---X--X----X-X-----X 7 | X--------X-X--X--X-- 8 | XX-------X-X--X--X-- 9 | X---X--X----X-X----- 10 | ---X-X-------X--X--- 11 | ----X--------------- 12 | -------------------- 13 | 14 | -------------------------------------------------------------------------------- /Assignment2/myinput.txt: -------------------------------------------------------------------------------- 1 | I am honored to be with you today at your commencement from one of the finest universities in the 2 | world. I never graduated from college. Truth be told, this is the closest I've ever gotten to a college 3 | graduation. Today I want to tell you three stories from my life. That's it. No big deal. Just three 4 | stories. 5 | The first story is about connecting the dots. 6 | I dropped out of Reed College after the first 6 months, but then stayed around as a drop-in for 7 | another 18 months or so before I really quit. So why did I drop out? 8 | It started before I was born. My biological mother was a young, unwed college graduate student, 9 | and she decided to put me up for adoption. She felt very strongly that I should be adopted by 10 | college graduates, so everything was all set for me to be adopted at birth by a lawyer and his wife. 11 | Except that when I popped out they decided at the last minute that they really wanted a girl. So my 12 | parents, who were on a waiting list, got a call in the middle of the night asking: "We have an 13 | unexpected baby boy; do you want him?" They said: "Of course." My biological mother later found 14 | out that my mother had never graduated from college and that my father had never graduated from 15 | high school. She refused to sign the final adoption papers. She only relented a few months later 16 | when my parents promised that I would someday go to college. 17 | And 17 years later I did go to college. But I naively chose a college that was almost as expensive 18 | as Stanford, and all of my working-class parents' savings were being spent on my college tuition. 19 | After six months, I couldn't see the value in it. I had no idea what I wanted to do with my life and no 20 | idea how college was going to help me figure it out. And here I was spending all of the money my 21 | parents had saved their entire life. So I decided to drop out and trust that it would all work out OK. 22 | It was pretty scary at the time, but looking back it was one of the best decisions I ever made. The 23 | minute I dropped out I could stop taking the required classes that didn't interest me, and begin 24 | dropping in on the ones that looked interesting. 25 | It wasn't all romantic. I didn't have a dorm room, so I slept on the floor in friends' rooms, I returned 26 | coke bottles for the 5¢ deposits to buy food with, and I would walk the 7 miles across town every 27 | Sunday night to get one good meal a week at the Hare Krishna temple. I loved it. And much of 28 | what I stumbled into by following my curiosity and intuition turned out to be priceless later on. Let 29 | me give you one example: 30 | Reed College at that time offered perhaps the best calligraphy instruction in the country. 31 | Throughout the campus every poster, every label on every drawer, was beautifully hand 32 | calligraphed. Because I had dropped out and didn't have to take the normal classes, I decided to 33 | take a calligraphy class to learn how to do this. I learned about serif and san serif typefaces, about 34 | varying the amount of space between different letter combinations, about what makes great 35 | typography great. It was beautiful, historical, artistically subtle in a way that science can't capture, 36 | and I found it fascinating. 37 | None of this had even a hope of any practical application in my life. But ten years later, when we 38 | were designing the first Macintosh computer, it all came back to me. And we designed it all into the 39 | Mac. It was the first computer with beautiful typography. If I had never dropped in on that single 40 | course in college, the Mac would have never had multiple typefaces or proportionally spaced fonts. 41 | And since Windows just copied the Mac, its likely that no personal computer would have them. If I 42 | had never dropped out, I would have never dropped in on this calligraphy class, and personal 43 | computers might not have the wonderful typography that they do. Of course it was impossible to 44 | connect the dots looking forward when I was in college. But it was very, very clear looking 45 | backwards ten years later. 46 | Again, you can't connect the dots looking forward; you can only connect them looking backwards. 47 | So you have to trust that the dots will somehow connect in your future. You have to trust in 48 | something — your gut, destiny, life, karma, whatever. This approach has never let me down, and it 49 | has made all the difference in my life. 50 | My second story is about love and loss. 51 | I was lucky — I found what I loved to do early in life. Woz and I started Apple in my parents garage 52 | when I was 20. We worked hard, and in 10 years Apple had grown from just the two of us in a 53 | garage into a $2 billion company with over 4000 employees. We had just released our finest 54 | creation — the Macintosh — a year earlier, and I had just turned 30. And then I got fired. How can 55 | you get fired from a company you started? Well, as Apple grew we hired someone who I thought 56 | was very talented to run the company with me, and for the first year or so things went well. But 57 | then our visions of the future began to diverge and eventually we had a falling out. When we did, 58 | our Board of Directors sided with him. So at 30 I was out. And very publicly out. What had been the 59 | focus of my entire adult life was gone, and it was devastating. 60 | I really didn't know what to do for a few months. I felt that I had let the previous generation of 61 | entrepreneurs down - that I had dropped the baton as it was being passed to me. I met with David 62 | Packard and Bob Noyce and tried to apologize for screwing up so badly. I was a very public failure, 63 | and I even thought about running away from the valley. But something slowly began to dawn on 64 | me — I still loved what I did. The turn of events at Apple had not changed that one bit. I had been 65 | rejected, but I was still in love. And so I decided to start over. 66 | I didn't see it then, but it turned out that getting fired from Apple was the best thing that could have 67 | ever happened to me. The heaviness of being successful was replaced by the lightness of being a 68 | beginner again, less sure about everything. It freed me to enter one of the most creative periods of 69 | my life. 70 | During the next five years, I started a company named NeXT, another company named Pixar, and 71 | fell in love with an amazing woman who would become my wife. Pixar went on to create the worlds 72 | first computer animated feature film, Toy Story, and is now the most successful animation studio in 73 | the world. In a remarkable turn of events, Apple bought NeXT, I returned to Apple, and the 74 | technology we developed at NeXT is at the heart of Apple's current renaissance. And Laurene and 75 | I have a wonderful family together. 76 | I'm pretty sure none of this would have happened if I hadn't been fired from Apple. It was awful 77 | tasting medicine, but I guess the patient needed it. Sometimes life hits you in the head with a brick. 78 | Don't lose faith. I'm convinced that the only thing that kept me going was that I loved what I did. 79 | You've got to find what you love. And that is as true for your work as it is for your lovers. Your work 80 | is going to fill a large part of your life, and the only way to be truly satisfied is to do what you 81 | believe is great work. And the only way to do great work is to love what you do. If you haven't 82 | found it yet, keep looking. Don't settle. As with all matters of the heart, you'll know when you find it. 83 | And, like any great relationship, it just gets better and better as the years roll on. So keep looking 84 | until you find it. Don't settle. 85 | My third story is about death. 86 | When I was 17, I read a quote that went something like: "If you live each day as if it was your last, 87 | someday you'll most certainly be right". It made an impression on me, and since then, for the past 88 | 33 years, I have looked in the mirror every morning and asked myself: "If today were the last day of 89 | my life, would I want to do what I am about to do today?" And whenever the answer has been "No" 90 | for too many days in a row, I know I need to change something. 91 | Remembering that I'll be dead soon is the most important tool I've ever encountered to help me 92 | make the big choices in life. Because almost everything — all external expectations, all pride, all 93 | fear of embarrassment or failure - these things just fall away in the face of death, leaving only what 94 | is truly important. Remembering that you are going to die is the best way I know to avoid the trap 95 | of thinking you have something to lose. You are already naked. There is no reason not to follow 96 | your heart. 97 | About a year ago I was diagnosed with cancer. I had a scan at 7:30 in the morning, and it clearly 98 | showed a tumor on my pancreas. I didn't even know what a pancreas was. The doctors told me 99 | this was almost certainly a type of cancer that is incurable, and that I should expect to live no 100 | longer than three to six months. My doctor advised me to go home and get my affairs in order, 101 | which is doctor's code for prepare to die. It means to try to tell your kids everything you thought 102 | you'd have the next 10 years to tell them in just a few months. It means to make sure everything is 103 | buttoned up so that it will be as easy as possible for your family. It means to say your goodbyes. 104 | I lived with that diagnosis all day. Later that evening I had a biopsy, where they stuck an 105 | endoscope down my throat, through my stomach and into my intestines, put a needle into my 106 | pancreas and got a few cells from the tumor. I was sedated, but my wife, who was there, told me 107 | that when they viewed the cells under a microscope the doctors started crying because it turned 108 | out to be a very rare form of pancreatic cancer that is curable with surgery. I had the surgery and 109 | I'm fine now. 110 | This was the closest I've been to facing death, and I hope its the closest I get for a few more 111 | decades. Having lived through it, I can now say this to you with a bit more certainty than when 112 | death was a useful but purely intellectual concept: 113 | No one wants to die. Even people who want to go to heaven don't want to die to get there. And yet 114 | death is the destination we all share. No one has ever escaped it. And that is as it should be, 115 | because Death is very likely the single best invention of Life. It is Life's change agent. It clears out 116 | the old to make way for the new. Right now the new is you, but someday not too long from now, 117 | you will gradually become the old and be cleared away. Sorry to be so dramatic, but it is quite true. 118 | Your time is limited, so don't waste it living someone else's life. Don't be trapped by dogma — 119 | which is living with the results of other people's thinking. Don't let the noise of others' opinions 120 | drown out your own inner voice. And most important, have the courage to follow your heart and 121 | intuition. They somehow already know what you truly want to become. Everything else is 122 | secondary. 123 | When I was young, there was an amazing publication called The Whole Earth Catalog, which was 124 | one of the bibles of my generation. It was created by a fellow named Stewart Brand not far from 125 | here in Menlo Park, and he brought it to life with his poetic touch. This was in the late 1960's, 126 | before personal computers and desktop publishing, so it was all made with typewriters, scissors, 127 | and polaroid cameras. It was sort of like Google in paperback form, 35 years before Google came 128 | along: it was idealistic, and overflowing with neat tools and great notions. 129 | Stewart and his team put out several issues of The Whole Earth Catalog, and then when it had run 130 | its course, they put out a final issue. It was the mid-1970s, and I was your age. On the back cover 131 | of their final issue was a photograph of an early morning country road, the kind you might find 132 | yourself hitchhiking on if you were so adventurous. Beneath it were the words: "Stay Hungry. Stay 133 | Foolish." It was their farewell message as they signed off. Stay Hungry. Stay Foolish. And I have 134 | always wished that for myself. And now, as you graduate to begin anew, I wish that for you. 135 | Stay Hungry. Stay Foolish. 136 | Thank you all very much. 137 | -------------------------------------------------------------------------------- /Assignment2/ngrams.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This program is a console based random text generator. The program code generates random text 3 | * from the information on a file. The generated sounds just like the author of the input text 4 | * because random text generation works like a Markov chain that each element is placed 5 | * according to its weighted probability. The code below involves functions and variables to 6 | * store and produce text. 7 | * @author EFE ACER 8 | * CS106B - Section Leader: Ryan Kurohara 9 | */ 10 | 11 | //necessary includes 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "console.h" 18 | #include "filelib.h" 19 | #include "simpio.h" 20 | #include "map.h" 21 | #include "vector.h" 22 | #include "random.h" 23 | 24 | using namespace std; 25 | 26 | //constant declerations for further editing 27 | const string INTRO = "Welcome to CS 106B Random Writer ('N-Grams').\n" 28 | "This program makes random text based on a document.\n" 29 | "Give me an input file and an 'N' value for groups\n" 30 | "of words, and I'll create random text for you.\n\n"; 31 | const string PROMPT_FILE = "Input file name? "; 32 | const string PROMPT_N = "Value of N? "; 33 | const string PROMPT_RANDOM_WORD_NUMBER = "# of random words to generate (0 to quit)? "; 34 | const string N_ERROR = "N must be 2 or greater.\n"; 35 | const string RANDOM_WORD_NUMBER_ERROR = "Must be at least 4 words.\n\n"; 36 | const string FILE_ERROR = "Unable to open that file. Try again.\n"; 37 | 38 | //function declerations 39 | void promptFile(string &file); 40 | void promptN(int &N); 41 | void promptRandomWordNumber(int &randomWordNumber); 42 | Vector getWords(string &file); 43 | Map, Vector> getNGramMap(Vector &words, int &N); 44 | void printVector(Vector &vec); 45 | void printRandomText(Map, Vector> &NGramMap, int &randomWordNumber, int &N); 46 | 47 | //main function 48 | int main() { 49 | cout << INTRO; //displaying the intro welcome message 50 | string file; 51 | promptFile(file); 52 | Vector words = getWords(file); //storing the words in the file 53 | int N; //asking for N 54 | promptN(N); 55 | Map, Vector> NGramMap = getNGramMap(words, N); //storing the map 56 | cout << endl; 57 | int randomWordNumber; 58 | do { 59 | promptRandomWordNumber(randomWordNumber); 60 | if (randomWordNumber != 0) { 61 | printRandomText(NGramMap, randomWordNumber, N); 62 | cout << endl; 63 | } 64 | } while (randomWordNumber != 0); 65 | cout << "Exiting." << endl; 66 | return 0; 67 | } 68 | 69 | /** 70 | * @brief promptFile Asks for a valid file name. Prints error messages if neccessary. 71 | * @param file A reference to the file name's string. 72 | */ 73 | void promptFile(string &file) { 74 | do { //promting a file and processing it 75 | file = getLine(PROMPT_FILE); 76 | if (!isFile(file)) { 77 | cout << FILE_ERROR; 78 | } 79 | } while (!isFile(file)); 80 | } 81 | 82 | /** 83 | * @brief promptN Asks for a valid N. Prints error messages if neccessary. 84 | * @param N A reference to the integer N. 85 | */ 86 | void promptN(int &N) { 87 | do { //asking for a valid value for N 88 | N = getInteger(PROMPT_N); 89 | if (N < 2) { 90 | cout << N_ERROR; 91 | } 92 | } while (N < 2); 93 | } 94 | 95 | /** 96 | * @brief promptRandomWordNumber Asks for a valid number for the random words. Prints 97 | * error messages if necessary. 98 | * @param randomWordNumber A reference to the integer storing the number of random 99 | * words. 100 | */ 101 | void promptRandomWordNumber(int &randomWordNumber) { 102 | do { 103 | randomWordNumber = getInteger(PROMPT_RANDOM_WORD_NUMBER); 104 | if (randomWordNumber != 0 && randomWordNumber < 4) { 105 | cout << RANDOM_WORD_NUMBER_ERROR; 106 | } 107 | } while (randomWordNumber != 0 && randomWordNumber < 4); 108 | } 109 | 110 | /** 111 | * @brief getWords Returns the words in a file as a Vector, reading one word at a time 112 | * @param file The file to read. 113 | * @return The collection (Vector) containing the words in the file. 114 | */ 115 | Vector getWords(string &file) { 116 | ifstream input; 117 | openFile(input, file); 118 | Vector words; 119 | string word; 120 | while (input >> word) { 121 | words.add(word); 122 | } 123 | return words; 124 | } 125 | 126 | /** 127 | * @brief getNGramMap Returns a Map, where each element is placed according to 128 | * its weighted probability (A Markov chain) 129 | * @param words The Vector containing all the words needed to generate the Map. 130 | * @param N is the number indicating the length of the Vectors in the 131 | * keys Vector of the Map. 132 | * @return The Map that is containing all the words and the probability information 133 | * (frequencies) needed to generate random text. 134 | */ 135 | Map, Vector> getNGramMap(Vector &words, int &N) { 136 | Map, Vector> NGramMap; 137 | Vector window; 138 | Vector values; 139 | for (int i = 0; i < words.size(); i++) { 140 | for (int j = i; j < i + N - 1; j++) { 141 | if (j >= words.size()) { //the case for wrapping 142 | window.add(words.get(j % words.size())); 143 | } 144 | else { 145 | window.add(words.get(j)); 146 | } 147 | } 148 | if (NGramMap.containsKey(window)) { 149 | values = NGramMap.get(window); 150 | } 151 | else { 152 | values.clear(); 153 | } 154 | if (i + N - 1 >= words.size()) { 155 | values.add(words.get((i + N - 1) % words.size())); //the case for wrapping 156 | NGramMap.put(window, values); 157 | } 158 | else { 159 | values.add(words.get(i + N - 1)); 160 | NGramMap.put(window, values); 161 | } 162 | window.clear(); 163 | } 164 | return NGramMap; 165 | } 166 | 167 | /** 168 | * @brief printVector Prints a Vector as desired. 169 | * @param vec The Vector to print. 170 | */ 171 | void printVector(Vector &vec) { 172 | for (string word: vec) { 173 | cout << word << " "; 174 | } 175 | } 176 | 177 | /** 178 | * @brief printRandomText Prints a random text using the Map containg the words according to 179 | * their frequencies. 180 | * @param NGramMap A reference to the Map, which contains words and information. 181 | * @param randomWordNumber Number of random words to be generated. 182 | * @param N The number determining the similarity between the actual text and the random text. 183 | */ 184 | void printRandomText(Map, Vector> &NGramMap, int &randomWordNumber, int &N) { 185 | Vector vec = NGramMap.keys().get(randomInteger(0, NGramMap.keys().size() - 1)); 186 | cout << "... "; 187 | printVector(vec); 188 | string value; 189 | for (int i = N - 1; i < randomWordNumber; i++) { 190 | value = NGramMap.get(vec).get(randomInteger(0, NGramMap.get(vec).size() - 1)); 191 | cout << value << " "; 192 | vec.remove(0); 193 | vec.add(value); 194 | } 195 | cout << "..." << endl; 196 | } 197 | 198 | -------------------------------------------------------------------------------- /Assignment2/ngrams_extra.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * INVOLVES EXTRA FEATURES 3 | * This program is a console based random text generator. The program code generates random text 4 | * from the information on a file. The generated sounds just like the author of the input text 5 | * because random text generation works like a Markov chain that each element is placed 6 | * according to its weighted probability. The code below involves functions and variables to 7 | * store and produce text. 8 | * Extensions: 9 | * Full sentence generation: changed getNGramMap and printRandomText functions. 10 | * @author EFE ACER 11 | * CS106B - Section Leader: Ryan Kurohara 12 | */ 13 | 14 | //necessary includes 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "console.h" 21 | #include "filelib.h" 22 | #include "simpio.h" 23 | #include "map.h" 24 | #include "vector.h" 25 | #include "random.h" 26 | 27 | using namespace std; 28 | 29 | //constant declerations for further editing 30 | const string INTRO = "Welcome to CS 106B Random Writer ('N-Grams').\n" 31 | "This program makes random text based on a document.\n" 32 | "Give me an input file and an 'N' value for groups\n" 33 | "of words, and I'll create random text for you.\n\n"; 34 | const string PROMPT_FILE = "Input file name? "; 35 | const string PROMPT_N = "Value of N? "; 36 | const string PROMPT_RANDOM_WORD_NUMBER = "# of random words to generate (0 to quit)? "; 37 | const string N_ERROR = "N must be 2 or greater.\n"; 38 | const string RANDOM_WORD_NUMBER_ERROR = "Must be at least 4 words.\n\n"; 39 | const string FILE_ERROR = "Unable to open that file. Try again.\n"; 40 | 41 | //function declerations 42 | void promptFile(string &file); 43 | void promptN(int &N); 44 | void promptRandomWordNumber(int &randomWordNumber); 45 | Vector getWords(string &file); 46 | Map, Vector> getNGramMap(Vector &words, int &N, Vector > &startWords, Vector > &endWords); 47 | void printVector(Vector &vec); 48 | void printRandomText(Map, Vector> &NGramMap, int &randomWordNumber, int &N, Vector > &startWords, Vector > &endWords); 49 | 50 | //main function 51 | int main() { 52 | cout << INTRO; //displaying the intro welcome message 53 | string file; 54 | promptFile(file); 55 | Vector words = getWords(file); //storing the words in the file 56 | int N; //asking for N 57 | promptN(N); 58 | Vector> startWords, endWords; 59 | Map, Vector> NGramMap = getNGramMap(words, N, startWords, endWords); //storing the map 60 | cout << endl; 61 | int randomWordNumber; 62 | do { 63 | promptRandomWordNumber(randomWordNumber); 64 | if (randomWordNumber != 0) { 65 | printRandomText(NGramMap, randomWordNumber, N, startWords, endWords); 66 | cout << endl; 67 | } 68 | } while (randomWordNumber != 0); 69 | cout << "Exiting." << endl; 70 | return 0; 71 | } 72 | 73 | /** 74 | * @brief promptFile Asks for a valid file name. Prints error messages if neccessary. 75 | * @param file A reference to the file name's string. 76 | */ 77 | void promptFile(string &file) { 78 | do { //promting a file and processing it 79 | file = getLine(PROMPT_FILE); 80 | if (!isFile(file)) { 81 | cout << FILE_ERROR; 82 | } 83 | } while (!isFile(file)); 84 | } 85 | 86 | /** 87 | * @brief promptN Asks for a valid N. Prints error messages if neccessary. 88 | * @param N A reference to the integer N. 89 | */ 90 | void promptN(int &N) { 91 | do { //asking for a valid value for N 92 | N = getInteger(PROMPT_N); 93 | if (N < 2) { 94 | cout << N_ERROR; 95 | } 96 | } while (N < 2); 97 | } 98 | 99 | /** 100 | * @brief promptRandomWordNumber Asks for a valid number for the random words. Prints 101 | * error messages if necessary. 102 | * @param randomWordNumber A reference to the integer storing the number of random 103 | * words. 104 | */ 105 | void promptRandomWordNumber(int &randomWordNumber) { 106 | do { 107 | randomWordNumber = getInteger(PROMPT_RANDOM_WORD_NUMBER); 108 | if (randomWordNumber != 0 && randomWordNumber < 4) { 109 | cout << RANDOM_WORD_NUMBER_ERROR; 110 | } 111 | } while (randomWordNumber != 0 && randomWordNumber < 4); 112 | } 113 | 114 | /** 115 | * @brief getWords Returns the words in a file as a Vector, reading one word at a time 116 | * @param file The file to read. 117 | * @return The collection (Vector) containing the words in the file. 118 | */ 119 | Vector getWords(string &file) { 120 | ifstream input; 121 | openFile(input, file); 122 | Vector words; 123 | string word; 124 | while (input >> word) { 125 | words.add(word); 126 | } 127 | return words; 128 | } 129 | 130 | /** 131 | * @brief getNGramMap Returns a Map, where each element is placed according to 132 | * its weighted probability (A Markov chain) 133 | * @param words The Vector containing all the words needed to generate the Map. 134 | * @param N is the number indicating the length of the Vectors in the 135 | * keys Vector of the Map. 136 | * @param startWords the words that start the sentences. 137 | * @param endWords the words that end the sentences. 138 | * @return The Map that is containing all the words and the probability information 139 | * (frequencies) needed to generate random text. 140 | */ 141 | Map, Vector> getNGramMap(Vector &words, int &N, Vector> &startWords, 142 | Vector> &endWords) { 143 | Map, Vector> NGramMap; 144 | Vector window; 145 | Vector values; 146 | for (int i = 0; i < words.size(); i++) { 147 | for (int j = i; j < i + N - 1; j++) { 148 | if (j >= words.size()) { //the case for wrapping 149 | window.add(words.get(j % words.size())); 150 | } 151 | else { 152 | window.add(words.get(j)); 153 | } 154 | } 155 | if (NGramMap.containsKey(window)) { 156 | values = NGramMap.get(window); 157 | } 158 | else { 159 | values.clear(); 160 | } 161 | if (i + N - 1 >= words.size()) { 162 | values.add(words.get((i + N - 1) % words.size())); //the case for wrapping 163 | NGramMap.put(window, values); 164 | } 165 | else { 166 | values.add(words.get(i + N - 1)); 167 | NGramMap.put(window, values); 168 | } 169 | if (charToString(window.get(0)[0]) == toUpperCase(charToString(window.get(0)[0]))) { 170 | startWords.add(window); 171 | } 172 | char check = window.get(window.size() - 1)[window.get(window.size() - 1).length() - 1]; 173 | if (check == '.' || check == '!' || check == '?') { 174 | endWords.add(window); 175 | } 176 | window.clear(); 177 | } 178 | return NGramMap; 179 | } 180 | 181 | /** 182 | * @brief printVector Prints a Vector as desired. 183 | * @param vec The Vector to print. 184 | */ 185 | void printVector(Vector &vec) { 186 | for (string word: vec) { 187 | cout << word << " "; 188 | } 189 | } 190 | 191 | /** 192 | * @brief printRandomText Prints a random text using the Map containg the words according to 193 | * their frequencies. 194 | * @param NGramMap A reference to the Map, which contains words and information. 195 | * @param randomWordNumber Number of random words to be generated. 196 | * @param startWords the words that start the sentences. 197 | * @param endWords the words that end the sentences. 198 | * @param N The number determining the similarity between the actual text and the random text. 199 | */ 200 | void printRandomText(Map, Vector> &NGramMap, int &randomWordNumber, int &N, 201 | Vector> &startWords, Vector> &endWords) { 202 | if (!startWords.isEmpty() && !endWords.isEmpty()) 203 | { 204 | Vector vec = startWords.get(randomInteger(0, startWords.size() - 1)); 205 | printVector(vec); 206 | string value; 207 | for (int i = N - 1; i < randomWordNumber; i++) { 208 | value = NGramMap.get(vec).get(randomInteger(0, NGramMap.get(vec).size() - 1)); 209 | cout << value << " "; 210 | vec.remove(0); 211 | vec.add(value); 212 | } 213 | char check = vec.get(vec.size() - 1)[vec[vec.size() - 1].length() - 1]; 214 | while (check != '.' && check != '!' && check != '?') { 215 | value = NGramMap.get(vec).get(randomInteger(0, NGramMap.get(vec).size() - 1)); 216 | cout << value << " "; 217 | vec.remove(0); 218 | vec.add(value); 219 | check = vec.get(vec.size() - 1)[vec[vec.size() - 1].length() - 1]; 220 | } 221 | cout << endl; 222 | } 223 | else { 224 | Vector vec = NGramMap.keys().get(randomInteger(0, NGramMap.keys().size() - 1)); 225 | cout << "... "; 226 | printVector(vec); 227 | string value; 228 | for (int i = N - 1; i < randomWordNumber; i++) { 229 | value = NGramMap.get(vec).get(randomInteger(0, NGramMap.get(vec).size() - 1)); 230 | cout << value << " "; 231 | vec.remove(0); 232 | vec.add(value); 233 | } 234 | cout << "..." << endl; 235 | } 236 | } 237 | 238 | -------------------------------------------------------------------------------- /Assignment2/wordladder.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This program is a console based game in which you enter an initial word and a destination 3 | * word. Then the program generates and displays a word ladder from the initial word to the 4 | * destination word. A word ladder is the shortest path generated by the meaningful words 5 | * that are different by their ancestors by a single letter. Following code involves functions 6 | * to produce, check and print the word ladder. 7 | * @author EFE ACER 8 | * CS106B - Section Leader: Ryan Kurohara 9 | */ 10 | 11 | //necessary includes 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "console.h" 18 | #include "filelib.h" 19 | #include "simpio.h" 20 | #include "lexicon.h" 21 | #include "queue.h" 22 | #include "stack.h" 23 | #include "hashset.h" 24 | 25 | using namespace std; 26 | 27 | //constant declerations for further editing 28 | const string INTRO = "Welcome to CS 106B Word Ladder.\n" 29 | "Please give me two English words, and I will change the\n" 30 | "first into the second by changing one letter at a time.\n\n"; 31 | const string FILE_PROMPT = "Dictionary file name? "; 32 | const string WORD1_PROMPT = "\nWord #1 (or Enter to quit): "; 33 | const string WORD2_PROMPT = "Word #2 (or Enter to quit): "; 34 | const string LADDER_DISPLAY = "A ladder from back to :\n"; 35 | const string LADDER_NOT_FOUND = "No word ladder found from back to .\n"; 36 | const string WORD_LENGTH_ERROR = "The two words must be the same length.\n"; 37 | const string NOT_FOUND_ERROR = "The two words must be found in the dictionary.\n"; 38 | const string SAME_WORD_ERROR = "The two words must be different.\n"; 39 | const string FILE_ERROR = "Unable to open that file. Try again.\n"; 40 | const string ALPHABET = "abcdefghijklmnopqrstuvwxyz"; 41 | 42 | //function declerations 43 | bool getWords(Lexicon &englishWords, string &word1, string &word2); 44 | Lexicon getLexiconFromFile(string &file); 45 | bool checkWords(Lexicon &words, string &word1, string &word2); 46 | Stack findShortestPath(Lexicon &words, string &word1, string &word2); 47 | HashSet findNeighbors(Lexicon &words, string word); 48 | void displayLadder(Stack &stack, string &word1, string &word2); 49 | 50 | //main function 51 | int main() { 52 | cout << INTRO; //displaying the intro welcome message 53 | string file; 54 | Lexicon englishWords = getLexiconFromFile(file); //generating a lexicon from a file containing words 55 | string word1, word2; 56 | bool quit; 57 | do { 58 | quit = getWords(englishWords, word1, word2); //getting the words till the user decides not to enter them 59 | if (!quit) { 60 | Stack toDisplay = findShortestPath(englishWords, word1, word2); 61 | displayLadder(toDisplay, word1, word2); //displays the ladder 62 | } 63 | } while (!quit); 64 | cout << "Have a nice day." << endl; 65 | return 0; 66 | } 67 | 68 | /** 69 | * @brief getWords Asks for the initial word and the destination word, prints specific error messages 70 | * if the user enters an invalid input. Repeats this process till the user decides not to enter a word. 71 | * @param englishWords A reference to the Lexicon containing english words. 72 | * @param word1 The initial word in the ladder. 73 | * @param word2 The destination word in the ladder. 74 | * @return A bool expression indicating user's decision to stop input. 75 | */ 76 | bool getWords(Lexicon &words, string &word1, string &word2) { 77 | bool quit = false; 78 | do { //asking for the words 79 | word1 = getLine(WORD1_PROMPT); 80 | word1 = toLowerCase(word1); 81 | if (word1 == "") { 82 | quit = true; 83 | } 84 | else { 85 | word2 = getLine(WORD2_PROMPT); 86 | word2 = toLowerCase(word2); 87 | } 88 | if (word2 == "") { 89 | quit = true; 90 | } 91 | } while (!quit && !checkWords(words, word1, word2)); 92 | return quit; 93 | } 94 | 95 | /** 96 | * @brief getLexiconFromFile Generates and returns a Lexicon from a file containing words, asks for the 97 | * desired file name before saving it as a lexicon. 98 | * @param file The name of the file containing the words. 99 | * @return The Lexicon generated from the specified file. 100 | */ 101 | Lexicon getLexiconFromFile(string &file) { 102 | do { //promting a file and processing it 103 | file = getLine(FILE_PROMPT); 104 | if (!isFile(file)) { 105 | cout << FILE_ERROR; 106 | } 107 | } while (!isFile(file)); 108 | Lexicon words(file); //placing the words to a lexicon 109 | return words; 110 | } 111 | 112 | /** 113 | * @brief checkWords Checks whether the first and second words are valid or not. If the words are the 114 | * same or their lengths are different or they are not english, prints a specified error message. 115 | * @param words A reference to the Lexicon containing english words. 116 | * @param word1 The first word that the user entered. 117 | * @param word2 The second word that the user entered. 118 | * @return A bool expression that is true if the words are valid and false otherwise. 119 | */ 120 | bool checkWords(Lexicon &words, string &word1, string &word2) { 121 | if (word1 == word2) { 122 | cout << SAME_WORD_ERROR; 123 | return false; 124 | } 125 | else if (word1.length() != word2.length()) { 126 | cout << WORD_LENGTH_ERROR; 127 | return false; 128 | } 129 | else if (!words.contains(word1) || !words.contains(word2)) { 130 | cout << NOT_FOUND_ERROR; 131 | return false; 132 | } 133 | return true; 134 | } 135 | 136 | /** 137 | * @brief findShortestPath Finds and returns the shortest word ladder connecting 138 | * two words as a stack of strings. Returns an empty stack if there is no such word 139 | * ladder. Uses BFS (Breath-first search) algorithm. 140 | * @param words A reference to the Lexicon containing english words. 141 | * @param word1 The initial word in the ladder. 142 | * @param word2 The destination word in the ladder. 143 | * @return The stack containing the words establishing the word ladder. 144 | */ 145 | Stack findShortestPath(Lexicon &words, string &word1, string &word2) { 146 | Queue> ladders = {{word1}}; 147 | Stack ladder; 148 | HashSet used = {word1}; 149 | while (!ladders.isEmpty()) { //implementing the BFS algorithm 150 | ladder = ladders.dequeue(); 151 | if (ladder.peek() == word2) { 152 | return ladder; 153 | } 154 | for (string neighbor: findNeighbors(words, ladder.peek())) { 155 | if (!used.contains(neighbor)) { 156 | Stack copyLadder = ladder; 157 | copyLadder.push(neighbor); 158 | used.add(neighbor); 159 | ladders.enqueue(copyLadder); 160 | } 161 | } 162 | } 163 | return {}; 164 | } 165 | 166 | /** 167 | * @brief findNeighbors Finds and returns all meaningful english words formed by changing 168 | * only a single letter in a given word as a HashSet of strings. 169 | * @param words A reference to the Lexicon containing english words. 170 | * @param word The given initial word. 171 | * @return The HashSet of strings containing all the neighbors of the given word. 172 | */ 173 | HashSet findNeighbors(Lexicon &words, string word) { 174 | HashSet neighbors; 175 | string copy = word; 176 | for (int i = 0; i < word.length(); i++) { //nested loops to find the neighbors 177 | for (int j = 0; j < ALPHABET.length(); j++) { 178 | copy[i] = ALPHABET[j]; 179 | if (words.contains(copy)) { 180 | neighbors.add(copy); 181 | } 182 | } 183 | copy = word; 184 | } 185 | return neighbors; 186 | } 187 | 188 | /** 189 | * @brief displayLadder Displays the word ladder on the console. 190 | * @param stack A reference to the collection representing the word ladder as a stack. 191 | * @param word1 The initial word. 192 | * @param word2 The destination word. 193 | */ 194 | void displayLadder(Stack &stack, string &word1, string &word2) { 195 | if (stack.isEmpty()) { 196 | cout << LADDER_NOT_FOUND.substr(0, 26) + word1 + LADDER_NOT_FOUND.substr(25, 9) 197 | + word2 + LADDER_NOT_FOUND.substr(LADDER_NOT_FOUND.length() - 2); 198 | } 199 | else { 200 | cout << LADDER_DISPLAY.substr(0, 14) + word2 + LADDER_DISPLAY.substr(13,9) 201 | + word1 + LADDER_DISPLAY.substr(LADDER_DISPLAY.length() - 2); 202 | while (!stack.isEmpty()) { 203 | cout << stack.pop() << " "; 204 | } 205 | cout << endl; 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /Assignment2/wordladder_extra.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * INVOLVES EXTRA FEATURES 3 | * This program is a console based game in which you enter an initial word and a destination 4 | * word. Then the program generates and displays a word ladder from the initial word to the 5 | * destination word. A word ladder is the shortest path generated by the meaningful words 6 | * that are different by their ancestors by a single letter. Following code involves functions 7 | * to produce, check and print the word ladder. 8 | * Extensions: 9 | * 1-endpoints outside the dictionary: changed the checkWords, getWords and findNeighbors 10 | * functions slightly. 11 | * @author EFE ACER 12 | * CS106B - Section Leader: Ryan Kurohara 13 | */ 14 | 15 | //necessary includes 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "console.h" 22 | #include "filelib.h" 23 | #include "simpio.h" 24 | #include "lexicon.h" 25 | #include "queue.h" 26 | #include "stack.h" 27 | #include "hashset.h" 28 | 29 | using namespace std; 30 | 31 | //constant declerations for further editing 32 | const string INTRO = "Welcome to CS 106B Word Ladder.\n" 33 | "Please give me two English words, and I will change the\n" 34 | "first into the second by changing one letter at a time.\n\n"; 35 | const string FILE_PROMPT = "Dictionary file name? "; 36 | const string WORD1_PROMPT = "\nWord #1 (or Enter to quit): "; 37 | const string WORD2_PROMPT = "Word #2 (or Enter to quit): "; 38 | const string LADDER_DISPLAY = "A ladder from back to :\n"; 39 | const string LADDER_NOT_FOUND = "No word ladder found from back to .\n"; 40 | const string WORD_LENGTH_ERROR = "The two words must be the same length.\n"; 41 | const string SAME_WORD_ERROR = "The two words must be different.\n"; 42 | const string FILE_ERROR = "Unable to open that file. Try again.\n"; 43 | const string ALPHABET = "abcdefghijklmnopqrstuvwxyz"; 44 | const string EXTRA = "As an extension the program allows the end-points of the ladder to be\n" 45 | "outside of the dictionary.\n\n"; 46 | 47 | //function declerations 48 | bool getWords(string &word1, string &word2); 49 | Lexicon getLexiconFromFile(string &file); 50 | bool checkWords(string &word1, string &word2); 51 | Stack findShortestPath(Lexicon &words, string &word1, string &word2); 52 | HashSet findNeighbors(Lexicon &words, string word, string &word2); 53 | void displayLadder(Stack &stack, string &word1, string &word2); 54 | 55 | //main function 56 | int main() { 57 | cout << INTRO << EXTRA; //displaying the intro welcome message 58 | string file; 59 | Lexicon englishWords = getLexiconFromFile(file); //generating a lexicon from a file containing words 60 | string word1, word2; 61 | bool quit; 62 | do { 63 | quit = getWords(word1, word2); //getting the words till the user decides not to enter them 64 | if (!quit) { 65 | Stack toDisplay = findShortestPath(englishWords, word1, word2); 66 | displayLadder(toDisplay, word1, word2); //displays the ladder 67 | } 68 | } while (!quit); 69 | cout << "Have a nice day." << endl; 70 | return 0; 71 | } 72 | 73 | /** 74 | * @brief getWords Asks for the initial word and the destination word, prints specific error messages 75 | * if the user enters an invalid input. Repeats this process till the user decides not to enter a word. 76 | * @param word1 The initial word in the ladder. 77 | * @param word2 The destination word in the ladder. 78 | * @return A bool expression indicating user's decision to stop input. 79 | */ 80 | bool getWords(string &word1, string &word2) { 81 | bool quit = false; 82 | do { //asking for the words 83 | word1 = getLine(WORD1_PROMPT); 84 | word1 = toLowerCase(word1); 85 | if (word1 == "") { 86 | quit = true; 87 | } 88 | else { 89 | word2 = getLine(WORD2_PROMPT); 90 | word2 = toLowerCase(word2); 91 | } 92 | if (word2 == "") { 93 | quit = true; 94 | } 95 | } while (!quit && !checkWords(word1, word2)); 96 | return quit; 97 | } 98 | 99 | /** 100 | * @brief getLexiconFromFile Generates and returns a Lexicon from a file containing words, asks for the 101 | * desired file name before saving it as a lexicon. 102 | * @param file The name of the file containing the words. 103 | * @return The Lexicon generated from the specified file. 104 | */ 105 | Lexicon getLexiconFromFile(string &file) { 106 | do { //promting a file and processing it 107 | file = getLine(FILE_PROMPT); 108 | if (!isFile(file)) { 109 | cout << FILE_ERROR; 110 | } 111 | } while (!isFile(file)); 112 | Lexicon words(file); //placing the words to a lexicon 113 | return words; 114 | } 115 | 116 | /** 117 | * @brief checkWords Checks whether the first and second words are valid or not. If the words are the 118 | * same or their lengths are different, prints a specified error message. Allows the words to be 119 | * outside of the dictionary as an extra feature. 120 | * @param word1 The first word that the user entered. 121 | * @param word2 The second word that the user entered. 122 | * @return A bool expression that is true if the words are valid and false otherwise. 123 | */ 124 | bool checkWords(string &word1, string &word2) { 125 | if (word1 == word2) { 126 | cout << SAME_WORD_ERROR; 127 | return false; 128 | } 129 | else if (word1.length() != word2.length()) { 130 | cout << WORD_LENGTH_ERROR; 131 | return false; 132 | } 133 | return true; 134 | } 135 | 136 | /** 137 | * @brief findShortestPath Finds and returns the shortest word ladder connecting 138 | * two words as a stack of strings. Returns an empty stack if there is no such word 139 | * ladder. Uses BFS (Breath-first search) algorithm. 140 | * @param words A reference to the Lexicon containing english words. 141 | * @param word1 The initial word in the ladder. 142 | * @param word2 The destination word in the ladder. 143 | * @return The stack containing the words establishing the word ladder. 144 | */ 145 | Stack findShortestPath(Lexicon &words, string &word1, string &word2) { 146 | Queue> ladders = {{word1}}; 147 | Stack ladder; 148 | HashSet used = {word1}; 149 | while (!ladders.isEmpty()) { //implementing the BFS algorithm 150 | ladder = ladders.dequeue(); 151 | if (ladder.peek() == word2) { 152 | return ladder; 153 | } 154 | for (string neighbor: findNeighbors(words, ladder.peek(), word2)) { 155 | if (!used.contains(neighbor)) { 156 | Stack copyLadder = ladder; 157 | copyLadder.push(neighbor); 158 | used.add(neighbor); 159 | ladders.enqueue(copyLadder); 160 | } 161 | } 162 | } 163 | return {}; 164 | } 165 | 166 | /** 167 | * @brief findNeighbors Finds and returns all meaningful english words formed by changing 168 | * only a single letter in a given word as a HashSet of strings. 169 | * @param words A reference to the Lexicon containing english words. 170 | * @param word The given initial word. 171 | * @param word2 is the destination word. 172 | * @return The HashSet of strings containing all the neighbors of the given word. 173 | */ 174 | HashSet findNeighbors(Lexicon &words, string word, string &word2) { 175 | HashSet neighbors; 176 | string copy = word; 177 | for (int i = 0; i < word.length(); i++) { //nested loops to find the neighbors 178 | for (int j = 0; j < ALPHABET.length(); j++) { 179 | copy[i] = ALPHABET[j]; 180 | if (copy == word2 || words.contains(copy)) { 181 | neighbors.add(copy); 182 | } 183 | } 184 | copy = word; 185 | } 186 | return neighbors; 187 | } 188 | 189 | /** 190 | * @brief displayLadder Displays the word ladder on the console. 191 | * @param stack A reference to the collection representing the word ladder as a stack. 192 | * @param word1 The initial word. 193 | * @param word2 The destination word. 194 | */ 195 | void displayLadder(Stack &stack, string &word1, string &word2) { 196 | if (stack.isEmpty()) { 197 | cout << LADDER_NOT_FOUND.substr(0, 26) + word1 + LADDER_NOT_FOUND.substr(25, 9) 198 | + word2 + LADDER_NOT_FOUND.substr(LADDER_NOT_FOUND.length() - 2); 199 | } 200 | else { 201 | cout << LADDER_DISPLAY.substr(0, 14) + word2 + LADDER_DISPLAY.substr(13,9) 202 | + word1 + LADDER_DISPLAY.substr(LADDER_DISPLAY.length() - 2); 203 | while (!stack.isEmpty()) { 204 | cout << stack.pop() << " "; 205 | } 206 | cout << endl; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Assignment3/fractals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * EXTENSION: Did the optional recursive tree part as an extension. 3 | * File: fractals.cpp 4 | * -------------------------- 5 | * Name: EFE ACER 6 | * Section leader: Ryan Kurohara 7 | * This file contains fractal problems for CS106B. 8 | */ 9 | 10 | 11 | #include "fractals.h" 12 | #include 13 | 14 | using namespace std; 15 | 16 | const int LEAF_COLOR = 0x2e8b57; /* Color of all leaves of recursive tree (level 1) */ 17 | const int BRANCH_COLOR = 0x8b7765; /* Color of all branches of recursive tree (level >=2) */ 18 | 19 | /** 20 | * @brief drawEquilateralTriangle Draws a tip-down equilateral triangle on a graphics window 21 | * with respect to the specified size and coordinates. 22 | * @param gw The graphics window, where to draw the equilateral triangle. 23 | * @param x The x coordinate of the top-left corner of the equilateral triangle. 24 | * @param y The y coordinate of the top-left corner of the equilateral triangle. 25 | * @param size The length of a side of the equilateral triangle. 26 | */ 27 | void drawEquilateralTriangle(GWindow & gw, double & x, double & y, double & size) { 28 | gw.drawLine(x, y, x + size, y); 29 | gw.drawLine(x, y, x + size / 2, y + size * sqrt(3) / 2); 30 | gw.drawLine(x + size, y, x + size / 2, y + size * sqrt(3) / 2); 31 | } 32 | 33 | /** 34 | * Draws a Sierpinski triangle of the specified size and order, placing its 35 | * top-left corner at position (x, y). 36 | * 37 | * This will be called by fractalgui.cpp. 38 | * 39 | * @param gw - The window in which to draw the Sierpinski triangle. 40 | * @param x - The x coordinate of the top-left corner of the triangle. 41 | * @param y - The y coordinate of the top-left corner of the triangle. 42 | * @param size - The length of one side of the triangle. 43 | * @param order - The order of the fractal. 44 | */ 45 | void drawSierpinskiTriangle(GWindow & gw, double x, double y, double size, int order) { 46 | if (x < 0 || y < 0 || size < 0 || order < 0) { //causes error 47 | throw("invalid input"); 48 | } else if (order != 0) { 49 | if (order == 1) { //base case 50 | drawEquilateralTriangle(gw, x, y, size); //drawing the triangle for order 1 51 | } else { //recursive step 52 | drawSierpinskiTriangle(gw, x, y, size / 2, order - 1); 53 | drawSierpinskiTriangle(gw, x + size / 2, y, size / 2, order - 1); 54 | drawSierpinskiTriangle(gw, x + size / 4, y + size * sqrt(3) / 4, size / 2, order - 1); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * @brief drawTree Draws a recursive tree fractal with the specified order and size. 61 | * The top-left corner of the bounding box is at position (x,y). 62 | * @param gw The graphics window, where to draw the recursive tree image. 63 | * @param x The x coordinate of the top-left corner of the bounding box. 64 | * @param y The y coordinate of the top-left corner of the bounding box. 65 | * @param size The length of one side of the bounding box. 66 | * @param order The order of the fractal. 67 | * @param angle The angle indicating the direction of the branches. 68 | */ 69 | void drawTree(GWindow & gw, double x, double y, double size, int order, double angle) { 70 | if (x < size / 2 || y < size || size < 0 || order < 0) { //causes error 71 | throw("invalid input"); 72 | } else if (order != 0) { //recursive step (base case is when order = 0 (draw nothing) 73 | if (order >= 2) { //setting the color of the branch 74 | gw.setColor(BRANCH_COLOR); 75 | } else { //setting the colot of the leaves 76 | gw.setColor(LEAF_COLOR); 77 | } 78 | gw.drawPolarLine(x, y, size / 2, 180 * angle / M_PI); //drawing a directed branch 79 | for (double i = -M_PI / 4; i <= M_PI / 4; i += M_PI / 12) { //recursing in different directions 80 | drawTree(gw, x + cos(angle) * size / 2, y - sin(angle) * size / 2, size / 2, order - 1, angle + i); 81 | } 82 | } 83 | } 84 | 85 | /** 86 | * Draws a recursive tree fractal image of the specified size and order, 87 | * placing the bounding box's top-left corner at position (x,y). 88 | * 89 | * This will be called by fractalgui.cpp. 90 | * 91 | * @param gw - The window in which to draw the recursive tree. 92 | * @param x - The x coordinate of the top-left corner of the bounding box. 93 | * @param y - The y coordinate of the top-left corner of the bounding box. 94 | * @param size - The length of one side of the bounding box. 95 | * @param order - The order of the fractal. 96 | */ 97 | void drawTree(GWindow& gw, double x, double y, double size, int order) { 98 | drawTree(gw, x + size / 2, y + size, size, order, M_PI / 2); 99 | } 100 | 101 | /** 102 | * Draws a Mandelbrot Set in the graphical window give, with maxIterations 103 | * (size in GUI) and in a given color (zero for palette) 104 | * 105 | * This will be called by fractalgui.cpp. 106 | * 107 | * @param gw - The window in which to draw the Mandelbrot set. 108 | * @param minX - left-most column of grid 109 | * @param incX - increment value of columns of grid 110 | * @param minY - top-most row of grid 111 | * @param incY - increment value of rows of grid 112 | * @param maxIterations - The maximum number of iterations to run recursive step 113 | * @param color - The color of the fractal; zero if palette is to be used 114 | */ 115 | void mandelbrotSet(GWindow& gw, double minX, double incX, 116 | double minY, double incY, int maxIterations, int color) { 117 | 118 | // Creates palette of colors 119 | // To use palette: 120 | // pixels[r][c] = palette[numIterations % palette.size()]; 121 | Vector palette = setPalette(); 122 | 123 | int width = gw.getCanvasWidth(); 124 | int height = gw.getCanvasHeight(); 125 | GBufferedImage image(width,height,0xffffff); 126 | gw.add(&image); 127 | Grid pixels = image.toGrid(); // Convert image to grid 128 | 129 | for (int r = 0; r < pixels.numRows(); r++) { //painting the image 130 | for (int c = 0; c < pixels.numCols(); c++) { 131 | int numIterations = mandelbrotSetIterations(Complex(minX + c * incX, minY + r * incY), 200); 132 | if (color != 0) { 133 | if (numIterations == maxIterations) { 134 | pixels[r][c] = color; 135 | } 136 | } else { 137 | pixels[r][c] = palette[numIterations % palette.size()]; 138 | } 139 | } 140 | } 141 | 142 | image.fromGrid(pixels); // Converts and puts the grid back into the image 143 | } 144 | 145 | /** 146 | * Runs the Mandelbrot Set recursive formula on complex number c a maximum 147 | * of maxIterations times. 148 | * 149 | * This will be called by you. Think about how this fits with the other two functions. 150 | * 151 | * @param c - Complex number to use for recursive formula. 152 | * @param maxIterations - The maximum number of iterations to run recursive step 153 | * @return number of iterations needed to determine if c is unbounded 154 | */ 155 | int mandelbrotSetIterations(Complex c, int maxIterations) { 156 | return mandelbrotSetIterations(Complex(0, 0), c, maxIterations); 157 | } 158 | 159 | /** 160 | * @brief mandelbrotSetIterations Determines whether a number is a member of the mandelbrot 161 | * set or not. 162 | * @param z Complex number for a given number of iterations. 163 | * @param c Complex number to use for recursive formula. 164 | * @param remainingIterations The remaining number of recursive runs. 165 | * @param maxIterations The initial number of remaining iterations. 166 | * @return Number of iterations needed to determine if c is unbounded. 167 | */ 168 | int mandelbrotSetIterations(Complex z, Complex c, int remainingIterations, int & maxIterations) { 169 | if ((z * z + c).abs() >= 4 || remainingIterations == 0) { //base case (the value diverges or c is succesfully 170 | return maxIterations - remainingIterations; // determined as a mandelbrot set number) 171 | } else { //recursive step (passing through the next recursively defined stage of the function) 172 | return mandelbrotSetIterations(z * z + c, c, remainingIterations - 1, maxIterations); 173 | } 174 | } 175 | 176 | /** 177 | * An iteration of the Mandelbrot Set recursive formula with given values z and c, to 178 | * run for a maximum of maxIterations. 179 | * 180 | * This will be called by you. Think about how this fits with the other two functions. 181 | * 182 | * @param z - Complex number for a given number of iterations 183 | * @param c - Complex number to use for recursive formula. 184 | * @param remainingIterations - The remaining number of iterations to run recursive step 185 | * @return number of iterations needed to determine if c is unbounded 186 | */ 187 | int mandelbrotSetIterations(Complex z, Complex c, int remainingIterations) { 188 | return mandelbrotSetIterations(z, c, remainingIterations, remainingIterations); 189 | } 190 | 191 | // Helper function to set the palette 192 | Vector setPalette() { 193 | Vector colors; 194 | 195 | // Feel free to replace with any palette. 196 | // You can find palettes at: 197 | // http://www.colourlovers.com/palettes 198 | 199 | // Example palettes: 200 | // http://www.colourlovers.com/palette/4480793/in_the_middle 201 | // string colorSt = "#A0B965,#908F84,#BF3C43,#9D8E70,#C9BE91,#A0B965,#908F84,#BF3C43"; 202 | 203 | // http://www.colourlovers.com/palette/4480786/Classy_Glass 204 | // string colorSt = "#9AB0E9,#C47624,#25269A,#B72202,#00002E,#9AB0E9,#C47624,#25269A"; 205 | 206 | // The following is the "Hope" palette: 207 | // http://www.colourlovers.com/palette/524048/Hope 208 | string colorSt = "#04182B,#5A8C8C,#F2D99D,#738585,#AB1111,#04182B,#5A8C8C,#F2D99D"; 209 | VectorcolorsStrVec = stringSplit(colorSt,","); 210 | for (string color : colorsStrVec) { 211 | colors.add(convertColorToRGB(trim(color))); 212 | } 213 | return colors; 214 | } 215 | -------------------------------------------------------------------------------- /Assignment3/grammarsolver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: grammarsolver.cpp 3 | * -------------------------- 4 | * Name: EFE ACER 5 | * Section leader: Ryan Kurohara 6 | * This file contains grammar generating code for CS106B. 7 | */ 8 | 9 | #include "grammarsolver.h" 10 | #include "hashmap.h" 11 | #include "random.h" 12 | 13 | using namespace std; 14 | 15 | /** 16 | * @brief generateMapFromFile Generates a HashMap of strings to Vector of strings by 17 | * reading a file that is written according to the BNF Grammar format. 18 | * @param input The istream, that is processing the file. 19 | * @param BNFMap The HashMap to be generated. 20 | */ 21 | void generateMapFromFile(istream & input, HashMap> & BNFMap) { 22 | string line; 23 | while (getline(input, line)) { 24 | Vector firstSplit = stringSplit(line, "::="); 25 | string nonTerminal = trim(firstSplit[0]); 26 | Vector rules = stringSplit(firstSplit[1], "|"); 27 | BNFMap.put(nonTerminal, rules); 28 | } 29 | } 30 | 31 | /** 32 | * @brief grammarGenerate Randomly generates grammar elements, which obey specified grammar rules. 33 | * @param input The istream, that is processing the file. 34 | * @param symbol An element of grammar. 35 | * @param BNFMap The HashMap containing the rules and elements of a grammar. 36 | * @param element The element to be generated. 37 | */ 38 | void grammarGenerate(istream & input, string symbol, HashMap> & BNFMap, string & element) { 39 | if (!BNFMap.containsKey(symbol)) { //base case 40 | element += " " + trim(symbol); 41 | } else { //recursive step 42 | Vector rules = BNFMap.get(symbol); 43 | string rule = rules[randomInteger(0, rules.size() - 1)]; 44 | rule = trim(rule); 45 | Vector symbols = stringSplit(rule, " "); 46 | for (string currentSymbol: symbols) { 47 | grammarGenerate(input, currentSymbol, BNFMap, element); //recursive call 48 | } 49 | } 50 | } 51 | 52 | /** 53 | * Generates grammar for a given symbol a certain number of times given 54 | * a BNF input file. 55 | * 56 | * This will be called by grammarmain.cpp. 57 | * 58 | * @param input - Input stream of BNF file. 59 | * @param symbol - Symbol to generate 60 | * @param times - Number of times grammar is generated 61 | * @return Vector of strings of size times with random generations of symbol 62 | */ 63 | Vector grammarGenerate(istream & input, string symbol, int times) { 64 | HashMap> BNFMap; //Chosed HashMap instead of Map for better performance. 65 | generateMapFromFile(input, BNFMap); 66 | Vector toReturn; 67 | for (int i = 0; i < times; i++) { 68 | string element = ""; 69 | grammarGenerate(input, symbol, BNFMap, element); //call to the helper function 70 | toReturn.add(element); 71 | } 72 | return toReturn; 73 | } 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Assignment3/mygrammar.txt: -------------------------------------------------------------------------------- 1 | ::= 2 | ::= | 3 | ::=the|a 4 | ::=| 5 | ::=handsome|little|beautiful|exciting|hard-working|lazy|drunk 6 | ::=programmer|computer|keyboard|student|dog|cat|telephone|desk|exam|school 7 | ::=Efe|Ryan|Anvit|Chris|Jason|Christopher|(Imnotgoodatenglishgrammar!=D) 8 | ::=.|!|?|… 9 | ::= | 10 | ::=hit|honored|kissed|helped|kicked|rewarded 11 | ::=died|collapsed|laughed|passed|programmed|walked|asked 12 | -------------------------------------------------------------------------------- /Assignment4/Boggle.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The Boggle class representing a Boggle game in which the objective of the player is to find the valid words on 3 | * the game board according to some set of rules. The code involves methods and properties to perform a Boggle game. 4 | * @author EFE ACER 5 | * @version 1.0 6 | * Section Leader: Ryan Kurohara 7 | */ 8 | 9 | #include "Boggle.h" 10 | #include "shuffle.h" 11 | #include "random.h" 12 | #include "strlib.h" 13 | #include "bogglegui.h" 14 | 15 | //constant decleration(s) 16 | const int ANIMATION_DELAY = 100; //constant to change animation delay for highlights 17 | 18 | // letters on all 6 sides of every cube 19 | static string CUBES[16] = { 20 | "AAEEGN", "ABBJOO", "ACHOPS", "AFFKPS", 21 | "AOOTTW", "CIMOTU", "DEILRX", "DELRVY", 22 | "DISTTY", "EEGHNW", "EEINSU", "EHRTVW", 23 | "EIOSST", "ELRTTY", "HIMNQU", "HLNNRZ" 24 | }; 25 | 26 | // letters on every cube in 5x5 "Big Boggle" version (extension) 27 | static string BIG_BOGGLE_CUBES[25] = { 28 | "AAAFRS", "AAEEEE", "AAFIRS", "ADENNN", "AEEEEM", 29 | "AEEGMU", "AEGMNN", "AFIRSY", "BJKQXZ", "CCNSTW", 30 | "CEIILT", "CEILPT", "CEIPST", "DDLNOR", "DDHNOT", 31 | "DHHLOR", "DHLNOR", "EIIITT", "EMOTTT", "ENSSSU", 32 | "FIPRSY", "GORRVW", "HIPRRY", "NOOTUW", "OOOTTU" 33 | }; 34 | 35 | /** 36 | * @brief Boggle::Boggle The constructor of the Boggle object. Initializes the dimension of the game board, 37 | * scores of the players, a few data structures to hold used words and a dictionary. 38 | * @param dictionary The reference of the Lexicon structure containing the dictionary words. 39 | * @param boardText The string representing the letters on the game board, the letters are randomized if 40 | * this string is passed empty. 41 | */ 42 | Boggle::Boggle(Lexicon& dictionary, string boardText) { 43 | dimension = 4; 44 | humanScore = 0; 45 | computerScore = 0; 46 | this->dictionary = dictionary; 47 | gameBoard.resize(dimension, dimension); 48 | if (boardText == "") { 49 | shuffle(CUBES, 16); //shuffling the cubes 50 | for (int r = 0; r < gameBoard.numRows(); r++) { 51 | for (int c = 0; c < gameBoard.numCols(); c++) { 52 | gameBoard[r][c] = stringToChar(toLowerCase(charToString(CUBES[r * dimension + c][randomInteger(0, 5)]))); //placing a random face of the cube 53 | } 54 | } 55 | } else { 56 | for (int r = 0; r < gameBoard.numRows(); r++) { 57 | for (int c = 0; c < gameBoard.numCols(); c++) { 58 | gameBoard[r][c] = boardText[r * dimension + c]; //placing the given boardText 59 | } 60 | } 61 | } 62 | } 63 | 64 | /** 65 | * @brief Boggle::getLetter Returns the letter in the specified row and column of the game board. 66 | * @param row The specified row of the game board. 67 | * @param col The specified column of the game board. 68 | * @return The letter in the specified position of the game board. 69 | */ 70 | char Boggle::getLetter(int row, int col) const { 71 | if (!gameBoard.inBounds(row,col)) { 72 | throw("Row and/or column are out of bounds."); 73 | } 74 | return gameBoard[row][col]; 75 | } 76 | 77 | /** 78 | * @brief Boggle::checkWord Checks a word to be valid for the Boggle game. Returns true if the word is valid, 79 | * returns false otherwise. 80 | * @param word The word that will be checked for validity. 81 | * @return True if the word is valid, false otherwise. 82 | */ 83 | bool Boggle::checkWord(string word) const { 84 | if (dictionary.contains(toLowerCase(word)) && word.length() >= 4 && !foundWords.contains(toUpperCase(word))) { 85 | return true; 86 | } 87 | return false; 88 | } 89 | 90 | /** 91 | * @brief Boggle::humanWordSearch Helper recursive function for the humanWordSearch() method, uses backtracking 92 | * to find if there is a solution. The main purpose of the method is to search for a specified word in the game 93 | * board. 94 | * @param word The specified word that will be searched. 95 | * @param isUsed The boolean grid indicating the marked (visited) positions. 96 | * @param row The row of the game board, for the function to know where the search is happening. 97 | * @param col The column of the game board, for the function to know where the search is happening. 98 | * @return A boolean expression that is true if the word is found, false otherwise. 99 | */ 100 | bool Boggle::humanWordSearch(string word, Grid & isUsed, int row, int col) { 101 | BoggleGUI::setAnimationDelay(ANIMATION_DELAY); //highlighting 102 | BoggleGUI::setHighlighted(row, col, true); 103 | if (gameBoard[row][col] == word[0] && !isUsed[row][col]) { 104 | if (word.substr(1) == "") { 105 | return true; 106 | } 107 | isUsed[row][col] = true; //choose 108 | for (int r = row - 1; r <= row + 1; r++) { 109 | for (int c = col - 1; c <= col + 1; c++) { 110 | if (gameBoard.inBounds(r, c) && !isUsed[r][c] && humanWordSearch(word.substr(1), isUsed, r, c)) { //explore 111 | return true; 112 | } 113 | } 114 | } 115 | isUsed[row][col] = false; //un-choose 116 | } 117 | BoggleGUI::setAnimationDelay(ANIMATION_DELAY); //de-highlighting 118 | BoggleGUI::setHighlighted(row, col, false); 119 | return false; 120 | } 121 | 122 | /** 123 | * @brief Boggle::humanWordSearch Uses the humanWordSearch helper function of more parameters. Performs that backtracking 124 | * method on each cell of the game board. Searches for a specified word. 125 | * @param word The word to be searched. 126 | * @return A boolean expression that is true if the word is found, false otherwise. 127 | */ 128 | bool Boggle::humanWordSearch(string word) { 129 | BoggleGUI::clearHighlighting(); 130 | Grid isUsed(dimension, dimension, false); 131 | if (checkWord(word)) { 132 | for (int r = 0; r < gameBoard.numRows(); r++) { 133 | for (int c = 0; c < gameBoard.numCols(); c++) { 134 | if (humanWordSearch(word, isUsed, r, c)) { 135 | foundWords.add(toUpperCase(word)); 136 | humanScore += word.length() - 3; 137 | return true; 138 | } 139 | } 140 | } 141 | } 142 | return false; 143 | } 144 | 145 | /** 146 | * @brief Boggle::getScoreHuman Accessor method for the score of the player. 147 | * @return The score of the player. 148 | */ 149 | int Boggle::getScoreHuman() const { 150 | return humanScore; 151 | } 152 | 153 | /** 154 | * @brief Boggle::computerWordSearch Helper method for computerWordSearch, uses recursive backtracking the find all 155 | * solutions to a problem. Finds and collects all possible valid words that can be found in the game board. 156 | * @param result The set containing all possible valid words that can be found in the game board. 157 | * @param word A string representing a possible valid word to be found. 158 | * @param isUsed The boolean grid indicating the marked (visited) positions. 159 | * @param row The row of the game board, for the function to know where the search is happening. 160 | * @param col The column of the game board, for the function to know where the search is happening. 161 | */ 162 | void Boggle::computerWordSearch(Set & result, string word, Grid & isUsed, int row, int col) { 163 | if (checkWord(word)) { 164 | foundWords.add(toUpperCase(word)); 165 | result.add(toUpperCase(word)); 166 | computerScore += word.length() - 3; 167 | } 168 | for (int r = row - 1; r <= row + 1; r++) { 169 | for (int c = col - 1; c <= col + 1; c++) { 170 | if (gameBoard.inBounds(r, c) && !isUsed[r][c] && dictionary.containsPrefix(word + gameBoard[r][c])) { 171 | isUsed[r][c] = true; 172 | computerWordSearch(result, word + gameBoard[r][c], isUsed, r, c); 173 | isUsed[r][c] = false; 174 | } 175 | } 176 | } 177 | } 178 | 179 | /** 180 | * @brief Boggle::computerWordSearch Uses computerWordSearch of more parameters. Performs that backtracking method 181 | * on each cell of the game board to find all possible words that can be found on the game board. 182 | * @return The Set of words containing all possible words generated from the game board. 183 | */ 184 | Set Boggle::computerWordSearch() { 185 | Set result; 186 | Grid isUsed(dimension, dimension, false); 187 | for (int r = 0; r < gameBoard.numRows(); r++) { 188 | for (int c = 0; c < gameBoard.numCols(); c++) { 189 | computerWordSearch(result, "", isUsed, r, c); 190 | } 191 | } 192 | return result; 193 | } 194 | 195 | /** 196 | * @brief Boggle::getScoreComputer Accessor method for the score of the computer. 197 | * @return The score of the computer. 198 | */ 199 | int Boggle::getScoreComputer() const { 200 | return computerScore; 201 | } 202 | 203 | /** 204 | * @brief Boggle::getFoundWords Accessor method for the HashSet of found words. 205 | * @return The HashSet of found words. 206 | */ 207 | HashSet Boggle::getFoundWords() const { 208 | return foundWords; 209 | } 210 | 211 | /** 212 | * @brief Boggle::getDimension Accessor method for the dimension of the game board. 213 | * @return The dimension of the game board. 214 | */ 215 | int Boggle::getDimension() const { 216 | return dimension; 217 | } 218 | 219 | /** 220 | * @brief operator << The operator overloaded to print a Boggle object. 221 | * @param out The ostream. 222 | * @param boggle A reference to the Boggle object. 223 | * @return The ostream with Boggle objects string representation. 224 | */ 225 | ostream& operator<<(ostream& out, Boggle& boggle) { 226 | for (int r = 0; r < boggle.gameBoard.numRows(); r++) { 227 | for (int c = 0; c < boggle.gameBoard.numCols(); c++) { 228 | out << toUpperCase(charToString(boggle.getLetter(r,c))); 229 | } 230 | out << "\n"; 231 | } 232 | return out; 233 | } 234 | -------------------------------------------------------------------------------- /Assignment4/Boggle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Header file, defining Boggle object's public and private methods. 3 | * @author EFE ACER 4 | * @version 1.0 5 | * Section Leader: Ryan Kurohara 6 | */ 7 | 8 | #ifndef _boggle_h 9 | #define _boggle_h 10 | 11 | #include 12 | #include 13 | #include "lexicon.h" 14 | #include "grid.h" 15 | #include "hashset.h" 16 | using namespace std; 17 | 18 | class Boggle { 19 | public: //const methods are mainly accessors so that they do not change the state of the object. 20 | Boggle(Lexicon& dictionary, string boardText); 21 | char getLetter(int row, int col) const; 22 | bool checkWord(string word) const; 23 | bool humanWordSearch(string word); 24 | Set computerWordSearch(); 25 | int getScoreHuman() const; 26 | int getScoreComputer() const; 27 | HashSet getFoundWords() const; 28 | int getDimension() const; 29 | friend ostream& operator<<(ostream& out, Boggle& boggle); 30 | 31 | private: 32 | bool humanWordSearch(string word, Grid & isUsed, int row, int col); 33 | void computerWordSearch(Set & result, string word, Grid & isUsed, int row, int col); 34 | int dimension; 35 | int humanScore; 36 | int computerScore; 37 | Grid gameBoard; 38 | Lexicon dictionary; 39 | HashSet foundWords; 40 | }; 41 | 42 | #endif // _boggle_h 43 | -------------------------------------------------------------------------------- /Assignment4/boggleplay.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Code involving functions to perform the interaction between the Boggle game and the user. Prints instructions, 3 | * reads inputs and so on. 4 | * @author EFE ACER 5 | * @version 1.0 6 | * Section Leader: Ryan Kurohara 7 | */ 8 | 9 | #include "lexicon.h" 10 | #include "simpio.h" 11 | #include "Boggle.h" 12 | #include "bogglegui.h" 13 | #include "console.h" 14 | #include "strlib.h" 15 | 16 | //constant declerations 17 | const int SMALL_GUI_DIMENSION = 4; 18 | 19 | //function declerations 20 | void setUpGame(Boggle & game, string message); 21 | void fillGameBoardGUI(Boggle &game, string & boardText); 22 | void setUpGUI(); 23 | void playHumanTurn(Boggle & game); 24 | void playComputerTurn(Boggle & game); 25 | void announceWinner(Boggle & game); 26 | string getBoardText(); 27 | bool isBoardTextValid(string & boardText); 28 | 29 | /** 30 | * @brief playOneGame Performs one complete Boggle game, calls some helper functions. 31 | * @param dictionary The dictionary, which will determine valid words. 32 | */ 33 | void playOneGame(Lexicon& dictionary) { 34 | setUpGUI(); 35 | string boardText = getBoardText(); 36 | Boggle game(dictionary, boardText); 37 | fillGameBoardGUI(game, boardText); 38 | playHumanTurn(game); 39 | playComputerTurn(game); 40 | announceWinner(game); 41 | } 42 | 43 | /** 44 | * @brief setUpGUI Initialisez the GUI for the game. 45 | */ 46 | void setUpGUI() { 47 | if (!BoggleGUI::isInitialized()) { 48 | BoggleGUI::initialize(SMALL_GUI_DIMENSION, SMALL_GUI_DIMENSION); 49 | } else { 50 | BoggleGUI::reset(); 51 | } 52 | } 53 | 54 | /** 55 | * @brief fillGameBoardGUI Fills the graphical game board accordingly. 56 | * @param game The reference to the Boggle object. 57 | * @param boardText The string determining how to fill the game board. 58 | */ 59 | void fillGameBoardGUI(Boggle & game, string & boardText) { 60 | if (boardText != "") { 61 | BoggleGUI::labelAllCubes(toUpperCase(boardText)); 62 | } else { 63 | for (int r = 0; r < game.getDimension(); r++) { 64 | for (int c = 0; c < game.getDimension(); c++) { 65 | BoggleGUI::labelCube(r, c, stringToChar(toUpperCase(charToString(game.getLetter(r, c)))), false); 66 | } 67 | } 68 | } 69 | } 70 | 71 | /** 72 | * @brief setUpGame Sets the game up on the console. 73 | * @param game The reference to the Boggle object. 74 | * @param message A specified message to display on console. 75 | */ 76 | void setUpGame(Boggle & game, string message) { 77 | clearConsole(); 78 | cout << message << endl << game << endl 79 | << "Your words (" << game.getFoundWords().size() << "): " << game.getFoundWords() 80 | << endl << "Your score: " << game.getScoreHuman() << endl; 81 | } 82 | 83 | /** 84 | * @brief playHumanTurn Plays the first half of the game, which is the players turn. Prints instructions, calls 85 | * Boggle functions and sets new graphics. 86 | * @param game The reference to the Boggle object. 87 | */ 88 | void playHumanTurn(Boggle & game) { 89 | clearConsole(); 90 | setUpGame(game, "It's your turn!"); 91 | BoggleGUI::setStatusMessage("It's your turn!"); 92 | string word = toLowerCase(getLine("Type a word (or Enter to stop): ")); 93 | while (word != "") { 94 | if (!game.checkWord(word)) { 95 | setUpGame(game, "You must enter an unfound 4+ letter word from the dictionary."); 96 | BoggleGUI::setStatusMessage("You must enter an unfound 4+ letter word from the dictionary."); 97 | } else if (game.humanWordSearch(word)) { 98 | setUpGame(game, "You found a new word! \"" + toUpperCase(word) + "\""); 99 | BoggleGUI::setStatusMessage("You found a new word! \"" + toUpperCase(word) + "\""); 100 | BoggleGUI::recordWord(toLowerCase(word), BoggleGUI::HUMAN); 101 | BoggleGUI::setScore(game.getScoreHuman(), BoggleGUI::HUMAN); 102 | } else if (word != "") { 103 | setUpGame(game, "That word can't be formed on this board."); 104 | BoggleGUI::setStatusMessage("That word can't be formed on this board."); 105 | } 106 | word = toLowerCase(getLine("Type a word (or Enter to stop): ")); 107 | } 108 | } 109 | 110 | /** 111 | * @brief playComputerTurn Plays the second half of the game, which is the computers turn. Prints instructions, calls 112 | * Boggle functions and sets new graphics. 113 | * @param game The reference to the Boggle object. 114 | */ 115 | void playComputerTurn(Boggle & game) { 116 | BoggleGUI::clearHighlighting(); 117 | Set wordsFoundByComputer = game.computerWordSearch(); 118 | cout << "\nIt's my turn!\nMy words (" << wordsFoundByComputer.size() << "): " << wordsFoundByComputer 119 | << "\nMy score: " << game.getScoreComputer() << endl; 120 | BoggleGUI::setStatusMessage("It's my turn!"); 121 | for (string word: wordsFoundByComputer) { 122 | BoggleGUI::recordWord(toLowerCase(word), BoggleGUI::COMPUTER); 123 | } 124 | BoggleGUI::setScore(game.getScoreComputer(), BoggleGUI::COMPUTER); 125 | } 126 | 127 | /** 128 | * @brief announceWinner Announces the winner both in the console and the graphics window by comparing the scores of 129 | * the player and the computer. 130 | * @param game The reference to the Boggle object. 131 | */ 132 | void announceWinner(Boggle & game) { 133 | if (game.getScoreComputer() > game.getScoreHuman()) { 134 | cout << "Ha ha ha, I destroyed you. Better luck next time, puny human!\n"; 135 | BoggleGUI::setStatusMessage("Ha ha ha, I destroyed you. Better luck next time, puny human!"); 136 | } else { 137 | cout << "WOW, you defeated me! Congratulations!\n"; 138 | BoggleGUI::setStatusMessage("WOW, you defeated me! Congratulations!"); 139 | } 140 | } 141 | 142 | /** 143 | * @brief getBoardText Prompts and returns a string representing the letters on the game board. 144 | * @return A string representing the letters on the game board. 145 | */ 146 | string getBoardText() { 147 | if (getYesOrNo("Do you want to generate a random board?")) { 148 | return ""; 149 | } else { 150 | string boardText; 151 | do { 152 | boardText = toLowerCase(getLine("Type the 16 letters to appear on the board: ")); 153 | if (!isBoardTextValid(boardText)) { 154 | cout << "That is not a valid 16-letter board string. Try again.\n"; 155 | } 156 | } while (!isBoardTextValid(boardText)); 157 | return boardText; 158 | } 159 | } 160 | 161 | /** 162 | * @brief isBoardTextValid Checks whether the board text is valid or not, returns a bool. 163 | * @param boardText A string representing the letters on the game board. 164 | * @return True if the string is valid, false otherwise. 165 | */ 166 | bool isBoardTextValid(string & boardText) { 167 | if (boardText.length() == SMALL_GUI_DIMENSION * SMALL_GUI_DIMENSION) { 168 | for (char check: boardText) { 169 | if (!isalpha(check)) { 170 | return false; 171 | } 172 | } 173 | return true; 174 | } 175 | return false; 176 | } 177 | -------------------------------------------------------------------------------- /Assignment5/HeapPatientQueue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The following code involves methods neccessary to make a Heap behave as a priority 3 | * queue. It completes the method definitions of the HeapPatientQueue class. 4 | * SectionLeader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | //THIS IS AN EXTENSION 10 | 11 | #include "HeapPatientQueue.h" 12 | #include "strlib.h" 13 | 14 | /** 15 | * @brief HeapPatientQueue::HeapPatientQueue The default constructor for the queue of patients. 16 | * Initializes the binary heap's size and locates heap memory for it. 17 | */ 18 | HeapPatientQueue::HeapPatientQueue() { 19 | capacity = INITIAL_CAPACITY; 20 | patients = new HeapPatient[capacity]; 21 | count = 0; 22 | } 23 | 24 | /** 25 | * @brief HeapPatientQueue::~HeapPatientQueue The destructor of the queue of patients. Deletes 26 | * the binary heap from the memory. 27 | */ 28 | HeapPatientQueue::~HeapPatientQueue() { 29 | delete [] patients; 30 | } 31 | 32 | /** 33 | * @brief HeapPatientQueue::clear Clears the binary heap and deletes the memory it covers. 34 | * After the call, patients pointer points to an empty binary heap. 35 | */ 36 | void HeapPatientQueue::clear() { 37 | delete [] patients; 38 | capacity = INITIAL_CAPACITY; 39 | patients = new HeapPatient[capacity]; 40 | count = 0; 41 | } 42 | 43 | /** 44 | * @brief HeapPatientQueue::frontName Returns the name of the most urgent patient in the queue of 45 | * patients, without removing him/her from the queue. In this case, returns the name of the root of 46 | * the binary heap. Throws a string exception if there are no patients in the queue. 47 | * @return The name of the most urgent patient in the queue of patients. 48 | */ 49 | string HeapPatientQueue::frontName() { 50 | if (count == 0) { //error case 51 | throw("Invalid Operation: The queue of patients is empty."); 52 | } else { 53 | return patients[1].name; //root is index 1 in order to make the arithmetic simpler 54 | } 55 | } 56 | 57 | /** 58 | * @brief HeapPatientQueue::frontName Returns the priority of the most urgent patient in the queue 59 | * of patients, without removing him/her from the queue. In this case, returns the priority of the 60 | * root of the binary heap. Throws a string exception if there are no patients in the queue. 61 | * @return The priority level of the most urgent patient in the queue of patients. 62 | */ 63 | int HeapPatientQueue::frontPriority() { 64 | if (count == 0) { //error case 65 | throw("Invalid Operation: The queue of patients is empty."); 66 | } else { 67 | return patients[1].priority; //root is index 1 in order to make the arithmetic simpler 68 | } 69 | } 70 | 71 | /** 72 | * @brief VectorPatientQueue::isEmpty Returns false if there are at least one person in the queue 73 | * of patients and returns true if the queue is empty. 74 | * @return True if the queue is empty, false otherwise. 75 | */ 76 | bool HeapPatientQueue::isEmpty() { 77 | return count == 0; 78 | } 79 | 80 | /** 81 | * @brief HeapPatientQueue::newPatient Enqueues a new patient with the given name and priority to 82 | * the queue of patients. Performs "bubble up" algorithm to place the enqued element to the binary 83 | * heap. 84 | * @param name The name of the incoming patient. 85 | * @param priority The priority level of the incoming patient. 86 | */ 87 | void HeapPatientQueue::newPatient(string name, int priority) { 88 | if (count + 1 == capacity) { 89 | expand(); 90 | } 91 | HeapPatient incoming = {name, priority}; 92 | patients[count + 1] = incoming; 93 | count++; 94 | bubbleUp(count); 95 | } 96 | 97 | /** 98 | * @brief HeapPatientQueue::processPatient Dequeus the most urgent patient from the queue of 99 | * patients. Performs "bubble down" algorithm to reform the binary heap after the removal. 100 | * Throws a string exception if the queue is empty. 101 | * @return The name of the dequeued patient. 102 | */ 103 | string HeapPatientQueue::processPatient() { 104 | if (count == 0) { //error case 105 | throw("Invalid Operation: The queue of patients is empty."); 106 | } else { 107 | string outgoing = patients[1].name; 108 | patients[1] = patients[count]; 109 | count--; 110 | if (count < capacity / 2) { 111 | shrink(); 112 | } 113 | bubbleDown(1); 114 | return outgoing; 115 | } 116 | } 117 | 118 | /** 119 | * @brief HeapPatientQueue::upgradePatient Upgrades the priority level of the patient with the 120 | * given name to be more urgent. Throws a string exception if the queue is empty or there is no 121 | * such patient or newPriority is not more urgent then the old one. 122 | * @param name The name of the patient whose priority level will be updated. 123 | * @param newPriority The new priority level of the patient. 124 | */ 125 | void HeapPatientQueue::upgradePatient(string name, int newPriority) { 126 | if (count == 0) { //error case 127 | throw("Invalid Operation: The queue of patients is empty."); 128 | } 129 | int index = 0; 130 | for (int i = 1; i <= count; i++) { 131 | if (patients[i].name == name) { 132 | if (patients[i].priority >= newPriority) { 133 | patients[i].priority = newPriority; 134 | } else { //error case 135 | throw("Invalid Operation: The priority of the patient is already greater than the" 136 | " new priority."); 137 | } 138 | index = i; 139 | break; 140 | } 141 | } 142 | if (index == 0) { //error case 143 | throw("Invalid Operation: There is no patient with the given name."); 144 | } else { 145 | bubbleUp(index); 146 | } 147 | } 148 | 149 | /** 150 | * @brief VectorPatientQueue::toString Returns a string representation of the patient queue. 151 | * The returned string involves information such as the names and priority values of the 152 | * patients. 153 | * @return The string representation of the patient queue. 154 | */ 155 | string HeapPatientQueue::toString() { 156 | string patientQueue = "{"; 157 | for (int i = 1; i <= count; i++) { 158 | if (i == count) { 159 | patientQueue += integerToString(patients[i].priority) + ":" + patients[i].name; 160 | } else { 161 | patientQueue += integerToString(patients[i].priority) + ":" + patients[i].name + ", "; 162 | } 163 | } 164 | return patientQueue + "}"; 165 | } 166 | 167 | /** 168 | * @brief HeapPatientQueue::expand Private function helping the other functions when count is 169 | * about to exceed capacity. Expands the binary heap exponentially by a factor of 2. Clears 170 | * the old memory and copies the original values to the expanded binary heap. 171 | */ 172 | void HeapPatientQueue::expand() { 173 | HeapPatient* newPatients = new HeapPatient[capacity * 2]; //locating new heap memory 174 | for (int i = 1; i <= count; i++) { //copying values to upgraded array 175 | newPatients[i] = patients[i]; 176 | } 177 | delete [] patients; //deleting the memory occupied by the old array 178 | patients = newPatients; //making patients point to the upgraded array 179 | capacity *= 2; //exponentially updating the capacity (by a factor of 2) 180 | } 181 | 182 | /** 183 | * @brief HeapPatientQueue::expand Private function helping the other functions when count is 184 | * half of the capacity. Shrinks the binary heap exponentially by a factor of 0.5. Clears 185 | * the old memory and copies the original values to the shrinked binary heap. 186 | */ 187 | void HeapPatientQueue::shrink() { 188 | if (capacity != INITIAL_CAPACITY) { 189 | HeapPatient* newPatients = new HeapPatient[capacity / 2]; //locating new heap memory 190 | for (int i = 1; i <= count; i++) { //copying values to upgraded array 191 | newPatients[i] = patients[i]; 192 | } 193 | delete [] patients; //deleting the memory occupied by the old array 194 | patients = newPatients; //making patients point to the upgraded array 195 | capacity /= 2; //exponentially updating the capacity (by a factor of 0.5) 196 | } 197 | } 198 | 199 | /** 200 | * @brief HeapPatientQueue::bubbleUp Private helper function implementing the bubble-up algorithm. 201 | */ 202 | void HeapPatientQueue::bubbleUp(int index) { 203 | while (index > 1 && patients[index].priority <= patients[index / 2].priority) { 204 | if (patients[index].priority == patients[index / 2].priority) { 205 | if (patients[index].name <= patients[index / 2].name) { 206 | swap(index, index / 2); //breaking ties by string comparison 207 | } 208 | } else { 209 | swap(index, index / 2); 210 | } 211 | index /= 2; 212 | } 213 | } 214 | 215 | /** 216 | * @brief HeapPatientQueue::bubbleDown Private helper function implementing the bubble-down 217 | * algorithm. 218 | */ 219 | void HeapPatientQueue::bubbleDown(int index) { 220 | int left = index * 2; 221 | while (left <= count) { 222 | int moreUrgent = left; 223 | int right = left + 1; 224 | if (right <= count) { 225 | if (patients[right].priority <= patients[left].priority) { 226 | if (patients[right].priority == patients[left].priority) { 227 | if (patients[right].name <= patients[left].name) { 228 | moreUrgent++; //breaking ties by string comparison 229 | } 230 | } else { 231 | moreUrgent++; 232 | } 233 | } 234 | } 235 | if (patients[moreUrgent].priority <= patients[index].priority) { 236 | if (patients[moreUrgent].priority == patients[index].priority) { 237 | if (patients[moreUrgent].name <= patients[index].name) { 238 | swap(index, moreUrgent); //breaking ties by string comparison 239 | } 240 | } else { 241 | swap(index, moreUrgent); 242 | } 243 | index = moreUrgent; 244 | left = index * 2; 245 | } else { 246 | break; 247 | } 248 | } 249 | } 250 | 251 | /** 252 | * @brief HeapPatientQueue::swap Private function helping other functions when two patients need 253 | * to be swapped. 254 | * @param index1 The index of the first element to swap. 255 | * @param index2 The index of the second element to swap. 256 | */ 257 | void HeapPatientQueue::swap(int index1, int index2) { 258 | HeapPatient temp = patients[index1]; 259 | patients[index1] = patients[index2]; 260 | patients[index2] = temp; 261 | } 262 | -------------------------------------------------------------------------------- /Assignment5/HeapPatientQueue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The header file defining private/public methods and properties used by 3 | * HeapPatientQueue class. 4 | * Section Leader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | //THIS IS AN EXTENSION 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include "patientnode.h" 16 | #include "patientqueue.h" 17 | using namespace std; 18 | 19 | //constant decletation(s) 20 | const int INITIAL_CAPACITY = 10; //initial size of the inner array structure 21 | 22 | struct HeapPatient { //struct modeling a Patient 23 | string name; 24 | int priority; 25 | }; 26 | 27 | class HeapPatientQueue : public PatientQueue { 28 | public: 29 | HeapPatientQueue(); //constructor 30 | ~HeapPatientQueue(); //destructor 31 | string frontName(); //accessor method for the front element's name 32 | void clear(); //clears the queue 33 | int frontPriority(); //accessor method for the front element's priority 34 | bool isEmpty(); //checks empty state of the queue 35 | //Time complexity of enqueing: O(logN) but O(1) for average 36 | void newPatient(string name, int priority); //adds a new element 37 | //Time complexity of dequeing: O(logN) 38 | string processPatient(); //removes the front element 39 | void upgradePatient(string name, int newPriority); //upgrades an element's priority 40 | string toString(); //returns a string representing the queue 41 | 42 | private: 43 | HeapPatient* patients; //array as internal storage 44 | int capacity; 45 | int count; 46 | void expand(); 47 | void shrink(); 48 | void bubbleUp(int index); 49 | void bubbleDown(int index); 50 | void swap(int index1, int index2); 51 | }; 52 | -------------------------------------------------------------------------------- /Assignment5/LinkedListPatientQueue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The following code involves the methods neccessary to make a linked list behave as a 3 | * priority queue. It completes the method definitions of the LinkedListPatientQueue class. 4 | * SectionLeader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | #include "LinkedListPatientQueue.h" 10 | #include "strlib.h" //for integerToString method 11 | 12 | /** 13 | * @brief LinkedListPatientQueue::LinkedListPatientQueue The default constructor of the 14 | * LinkedListPatientQueue class. Initializes the front pointer of the linked list to null pointer. 15 | */ 16 | LinkedListPatientQueue::LinkedListPatientQueue() { 17 | front = nullptr; 18 | } 19 | 20 | /** 21 | * @brief LinkedListPatientQueue::~LinkedListPatientQueue The destructor of the 22 | * LinkedListPatientQueue class. Walks through the linked list and deletes all elements. 23 | * Prevents any memory leak. 24 | */ 25 | LinkedListPatientQueue::~LinkedListPatientQueue() { 26 | while (front != nullptr) { 27 | PatientNode* trash = front; 28 | front = front->next; 29 | delete trash; 30 | } 31 | } 32 | 33 | /** 34 | * @brief LinkedListPatientQueue::clear Clears the queue of patients and turns it to an empty 35 | * list. Prevents any memory leak by deleting the data stored in the heap. 36 | */ 37 | void LinkedListPatientQueue::clear() { 38 | while (front != nullptr) { 39 | PatientNode* trash = front; 40 | front = front->next; 41 | delete trash; 42 | } 43 | } 44 | 45 | /** 46 | * @brief LinkedListPatientQueue::frontName Returns the name of the most ugrent patient without 47 | * removing him/her from the queue. Throws a string exception if the queue is empty. 48 | * @return The name of the most urgent patient. 49 | */ 50 | string LinkedListPatientQueue::frontName() { 51 | if (front == nullptr) { 52 | throw("Invalid Operation: The queue of patients is empty."); 53 | } else { 54 | return front->name; 55 | } 56 | } 57 | 58 | /** 59 | * @brief LinkedListPatientQueue::frontName Returns the pripority of the most ugrent patient 60 | * without removing him/her from the queue. Throws a string exception if the queue is empty. 61 | * @return The priority level of the most urgent patient. 62 | */ 63 | int LinkedListPatientQueue::frontPriority() { 64 | if (front == nullptr) { 65 | throw("Invalid Operation: The queue of patients is empty."); 66 | } else { 67 | return front->priority; 68 | } 69 | } 70 | 71 | /** 72 | * @brief VectorPatientQueue::isEmpty Returns false if there are at least one person in the queue 73 | * of patients and returns true if the queue is empty. 74 | * @return True if the queue is empty, false otherwise. 75 | */ 76 | bool LinkedListPatientQueue::isEmpty() { 77 | return front == nullptr; 78 | } 79 | 80 | /** 81 | * @brief LinkedListPatientQueue::newPatient Adds an incoming patient to the queue of patients. 82 | * The incoming patient is placed in the queue according to his/her priority level. 83 | * @param name The name of the incoming patient. 84 | * @param priority The priority value of the incoming patient. 85 | */ 86 | void LinkedListPatientQueue::newPatient(string name, int priority) { 87 | PatientNode* incoming = new PatientNode(name, priority); 88 | if (front == nullptr) { //case 1: link list is empty 89 | front = incoming; 90 | } else if (front->priority > priority) { //case 2: the incoming element is the front element 91 | incoming->next = front; 92 | front = incoming; 93 | } else { //case 3: link list has N elements 94 | PatientNode* current = front; 95 | while (current->next != nullptr && current->next->priority <= priority) { 96 | current = current->next; 97 | } 98 | incoming->next = current->next; 99 | current->next = incoming; 100 | } 101 | } 102 | 103 | /** 104 | * @brief LinkedListPatientQueue::processPatient Dequeues the most urgent patient from the queue 105 | * of patients. In other words, removes the front element of the linked list (Linked list 106 | * implementation allows us to store a sorted priority queue.) Throws a string exception if the 107 | * queue of patients is empty. 108 | * @return The most urgent patient in the queue (The front of the linked list). 109 | */ 110 | string LinkedListPatientQueue::processPatient() { 111 | if (front == nullptr) { //error case 112 | throw("Invalid Operation: The queue of patients is empty."); 113 | } else { 114 | PatientNode* trash = front; 115 | string outgoing = trash->name; 116 | front = front->next; 117 | delete trash; 118 | return outgoing; 119 | } 120 | } 121 | 122 | /** 123 | * @brief LinkedListPatientQueue::upgradePatient Modifies the priority of a given existing patient 124 | * to be more urgent. Throws a string exception if the given priority is not more urgent than 125 | * the patient's priority or there is no such patient with the given name. 126 | * @param name Name of the patient whose priority will be modified. 127 | * @param newPriority The modified priority of the patient. 128 | */ 129 | void LinkedListPatientQueue::upgradePatient(string name, int newPriority) { 130 | if (front == nullptr) { //error case 131 | throw("Invalid Operation: The queue of patients is empty."); 132 | } else { 133 | PatientNode* current = front; 134 | while (current->next != nullptr && current->next->name != name) { 135 | current = current->next; 136 | } 137 | if (current->next == nullptr) { //error case 138 | throw("Invalid Operation: There is no patient with the given name."); 139 | } else { 140 | PatientNode* toModify = current->next; 141 | if (toModify->priority < newPriority) { //error case 142 | throw("Invalid Operation: The priority of the patient is already greater than the" 143 | " new priority."); 144 | } else { 145 | current->next = toModify->next; 146 | newPatient(toModify->name, newPriority); 147 | delete toModify; //preventing memory leak. 148 | } 149 | } 150 | } 151 | } 152 | 153 | /** 154 | * @brief LinkedListPatientQueue::toString Returns a string representation of the queue of 155 | * patients. The returned string contains information such as patients priority levels and 156 | * names. 157 | * @return The string representation of the list. 158 | */ 159 | string LinkedListPatientQueue::toString() { 160 | if (front == nullptr) { 161 | return "{}"; 162 | } else { 163 | string patientQueue; 164 | PatientNode* current = front; 165 | while (current->next != nullptr) { 166 | patientQueue += integerToString(current->priority) + ":" + current->name + ", "; 167 | current = current->next; 168 | } 169 | patientQueue += integerToString(current->priority) + ":" + current->name; 170 | return "{" + patientQueue + "}"; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Assignment5/LinkedListPatientQueue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The header file defining private/public methods and properties used by 3 | * LinkedListPatientQueue class. 4 | * Section Leader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "patientnode.h" 14 | #include "patientqueue.h" 15 | using namespace std; 16 | 17 | class LinkedListPatientQueue : public PatientQueue { 18 | public: 19 | LinkedListPatientQueue(); //constructor 20 | ~LinkedListPatientQueue(); //destructor 21 | string frontName(); //accessor method for the front element's name 22 | void clear(); //clears the queue 23 | int frontPriority(); //accessor method for the front element's priority 24 | bool isEmpty(); //checks empty state of the queue 25 | void newPatient(string name, int priority); //adds a new element 26 | string processPatient(); //removes the front element 27 | void upgradePatient(string name, int newPriority); //upgrades an element's priority 28 | string toString(); //returns a string representing the queue 29 | 30 | private: 31 | PatientNode* front; //the reference to the front of the queue 32 | }; 33 | -------------------------------------------------------------------------------- /Assignment5/VectorPatientQueue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The following code involves methods neccessary to make a Vector behave as a priority 3 | * queue. It completes the method definitions of the VectorPatientQueue class. 4 | * SectionLeader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | #include "VectorPatientQueue.h" 10 | #include "vector.h" 11 | #include "strlib.h" 12 | 13 | /** 14 | * @brief VectorPatientQueue::VectorPatientQueue The default constructor of the VectorPatientQueue 15 | * class. Initializes an empty Vector which will behave as a priority queue of patients. 16 | */ 17 | VectorPatientQueue::VectorPatientQueue() {} 18 | 19 | /** 20 | * @brief VectorPatientQueue::~VectorPatientQueue The destructor of the VectorPatientQueue class. 21 | * The Vector of Stanford C++ Library handles memory leaks by itself. Thus, the destructor is 22 | * only defined. 23 | */ 24 | VectorPatientQueue::~VectorPatientQueue() {} 25 | 26 | /** 27 | * @brief VectorPatientQueue::clear Removes all elements in the collection of patients. 28 | */ 29 | void VectorPatientQueue::clear() { 30 | patients.clear(); //removing all elements from the vector 31 | } 32 | 33 | /** 34 | * @brief VectorPatientQueue::frontName Returns the name of the most urgent patient in the queue of 35 | * patients without removing the patient from the queue. Throws a string exception if there are no 36 | * patients in the queue of patients. 37 | * @return The name of the most urgent patient. 38 | */ 39 | string VectorPatientQueue::frontName() { 40 | if (patients.isEmpty()) { //error case 41 | throw("Invalid Operation: The queue of patients is empty."); 42 | } else { 43 | int outgoing = 0; 44 | for (int i = 1; i < patients.size(); i++) { 45 | if (patients[i].priority < patients[outgoing].priority) { 46 | outgoing = i; 47 | } else if (patients[i].priority == patients[outgoing].priority) { 48 | if (patients[i].timestamp < patients[outgoing].timestamp) { 49 | outgoing = i; 50 | } 51 | } 52 | } 53 | return patients[outgoing].name; 54 | } 55 | } 56 | 57 | /** 58 | * @brief VectorPatientQueue::frontPriority Returns the priority of the most urgent patient in the 59 | * queue of patients without removing the patient from the queue. Throws a string exception if 60 | * there are no patients in the queue of patients. 61 | * @return The priority of the most urgent patient. 62 | */ 63 | int VectorPatientQueue::frontPriority() { 64 | if (patients.isEmpty()) { //error case 65 | throw("Invalid Operation: The queue of patients is empty."); 66 | } else { 67 | int outgoing = 0; 68 | for (int i = 1; i < patients.size(); i++) { 69 | if (patients[i].priority < patients[outgoing].priority) { 70 | outgoing = i; 71 | } 72 | } 73 | return patients[outgoing].priority; 74 | } 75 | } 76 | 77 | /** 78 | * @brief VectorPatientQueue::isEmpty Returns false if there are at least one person in the queue 79 | * of patients and returns true if the queue is empty. 80 | * @return True if the queue is empty, false otherwise. 81 | */ 82 | bool VectorPatientQueue::isEmpty() { 83 | return patients.isEmpty(); 84 | } 85 | 86 | /** 87 | * @brief VectorPatientQueue::newPatient Enques a new patient to the queue of patients. Incoming 88 | * Patients have a priority level and a name. 89 | * @param name The name of the incoming patient. 90 | * @param priority The priority level of the incoming patient. 91 | */ 92 | void VectorPatientQueue::newPatient(string name, int priority) { 93 | Patient incoming = {name, priority, patients.size() + 1}; 94 | patients.add(incoming); 95 | } 96 | 97 | /** 98 | * @brief VectorPatientQueue::processPatient Dequeues the paitent with the highest priority from 99 | * the queue of patients. Returns the name of the dequeued patient. Throws a string exception if 100 | * there are no patients in the queue of patients. 101 | * @return The name of the dequeued patient. 102 | */ 103 | string VectorPatientQueue::processPatient() { 104 | if (patients.isEmpty()) { //error case 105 | throw("Invalid Operation: The queue of patients is empty."); 106 | } else { 107 | int outgoing = 0; 108 | for (int i = 1; i < patients.size(); i++) { 109 | if (patients[i].priority < patients[outgoing].priority) { 110 | outgoing = i; 111 | } else if (patients[i].priority == patients[outgoing].priority) { 112 | if (patients[i].timestamp < patients[outgoing].timestamp) { 113 | outgoing = i; 114 | } 115 | } 116 | } 117 | string patientName = patients[outgoing].name; 118 | patients.remove(outgoing); 119 | return patientName; 120 | } 121 | } 122 | 123 | /** 124 | * @brief VectorPatientQueue::upgradePatient Modifies an existing patient's priority. Searches the 125 | * patient by name, then changes the priority to be more urgent. Throws a string exception if the 126 | * existing person has a higher priority or the person does not exist in the queue. 127 | * @param name The patient's name, which will be searched in the queue. 128 | * @param newPriority The given priority that will be changed with the searched patient's priority. 129 | */ 130 | void VectorPatientQueue::upgradePatient(string name, int newPriority) { 131 | if (patients.isEmpty()) { //error case 132 | throw("Invalid Operation: The queue of patients is empty."); 133 | } else { 134 | int toModify = 0; 135 | for (int i = 1; i < patients.size(); i++) { 136 | if (patients[i].name == name) { 137 | if (patients[toModify].name == name) { 138 | if (patients[toModify].priority > patients[i].priority) { 139 | toModify = i; 140 | } else if (patients[toModify].priority == patients[i].priority && 141 | patients[toModify].timestamp > patients[i].timestamp) { 142 | toModify = i; 143 | } 144 | } else { 145 | toModify = i; 146 | } 147 | } 148 | } 149 | if (patients[toModify].name != name) { //error case 150 | throw("Invalid Operation: There is no patient with the given name."); 151 | } else if (patients[toModify].priority < newPriority) { //error case 152 | throw("Invalid Operation: The priority of the patient is already greater than the" 153 | " new priority."); 154 | } else { 155 | patients[toModify].priority = newPriority; 156 | } 157 | } 158 | } 159 | 160 | /** 161 | * @brief VectorPatientQueue::toString Returns a string representation of the patient queue. 162 | * The returned string involves information such as the names and priority values of the 163 | * patients. 164 | * @return The string representation of the patient queue. 165 | */ 166 | string VectorPatientQueue::toString() { 167 | string patientQueue = ""; 168 | for (int i = 0; i < patients.size(); i++) { 169 | if (i == patients.size() - 1) { 170 | patientQueue += integerToString(patients[i].priority) + ":" + patients[i].name; 171 | } else { 172 | patientQueue += integerToString(patients[i].priority) + ":" + patients[i].name + ", "; 173 | } 174 | } 175 | return "{" + patientQueue + "}"; 176 | } 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /Assignment5/VectorPatientQueue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The header file defining private and public methods, properties used by 3 | * VectorPatientQueue class. 4 | * Section Leader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "patientqueue.h" 14 | #include "vector.h" 15 | using namespace std; 16 | 17 | struct Patient { //struct modeling a Patient 18 | string name; 19 | int priority; 20 | int timestamp; 21 | }; 22 | 23 | class VectorPatientQueue : public PatientQueue { 24 | public: 25 | VectorPatientQueue(); //constructor 26 | ~VectorPatientQueue(); //destructor 27 | string frontName(); //accessor method for the front element's name 28 | void clear(); //clears the queue 29 | int frontPriority(); //accessor method for the front element's priority 30 | bool isEmpty(); //checks empty state of the queue 31 | void newPatient(string name, int priority); //adds a new element 32 | string processPatient(); //removes the front element 33 | void upgradePatient(string name, int newPriority); //upgrades an element's priority 34 | string toString(); //returns a string representing the queue 35 | 36 | private: 37 | Vector patients; //inner data structure for the priority queue 38 | }; 39 | -------------------------------------------------------------------------------- /Assignment6/encoding.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The following code involves the methods neccessary to compress, decompress, 3 | * encode, decode files and strings. The compression uses Huffman encoding algortihm. 4 | * The code uses abstract data structures such as maps, queues and trees in order to 5 | * perform Huffman's encoding algorithm. 6 | * SectionLeader: Ryan Kurohara 7 | * @author EFE ACER 8 | * @version 1.0 9 | */ 10 | 11 | #include "encoding.h" 12 | #include "mymap.h" 13 | #include "pqueue.h" 14 | #include "filelib.h" 15 | 16 | //constant decleration(s) 17 | const int ASCII_OF_0 = 48; //used in encodeData function 18 | 19 | /** 20 | * @brief buildFrequencyTable Builds a frequency table from the a given input stream containing 21 | * data. 22 | * @param input The given input stream whose data will be used to generate a frequency table. 23 | * @return The frequency table, with the frequencies of the characters in the input stream's data. 24 | */ 25 | MyMap buildFrequencyTable(istream& input) { 26 | MyMap freqTable; 27 | int byte = input.get(); 28 | while (byte != -1) { 29 | if (freqTable.containsKey(byte)) { 30 | freqTable.put(byte, freqTable.get(byte) + 1); 31 | } else { 32 | freqTable.put(byte, 1); 33 | } 34 | byte = input.get(); 35 | } 36 | freqTable.put(PSEUDO_EOF, 1); 37 | return freqTable; 38 | } 39 | 40 | /** 41 | * @brief buildEncodingTree Builds an encoding tree to from a given frequency table. The tree is 42 | * built according to the Huffman's algorithm and a priority queue is used in the steps. 43 | * @param freqTable The given frequency table, which contains the data for the tree. 44 | * @return The encoding tree built from Huffman's algorithm. 45 | */ 46 | HuffmanNode* buildEncodingTree(const MyMap& freqTable) { 47 | PriorityQueue frequencies; 48 | for (int key: freqTable.keys()) { 49 | HuffmanNode* node = new HuffmanNode(key, freqTable.get(key)); 50 | frequencies.enqueue(node, node->count); 51 | } 52 | while (frequencies.size() != 1) { 53 | HuffmanNode* zero = frequencies.dequeue(); 54 | HuffmanNode* one = frequencies.dequeue(); 55 | HuffmanNode* root = new HuffmanNode(NOT_A_CHAR, zero->count + one->count, zero, one); 56 | frequencies.enqueue(root, root->count); 57 | } 58 | return frequencies.dequeue(); 59 | } 60 | 61 | /** 62 | * @brief generateEncodingMap A recursive helper function used by the buildEncodingMap function. 63 | * Basically performs pre-order traversal on the encoding tree and adds the binary code of the data 64 | * , which meets the conditions to the map. Stores the binary code through the recursive calls. 65 | * @param encodingMap The reference to the encoding map. 66 | * @param node A pointer to the encoding tree. 67 | * @param binaryCode The stored binary code. 68 | */ 69 | void generateEncodingMap(Map &encodingMap, HuffmanNode* node, string binaryCode) { 70 | if (node != nullptr) { 71 | if (node->character != NOT_A_CHAR) { 72 | encodingMap.put(node->character, binaryCode); 73 | } 74 | generateEncodingMap(encodingMap, node->zero, binaryCode + "0"); 75 | generateEncodingMap(encodingMap, node->one, binaryCode + "1"); 76 | } 77 | } 78 | 79 | /** 80 | * @brief buildEncodingMap Builds an encoding map, where every character in a given encoding tree 81 | * have a suitable Huffman binary code. Those binary codes are added to the encoding map by 82 | * traversing the given encoding tree with a call to the generateEncodingMap function. 83 | * @param encodingTree The given encoding tree which is used to build the encoding map. 84 | * @return The encoding map built from Huffman's algorithm. 85 | */ 86 | Map buildEncodingMap(HuffmanNode* encodingTree) { 87 | Map encodingMap; 88 | generateEncodingMap(encodingMap, encodingTree, ""); 89 | return encodingMap; 90 | } 91 | 92 | /** 93 | * @brief encodeData Encodes a data using Huffman's algorithm. 94 | * @param input The input stream containing the data. 95 | * @param encodingMap The map storing Huffman binary codes for the data. 96 | * @param output The output stream, where the encoded data goes. 97 | */ 98 | void encodeData(istream& input, const Map& encodingMap, obitstream& output) { 99 | int byte = input.get(); 100 | while (byte != -1) { 101 | string binaryCode = encodingMap.get(byte); 102 | for (int bit: binaryCode) { 103 | output.writeBit(bit - ASCII_OF_0); 104 | } 105 | byte = input.get(); 106 | } 107 | for (int bit: encodingMap.get(PSEUDO_EOF)) { 108 | output.writeBit(bit - ASCII_OF_0); 109 | } 110 | } 111 | 112 | /** 113 | * @brief decodeData Decodes a data using Huffman's algorithm. 114 | * @param input The input stream containing the data. 115 | * @param encodingTree The tree used to perform reverse-Huffman encoding. 116 | * @param output The output stream, where the encoded data goes. 117 | */ 118 | void decodeData(ibitstream& input, HuffmanNode* encodingTree, ostream& output) { 119 | int bit = input.readBit(); 120 | HuffmanNode* current = encodingTree; 121 | while (bit != -1) { 122 | if (current != nullptr) { //not neccessary but it's always good to prevent nullptrs 123 | if (current->character == PSEUDO_EOF) { 124 | return; 125 | } else if (current->character != NOT_A_CHAR) { 126 | output.put(current->character); 127 | current = encodingTree; 128 | } 129 | if (bit == 0) { 130 | current = current->zero; 131 | } else { 132 | current = current->one; 133 | } 134 | } 135 | bit = input.readBit(); 136 | } 137 | } 138 | 139 | /** 140 | * @brief compress Encodes the data in a file and makes it smaller in size. Uses Huffman 141 | * encoding by calling several functions. Generates a compressed version of data. 142 | * @param input The input stream to be compressed. 143 | * @param output The compressed data's output stream. 144 | */ 145 | void compress(istream& input, obitstream& output) { 146 | MyMap freqTable = buildFrequencyTable(input); 147 | rewindStream(input); 148 | HuffmanNode* encodingTree = buildEncodingTree(freqTable); 149 | Map encodingMap = buildEncodingMap(encodingTree); 150 | output << freqTable; 151 | encodeData(input, encodingMap, output); 152 | } 153 | 154 | /** 155 | * @brief decompress Decodes the data in a file and makes it larger in size. Used Huffman 156 | * decoding by calling several functions. Generates a decompressed version of data. 157 | * @param input The input stream to be decompressed. 158 | * @param output The decompressed data's output stream. 159 | */ 160 | void decompress(ibitstream& input, ostream& output) { 161 | MyMap freqTable; 162 | input >> freqTable; 163 | HuffmanNode* encodingTree = buildEncodingTree(freqTable); 164 | decodeData(input, encodingTree, output); 165 | } 166 | 167 | /** 168 | * @brief freeTree Frees and deletes all the memory associated with a given tree. 169 | * @param node The reference to the tree to be deleted. 170 | */ 171 | void freeTree(HuffmanNode* node) { 172 | if (node != nullptr) { 173 | HuffmanNode* trash = node; 174 | freeTree(node->zero); 175 | freeTree(node->one); 176 | delete trash; 177 | node = nullptr; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Assignment6/mymap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The following code involves the methods neccessary to build a hash map. 3 | * It completes the methods defined by the MyMap class. Most of the methods run 4 | * on constant time so that accessing and manipulating the map is fast. 5 | * SectionLeader: Ryan Kurohara 6 | * @author EFE ACER 7 | * @version 1.0 8 | */ 9 | 10 | #include "mymap.h" 11 | #include "vector.h" 12 | using namespace std; 13 | 14 | //constant decleration(s) 15 | const int INITIAL_SIZE = 1000; //can be changed depending on time-space concerns 16 | 17 | /** 18 | * @brief MyMap::MyMap The default constructor of the MyMap class. Initializes the size and 19 | * constructs an array (buckets) with desired size (this can be changed based on time-space 20 | * concerns by changing the INITIAL_SIZE constant). 21 | */ 22 | MyMap::MyMap() { 23 | nElems = 0; 24 | nBuckets = INITIAL_SIZE; 25 | buckets = createBucketArray(nBuckets); 26 | } 27 | 28 | /** 29 | * @brief MyMap::~MyMap Destructor of the MyMap class. Walks through the linked lists in the 30 | * buckets and deletes all elements. Prevents any memory leak. 31 | */ 32 | MyMap::~MyMap() { 33 | for (int i = 0; i < nBuckets; i++) { 34 | while (buckets[i] != nullptr) { 35 | key_val_pair* trash = buckets[i]; 36 | buckets[i] = buckets[i]->next; 37 | delete trash; 38 | } 39 | } 40 | delete [] buckets; 41 | } 42 | 43 | /** 44 | * @brief MyMap::put Adds a new value associated with the given key; if such a key already exists, 45 | * updates its value. 46 | * @param key The given key which is unique for the map. 47 | * @param value The value associated with the given key. 48 | */ 49 | void MyMap::put(int key, int value) { 50 | int bucketIndex = hashFunction(key) % nBuckets; 51 | key_val_pair* existing = nullptr; 52 | key_val_pair* current = buckets[bucketIndex]; 53 | while (current != nullptr) { 54 | if (current->key == key) { 55 | existing = current; 56 | break; 57 | } 58 | current = current->next; 59 | } 60 | if (existing != nullptr) { 61 | current->value = value; 62 | } else { 63 | key_val_pair* incoming = new key_val_pair(); 64 | incoming->key = key; 65 | incoming->value = value; 66 | incoming->next = buckets[bucketIndex]; 67 | buckets[bucketIndex] = incoming; 68 | nElems++; 69 | } 70 | } 71 | 72 | /** 73 | * @brief MyMap::get Returns the value associated with the given key. Throws a string 74 | * exception if there is no such key in the map. 75 | * @param key The given key, whose value will be returned. 76 | * @return The value associated with the given key. 77 | */ 78 | int MyMap::get(int key) const { 79 | int bucketIndex = hashFunction(key) % nBuckets; 80 | key_val_pair* current = buckets[bucketIndex]; 81 | while (current != nullptr) { 82 | if (current->key == key) { 83 | return current->value; 84 | } 85 | current = current->next; 86 | } 87 | throw("Invalid operation: The given key does not exist in the map."); //error case 88 | } 89 | 90 | /** 91 | * @brief MyMap::containsKey Checks whether or not a key is present in the map. 92 | * @param key The key to be searched. 93 | * @return A bool expression indicating whether or not the given key is present. 94 | */ 95 | bool MyMap::containsKey(int key) { 96 | int bucketIndex = hashFunction(key) % nBuckets; 97 | key_val_pair* current = buckets[bucketIndex]; 98 | while (current != nullptr) { 99 | if (current->key == key) { 100 | return true; 101 | } 102 | current = current->next; 103 | } 104 | return false; 105 | } 106 | 107 | /** 108 | * @brief MyMap::keys Returns a vector of the keys in the map. 109 | * @return The vector of the keys in the map. 110 | */ 111 | Vector MyMap::keys() const { 112 | Vector keys; 113 | for (int i = 0; i < nBuckets; i++) { 114 | key_val_pair* current = buckets[i]; 115 | while (current != nullptr) { 116 | keys.add(current->key); 117 | current = current->next; 118 | } 119 | } 120 | return keys; 121 | } 122 | 123 | /** 124 | * @brief MyMap::size Returns the current size of the map. 125 | * @return Number of elements in the map. 126 | */ 127 | int MyMap::size() { 128 | return nElems; 129 | } 130 | 131 | /** 132 | * STARTER CODE, DO NOT MODIFY 133 | */ 134 | 135 | // copy constructor 136 | MyMap::MyMap(const MyMap &myMap) { 137 | // make a deep copy of the map 138 | nBuckets = myMap.nBuckets; 139 | 140 | buckets = createBucketArray(nBuckets); 141 | 142 | // walk through the old array and add all elements to this one 143 | Vector keys = myMap.keys(); 144 | for (int i=0; i < keys.size(); i++) { 145 | int key = keys[i]; 146 | int value = myMap.get(key); 147 | put(key,value); 148 | } 149 | 150 | } 151 | 152 | // assignment overload 153 | MyMap& MyMap::operator= (const MyMap &myMap) { 154 | // make a deep copy of the map 155 | 156 | // watch for self-assignment 157 | if (this == &myMap) { 158 | return *this; 159 | } 160 | 161 | // if data exists in the map, delete it 162 | for (int i=0; i < nBuckets; i++) { 163 | MyMap::key_val_pair* bucket = buckets[i]; 164 | while (bucket != nullptr) { 165 | // walk the linked list and delete each node 166 | MyMap::key_val_pair* temp = bucket; 167 | bucket = bucket->next; 168 | delete temp; 169 | } 170 | buckets[i] = nullptr; 171 | } 172 | nElems = 0; 173 | // walk through the old array and add all elements to this one 174 | Vector keys = myMap.keys(); 175 | for (int i=0; i < keys.size(); i++) { 176 | int key = keys[i]; 177 | int value = myMap.get(key); 178 | put(key,value); 179 | } 180 | 181 | // return the existing object so we can chain this operator 182 | return *this; 183 | } 184 | 185 | ostream &operator<<(ostream &out, MyMap &myMap) { 186 | out << "{"; 187 | Vector keys = myMap.keys(); 188 | for (int i=0; i < keys.size(); i++) { 189 | int key = keys[i]; 190 | int value = myMap.get(key); 191 | out << key << ":" << value; 192 | if (i < keys.size() - 1) { // print the comma after each pair except the last 193 | out << ", "; 194 | } 195 | } 196 | out << "}"; 197 | return out; 198 | } 199 | 200 | istream &operator>>(istream &in, MyMap &myMap) { 201 | // assume the format {1:2, 3:4} 202 | bool done = false; 203 | in.get(); // get the first char, { 204 | int nextChar = in.get(); // get the first real character 205 | while (!done) { 206 | string nextInput; 207 | while (nextChar != ',' and nextChar != '}') { 208 | nextInput += nextChar; 209 | nextChar = in.get(); 210 | } 211 | if (nextChar == ',') { 212 | // read the space as well 213 | in.get(); // should be a space 214 | nextChar = in.get(); // get the next character 215 | } else { 216 | done = true; // we have reached } 217 | } 218 | // at this point, nextInput should be in the form 1:2 219 | // (we should have two integers separated by a colon) 220 | // BUT, we might have an empty map (special case) 221 | if (nextInput != "") { 222 | vector kvp = stringSplit(nextInput,":"); 223 | myMap.put(stringToInteger(kvp[0]),stringToInteger(kvp[1])); 224 | } 225 | } 226 | return in; 227 | } 228 | /** 229 | * STARTER CODE, DO NOT MODIFY 230 | * 231 | * Given a number of buckets, creates a hashtable (array of linked list heads). 232 | * 233 | * @param nBuckets the number of buckets you want in the hashtable. 234 | * return an array of heads of linked lists of key_val_pairs 235 | */ 236 | MyMap::bucketArray MyMap::createBucketArray(int nBuckets) { 237 | bucketArray newBuckets = new key_val_pair*[nBuckets]; 238 | for (int i = 0; i < nBuckets; i++) { 239 | newBuckets[i] = nullptr; 240 | } 241 | return newBuckets; 242 | } 243 | 244 | /** 245 | * STARTER CODE 246 | * The hash function for your HashMap implementation. 247 | * For an extension, you might want to improve this function. 248 | * 249 | * @param input - an integer to be hashed 250 | * return the hashed integer 251 | */ 252 | int MyMap::hashFunction(int input) const { 253 | // use unsigned integers for calculation 254 | // we are also using so-called "magic numbers" 255 | // see https://stackoverflow.com/a/12996028/561677 for details 256 | unsigned int temp = ((input >> 16) ^ input) * 0x45d9f3b; 257 | temp = ((temp >> 16) ^ temp) * 0x45d9f3b; 258 | temp = (temp >> 16) ^ temp; 259 | 260 | // convert back to positive signed int 261 | // (note: this ignores half the possible hashes!) 262 | int hash = (int) temp; 263 | if (hash < 0) { 264 | hash *= -1; 265 | } 266 | 267 | return hash; 268 | } 269 | 270 | /** 271 | * @brief MyMap::sanityCheck 272 | * 273 | * Checks a map for internal consistency 274 | */ 275 | void MyMap::sanityCheck(){ 276 | for(int i = 0; i < 1000; i++) { 277 | put(i,i); 278 | } 279 | for(int i = 0; i < 1000; i++) { 280 | 281 | if(!containsKey(i)) { 282 | string err = integerToString(i) + " should be a key in the map but cannot be found"; 283 | } 284 | int val; 285 | 286 | try { 287 | val = get(i); 288 | } catch(string exception) { 289 | string err = "Unable to get value for " + integerToString(i); 290 | throw(err); 291 | } 292 | 293 | if (i != val) { 294 | string err = integerToString(i) + " should be mapped to " + integerToString(i) + " but is mapped to " + integerToString(val) + "instead"; 295 | throw(err); 296 | } 297 | } 298 | cout << "Map seems ok" << endl; 299 | } 300 | -------------------------------------------------------------------------------- /Assignment6/mymap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The header file defining public/private methods and properties used by the 3 | * MyMap class. 4 | * Section Leader: Ryan Kurohara 5 | * @author EFE ACER 6 | * @version 1.0 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "vector.h" 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | class MyMap 17 | { 18 | public: 19 | MyMap(); //constructor 20 | ~MyMap(); //destructor 21 | 22 | int get(int key) const; //accessor method for the value of a given key 23 | void put(int key, int value); //adds a new value with the associated key to the map 24 | bool containsKey(int key); //checks whether or not a key is present in the map 25 | Vector keys() const; //returns a Vector of keys 26 | int size(); //returns the size of the map 27 | 28 | void sanityCheck(); 29 | MyMap(const MyMap &myMap); // copy constructor 30 | MyMap& operator= (const MyMap &myMap); // assignment overload 31 | friend ostream &operator<<(ostream &out, MyMap &myMap); 32 | friend istream &operator>>(istream &in, MyMap &myMap); 33 | private: 34 | struct key_val_pair { //struct modeling a key value pair with its reference to the next pair 35 | int key; 36 | int value; 37 | key_val_pair* next; 38 | }; 39 | 40 | typedef key_val_pair** bucketArray; //synonym for a bucketArray pointer 41 | 42 | bucketArray createBucketArray(int nBuckets); //creates a bucketArray of desired size 43 | int hashFunction(int input) const; //hash function used when the elements are placed to buckets 44 | 45 | bucketArray buckets; //the main inner data structure 46 | 47 | int nBuckets; //number of buckets in the hash map 48 | int nElems; //number of elements in the hash map 49 | }; 50 | -------------------------------------------------------------------------------- /Assignment6/secretmessage.huf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efeacer/Stanford_CS106B_Assignments/57e8b68fc86adee33f028e0cbf1a6646333847b6/Assignment6/secretmessage.huf -------------------------------------------------------------------------------- /Assignment7/Trailblazer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief The following code involves the implementations of efficient path finding algorithms 3 | * such as BFS, Dijkstra and A*. It also involves an algorithm finding an alternative path to a 4 | * best path. 5 | * Section Leader: Ryan Kurohara 6 | * @author EFE ACER 7 | * @version 1.0 8 | */ 9 | 10 | //I did not write a general search function that can adapt itself to all algorithms because it is 11 | //slightly less efficient (performs a bit more operations, constructs priority queue instead of 12 | //queue etc.). I chose to implement them seperately and specifically. 13 | 14 | #include "Trailblazer.h" 15 | #include "queue.h" 16 | #include "pqueue.h" 17 | #include "hashset.h" 18 | using namespace std; 19 | 20 | static const double SUFFICIENT_DIFFERENCE = 0.2; 21 | 22 | /** 23 | * @brief breadthFirstSearch Performs Breadth First Search Algorithm on a graph in order to find 24 | * the shortest path between two vertexes in terms of the number of travelled vertexes. Returns the 25 | * shortest path as a collection of its actually travelled vertexes. 26 | * @param graph A reference to the graph, on which the algorithm functions. 27 | * @param start A pointer to the starting vertex of the path to search. 28 | * @param end A pointer to the ending vertex of the path to search. 29 | * @return The shortest path as a collection of its actually travelled vertexes. 30 | */ 31 | Path breadthFirstSearch(const RoadGraph& graph, RoadNode* start, RoadNode* end) { 32 | Queue paths; 33 | HashSet visited; 34 | paths.enqueue(Path(1, start)); 35 | start->setColor(Color::YELLOW); 36 | while (!paths.isEmpty() && !visited.contains(end)) { 37 | Path possiblePath = paths.dequeue(); 38 | RoadNode* toVisit = possiblePath[possiblePath.size() - 1]; 39 | if (!visited.contains(toVisit)) { 40 | visited.add(toVisit); 41 | toVisit->setColor(Color::GREEN); 42 | if (toVisit == end) { 43 | return possiblePath; 44 | } 45 | for (RoadNode* neighbor: graph.neighborsOf(toVisit)) { 46 | if (!visited.contains(neighbor)) { 47 | paths.enqueue(possiblePath + Path(1, neighbor)); 48 | neighbor->setColor(Color::YELLOW); 49 | } 50 | } 51 | } 52 | } 53 | return Path(); 54 | } 55 | 56 | /** 57 | * @brief dijkstrasAlgorithm Performs Dijkstra's Algorithm on a graph in order to find the shortest 58 | * path between two vertexes in terms of the total cost of travelled edges. Returns the shortest 59 | * path as a collection of its actually travelled vertexes. 60 | * @param graph A reference to the graph, on which the algorithm functions. 61 | * @param start A pointer to the starting vertex of the path to search. 62 | * @param end A pointer to the ending vertex of the path to search. 63 | * @return The shortest path as a collection of its actually travelled vertexes. 64 | */ 65 | Path dijkstrasAlgorithm(const RoadGraph& graph, RoadNode* start, RoadNode* end) { 66 | PriorityQueue paths; 67 | HashSet visited; 68 | paths.enqueue(Path(1, start), 0); 69 | start->setColor(Color::YELLOW); 70 | while (!paths.isEmpty() && !visited.contains(end)) { 71 | double pathCost = paths.peekPriority(); 72 | Path possiblePath = paths.dequeue(); 73 | RoadNode* toVisit = possiblePath[possiblePath.size() - 1]; 74 | visited.add(toVisit); 75 | toVisit->setColor(Color::GREEN); 76 | if (toVisit == end) { 77 | return possiblePath; 78 | } 79 | for (RoadNode* neighbor: graph.neighborsOf(toVisit)) { 80 | if (!visited.contains(neighbor)) { 81 | paths.enqueue(possiblePath + Path(1, neighbor), 82 | pathCost + graph.edgeBetween(toVisit, neighbor)->cost()); 83 | neighbor->setColor(Color::YELLOW); 84 | } 85 | } 86 | } 87 | return Path(); 88 | } 89 | 90 | /** 91 | * @brief timeHeuristic Returns an admissible heuristic for the cost of a particular edge in the 92 | * graph. Indeed, the heuristic computes an estimated travel time between two locations by dividing 93 | * the crow fly distance between the locations to the maximum possible road speed. 94 | * @param graph A reference to the graph, on which the algorithm functions. 95 | * @param start A pointer to the starting vertex of the path to search. 96 | * @param end A pointer to the ending vertex of the path to search. 97 | * @return An estimated travel time between two locations. 98 | */ 99 | double timeHeuristic(const RoadGraph& graph, RoadNode* start, RoadNode* end) { 100 | return graph.crowFlyDistanceBetween(start, end) / graph.maxRoadSpeed(); 101 | } 102 | 103 | /** 104 | * @brief aStar Performs A* Algorithm on a graph in order to find the shortest path between two 105 | * vertexes in terms of the total cost of travelled edges. Uses the power of admissible heuristics 106 | * to make searching process faster. Returns the shortest path as a collection of its actually 107 | * travelled vertexes. 108 | * @param graph A reference to the graph, on which the algorithm functions. 109 | * @param start A pointer to the starting vertex of the path to search. 110 | * @param end A pointer to the ending vertex of the path to search. 111 | * @return The shortest path as a collection of its actually travelled vertexes. 112 | */ 113 | Path aStar(const RoadGraph& graph, RoadNode* start, RoadNode* end) { 114 | PriorityQueue paths; 115 | HashSet visited; 116 | paths.enqueue(Path(1, start), timeHeuristic(graph, start, end)); 117 | start->setColor(Color::YELLOW); 118 | while (!paths.isEmpty() && !visited.contains(end)) { 119 | double pathCost = paths.peekPriority(); 120 | Path possiblePath = paths.dequeue(); 121 | RoadNode* toVisit = possiblePath[possiblePath.size() - 1]; 122 | pathCost -= timeHeuristic(graph, toVisit, end); 123 | visited.add(toVisit); 124 | toVisit->setColor(Color::GREEN); 125 | if (toVisit == end) { 126 | return possiblePath; 127 | } 128 | for (RoadNode* neighbor: graph.neighborsOf(toVisit)) { 129 | if (!visited.contains(neighbor)) { 130 | paths.enqueue(possiblePath + Path(1, neighbor), pathCost + 131 | graph.edgeBetween(toVisit, neighbor)->cost() + 132 | timeHeuristic(graph, neighbor, end)); 133 | neighbor->setColor(Color::YELLOW); 134 | } 135 | } 136 | } 137 | return Path(); 138 | } 139 | 140 | /** 141 | * @brief setFromPath Returns a set generated from the given path. 142 | * @param path The given path, which will be converted to a set. 143 | * @return The set generated from the path. 144 | */ 145 | HashSet setFromPath(Path &path) { 146 | HashSet set; 147 | for (RoadNode* node: path) { 148 | set.add(node); 149 | } 150 | return set; 151 | } 152 | 153 | /** 154 | * @brief getPathDifference Given two paths, returns the number of elements that are in the first 155 | * path and not in the second path over the number of elements in the second path. 156 | * @param path1 The first path. 157 | * @param path2 The second path. 158 | * @return The number of elements that are in the first 159 | * path and not in the second path over the number of elements in the second path. 160 | */ 161 | double getPathDifference(Path &path1, Path &path2) { 162 | HashSet set1 = setFromPath(path1); 163 | HashSet set2 = setFromPath(path2); 164 | return (set2 - set1).size() / (double) set2.size(); 165 | } 166 | 167 | /** 168 | * @brief alternativeRoute Explores an alternative path to the best path of a graph. Uses A* as 169 | * the search algorithm. Returns an alternative poth if it is the cheapest among all alternatives 170 | * and it has a sufficient difference from the best path. 171 | * @param graph A reference to the graph, on which the algorithm functions. 172 | * @param start A pointer to the starting vertex of the path to search. 173 | * @param end A pointer to the ending vertex of the path to search. 174 | * @return The shortest alternative with a sufficient difference from the best path. 175 | */ 176 | Path alternativeRoute(const RoadGraph& graph, RoadNode* start, RoadNode* end) { 177 | Path bestPath = aStar(graph, start, end); 178 | Path bestAlternativePath; 179 | double minPathCost = 0; 180 | for (int i = 1; i < bestPath.size(); i++) { 181 | PriorityQueue paths; 182 | HashSet visited; 183 | paths.enqueue(Path(1, start), timeHeuristic(graph, start, end)); 184 | start->setColor(Color::YELLOW); 185 | while (!paths.isEmpty() && !visited.contains(end)) { 186 | double pathCost = paths.peekPriority(); 187 | Path possiblePath = paths.dequeue(); 188 | RoadNode* toVisit = possiblePath[possiblePath.size() - 1]; 189 | pathCost -= timeHeuristic(graph, toVisit, end); 190 | visited.add(toVisit); 191 | toVisit->setColor(Color::GREEN); 192 | if (toVisit == end && (minPathCost == 0 || pathCost < minPathCost) && 193 | getPathDifference(possiblePath, bestPath) > SUFFICIENT_DIFFERENCE) { 194 | bestAlternativePath = possiblePath; 195 | minPathCost = pathCost; 196 | } 197 | RoadEdge* edgeToIgnore = graph.edgeBetween(bestPath[i - 1], bestPath[i]); 198 | for (RoadNode* neighbor: graph.neighborsOf(toVisit)) { 199 | RoadEdge* edgeToVisit = graph.edgeBetween(toVisit, neighbor); 200 | if (!visited.contains(neighbor) && edgeToVisit != edgeToIgnore) { 201 | paths.enqueue(possiblePath + Path(1, neighbor), pathCost + 202 | graph.edgeBetween(toVisit, neighbor)->cost() + 203 | timeHeuristic(graph, neighbor, end)); 204 | neighbor->setColor(Color::YELLOW); 205 | } 206 | } 207 | } 208 | } 209 | return bestAlternativePath; 210 | } 211 | 212 | -------------------------------------------------------------------------------- /Assignment7/map-custom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efeacer/Stanford_CS106B_Assignments/57e8b68fc86adee33f028e0cbf1a6646333847b6/Assignment7/map-custom.jpg -------------------------------------------------------------------------------- /Assignment7/map-custom.txt: -------------------------------------------------------------------------------- 1 | IMAGE 2 | map-custom.jpg 3 | 944 4 | 765 5 | 6 | VERTEXES 7 | Nallihan;86;256 8 | Beypazari;191;255 9 | Polatli;250;516 10 | Ayas;288;329 11 | Gudul;276;250 12 | Camlidere;331;175 13 | Kizilcahamam;400;159 14 | Kazan;377;255 15 | Sincan;340;305 16 | Etimesgut;372;345 17 | Yenimahalle;357;391 18 | Haymana;356;583 19 | Golbasi;417;434 20 | Cankaya;427;343 21 | Kecioren;423;308 22 | Cubuk;475;259 23 | Altindag;468;313 24 | Mamak;472;356 25 | Bala;490;518 26 | Elmadag;534;370 27 | Akyurt;509;256 28 | Kalecik;587;294 29 | Sultan Kochisar;597;662 30 | Evren;676;631 31 | 32 | EDGES 33 | Golbasi;Bala;30 34 | Golbasi;Haymana;15 35 | Golbasi;Cankaya;15 36 | Cankaya;Yenimahalle;15 37 | Cankaya;Polatli;45 38 | Sultan Kochisar;Cankaya;75 39 | Evren;Cankaya;75 40 | Sultan Kochisar;Evren;10 41 | Elmadag;Cankaya;30 42 | Ayas;Sincan;10 43 | Cankaya;Sincan;25 44 | Camlidere;Gudul;10 45 | Nallihan;Cankaya;75 46 | Nallihan;Sultan Kochisar;100 47 | Beypazari;Kalecik;60 48 | Kalecik;Cankaya;30 49 | Elmadag;Cankaya;20 50 | Elmadag;Kalecik;10 51 | Elmadag;Gudul;80 52 | Elmadag;Altindag;80 53 | Elmadag;Mamak;35 54 | Kecioren;Cankaya;20 55 | Kecioren;Polatli;320 56 | Kecioren;Evren;39 57 | Kecioren;Cubuk;31 58 | Kecioren;Kazan;32 59 | Bala;Kazan;60 60 | Cankaya;Etimesgut;10 61 | Cankaya;Haymana;28 62 | -------------------------------------------------------------------------------- /Assignment7/trailblazerHandout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/efeacer/Stanford_CS106B_Assignments/57e8b68fc86adee33f028e0cbf1a6646333847b6/Assignment7/trailblazerHandout.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stanford_CS106B_Assignments 2 | 3 | My solutions to the assignments I have undertaken for the CS106B (Programming Abstractions in C++) course, 4 | in Stanford University. I provided the source codes and input files only, no project files. 5 | 6 | ## The assignment topics are as follows: 7 | 8 | **Assignment 1**: Pixel manipulation using Grid and Vector data structures. 9 | 10 | **Assignment 2**: Breadth first search, file reading, and random text generation through Markov chains. 11 | 12 | **Assignment 3**: Fractal graphics using recursion (fractals such as Sierpinski, Tree and Mandelbrot Set), grammar structure 13 | solver using recursive exploration. 14 | 15 | **Assignment 4**: Code for the game Boggle(human vs computer), uses recursive backtracking to explore words 16 | in a boggle game grid. 17 | 18 | **Assignment 5**: Implementation of priority queues using dynamically allocated arrays, binary heaps, and linked lists. 19 | 20 | **Assignment 6**: Implementation of the huffman algorithm using binary trees to build a compression program. 21 | 22 | **Assignment 7**: A* algorithm, Dijkstra, BFS, Alternative path algorithms for path finding in a geographic map that is 23 | represented as a graph. 24 | 25 | --------------------------------------------------------------------------------