310 lines
8.6 KiB
C++
310 lines
8.6 KiB
C++
// Submission-01.cpp : Defines the entry point for the application.
|
|
//
|
|
|
|
#include "main.h"
|
|
#include <iostream>
|
|
|
|
|
|
|
|
// Movie class with bitwise genre flags
|
|
enum EGenreFlags {
|
|
Action = 0x0001,
|
|
Comedy = 0x0002,
|
|
Drama = 0x0004,
|
|
Horror = 0x0008,
|
|
SciFi = 0x0010,
|
|
Romance = 0x0020,
|
|
Documentary = 0x0040,
|
|
Thriller = 0x0080,
|
|
Crime = 0x0100,
|
|
Fantasy = 0x0200,
|
|
Animation = 0x0400,
|
|
Adventure = 0x0800
|
|
};
|
|
|
|
static std::string GenreFlagsToString(int genreFlags) {
|
|
std::string result;
|
|
if (genreFlags & EGenreFlags::Action) result += "Action ";
|
|
if (genreFlags & EGenreFlags::Comedy) result += "Comedy ";
|
|
if (genreFlags & EGenreFlags::Drama) result += "Drama ";
|
|
if (genreFlags & EGenreFlags::Horror) result += "Horror ";
|
|
if (genreFlags & EGenreFlags::SciFi) result += "SciFi ";
|
|
if (genreFlags & EGenreFlags::Romance) result += "Romance ";
|
|
if (genreFlags & EGenreFlags::Documentary) result += "Documentary ";
|
|
if (genreFlags & EGenreFlags::Thriller) result += "Thriller ";
|
|
if (genreFlags & EGenreFlags::Crime) result += "Crime ";
|
|
if (genreFlags & EGenreFlags::Fantasy) result += "Fantasy ";
|
|
if (genreFlags & EGenreFlags::Animation) result += "Animation ";
|
|
if (genreFlags & EGenreFlags::Adventure) result += "Adventure ";
|
|
return result.empty() ? "None" : result;
|
|
}
|
|
|
|
// Movie class definition
|
|
class TMovie {
|
|
private:
|
|
std::string title;
|
|
std::string director;
|
|
int year;
|
|
int genreFlags; // Bitwise combination of EGenreFlags
|
|
float rating; // Scale from 0.0 to 10.0
|
|
|
|
public:
|
|
TMovie(std::string t, std::string d, int y, int g, float r)
|
|
: title(t), director(d), year(y), genreFlags(g), rating(r) {}
|
|
void PrintInfo() const {
|
|
std::cout << "Title: " << title << "\nDirector: " << director
|
|
<< "\nYear: " << year << "\nGenres: " << GenreFlagsToString(genreFlags)
|
|
<< "\nRating: " << rating << "/10\n";
|
|
}
|
|
std::string GetTitle() const { return title; }
|
|
std::string GetDirector() const { return director; }
|
|
int GetYear() const { return year; }
|
|
float GetRating() const { return rating; }
|
|
int GetGenreFlags() const { return genreFlags; }
|
|
bool HasGenre(EGenreFlags genre) const {
|
|
return (genreFlags & genre) != 0;
|
|
}
|
|
};
|
|
|
|
typedef bool (*FCheckMovie)(TMovie*, void*);
|
|
typedef void (*FMovieIndex)(TMovie*, int);
|
|
|
|
// Doubly Linked List TMovieNode definition
|
|
struct TMovieNode {
|
|
TMovie* movie;
|
|
TMovieNode* next;
|
|
TMovieNode* prev;
|
|
TMovieNode(TMovie* m) : movie(m), next(nullptr), prev(nullptr) {}
|
|
};
|
|
|
|
// Doubly Linked List class definition with dummy node, head, and tail O(1) operations
|
|
class TMovieList {
|
|
private:
|
|
TMovieNode* head; // Always points to dummy node
|
|
TMovieNode* tail;
|
|
int size;
|
|
|
|
// Helper function to get node at index
|
|
TMovieNode* InternalGetAtIndex(int aIndex) {
|
|
if (aIndex < 0 || aIndex >= size) return nullptr;
|
|
TMovieNode* current;
|
|
// Optimize traversal direction, if index is in the first half, start from head, else from tail
|
|
if (aIndex < size / 2) {
|
|
current = head->next; // Start from the beginning
|
|
for (int i = 0; i < aIndex; i++) {
|
|
current = current->next;
|
|
}
|
|
}
|
|
else {
|
|
current = tail; // Start from the end
|
|
for (int i = size - 1; i > aIndex; i--) {
|
|
current = current->prev;
|
|
}
|
|
}
|
|
return current;
|
|
}
|
|
|
|
public:
|
|
TMovieList() {
|
|
head = new TMovieNode(nullptr); // Dummy node
|
|
tail = head; // Initially, tail is the same as head
|
|
size = 0;
|
|
}
|
|
~TMovieList() {
|
|
Clear();
|
|
delete head; // Delete dummy node
|
|
}
|
|
void Clear() {
|
|
TMovieNode* current = head->next; // Start from the first real node
|
|
while (current) {
|
|
TMovieNode* toDelete = current;
|
|
current = current->next;
|
|
delete toDelete->movie;
|
|
delete toDelete;
|
|
}
|
|
head->next = nullptr;
|
|
tail = head; // Reset tail to dummy node
|
|
size = 0;
|
|
}
|
|
|
|
// Insertion at the end O(1)
|
|
void Append(TMovie* aMovie) {
|
|
TMovieNode* newNode = new TMovieNode(aMovie);
|
|
newNode->prev = tail;
|
|
tail->next = newNode;
|
|
tail = newNode;
|
|
size++;
|
|
}
|
|
|
|
// Prepend at the beginning O(1)
|
|
void Prepend(TMovie* aMovie) {
|
|
TMovieNode* newNode = new TMovieNode(aMovie);
|
|
newNode->next = head->next;
|
|
newNode->prev = head;
|
|
if (head->next) {
|
|
head->next->prev = newNode;
|
|
} else {
|
|
tail = newNode; // If list was empty, update tail
|
|
}
|
|
head->next = newNode;
|
|
size++;
|
|
}
|
|
|
|
// GetAtIndex O(n) check direction to optimize
|
|
TMovie* GetAtIndex(int aIndex) {
|
|
return InternalGetAtIndex(aIndex)->movie;
|
|
}
|
|
|
|
// Remove at index O(n) use GetAtIndex to find node
|
|
bool RemoveAtIndex(int aIndex) {
|
|
if (aIndex < 0 || aIndex >= size) return false;
|
|
TMovieNode* toDelte = InternalGetAtIndex(aIndex);
|
|
if (!toDelte) return false;
|
|
if (toDelte->prev) {
|
|
toDelte->prev->next = toDelte->next;
|
|
}
|
|
if (toDelte->next) {
|
|
toDelte->next->prev = toDelte->prev;
|
|
} else {
|
|
tail = toDelte->prev; // Update tail if last node is removed
|
|
}
|
|
delete toDelte->movie;
|
|
delete toDelte;
|
|
size--;
|
|
return true;
|
|
}
|
|
|
|
// Reverse the list O(n)
|
|
void Reverse() {
|
|
TMovieNode* current = head->next;
|
|
TMovieNode* prev = nullptr;
|
|
tail = head->next;
|
|
while (current) {
|
|
TMovieNode* nextNode = current->next;
|
|
current->next = prev;
|
|
current->prev = nextNode;
|
|
prev = current;
|
|
current = nextNode;
|
|
}
|
|
head->next = prev;
|
|
if (prev) {
|
|
prev->prev = head;
|
|
}
|
|
}
|
|
|
|
// SearchFor O(n)
|
|
TMovie* SearchFor(FCheckMovie aCheckFunc, void* aUserData) {
|
|
TMovieNode* current = head->next;
|
|
while (current) {
|
|
if (aCheckFunc(current->movie, aUserData)) {
|
|
return current->movie;
|
|
}
|
|
current = current->next;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// Every movie in the list O(n)
|
|
void Every(FMovieIndex aIndexFunc) {
|
|
TMovieNode* current = head->next;
|
|
int index = 0;
|
|
while (current) {
|
|
aIndexFunc(current->movie, index);
|
|
current = current->next;
|
|
index++;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
using namespace std;
|
|
|
|
static void PrintNode(std::string* data, int index) {
|
|
cout << "Node " << index << ": " << *data << endl;
|
|
}
|
|
|
|
static bool CheckMovieByTitle(TMovie* movie, void* title) {
|
|
return movie->GetTitle() == *(static_cast<std::string*>(title));
|
|
}
|
|
|
|
static bool CheckMovieByDirector(TMovie* movie, void* director) {
|
|
return movie->GetDirector() == *(static_cast<std::string*>(director));
|
|
}
|
|
|
|
static bool FindAllMovieByGenre(TMovie* movie, void* genre) {
|
|
if(movie->HasGenre(*(static_cast<EGenreFlags*>(genre)))) {
|
|
movie->PrintInfo();
|
|
std::cout << "-------------------" << std::endl;
|
|
}
|
|
// Always return false to continue searching
|
|
return false;
|
|
}
|
|
|
|
|
|
int main()
|
|
{
|
|
|
|
std::cout << "--- Submission 1: Linked List ---" << std::endl;
|
|
|
|
// Create a movie list
|
|
TMovieList movieList;
|
|
// Add some movies
|
|
movieList.Append(new TMovie("Inception", "Christopher Nolan", 2010, EGenreFlags::Action | EGenreFlags::SciFi, 8.8f));
|
|
movieList.Append(new TMovie("The Godfather", "Francis Ford Coppola", 1972, EGenreFlags::Crime | EGenreFlags::Drama, 9.2f));
|
|
movieList.Prepend(new TMovie("Toy Story", "John Lasseter", 1995, EGenreFlags::Animation | EGenreFlags::Adventure | EGenreFlags::Comedy, 8.3f));
|
|
movieList.Append(new TMovie("The Dark Knight", "Christopher Nolan", 2008, EGenreFlags::Action | EGenreFlags::Crime | EGenreFlags::Drama, 9.0f));
|
|
// Print movie info
|
|
for (int i = 0; i < 3; i++) {
|
|
TMovie* movie = movieList.GetAtIndex(i);
|
|
if (movie) {
|
|
movie->PrintInfo();
|
|
std::cout << "-------------------" << std::endl;
|
|
}
|
|
}
|
|
std::cout << std::endl;
|
|
// Wait for user input to proceed
|
|
std::cout << "Press Enter to continue..." << std::endl;
|
|
std::cin.get();
|
|
|
|
// Search for a movie by title
|
|
std::string searchTitle = "Inception";
|
|
TMovie* foundMovie = movieList.SearchFor(CheckMovieByTitle, &searchTitle);
|
|
if (foundMovie) {
|
|
std::cout << "Found movie by title '" << searchTitle << "':" << std::endl;
|
|
foundMovie->PrintInfo();
|
|
} else {
|
|
std::cout << "Movie with title '" << searchTitle << "' not found." << std::endl;
|
|
}
|
|
std::cout << "-------------------" << std::endl;
|
|
std::cout << std::endl;
|
|
|
|
// Search for a movie by director
|
|
std::string searchDirector = "John Lasseter";
|
|
foundMovie = movieList.SearchFor(CheckMovieByDirector, &searchDirector);
|
|
if (foundMovie) {
|
|
std::cout << "Found movie by director '" << searchDirector << "':" << std::endl;
|
|
foundMovie->PrintInfo();
|
|
} else {
|
|
std::cout << "Movie with director '" << searchDirector << "' not found." << std::endl;
|
|
}
|
|
std::cout << "-------------------" << std::endl;
|
|
std::cout << std::endl;
|
|
|
|
// Find all movies in the Action genre
|
|
EGenreFlags searchGenre = EGenreFlags::Action;
|
|
std::cout << "Movies in the Action genre:" << std::endl;
|
|
movieList.SearchFor(FindAllMovieByGenre, &searchGenre);
|
|
std::cout << std::endl;
|
|
|
|
// Reverse the list
|
|
movieList.Reverse();
|
|
std::cout << "Movies after reversing the list:" << std::endl;
|
|
movieList.Every([](TMovie* movie, int index) {
|
|
std::cout << "Index " << index << ":" << std::endl;
|
|
movie->PrintInfo();
|
|
std::cout << "-------------------" << std::endl;
|
|
});
|
|
|
|
return 0;
|
|
}
|