halfway part 2

This commit is contained in:
Christopher Sanden
2025-11-05 23:32:00 +01:00
parent 1ec6da4771
commit d6bb9bd233
10 changed files with 371 additions and 10 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,2 @@
# Ignore
*.zip
*.zip

View File

@@ -5,10 +5,13 @@
#include <string>
#include "option1.h"
#include "SharedLib.h"
#include "TLinkedList.h"
#include "TPerson.h"
TLinkedList g, e;
/**
* @brief Callback function to process one name.
*/
static bool NameReadCallback(const int aIndex, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName)
{
std::cout << "Reading Name " << (aIndex + 1) << " of " << aTotalCount << ": "
@@ -18,19 +21,70 @@ static bool NameReadCallback(const int aIndex, const int aTotalCount, const std:
// Return false when aIndex is 9 to stop the loop after this one.
return (aIndex < 9);
}
*/
// *Inspired* by the provided NameReadCallback given above
static bool onNameRead(const int aIndex, int aTotalCount, const std::string& aFirstName, const std::string& aLastName)
{
const ENumStatus status = (aIndex < 1500) ? EMPLOYEE : GUEST;
const TPerson p(aFirstName, aLastName, status);
if (status == EMPLOYEE)
e.Append(p);
else
g.Append(p);
std::cout << "[" <<aIndex << "] " << aLastName << ", " << aFirstName << " | status: " << (status == 1 ? "Employee" : "Guest")
<< " | cabin size: " << p.cabinSize << std::endl;
std::cout << "---------------------------------------------------------------" << std::endl;
return true;
}
int RunApp()
{
// Path to the names data file
std::string filename = "F:\\IKT203\\VisualStudio\\DATA\\random_names.txt";
/* Path to the names data file
This is MY absolute path -- change to your local path for this to read properly
something like "C:\Users\Username\FolderYouSavedTheSubmissionIn\Exam\IKT203Exam\DATA\random_names.txt"
Double slash is needed for string to pass the correct file path */
const std::string filename = "C:\\Users\\csand\\IKT203\\Exam\\IKT203Exam\\DATA\\random_names.txt";
std::cout << "Reading first 10 names from file: " << filename << "\n\n";
std::cout << "Reading names and grouping them: " << "\n" << std::endl;
// Call the utility function with the name callback
readNamesFromFile(filename, NameReadCallback);
readNamesFromFile(filename, onNameRead);
std::cout << "\nFinished reading names." << std::endl;
std::cout << "\nFinished reading names.\n\nSorting." << std::endl;
// Merge sorting
e.Sort();
g.Sort();
// Attempt at "beautifying" the terminal output somewhat
std::cout << "\n\n\n---------------------------------------------------------------" << std::endl;
std::cout << "Employees merge sorted alphabetically" << std::endl;
std::cout << "---------------------------------------------------------------" << std::endl;
for (int i = 0; i < e.GetSize(); i++) {
std::cout << "[" << i << "] " << e.GetAtIndex(i).lastName << ", " << e.GetAtIndex(i).firstName
<< " | status: Employee | cabin size: " << e.GetAtIndex(i).cabinSize << std::endl;
std::cout << "---------------------------------------------------------------" << std::endl;
}
std::cout << "\n\n\n---------------------------------------------------------------" << std::endl;
std::cout << "Guests merger sorted alphabetically" << std::endl;
std::cout << "---------------------------------------------------------------" << std::endl;
for (int i = 0; i < g.GetSize(); i++) {
std::cout << "[" << i << "] " << g.GetAtIndex(i).lastName << ", " << g.GetAtIndex(i).firstName
<< " | status: Guest | cabin size: " << g.GetAtIndex(i).cabinSize << std::endl;
std::cout << "---------------------------------------------------------------" << std::endl;
}
return 0;
}

View File

@@ -2,7 +2,11 @@
# Define a library target named "SharedLib".
# We use STATIC because we are using cpp and header files.
add_library(SharedLib STATIC)
add_library(SharedLib STATIC
TPerson.cpp
TPerson.h
TLinkedList.cpp
TLinkedList.h)
# --- Step 2: Add Header Files to the Library ---

View File

@@ -1,7 +1,5 @@
#include "FileReaderUtils.h"
#include "FileReaderUtils.h"
int GetRecordCount(const std::string& aHeaderLine)
{
size_t recordPos = aHeaderLine.find("records:=");

View File

@@ -0,0 +1,187 @@
#include "TLinkedList.h"
#include <iostream>
TLinkedList::~TLinkedList()
{
const Node* cur = head;
while (cur) {
const Node* next = cur->next;
delete cur;
cur = next;
}
}
void TLinkedList::Append(const TPerson& person)
{
Node* newNode = new Node(person);
if (size == 0) {
head = tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
size++;
}
void TLinkedList::Prepend(const TPerson& person)
{
Node* newNode = new Node(person);
if (size == 0) {
head = tail = newNode;
} else {
newNode->next = head;
head = newNode;
}
size++;
}
void TLinkedList::InsertAtIndex(const int index, const TPerson& person)
{
if (index < 0 || index > size) {
std::cout << "Index out of range\n";
return;
}
if (index == 0) {
Prepend(person);
return;
}
if (index == size) {
Append(person);
return;
}
Node* prev = head;
for (int i = 0; i < index - 1; ++i)
prev = prev->next;
Node* newNode = new Node(person);
newNode->next = prev->next;
prev->next = newNode;
size++;
}
void TLinkedList::Remove(const int index)
{
if (index < 0 || index >= size)
return;
if (index == 0) {
const Node* oldHead = head;
head = head->next;
if (size == 1)
tail = nullptr;
delete oldHead;
size--;
return;
}
Node* prev = head;
for (int i = 0; i < index - 1; ++i)
prev = prev->next;
const Node* toDelete = prev->next;
prev->next = toDelete->next;
if (toDelete == tail)
tail = prev;
delete toDelete;
size--;
}
TPerson TLinkedList::GetAtIndex(const int index) const
{
if (index < 0 || index >= size) {
std::cout << "Index out of range\n";
// return dummy
return {"N/A", "N/A", GUEST};
}
Node* cur = head;
for (int i = 0; i < index; ++i)
cur = cur->next;
return cur->person;
}
void TLinkedList::MergeSortSplit(Node *source, Node **front, Node **back)
{
if (source == nullptr || source->next == nullptr) {
*front = source;
*back = nullptr;
return;
}
Node* slow = source;
const Node* fast = source->next;
while (fast != nullptr) {
fast = fast->next;
if (fast != nullptr) {
slow = slow->next;
fast = fast->next;
}
}
*front = source;
*back = slow->next;
slow->next = nullptr;
}
TLinkedList::Node *TLinkedList::MergeList(Node *a, Node *b)
{
if (a == nullptr)
return b;
if (b == nullptr)
return a;
Node* result = nullptr;
if (a->person < b->person) {
result = a;
result->next = MergeList(a->next, b);
}
else {
result = b;
result->next = MergeList(a, b->next);
}
return result;
}
TLinkedList::Node *TLinkedList::MergeSort(Node *head)
{
if (head == nullptr || head->next == nullptr)
return head;
Node* front;
Node* back;
MergeSortSplit(head, &front, &back);
front = MergeSort(front);
back = MergeSort(back);
return MergeList(front, back);
}
void TLinkedList::Sort()
{
this->head = MergeSort(head);
Node* cur = this->head;
tail = nullptr;
while (cur) {
if (cur->next == nullptr)
tail = cur;
cur = cur->next;
}
}

View File

@@ -0,0 +1,56 @@
#ifndef IKT203_COURSE_ASSIGNMENTS_TLINKEDLIST_H
#define IKT203_COURSE_ASSIGNMENTS_TLINKEDLIST_H
#include "TPerson.h"
class TLinkedList {
private:
struct Node {
TPerson person;
Node* next;
explicit Node(const TPerson& p) : person(p), next(nullptr) {}
void setNext(Node* n)
{
this->next = n;
}
[[nodiscard]] static Node* GetNext(const Node* n)
{
return n->next;
}
[[nodiscard]] static TPerson GetPerson(Node* n)
{
return n->person;
}
};
Node* head;
Node* tail;
int size;
public:
TLinkedList() : head(nullptr), tail(nullptr), size(0) {}
~TLinkedList();
void Append(const TPerson& person);
void Prepend(const TPerson& person);
void InsertAtIndex(int index, const TPerson& person);
void Remove(int index);
[[nodiscard]] TPerson GetAtIndex(int index) const;
[[nodiscard]] int GetSize() const { return size; }
static void MergeSortSplit(Node* source, Node** front, Node** back);
static Node* MergeList(Node*, Node*);
static Node* MergeSort(Node*);
void Sort();
};
#endif //IKT203_COURSE_ASSIGNMENTS_TLINKEDLIST_H

View File

@@ -0,0 +1,14 @@
#include "TPerson.h"

View File

@@ -0,0 +1,32 @@
#ifndef IKT203_COURSE_ASSIGNMENTS_TPERSON_H
#define IKT203_COURSE_ASSIGNMENTS_TPERSON_H
#include <string>
#include "Utils.h"
enum ENumStatus {
GUEST,
EMPLOYEE
};
struct TPerson {
std::string firstName;
std::string lastName;
ENumStatus status;
int cabinSize = Utils::RandomInt(1, 4);
TPerson(std::string f, std::string l, ENumStatus s) : firstName(std::move(f)), lastName(std::move(l)), status(s){}
~TPerson() = default;
bool operator<(const TPerson& other) const
{
if (lastName < other.lastName) return true;
if (lastName > other.lastName) return false;
// same last name → compare first name
return firstName < other.firstName;
}
};
#endif //IKT203_COURSE_ASSIGNMENTS_TPERSON_H

View File

@@ -1,5 +1,6 @@
#include "Utils.h"
#include <ctime>
#include <iostream>
#include <limits>
@@ -76,3 +77,17 @@ int Utils::RemoveLine(TDoublyLinkedList &document, TStack &undoStack, TStack &re
}
return index;
}
int Utils::RandomInt(const int min, const int max)
{
static bool isSeeded = false;
if (!isSeeded) {
std::srand(static_cast<unsigned>(std::time(nullptr))); //<---- not the "best" random seeding available
isSeeded = true; // but sufficient for this use case
}
if (max <= min)
return 0;
return min + rand() % (max - min + 1); // <---- Limited randomness, but again
} // sufficient for this use case

View File

@@ -10,6 +10,7 @@ class Utils {
static int Insert(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index);
static void PrintList(const TDoublyLinkedList &document);
static int RemoveLine(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index);
static int RandomInt(int, int);