From 3c44dff236aa028c611990c98a20272b9c395720 Mon Sep 17 00:00:00 2001 From: Xenofon Konitsas Date: Fri, 23 Apr 2021 12:31:40 +0300 Subject: [PATCH] Added 2021 solutions Added 2021 solutions for specker (n = new) and polynomial --- polynomial.cpp | 465 ++++++++++++++++++++++++------------------------- specker1n.cpp | 130 ++++++++++++++ specker2n.cpp | 129 ++++++++++++++ specker3n.cpp | 80 +++++++++ 4 files changed, 566 insertions(+), 238 deletions(-) create mode 100644 specker1n.cpp create mode 100644 specker2n.cpp create mode 100644 specker3n.cpp diff --git a/polynomial.cpp b/polynomial.cpp index 7e95502..1420e64 100644 --- a/polynomial.cpp +++ b/polynomial.cpp @@ -1,254 +1,243 @@ #include +#include + using namespace std; class Polynomial { - public: - class Term { - public: - int exponent; - int coefficient; - Term *next; +protected: + class Term { protected: - Term(int exp, int coeff, Term *n) : exponent(exp), coefficient(coeff), next(n){}; - friend class Polynomial; - }; + int exponent; + int coefficient; + Term *next; + + Term(int e, int c, Term *n) { + exponent = e; + coefficient = c; + next = n; + } + + friend class Polynomial; + friend Polynomial operator + (const Polynomial &p, const Polynomial &q); + friend Polynomial operator * (const Polynomial &p, const Polynomial &q); + friend ostream & operator << (ostream &out, const Polynomial &p); + }; + + Term *head; - Term *head; - int degree; - int size; - - Polynomial():head(nullptr), degree(0), size(0) {} - Polynomial(const Polynomial &p): head(nullptr), degree(0), size(0) {copy(p);}; - ~Polynomial() {purge();} - - Polynomial & operator =(const Polynomial &p) {clear(); copy(p); return *this;} - - void purge() { - Term *l=head; - degree=0; - size=0; - while(l!=nullptr) { - Term *q=l; - l=l->next; - delete q; + void purge() { + Term *p = head; + while(p != nullptr) { + Term *q = p; + p = p->next; + delete q; + } } - } + + void push_back(const int &e, const int &c) { + Term *n = new Term(e, c, nullptr); + Term *p; - void clear() { - purge(); - head=nullptr; - degree=0; - size=0; - } - - void remove(int exp) /* AFAIREI STOIXEIO*/ { - Term* temp=head; - Term* prev; - if(head==nullptr) return; - else { - if(head->exponent==exp) { - head=head->next; - delete temp; - } - else { - for(temp = head;temp->next!=nullptr && temp->exponent !=exp;temp = temp->next) { - prev=temp; - } - if(temp->exponent==exp) { - prev->next = temp->next; - delete temp; + if(head == nullptr) { + head = n; + return; + } + + p = head; + while(p->next != nullptr) { + p = p->next; } - else return; - } - --size; - } - } - - - - void addTerm(int expon, int coeff) { - if(coeff==0 || expon<0) return; - Term *newTerm = new Term(expon,coeff,nullptr); - Term *temp = head; - if(expon>degree) degree=expon; - if(head==nullptr) { - newTerm->next=nullptr; - head=newTerm; - ++size; - return; - } - if(expon>head->exponent) { - newTerm->next=head; - head=newTerm; - ++size; - return; - } - if(expon==head->exponent) /* HERE */ { - head->coefficient=head->coefficient+newTerm->coefficient; - if(head->coefficient==0) remove(head->exponent); - return; - } - while(temp->next!=nullptr) { - if(expon==temp->exponent) /*here*/ { - temp->coefficient=temp->coefficient+newTerm->coefficient; - if(temp->coefficient==0) - remove(temp->exponent); - return; - } - if(expon>temp->next->exponent) { - newTerm->next = temp->next; - temp->next = newTerm; - return; - } - temp = temp->next; - } - if(newTerm->exponent==temp->exponent) /*HERE*/ { - temp->coefficient=temp->coefficient + newTerm->coefficient; - if(temp->coefficient==0) remove(temp->exponent); - return; - } - else { - newTerm->next=nullptr; - temp->next=newTerm; - //temp->coefficient=temp->coefficient+newTerm->coefficient; - ++size; - } - return; - } - - double evaluate(double x) { - double sum=0; - int exp; - for(Term *l=head; l!=nullptr; l=l->next) { - exp=l->exponent; - double expvalue=1; - if (exp==0) expvalue=1; - else { - for(int i=0; icoefficient)*expvalue; + p->next = n; } - return sum; - } - friend Polynomial operator+ (const Polynomial &p, const Polynomial &q) { - Polynomial r; - Polynomial::Term *temp_p = p.head; - Polynomial::Term *temp_q = q.head; - while(!(temp_p==nullptr && temp_q ==nullptr)) { - if(temp_p==nullptr && temp_q!=nullptr) { - r.addTerm(temp_q->exponent,temp_q->coefficient); - temp_q=temp_q->next; - continue; - } - if(temp_q==nullptr && temp_p!=nullptr) { - r.addTerm(temp_p->exponent,temp_p->coefficient); - temp_p=temp_p->next; - continue; - } - if(temp_p->exponent == temp_q->exponent) { - r.addTerm(temp_p->exponent,temp_p->coefficient + temp_q ->coefficient); - temp_p=temp_p->next; - temp_q=temp_q->next; - } - else if(temp_p->exponent > temp_q ->exponent ) { - r.addTerm(temp_p->exponent, temp_p->coefficient); - temp_p=temp_p->next; - } - else if(temp_p->exponent < temp_q->exponent) { - r.addTerm(temp_q->exponent,temp_q->coefficient); - temp_q = temp_q->next; - } - } - return r; -} - friend Polynomial operator* (const Polynomial &p, const Polynomial &q) { - Polynomial r[p.size+q.size+30]; - Polynomial product; - int counter=0; - for(Polynomial :: Term *i = p.head; i!=nullptr; i = i->next) { - for(Polynomial :: Term * j= q.head; j!=nullptr; j = j->next) { - r[counter].addTerm(i->exponent+j->exponent, (i->coefficient)*(j->coefficient)); - } - //cout<next) { + push_back(i->exponent, i->coefficient); + } + } - friend ostream & operator << (ostream &out, const Polynomial &p) { - if(p.head==nullptr) { - out<<"0"; - return out; - } - for(Polynomial::Term *i = p.head;i!=nullptr;i=i->next) { - if(i==p.head) { - if(i->exponent==0) { - if(i->coefficient < 0) out<<"- "<<-(i->coefficient); - else if(i->coefficient > 0) out<coefficient; - } - else if(i->exponent==1) { - if(i->coefficient < 0) { - if(i->coefficient==-1) out<<"- "<<"x"; - else out<<"- "<<-(i->coefficient)<<"x"; - } - else if(i->coefficient > 0) { - if(i->coefficient==1) out<<"x"; - else out<coefficient<<"x"; - } - } - else if(i->exponent > 1) { - if(i->coefficient < 0) { - if(i->coefficient==-1) out<<"- "<<"x^"<exponent; - else out<<"- "<<-(i->coefficient)<<"x^"<exponent; - } - else if(i->coefficient > 0) { - if(i->coefficient==1) out<<"x^"<exponent; - else out<coefficient<<"x^"<exponent; - } - } - } - else { - if(i->exponent==0) { - if(i->coefficient < 0) out<<" - "<<-(i->coefficient); - else if(i->coefficient > 0) out<<" + "<coefficient; - } - else if(i->exponent==1) { - if(i->coefficient < 0) { - if(i->coefficient==-1) out<<" - "<<"x"; - else out<<" - "<<-(i->coefficient)<<"x"; - } - else if(i->coefficient > 0) { - if(i->coefficient==1) out<<" + "<<"x"; - else out<<" + "<coefficient<<"x"; - } - } - else if(i->exponent > 1) { - if(i->coefficient < 0) { - if(i->coefficient==-1) out<<" - "<<"x^"<exponent; - else out<<" - "<<-(i->coefficient)<<"x^"<exponent; - } - else if(i->coefficient > 0) { - if(i->coefficient==1) out<<" + "<<"x^"<exponent; - else out<<" + "<coefficient<<"x^"<exponent; - } - } - } - } - //out<<"\n"; - return out; - } +public: + Polynomial() { + head = nullptr; + } + + Polynomial(const Polynomial &p) { + head = nullptr; + copy(p); + } + + ~Polynomial() { + purge(); + }; - private: - void copy(const Polynomial &p) { - for(Term *l=p.head; l!=nullptr; l=l->next) addTerm(l->exponent, l->coefficient); - } + Polynomial & operator = (const Polynomial &p) { + purge(); + head = nullptr; + copy(p); + return *this; + } + + void addTerm(int e, int c) { + Term *n = new Term(e, c, nullptr); + Term *p, *q; + + if(c == 0) { + delete n; + return; + } + + if(head == nullptr) { + head = n; + head->next = nullptr; + return; + } + + if(head->exponent == e) { + head->coefficient += c; + if(head->coefficient == 0) { + p = head; + head = head->next; + delete p; + } + delete n; + return; + } + + p = head; + q = p->next; + while(q != nullptr && q->exponent > e) { + p = q; + q = q->next; + } + if(q != nullptr && q->exponent == e) { + q->coefficient += c; + if(q->coefficient == 0) { + p->next = q->next; + delete q; + } + delete n; + } else { + if(n->exponent < p->exponent) { + n->next = p->next; + p->next = n; + } else { + n->next = p; + head = n; + } + } + } + double evaluate(double x) { + double result = 0; + Term *p = head; + while(p != nullptr) { + result += (double) p->coefficient * pow(x, p->exponent); + p = p->next; + } + return result; + } + + friend Polynomial operator + (const Polynomial &p, const Polynomial &q) { + Polynomial result; + Term *i, *j, *k; + + i = p.head; + j = q.head; + + while(i != nullptr && j != nullptr) { + if(i->exponent > j->exponent) { + result.addTerm(i->exponent, i->coefficient); + i = i->next; + } + else if(j->exponent > i->exponent) { + result.addTerm(j->exponent,j->coefficient); + j = j->next; + } + else { + result.addTerm(i->exponent, i->coefficient + j->coefficient); + i = i->next; + j = j->next; + } + } + + if(i == nullptr) { + k = j; + } + else if(j == nullptr) { + k = i; + } + + while(k != nullptr){ + result.addTerm(k->exponent, k->coefficient); + k = k->next; + } + return result; + } + friend Polynomial operator * (const Polynomial &p, const Polynomial &q) { + Polynomial result; + + for(Term *i = p.head; i != nullptr; i = i->next) { + for(Term *j = q.head; j != nullptr; j = j->next) { + result.addTerm(i->exponent + j->exponent, i->coefficient * j-> coefficient); + } + } + return result; + } + + friend ostream & operator << (ostream &out, const Polynomial &p) { + Term *n = p.head; + + if(n == nullptr) { + out << "0"; + return out; + } + + if(n->coefficient < 0) + out << "- "; + if(abs(n->coefficient) != 1) + out << abs(n->coefficient); + if(n->exponent == 0 && abs(n->coefficient) == 1) + out << "1"; + if(n->exponent == 1) + out << "x"; + else if(n->exponent != 0) + out << "x^" << n->exponent; + n = n->next; + while(n != nullptr) { + if(n->coefficient < 0) { + out << " - "; + } + else { + out << " + "; + } + if(abs(n->coefficient) != 1 || n->exponent == 0) { + out << abs(n->coefficient); + } + if(n->exponent == 1) { + out << "x"; + } + else if(n->exponent != 0) { + out << "x^" << n->exponent; + } + n = n->next; + } + + return out; + } }; +int main() { + Polynomial p; + p.addTerm(1, 3); + p.addTerm(2, 1); + p.addTerm(0, -1); + Polynomial q(p); + q.addTerm(1, -3); + q.addTerm(3, -12); + cout << "P(X) = " << p << endl; + cout << "P(1) = " << p.evaluate(1) << endl; + cout << "Q(X) = " << q << endl; + cout << "Q(1) = " << q.evaluate(1) << endl; + cout << "(P+Q)(X) = " << p+q << endl; + cout << "(P*Q)(X) = " << p*q << endl; +} diff --git a/specker1n.cpp b/specker1n.cpp new file mode 100644 index 0000000..800e409 --- /dev/null +++ b/specker1n.cpp @@ -0,0 +1,130 @@ +#include +#include + +using namespace std; + +class Move { +public: + + // Take sc coins from heap sh and put tc coins to heap th. + + Move(int sh, int sc, int th, int tc) { + sourceHeap = sh; + sourceCoins = sc; + targetHeap = th; + targetCoins = tc; + } + + int getSource() const { return sourceHeap; } + int getSourceCoins() const { return sourceCoins; } + int getTarget() const { return targetHeap; } + int getTargetCoins() const { return targetCoins; } + + friend ostream & operator << (ostream &out, Move &move) { + + if (move.getTargetCoins() != 0) { + out << "takes " << move.getSourceCoins() << " coins from heap " << move.getSource() << " and puts " << move.getTargetCoins() << " coins to heap " << move.getTarget(); + } + else { + out << "takes " << move.getSourceCoins() << " coins from heap " << move.getSource() << " and puts nothing"; + } + return out; + + } + +private: + + int sourceHeap, sourceCoins, targetHeap, targetCoins; + +}; + +class State { +public: + + // State with h heaps, where the i-th heap starts with c[i] coins. + // A total of n players are in the game, numbered from 0 to n-1, + // and player 0 is the first to play. + + State(int h, const int c[], int n) { + + maxHeaps = h; + coins = new int[maxHeaps]; + for (int i = 0; i < maxHeaps; i++) { + coins[i] = c[i]; + } + maxPlayers = n; + playing = 0; + } + + State(const State &s) { + maxHeaps = s.maxHeaps; + coins = new int[maxHeaps]; + for (int i = 0; i < maxHeaps; i++) { + coins[i] = s.coins[i]; + } + maxPlayers = s.maxPlayers; + playing = s.playing; + } + + ~State() { + delete[] coins; + } + + int getHeaps() const { return maxHeaps; } + int getCoins(int h) const throw(logic_error) { + if (h < 0 || h >= maxHeaps) { + throw logic_error("Invalid heap"); + } + else { + return coins[h]; + } + } + + int getPlayers() const { return maxPlayers; } + int getPlaying() const { return playing; } + + void next(const Move &move) throw(logic_error) { + if ((move.getSource() < 0 || move.getSource() >= maxHeaps) || (move.getTarget() < 0 || move.getTarget() >= maxHeaps)) { + throw logic_error("Heaps go from 0 to " + maxHeaps); + } + else if (move.getSourceCoins() < 1 || move.getTargetCoins() < 0) { + throw logic_error("Invalid move"); + } + else if (move.getSourceCoins() <= move.getTargetCoins() || move.getSourceCoins() > getCoins(move.getSource())) { + throw logic_error("Not enough coins"); + } + else { + + + coins[move.getSource()] -= move.getSourceCoins(); + coins[move.getTarget()] += move.getTargetCoins(); + + if (playing == maxPlayers - 1) playing = 0; + else playing++; + + } + } + bool winning() const { + int total; + for (int i = 0; i < maxHeaps; i++) { + total += coins[i]; + } + if (total != 0) return false; + else return true; + } + + + friend ostream & operator << (ostream &out, const State &state) { + out << state.getCoins(0); + for (int i = 1; i < state.getHeaps(); i++) { + out << ", " << state.getCoins(i); + } + out << " with " << state.getPlaying() << "/" << state.getPlayers() << " playing next"; + return out; + } + +private: + + int maxHeaps, maxPlayers, playing; + int *coins; +}; diff --git a/specker2n.cpp b/specker2n.cpp new file mode 100644 index 0000000..f03dd0d --- /dev/null +++ b/specker2n.cpp @@ -0,0 +1,129 @@ +#include +#include +#include + +using namespace std; + +class Player { +public: + Player(const string &n) { + playerName = n; + } + virtual ~Player() { + playerName.clear(); + } + + virtual const string & getType() const = 0; + virtual Move play(const State &s) = 0; + + friend ostream & operator << (ostream &out, const Player &player) { + out << player.getType() << " player " << player.playerName; + return out; + } + +protected: + string playerName; +}; + +class GreedyPlayer: public Player { +public: + GreedyPlayer(const string &n) : Player(n) { + playerType = "Greedy"; + } + + virtual const string & getType() const override { return playerType; } + + virtual Move play(const State &s) override { + int mostCoins = 0; + for (int i = 0; i < s.getHeaps(); i++) { + if (s.getCoins(i) > s.getCoins(mostCoins)) { + mostCoins = i; + } + } + return Move (mostCoins, s.getCoins(mostCoins), 0, 0); + } + +private: + string playerType; +}; + +class SpartanPlayer: public Player { +public: + SpartanPlayer(const string &n) : Player(n) { + playerType = "Spartan"; + } + + virtual const string & getType() const override { return playerType; } + + virtual Move play(const State &s) override { + int mostCoins = 0; + for (int i = 0; i < s.getHeaps(); i++) { + if (s.getCoins(i) > s.getCoins(mostCoins)) { + mostCoins = i; + } + } + return Move (mostCoins, 1, 0, 0); + } + +private: + string playerType; +}; + +class SneakyPlayer: public Player { +public: + SneakyPlayer(const string &n) : Player(n) { + playerType = "Sneaky"; + } + + virtual const string & getType() const override { return playerType; } + + virtual Move play(const State &s) override { + int i = 0; + while(s.getCoins(i) == 0) { i++; } + + int leastCoins = i; + + for (int i = leastCoins + 1; i < s.getHeaps(); i++) { + if (s.getCoins(i) != 0 && s.getCoins(i) < s.getCoins(leastCoins)) { + leastCoins = i; + } + } + return Move(leastCoins, s.getCoins(leastCoins), 0, 0); + } + +private: + string playerType; +}; + +class RighteousPlayer: public Player { +public: + RighteousPlayer(const string &n) : Player(n) { + playerType = "Righteous"; + } + + virtual const string & getType() const override { return playerType; } + + virtual Move play(const State &s) override { + int mostCoins = 0, leastCoins = 0, coins; + for (int i = 0; i < s.getHeaps(); i++) { + if (s.getCoins(i) > s.getCoins(mostCoins)) { + mostCoins = i; + } + if (s.getCoins(i) < s.getCoins(leastCoins)) { + leastCoins = i; + } + } + if (s.getCoins(mostCoins) % 2 == 0) { + coins = s.getCoins(mostCoins) / 2; + } + else { + coins = (s.getCoins(mostCoins) / 2) + 1; + } + return Move(mostCoins, coins, leastCoins, coins - 1); + + } + +private: + string playerType; +}; + diff --git a/specker3n.cpp b/specker3n.cpp new file mode 100644 index 0000000..f8717a2 --- /dev/null +++ b/specker3n.cpp @@ -0,0 +1,80 @@ +#include +#include + +using namespace std; + +class Game { +public: + Game(int h, int p) { + maxHeaps = h; maxPlayers = p; + heapCounter = 0; + playerCounter = 0; + heaps = new int[maxHeaps]; + players = new Player*[maxPlayers]; + } + ~Game() { + delete[] heaps; + delete[] players; + } + + void addHeap(int c) throw(logic_error) { + if (c < 0) { + throw logic_error("Coins can't be less than zero"); + } + else if (heapCounter == maxHeaps) { + throw logic_error("Cannot add more heaps"); + } + else { + heaps[heapCounter] = c; + heapCounter++; + } + + } + void addPlayer(Player *p) throw(logic_error) { + if (playerCounter == maxPlayers) { + throw logic_error("Cannot add more players"); + } + else { + players[playerCounter] = p; + playerCounter++; + } + } + void play(ostream &out) throw(logic_error) { + if (playerCounter != maxPlayers || heapCounter != maxHeaps) { + throw logic_error("Not enough players/heaps"); + } + else { + State s(maxHeaps, heaps, maxPlayers); + while (!s.winning()) { + out << "State: " << s << endl; + out << *getPlayer(s.getPlaying()) << " " << players[s.getPlaying()]->play(s) << endl; + s.next(players[s.getPlaying()]->play(s)); + + } + out << "State: " << s << endl; + int winner; + if (s.getPlaying() == 0) winner = maxPlayers - 1; + else winner = s.getPlaying() - 1; + out << *players[winner] << " wins" << endl; + } + } + + + int getPlayers() const { return maxPlayers; } + + const Player *getPlayer(int p) const throw(logic_error) { + if (p < 0 || p > maxPlayers) { + throw logic_error("No such player"); + } + else { + return players[p]; + } + } + +private: + int maxHeaps, maxPlayers, heapCounter, playerCounter; + int *heaps; + Player **players; +}; + +