Septembrie 2023

Screenshot 2024-06-29 at 11.17.55.png

// Algorithm for determining the position of a value x in a given array 
// or the position of inserting the value x in the array such that the sorting order is maintained
Input: 
	array a[1],a[2], .. a[n], n>=1, with distinct natural numbers
	integer x, natural number
Output: 
	integer pos, natural number 

Pseudocode:
	Sub position()
		pos = -1
		left = 1
		right = n // length of the input array
	
		While left <= right
			middle = left + (right-left)/2
			
			If a[middle] == x // found exact match
				pos = middle
				Return pos
			
			Else If a[middle] < x // search in left half
				right = middle - 1
				
			Else If a[middle] > x
				left = middle + 1 // search in right half
				pos = middle // update position to middle, as x should come after middle
			End If
		End While
		
		If pos == -1
			pos = left // no larger element found, x should be inserted at the beginning
			Return pos
		Else
			pos = pos + 1 // 
			Return pos
		End If
	End Sub
	
Complexity:
	O(log(n))

Screenshot 2024-06-29 at 11.18.03.png

// Algorithm for determining the circular permutation 
// of a given array k positions to the right
Input:
	array x[1], x[2], ..., x[n], n>=1, with characters
	integer k, 0 < k <=n

Output:
	array y[1], y[2], ..., y[n], with characters

Pseudocode:
	Sub k_permutation():
		n = length of aray x
		y = new array of size n
		
		If p == 0
			y = x
			return y
	
		For i = 0 to n-1
			new_index = (i + k) % n
			y[new_index] = x[i]
		EndFor
		
		Return y
		
	End Sub

Complexity: O(n)

Screenshot 2024-06-29 at 11.18.10.png

// Algorithm for determining if an array can represent 
// an inorder traversal of binary search tree
// or the list of swaps to produce an array that satisfies the condition
Input:
	array a[1], a[2], ..., a[n], n>0, with permutations of {1,...,n}

Output:
	value 0 if array can represent inorder traversal of binary search tree
	or list of swaps y to produce an array that satisfies the condition

Pseudocode:
	Sub verify_bst_representation():
		n = length of aray a
		y = new array to hold list of possible interchanges
		j = 0
		visited = map to store the already swapped elements
				
		For i = 1 to n
			If a[i] != i and i not in visited
				y[j] = (i, a[i])
				
				tmp = a[i]
				a[i] = a[a[i]]
				a[a[i]] = tmp
				
				visited[i] = true
				j = j + 1
			EndIf
		EndFor
		
		If y is not empty
			Return y
		Else
			Return 0 // reaching this means the permutation represents a binary search tree
		
	End Sub

Complexity: O(n)

Screenshot 2024-06-29 at 11.18.25.png

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class Product {
	private:
		string name;
		int baseprice;
		
	public:
		Product(const string& name, int baseprice):
			name{name},
			baseprice{baseprice} {}
			
		virtual int total_price() {
			return this->baseprice;
		}
		
		virtual string toString() {
			return this->name;
		}
		
		virtual ~Product() {}
};

class Computer: public Product {
	private:
		int tax;
	
	public:
		Computer(const string& name, int baseprice, int tax)
			: Product(name, baseprice) {
			this->tax = tax;
		}
		
		int total_price() {
			return Product::total_price() + tax;
		}
		
		string toString() {
			return Product::toString() + ", " + to_string(this->total_price());
		}
};

class SorterByTotalPrice {
   **public:**
		**static** bool compareByTotalPrice(Product* a, Product* b){
			return a->total_price() **>** b->total_price();
		}

		**static** void sort(vector<Product*>& computers){
			std::sort(computers.begin(), computers.end(), compareByTotalPrice);
		}
};

int main() {
	vector<Product*> computers{
	    new Computer("HC90", 140, 10),
	    new Computer("HC91", 100, 12),
		new Computer("HC85", 150, 15)
	};
	**SorterByTotalPrice::sort(computers);**
	cout << computers[0]->toString();
	for(auto c : computers)
		delete c;
		
	return 0;
}

Screenshot 2024-06-29 at 11.18.31.png

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

class Contact {
	private:
		string name;
	
	public:
		Contact(string name) {
			this->name = name;
		}
		virtual void sendMessage(const string& message) const = 0;
		
