diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1098516..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.norg -*.md diff --git a/Informatik_I/Bonus_2/README.org b/Informatik_I/Bonus_2/README.org index db5d920..7402669 100644 --- a/Informatik_I/Bonus_2/README.org +++ b/Informatik_I/Bonus_2/README.org @@ -1,15 +1,182 @@ -#+title: Magic Growing +#+TITLE: Magic Growing +#+AUTHOR: JirR02 -#+author: JirR02 -* SIKE! -:PROPERTIES: -:CUSTOM_ID: sike -:END: -[[./pictures/sike.jpg]] +* Magic Wand Tool -Spass... ist in einem seperaten Repo -[[https://www.youtube.com/watch?v=xvFZjo5PgG0][hier]]. + In this task, you will implement the =Magic Wand Tool=, a helpful tool in many image editing softwares (like Photoshop). --------------- + The =Magic Wand Tool= (or MWT) is a selection tool. It allows you to quickly select areas of your images and make independent edits to them. Conceptually, MWT selects all pixels which are /similar/ to a given reference pixel. In this task, a pixel is considered similar to the reference pixel if and only if their intensity is not too different from the reference pixel and they are connected to the reference pixel. We define what we mean by /"not too different"/ and /"connected to the reference pixel"/ more formally later. -Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ +* Images + + Note: For some browsers, the images might not be displayed correctly. Using a Chrome/Chromium-based browser should resolve the issue. + + An image is a 2D array of pixels. Every pixel can be identified by its row index \(i\) and column index \(j\). We assume that row \(0\) is at the top of the image, and column j\(0\) is on the left of the image. + +** Caution! + + Images are commonly stored in a =row-major= format. This means that we store an image as a vector of =rows= and a row as a vector of pixels. When accessing an image, you first get the correct row, then the correct column in that row. For example, if we have an image \(I\) and want to access the pixel at row \(i\) and column \(j\), we would write =I[i][j]=. + + However, pixel coordinates are commonly given as \((x , y)\), where \(x\) refers to the column (or width) and \(y\) to the row (or height). If we want to access the coordinate \((x , y)\) in image \(I\), we would write =I[y][x]= as visualized below. + + [[./pictures/images_explanation.png]] + + This exercise contains three different types of images, which are defined in =bitmap.h= and explained below. + +** RGB Image + + You won't have to deal with this type of image yourself, so feel free to skip this section. + + An RGB image is an image where each pixel consists of three values: \(r\), \(g\), and \(b\). These values indicate how much red, green, and blue light is emitted by the pixel. The three values are in the range \([0, 255]\), giving us \(256^3\) different colors we can represent. + + In this task, an RGB image is stored as an =RGBImage=, which is a type alias for =std::vector>>=. For simplicity, we represent each pixel value using an =int= in the code, and you can assume that our provided images have values in the valid range. + + Note: Since we are using =.bmp= images, the pixels are actually stored in the BGR format. + +** Grayscale Image + + Grayscale images do not contain any color information. Instead, every pixel consists of a single number indicating how bright the pixel is. The values are in the range \([0, 255]\), giving us \(256\) possible brightness values. \(0\) means the pixels emits no light (black), and \(255\) means the pixel emits as much light as possible (white). + + In this task, a grayscale image is stored as a =GrayscaleImage=, which is a type alias for =std::vector>=. For simplicity, we represent each pixel value using an =int= in the code, and you can assume that our provided images have values in the valid range. + Image Mask + + Image masks are similar to grayscale images, but we represent each pixel with a =bool=. Therefore, pixels can either be /on/ (=true=) or /off/ (=false=). + + In this task, an image mask is stored as an =ImageMask=, which is a type alias for =std::vector>=. + +* Pixel Neighborhood + + A pixel neighborhood defines the set of pixels which are considered neighbors of a given pixel. + + In this exercise, we use the so-called 4-neighborhood, which consists of four pixels, i.e., the pixels to the left, right, top, and bottom of the current pixel. Formally, the 4-neighborhood of a pixel \((x,y)\) is defined as the set of pixels at the coordinates \((x-1,y)\), \((x+1,y)\), \((x,y-1)\), and \((x,y+1)\). + + Of course, the neighborhood only consists of pixels that are part of the image, so a pixel at the left edge of the image does not have a left neighbor. + +* Task + + Your task is to implement the function =ImageMask MWT(...)= in =mwt.cpp=. The function takes a grayscale image \(I\), a pixel coordinate \((x,y)\), and a threshold \(T\) as arguments. It returns an image mask \(M\), which indicates for each pixel in the grayscale image whether or not it is similar to the pixel at coordinate \((x,y)\). A pixel \((x',y')\) is considered similar to reference pixel \((x,y)\) if the absolute difference between \(I[(x,y)]\) and \(I[(x,y)\) is at most \(T\) *and* there exists a path of /similar/ pixels from \((x,y)\) to \((x',y')\). + + Formally, \(M[(x',y')]\) is =true= if and only if there exists a sequence of pixels \(P = [p_1, ... , p_n]\) for which the following conditions hold: + + 1. \(p_1 = (x,y)\) + 1. \(p_n = (x',y')\) + 1. \(p_{i+1}\) is in the 4-neigborhood of \(p_i \forall i \in [1, ... , n-1]\) + 1. \(|I[p_i] - I[(x',y')]| \leq T \forall i \in [1, ... , n]\) + +** Hints + + - You might need helper functions for the recursive call. + - If you pass a *reference* to an image to a function, any changes that function makes to the image will be visible outside of the function. + +* Input + + When the program starts, you are first prompted to select an image. Your options are: /bank/, /field/, /peppers/, and /pigs/. + + Next, you are prompted to enter the \((x,y)\)-coordinate of the reference pixel and the similarity threshold \(T\) as three integers separated by spaces. + + Then, the selected image is loaded, converted to =GrayscaleImage=, and the =ImageMask= indicating similar pixels is computed using the =ImageMask MWT(...)= function. + + Finally, the number of identified similar pixels (including the initial pixel) and the bounding box of the selected area (as \((x_{left}, y_{top}, x_{right}, y_{bottom})\)) are printed to the console. + + Additionally, an image is saved, which visualizes the reference pixel in red, the bounding box in green, and makes non-similar pixels darker, so that the similar pixels can be seen easier. The saved image can be found under the =Files= tab. + +** Example + + #+BEGIN_src shell + Select an image: pigs + + Select a pixel (x y) and a threshold (T): 135 360 20 + + Number of selected pixels: 712 + + Bounding box (97, 328, 153, 375) + #+END_src + + The example above should result in the following output image: + + [[./pictures/example_pigs_135_360_20.png]] + +** Notes About Program Robustness + + - You don't have to make your code robust against wrongly formatted inputs. This means that you can safely assume that the entered image exists and the coordinates are valid indices of the image. + - Large thresholds may produce an excessive number of recursive calls leading to a segmentation fault (=The process exited with code -11=). The current test cases (also the replaced and hidden ones) have relatively small selected regions and should thus not cause segmentation faults for correct implementations. + +* Important: Testing and Grading + + - When grading your solution, we are going to test your submission with two sets of tests: *replaced* and *hidden*, which make up ~70% and ~30% of the total number of points respectively. The *replaced* tests are going to be very similar to the ones that are used by the auto-grader when you click on the β€œtest” button. The *hidden* tests are additional tests that check some tricky corner cases not covered by the typical tests. The *hidden* tests will be used only when grading your final submission after the deadline. The final number of points awarded to your solution is the sum of the points from the *replaced* and *hidden* test cases. As we have not added the hidden test cases yet, the maximum percantage you can achieve before we add them during grading is 71.43%. + + - Please check the autograder output carefully. It is possible to pass test cases, but not get any credits for them. This is the case when your code contains compiler warnings or errors. Note that the message detailing the final score might take some time to appear. For example, with the following output, you would not receive any credits for this bonus exercise even though one test case passes: + + #+BEGIN_src shell + Tests result: passed 1 of 10 + + [ERROR] Your program had compilation warnings. Please click on the compile button to see them. + + Please fix the errors reported above. + + The final score assigned by automatic checks: 0.00% + #+END_src + + - We recommend that you print all output that is not part of the output required by us (i.e., additional output that you use for debugging) to =std::cerr= instead of =std::cout=, as additional output might confuse the autograder and lead to hidden or replaced test cases failing. + + - /Hint/: To ensure that your solution passes not only the *replaced* tests but also the *hidden* ones, test it thoroughly with additional examples. When doing so, do not forget to check for edge cases because these are the ones we may focus on in the *hidden* test suite. *Remember!* Passing all tests does not imply that your program is correct: β€œProgram testing can be used to show the presence of bugs, but never to show their absence!” (Edsger W. Dijkstra). + +* Solution + + #+BEGIN_src cpp + #include "mwt.h" + + #include + #include + + void MWT_rec(int ref, ImageMask &mask, const GrayscaleImage &image, int x, + int y, const int T) { + int height = image.size(); + int width = image[0].size(); + + if (x < 0 || x > height || y < 0 || y > width) + return; + + int new_ref = image[y][x]; + + if (std::abs(ref - new_ref) > T) { + mask[y][x] = false; + return; + } + + if (!mask[y][x]) { + mask[y][x] = true; + MWT_rec(ref, mask, image, x - 1, y, T); + MWT_rec(ref, mask, image, x + 1, y, T); + MWT_rec(ref, mask, image, x, y - 1, T); + MWT_rec(ref, mask, image, x, y + 1, T); + } + } + + // PRE: All rows in image have the same size. + // x and y must be valid indices of the image. + // POST: Returns a matrix of bools where every true value corresponds to a pixel + // with at least one path of T-similar pixels starting at x,y. + ImageMask MWT(const GrayscaleImage &image, const int x, const int y, + const int T) { + // get image dimensions + const int height = image.size(); + assert(height > 0); + const int width = image[0].size(); + assert(y < height && x < width); + + // init mask + ImageMask mask(height, ImageMaskRow(width, false)); + + int ref = image[y][x]; + + MWT_rec(ref, mask, image, x, y, T); + + // return mask + return mask; + } + #+END_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Bonus_2/pictures/example_pigs_135_360_20.png b/Informatik_I/Bonus_2/pictures/example_pigs_135_360_20.png new file mode 100644 index 0000000..d92ddcb Binary files /dev/null and b/Informatik_I/Bonus_2/pictures/example_pigs_135_360_20.png differ diff --git a/Informatik_I/Bonus_2/pictures/images_explanation.png b/Informatik_I/Bonus_2/pictures/images_explanation.png new file mode 100644 index 0000000..a1db9e0 Binary files /dev/null and b/Informatik_I/Bonus_2/pictures/images_explanation.png differ diff --git a/Informatik_I/Bonus_3/README.org b/Informatik_I/Bonus_3/README.org new file mode 100644 index 0000000..db5d920 --- /dev/null +++ b/Informatik_I/Bonus_3/README.org @@ -0,0 +1,15 @@ +#+title: Magic Growing + +#+author: JirR02 +* SIKE! +:PROPERTIES: +:CUSTOM_ID: sike +:END: +[[./pictures/sike.jpg]] + +Spass... ist in einem seperaten Repo +[[https://www.youtube.com/watch?v=xvFZjo5PgG0][hier]]. + +-------------- + +Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Bonus_2/pictures/sike.jpg b/Informatik_I/Bonus_3/pictures/sike.jpg similarity index 100% rename from Informatik_I/Bonus_2/pictures/sike.jpg rename to Informatik_I/Bonus_3/pictures/sike.jpg diff --git a/Informatik_I/Exercise_10/Task_1a/README.org b/Informatik_I/Exercise_10/Task_1a/README.org index f5555be..8d9f97c 100644 --- a/Informatik_I/Exercise_10/Task_1a/README.org +++ b/Informatik_I/Exercise_10/Task_1a/README.org @@ -44,3 +44,7 @@ For example, for the input given above, this value is 8. // POST: Returns the address of the i-th element of vec. const int *lookup(const std::vector &vec, const int i) { return &vec[i]; } #+end_src + +-------------- + +Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_10/Task_1b/README.org b/Informatik_I/Exercise_10/Task_1b/README.org index 5783a11..7836224 100644 --- a/Informatik_I/Exercise_10/Task_1b/README.org +++ b/Informatik_I/Exercise_10/Task_1b/README.org @@ -43,3 +43,7 @@ For example, for the input given above this value is 56. // location a and the integer at location b. void add(int *res, const int *a, const int *b) { *res = *a + *b; } #+end_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_10/Task_2/README.org b/Informatik_I/Exercise_10/Task_2/README.org index 873f4ac..eb04327 100644 --- a/Informatik_I/Exercise_10/Task_2/README.org +++ b/Informatik_I/Exercise_10/Task_2/README.org @@ -67,3 +67,7 @@ int largest_difference(iterator begin, iterator end) { return max_dif; } #+end_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_10/Task_3/README.org b/Informatik_I/Exercise_10/Task_3/README.org index aa96fd4..4cf320d 100644 --- a/Informatik_I/Exercise_10/Task_3/README.org +++ b/Informatik_I/Exercise_10/Task_3/README.org @@ -183,3 +183,7 @@ void Queue::print() const { std::cout << "]"; } #+end_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_10/Task_4/README.org b/Informatik_I/Exercise_10/Task_4/README.org index 42c75d4..665ca39 100644 --- a/Informatik_I/Exercise_10/Task_4/README.org +++ b/Informatik_I/Exercise_10/Task_4/README.org @@ -122,3 +122,7 @@ int main() { return 0; } #+end_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_11/Task_1/README.org b/Informatik_I/Exercise_11/Task_1/README.org new file mode 100644 index 0000000..202ab35 --- /dev/null +++ b/Informatik_I/Exercise_11/Task_1/README.org @@ -0,0 +1,175 @@ +#+title: [Exam 2022.01 (MATH/PHYS/RW)] Circular Linked List +#+author: JirR02 + +* Circular Linked List + + A circular linked list is a variation of a linked list in which the last node points to the first node, completing a full circle of nodes. In other words, this variation of the linked list doesn't have a null element at the end. + + Take a brief look at the file Node.hpp. + + A Node contains a pointer to the next Node, as well as a value, which is the data stored in the node: + + #+BEGIN_src cpp + struct Node { + int value; + Node* next; + } + #+END_src + + In our implementation, each Node stores a value of type int. Moreover, we reserve the value 0 to indicate the sentinel Node (see below). + + Now open the the file =CircularLinkedList.hpp=. + + A =CircularLinkedList= contains a single public member variable =Node* sentinel=. The sentinel node is only there to facilitate the implementation. It is the only node in the list when the list is empty, and it can be identified as being the only node where ~value = 0~. + + [[./pictures/1_1.png]] + + Notice that, in an empty list, the next pointer of the sentinel node points to the sentinel itself. + + A list containing a single value 1 looks like in the following image: the sentinel's next points to the first node of the list, and that node points to the sentinel in a circular fashion. + + [[./pictures/one_value.png]] + + New values can be inserted in the list either at the beginning or at the end. A node inserted at the beginning comes immediately after the sentinel, while a node inserted at the end comes immediately before the sentinel. + +** Your Task + + Your task is to implement the following functions in file =tasks.hpp=: + + 1. =void CircularLinkedList::insertAtBegin(int value)=: given a strictly positive value, inserts the value in a node at the beginning of the list; + 1. =void CircularLinkedList::insertAtEnd(int value)=: given a strictly positive value, inserts the value in a node at the end of the list; hint: a sentinel can become a normal node (and vice versa); + 1. =void CircularLinkedList::removeValues(int value)=: removes all the nodes containing the provided value; leaves the list in the same state if no node with the provided value is present. + 1. =CircularLinkedList::~CircularLinkedList()=: deconstructs the whole list, which includes deallocating all its nodes and the sentinel + +** Input Format + + Various commands can be entered to test your implementation; each consists of a command followed by appropriate arguments: + + - =ib V= : add value V at the beginning + + - =ie V= : add value V at the end + + - =r V= : removes all nodes with value V + + - =s= : show the current status of the list + + - =exit= : exits the program without checking for the correct deallocation of all the nodes + + - =exitSafe= : exits the program checking the correct deallocation of all the nodes + +*** Sample Interactions + + #+BEGIN_QUOTE + Copy & Paste: in the ETH exam room use CTRL+SHIFT+C to copy and CTRL+SHIFT+V to paste into the console. + #+END_QUOTE + +**** Creating and showing a simple list with two values + + Input: + + #+BEGIN_src shell + ib 1 + ib 2 + s + exit + #+END_src + + Output: + + #+BEGIN_src shell + List=[(2)=>(1)] + #+END_src + +**** Inserting two elements and removing one + + Input: + + #+BEGIN_src shell + ib 1 + ie 2 + s + r 1 + s + exit + #+END_src + + Output: + + #+BEGIN_src shell + List=[(1)=>(2)] + List=[(2)] + #+END_src + +* Solution + + #+BEGIN_src cpp + #pragma once + + #include "CircularLinkedList.hpp" + #include "Node.hpp" + #include + + // PRE: value > 0 + // POST: insert a new Node containing the value at the beginning of the list + void CircularLinkedList::insertAtBegin(int value) { + assert(value > 0); + + Node *ram = new Node(value); + ram->next = sentinel->next; + sentinel->next = ram; + } + + // PRE: value > 0 + // POST: insert a new Node containing the value at the end of the list + void CircularLinkedList::insertAtEnd(int value) { + assert(value > 0); + + Node *last = sentinel->next; + + while (last->next != sentinel) + last = last->next; + + Node *ram = new Node(value); + last->next = ram; + ram->next = sentinel; + } + + // PRE: value > 0 + // POST: removes *all* the nodes with the provided value from the list + // and deallocates the memory of the deleted nodes. + void CircularLinkedList::removeValues(int value) { + assert(value > 0); + + Node *cur = sentinel; + Node *ram = cur->next; + + while (ram != sentinel) { + if (ram->value == value) { + cur->next = ram->next; + delete ram; + ram = cur->next; + } else { + cur = ram; + ram = cur->next; + } + } + } + + // POST: Deconstructs the whole list, which includes deallocating + // all its nodes and the sentinel + CircularLinkedList::~CircularLinkedList() { + Node *cur = sentinel; + Node *ram = cur->next; + + while (ram != sentinel) { + cur->next = ram->next; + delete ram; + ram = cur->next; + } + delete ram; + } + #+END_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_11/Task_1/pictures/1_1.png b/Informatik_I/Exercise_11/Task_1/pictures/1_1.png new file mode 100644 index 0000000..99bbb78 Binary files /dev/null and b/Informatik_I/Exercise_11/Task_1/pictures/1_1.png differ diff --git a/Informatik_I/Exercise_11/Task_1/pictures/one_value.png b/Informatik_I/Exercise_11/Task_1/pictures/one_value.png new file mode 100644 index 0000000..5183db9 Binary files /dev/null and b/Informatik_I/Exercise_11/Task_1/pictures/one_value.png differ diff --git a/Informatik_I/Exercise_11/Task_1/pictures/operations.png b/Informatik_I/Exercise_11/Task_1/pictures/operations.png new file mode 100644 index 0000000..e23aca7 Binary files /dev/null and b/Informatik_I/Exercise_11/Task_1/pictures/operations.png differ diff --git a/Informatik_I/Exercise_11/Task_1/pictures/operations_2.png b/Informatik_I/Exercise_11/Task_1/pictures/operations_2.png new file mode 100644 index 0000000..e23aca7 Binary files /dev/null and b/Informatik_I/Exercise_11/Task_1/pictures/operations_2.png differ diff --git a/Informatik_I/Exercise_11/Task_2/README.org b/Informatik_I/Exercise_11/Task_2/README.org new file mode 100644 index 0000000..940138e --- /dev/null +++ b/Informatik_I/Exercise_11/Task_2/README.org @@ -0,0 +1,152 @@ +#+TITLE: Smart Pointers +#+AUTHOR: JirR02 + +* Task + + The objective of this problem is to implement a reference-count smart pointer, with functionality similar to that of a std::shared_ptr. Smart pointers implement the same functionality as regular pointers, but additionally they automatically take care of deallocating the object they point to when it is no longer needed. Reference-count smart pointers achieve this by allocating and maintaining a counter in memory together with the actual pointed-to object, which represents the number of smart pointers currently referencing the object. Any time a new smart pointer to an object is created or one is destroyed, this counter has to be incremented or decremented, respectively. When the last smart pointer to an object is destroyed, the counter will be decremented to + + and the smart pointer will know that the object is no longer referenced; it can then deallocate the object. + + The following example illustrates the process: + + #+BEGIN_src cpp + Smart a, b, c; + a = Smart(new tracked()); + // The smart pointer 'a' now points to the new + // tracked object with a reference count of 1. + c = Smart(new tracked()); + // Another smart pointer 'c' now points to the + // second new tracked object with count 1. + b = a; + // 'a' and 'b' now both point to the first object, + // their shared counter is incremented to 2. + c = Smart(); + // A null smart pointer is assigned to 'c'; the + // smart pointer previously stored in 'c' is destroyed + // and its counter is decremented. Since the count + // is now zero, the second tracked object is deallocated. + return; + // At the end of the function, the smart + // pointers 'a' and 'b' are both destroyed, their + // counter is decremented twice, and the first + // tracked object is deallocated. + #+END_src + + + *Locations*: The declarations of the smart pointer class (Smart) and member functions is provided in file =smart.h=. The implementation of member functions should be done in file =smart.cpp=. Smart pointers encapsulate pointers to objects of class tracked, which is declared in file =smart.h=. + + *Structure*: In class Smart, member variable =ptr= represents the pointer (potentially shared by several object of class Smart) to the underlying pointed-to object. Member variable =count= represents the (shared) location containing the number of objects of class Smart currently holding the pointed-to object. Alternatively, both pointers may be =nullptr=, which corresponds to the notion of a /null/ smart pointer. A null smart pointer does not manage any memory. + + Objects pointed by smart pointers belong to class tracked, which is a linked list node where the next pointer is represented using a smart pointer. In particular, tests will use this structure to build linked lists with shared nodes, and check at the end that everything was correctly deallocated. To that end, every object of class tracked is tracked behind the scenes. + + Steps: + + 1. Implement the default constructor for class =Smart=. The default constructor should create a null smart pointer. + + 1. Implement the constructor =Smart(tracked* t)=. If =t==nullptr=, this should return a null smart pointer, otherwise, this should create a smart pointer to =t= with a reference count of \(1\). You may assume that =t= points to memory newly allocated by =new= that is not already being managed by another smart pointer. + + 1. Implement the copy constructor =Smart(const Smart& src)= that returns a new smart pointer to the memory pointed to by =src= and increments the shared reference counter. + + 1. Implement the destructor =~Smart()=. For non-null pointers, it should decrement the reference counter and deallocate the pointed-to object if the resulting count is zero. + + 1. Implement the assignment operator =Smart& operator=(const Smart& src)= that creates a copy of the provided smart pointer (incrementing its reference counter) and decrements the counter of the smart pointer of the left hand side of the assignment (and potentially deallocates the memory it points to). + + *Optional*: Figure out the situations in which smart pointers are not suitable for memory management, in the sense that they may lead to memory leaks. You may look at the tests which leak memory for inspiration. + + *Note*: In order to *debug*, you may execute code that you place in the function =your_own_tests= located in the =smart.cpp= file. The main function has a =switch= statement that chooses between a series of functions for different test scenarios. This =switch= defaults to =your_own_tests=. So if you enter =-1= for =test_id=, =your_own_tests= will be executed. + +* Solutions + + #+BEGIN_src cpp + #include "smart.h" + #include "tracker.h" + + Smart::Smart() { + count = nullptr; + ptr = nullptr; + } + + Smart::Smart(tracked *t) /* TODO */ { + if (t == nullptr) { + count = nullptr; + ptr = nullptr; + } else { + ptr = t; + int *counter = new int; + *counter = 1; + count = counter; + } + } + + Smart::Smart(const Smart &src) /* TODO */ { + count = src.count; + ptr = src.ptr; + if (count != nullptr) + (*count)++; + } + + Smart::~Smart() { + if (count != nullptr) { + (*count)--; + if (*count == 0) { + delete count; + delete ptr; + count = nullptr; + ptr = nullptr; + } + } + } + + Smart &Smart::operator=(const Smart &src) { + if (src == *this) + return *this; + + if (count != nullptr) { + (*count)--; + if (*count == 0) { + delete count; + delete ptr; + } + } + + count = src.count; + ptr = src.ptr; + + if (count != nullptr) + (*count)++; + + return *this; + } + + tracked &Smart::operator*() { return *ptr; } + + const tracked &Smart::operator*() const { return *ptr; } + + tracked *Smart::operator->() { return ptr; } + + const tracked *Smart::operator->() const { return ptr; } + + bool Smart::operator==(const Smart &cmp) const { return (ptr == cmp.ptr); } + + bool Smart::operator!=(const Smart &cmp) const { return !(*this == cmp); } + + int Smart::get_count() const { + if (this->count == nullptr) + return 0; + else + return *(this->count); + } + + void your_own_tests() { + // EXTRA TESTS ? + } + + // Answer to optional question + /* + FILL IN WITH YOUR ANSWER + */ + #+END_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_11/Task_3/README.org b/Informatik_I/Exercise_11/Task_3/README.org new file mode 100644 index 0000000..bf963dc --- /dev/null +++ b/Informatik_I/Exercise_11/Task_3/README.org @@ -0,0 +1,98 @@ +#+TITLE: [Hidden tests][Exam 2019.02 RW] Sorted List +#+AUTHOR: JirR02 + +* Sorted Linked List + + In this task you complete the functions =add= and =remove= of a singly linked sorted (in ascending order) list. + + One invariant of the sorted linked list is the following: for subsequent nodes =n= and =next= it holds \(n.value \leq next.value \). + + [[./pictures/SortedLinkedList.png]] + +*** Chosen memory management + + We do not want to deal with the memory management by ourselves. Therefore we use =std::shared_ptr= instead of normal pointers. Behind the scenes, shared pointers contain a counter that counts the number of references to the pointer. As soon as this counter reaches the value zero, the object behind the pointer is removed, i.e. =delete= is called automatically. + + Otherwise, a shared pointer has nearly the same functionality as a normal pointer. For this exercise: + + - Where we previously used the pointer type node*, we now use =std::shared_ptr= + - Members of a shared pointer are accessed like on a normal pointer: using the =->= operator. + - Assignments and comparisons work in the same way as for normal pointers. + - Only allocation, like new node(=value=), is replaced by =std::make_shared(value)=. + - Calls to delete can be omitted completely. Shared pointers call delete automatically when required. + + Consider for example the finished implementation of the =print= function and the already implemented part of the add function. + +** Tasks + + 1. Complete the function =void sorted_list::add(int value)= such that a new node with the provided value is inserted into the linked list. The list needs to remain sorted in ascending order. Several nodes with the same value may be contained. The order of the nodes with same value is unimportant. + + 1. Complete the function bool =sorted_list::remove(int value)= such that a node with the given value is removed from the list. If no node with this value exists, the function should return =false=. Otherwise one (and only one) element is removed and the function returns =true=. *Hint*: help yourself with copy&paste from the previous function add. + +** The command interface + + The main function implements the command interface that understands the following commands: + + - =add {int}= ("add" followed by a sequence of integers) -- calls add on a sorted list for all the integers provided. Example: add 1 2 3 adds numbers 1, 2 and 3 to the list. + - =remove {int}= ("remove" followed by a sequence of integers) -- calls remove on a sorted list for all integers provided. Example: remove 3 6 removes an element with value 3 and an element with value 6 from the list (as far as available). + - =print= -- calls print on the linked list. + - =end= -- ends the program. + +* Solution + + #+BEGIN_src cpp + #include "sorted_list.h" + + // post: add a new node with value to the sorted linked list + // several nodes with the same value are possible + void sorted_list::add(int value) { + // this creates a new node in dynamic memory, wrapped in a shared pointer + // analogously to new node(value) for normal pointers + node_ptr newNode = std::make_shared(value); + + node_ptr prev = nullptr; + node_ptr n = first; + while (n != nullptr && n->value < value) { + prev = n; + n = n->next; + } + + if (prev == nullptr) { + newNode->next = first; + first = newNode; + } else { + newNode->next = n; + prev->next = newNode; + } + } + + // post: remove the first node which holds 'value', if any. + // if there is no such node, return false + // otherwise return true + bool sorted_list::remove(int value) { + node_ptr searchNode = std::make_shared(value); + + node_ptr prev = nullptr; + node_ptr n = first; + while (n != nullptr && n->value != searchNode->value) { + prev = n; + n = n->next; + } + + if (n != nullptr) { + if (prev != nullptr) { + prev->next = n->next; + return true; + } else { + first = n->next; + return true; + } + } else { + return false; + } + } + #+END_src + + -------------- + + Made by JirR02 in Switzerland πŸ‡¨πŸ‡­ diff --git a/Informatik_I/Exercise_11/Task_3/pictures/SortedLinkedList.png b/Informatik_I/Exercise_11/Task_3/pictures/SortedLinkedList.png new file mode 100644 index 0000000..8c29c85 Binary files /dev/null and b/Informatik_I/Exercise_11/Task_3/pictures/SortedLinkedList.png differ diff --git a/README.org b/README.org index ed4413e..eb724be 100644 --- a/README.org +++ b/README.org @@ -1,16 +1,12 @@ #+title: ETH Computer Science Projects - #+author: JirR02 + In this respository the computer science project of the ETH of D-ITET 2024 are managed. They can be used for inspiration. -The projects are uploaded on -[[https://expert.ethz.ch/enrolled/AS24/itet0/exercises][Code Expert]]. +The projects are uploaded on [[https://expert.ethz.ch/enrolled/AS24/itet0/exercises][Code Expert]]. * DISCLAIMER!!! -:PROPERTIES: -:CUSTOM_ID: disclaimer -:END: I assume no liability for possible errors in the code (it certainly has a few in it, since I write it myself).