		virtual string getName() const {
			return name;
		}
		virtual ~Contact() {}
};

class Person : public Contact {
	private:
		string number;
		
	public:
		Person(string name, string number) 
			: Contact(name) {
			this->number = number;
		}
		
		string getNumber() const {
            return number;
        }
		
		void sendMessage(const string& message) const {
			cout << getName() << " " << number << " " << endl << message << endl;
		}
};

class Group : public Contact {
	private:
		vector<Contact*> contacts;
	
	public:
		Group(string name) 
		    : Contact(name) {}
		
		void addContact(Contact* contact) {
			contacts.push_back(contact);
		}
		
		void sendMessage(const string& message) const {
			for(const Contact* contact : contacts){
			    const Person* person = dynamic_cast<const Person*>(contact); //static_cast
				cout << person->getName() << " " << person->Person::getNumber() << endl;
			}
			cout << message << endl;
		}
		
		~Group() {
		    for (Contact* contact : contacts){
		        delete contact;
		    }
		}
};

int main() {
	Person* p1 = new Person("Mother", "01");
	Person* p2 = new Person("Father", "02");
	Person* p3 = new Person("Jane", "03");
	Person* p4 = new Person("John", "04");
	
	Group* parents = new Group("Parents");
	parents->addContact(p1);
	parents->addContact(p2);
	
	Group* family = new Group("Family");
	family->addContact(p1);
	family->addContact(p2);
	family->addContact(p3);
	
	family->sendMessage("You are invited");
	p4->sendMessage("You are invited");
	
	delete family;
	delete p4;
	
	return 0;
}

Iulie 2023

Screenshot 2024-06-29 at 19.23.11.png

To understand the behavior of the subalgorithms g and transformare, we need to analyze the code.

Subalgorithm g(x, n, y, i)

This subalgorithm takes as input arrays x and y, integers n and i. Here's what it does:

If i≤n, it assigns y[i]←x[i]

i≤ni \leq n

y[i]←x[i]y[i] \leftarrow x[i]

It then recursively calls itself with i+1.

i+1i + 1

So, it essentially copies elements from x to y until it reaches the end of x.

Subalgorithm transformare(x, n, y, m, z, k)

This subalgorithm calls g and modifies k. Here's what it does:

If n=0, it calls g(y, m, z, 1) and sets k←m.

n=0n = 0

k←mk \leftarrow m

Else, it copies x[n] to y[m+1], then recursively calls itself with n−1 and m+1.

x[n]x[n]

y[m+1]y[m + 1]

n−1n - 1

m+1m + 1

To find out what the array z contains, let's trace the call:

Initial Call: transformare(x, n, y, 0, z, k)

n is the length of x.

m starts at 0.

On each call, the elements of x are copied to y in reverse order.

Finally, when n becomes 0, it copies y to z using g.

Therefore, z will contain elements of x in reverse order.

**#include <iostream>
#include <vector>
#include <unordered_map>**

using namespace std;

int main() {
    **int n;
    cin >> n;
    
    vector<int> a(n);
    for(int i = 0; i < n; ++i) {
        cin >> a[i];
    }**

    **unordered_map<int, pair<int, int>> sumPairs;**

    for(int i = 0; i < n; ++i) {
        for(int j = i + 1; j < n; ++j) {
            int sum = a[i] + a[j];
            
            if(**sumPairs.find(-sum)** != **sumPairs.end()**) {
                **auto p = sumPairs[-sum];**
                **int x = p.first;
                int y = p.second;**
                if(**x != i && x != j && y != i && y != j**) {
                     vector<int> indices = {x + 1, y + 1, i + 1, j + 1};
							       sort(indices.begin(), indices.end());
							       cout << indices[0] << " " << indices[1] << " " << indices[2] << " " << indices[3] << endl;
                     return 0;
                }
            }
            **sumPairs[sum] = {i, j};**
        }
    }

    cout << -1 << endl;
    return 0;
}

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class MyObject {
public:
    **virtual void print() const = 0;**
    **virtual ~MyObject() {}**
};

class MyInteger : public MyObject {
    int value;
public:
    MyInteger(int v) **: value(v)** {}
    **void print() const override {**
        cout << value;
    }
};

class MyString : public MyObject {
    string value;
public:
    **MyString(const string&** v) **: value(v)** {}
    **void print() const override {**
        cout << value;
    }
};

**class MyObjectList** {
    **vector<MyObject*> objects;**
public:
    **~MyObjectList() {
        for(auto obj : objects) {
            delete obj;
        }
    }**

    **MyObjectList& add(MyObject* obj) {
        objects.push_back(obj);
        return *this;
    }**
};

**class MyListIterator {
        vector<MyObject*>& objects;
        size_t index;**
    public:
        **MyListIterator(vector<MyObject*>& objs) : objects(objs), index(0) {}**

        bool isValid() const {
            **return index < objects.size();**
        }

        **MyObject* element() const {
            return objects[index];
        }**

        **void next() {
            ++index;
        }**
}; 
int main() {
    MyObjectList list;
    list.add(new MyInteger(2)).add(new MyString("Hi"));
    MyString* s = new MyString("Bye");
    list.add(s);
    list.add(new MyString("5"));

    MyListIterator i {list};
    while (i.isValid()) {
        MyObject* o = i.element();
        o->print();
        cout << " ";
        i.next();
    }
    // prints: 2 Hi Bye 5
    return 0;
}

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Person {
    string surname;
    string firstname;
    int age;
public:
    Person(string s, string f, int a) : surname(s), firstname(f), age(a) {}

    string getSurname() const { return surname; }
    string getFirstname() const { return firstname; }
    int getAge() const { return age; }

    bool operator<(const Person& other) const {
        return surname < other.surname;
    }
};

void merge(vector<Person*>& persons, int left, int mid, int right, bool (*compare)(const Person*, const Person*)) {
    int n1 = mid - left + 1;
    int n2 = right - mid;

    vector<Person*> L(n1);
    vector<Person*> R(n2);

    for (int i = 0; i < n1; ++i)
        L[i] = persons[left + i];
    for (int j = 0; j < n2; ++j)
        R[j] = persons[mid + 1 + j];

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (compare(L[i], R[j])) {
            persons[k] = L[i];
            ++i;
        } else {
            persons[k] = R[j];
            ++j;
        }
        ++k;
    }

    while (i < n1) {
        persons[k] = L[i];
        ++i;
        ++k;
    }

    while (j < n2) {
        persons[k] = R[j];
        ++j;
        ++k;
    }
}

void mergeSort(vector<Person*>& persons, int left, int right, bool (*compare)(const Person*, const Person*)) {
    if (left < right) {
        int mid = left + (right - left) / 2;

        mergeSort(persons, left, mid, compare);
        mergeSort(persons, mid + 1, right, compare);

        merge(persons, left, mid, right, compare);
    }
}

bool compareBySurname(const Person* a, const Person* b) {
    return a->getSurname() < b->getSurname();
}

bool compareByAge(const Person* a, const Person* b) {
    return a->getAge() < b->getAge();
}

bool compareByAgeAndName(const Person* a, const Person* b) {
    if (a->getAge() == b->getAge()) {
        return a->getSurname() < b->getSurname();
    }
    return a->getAge() < b->getAge();
}

int main() {
    vector<Person*> persons = {
        new Person("Doe", "John", 30),
        new Person("Smith", "Jane", 25),
        new Person("Doe", "Alice", 30),
        new Person("Brown", "Charlie", 20)
    };

    cout << "Sorted by surname:\\n";
    mergeSort(persons, 0, persons.size() - 1, compareBySurname);
    for (const auto& person : persons) {
        cout << person->getSurname() << " " << person->getFirstname() << " " << person->getAge() << endl;
    }

    cout << "\\nSorted by age:\\n";
    mergeSort(persons, 0, persons.size() - 1, compareByAge);
    for (const auto& person : persons) {
        cout << person->getSurname() << " " << person->getFirstname() << " " << person->getAge() << endl;
    }

    cout << "\\nSorted by age and name:\\n";
    mergeSort(persons, 0, persons.size() - 1, compareByAgeAndName);
    for (const auto& person : persons) {
        cout << person->getSurname() << " " << person->getFirstname() << " " << person->getAge() << endl;
    }

    // Clean up allocated memory
    for (auto person : persons) {
        delete person;
    }

    return 0;
}

Iulie 2019