Added 2021 solutions

Added 2021 solutions for specker (n = new) and polynomial
This commit is contained in:
Xenofon Konitsas 2021-04-23 12:31:40 +03:00
parent 2c2dd26302
commit 3c44dff236
4 changed files with 566 additions and 238 deletions

View file

@ -1,254 +1,243 @@
#include <iostream>
#include <cmath>
using namespace std;
class Polynomial {
public:
protected:
class Term {
public:
protected:
int exponent;
int coefficient;
Term *next;
protected:
Term(int exp, int coeff, Term *n) : exponent(exp), coefficient(coeff), next(n){};
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;
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;
Term *p = head;
while(p != nullptr) {
Term *q = p;
p = p->next;
delete q;
}
}
void clear() {
void push_back(const int &e, const int &c) {
Term *n = new Term(e, c, nullptr);
Term *p;
if(head == nullptr) {
head = n;
return;
}
p = head;
while(p->next != nullptr) {
p = p->next;
}
p->next = n;
}
void copy(const Polynomial &p) {
for(Term *i = p.head; i != nullptr; i = i->next) {
push_back(i->exponent, i->coefficient);
}
}
public:
Polynomial() {
head = nullptr;
}
Polynomial(const Polynomial &p) {
head = nullptr;
copy(p);
}
~Polynomial() {
purge();
};
Polynomial & operator = (const Polynomial &p) {
purge();
head = nullptr;
degree=0;
size=0;
copy(p);
return *this;
}
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;
}
else return;
}
--size;
}
void addTerm(int e, int c) {
Term *n = new Term(e, c, nullptr);
Term *p, *q;
if(c == 0) {
delete n;
return;
}
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;
}
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 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; i<exp; ++i) {
expvalue*=x;
double result = 0;
Term *p = head;
while(p != nullptr) {
result += (double) p->coefficient * pow(x, p->exponent);
p = p->next;
}
}
sum+=(l->coefficient)*expvalue;
}
return sum;
return result;
}
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;
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;
}
if(temp_q==nullptr && temp_p!=nullptr) {
r.addTerm(temp_p->exponent,temp_p->coefficient);
temp_p=temp_p->next;
continue;
else if(j->exponent > i->exponent) {
result.addTerm(j->exponent,j->coefficient);
j = j->next;
}
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;
else {
result.addTerm(i->exponent, i->coefficient + j->coefficient);
i = i->next;
j = j->next;
}
}
return r;
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 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));
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);
}
//cout<<r[counter];
++counter;
}
product = r[0];
for(int i=1;i<counter;i++) {
product = product + r[i];
}
return product;
return result;
}
friend ostream & operator << (ostream &out, const Polynomial &p) {
if(p.head==nullptr) {
Term *n = p.head;
if(n == 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<<i->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<<i->coefficient<<"x";
}
}
else if(i->exponent > 1) {
if(i->coefficient < 0) {
if(i->coefficient==-1) out<<"- "<<"x^"<<i->exponent;
else out<<"- "<<-(i->coefficient)<<"x^"<<i->exponent;
}
else if(i->coefficient > 0) {
if(i->coefficient==1) out<<"x^"<<i->exponent;
else out<<i->coefficient<<"x^"<<i->exponent;
}
}
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 {
if(i->exponent==0) {
if(i->coefficient < 0) out<<" - "<<-(i->coefficient);
else if(i->coefficient > 0) out<<" + "<<i->coefficient;
out << " + ";
}
else if(i->exponent==1) {
if(i->coefficient < 0) {
if(i->coefficient==-1) out<<" - "<<"x";
else out<<" - "<<-(i->coefficient)<<"x";
if(abs(n->coefficient) != 1 || n->exponent == 0) {
out << abs(n->coefficient);
}
else if(i->coefficient > 0) {
if(i->coefficient==1) out<<" + "<<"x";
else out<<" + "<<i->coefficient<<"x";
if(n->exponent == 1) {
out << "x";
}
else if(n->exponent != 0) {
out << "x^" << n->exponent;
}
else if(i->exponent > 1) {
if(i->coefficient < 0) {
if(i->coefficient==-1) out<<" - "<<"x^"<<i->exponent;
else out<<" - "<<-(i->coefficient)<<"x^"<<i->exponent;
}
else if(i->coefficient > 0) {
if(i->coefficient==1) out<<" + "<<"x^"<<i->exponent;
else out<<" + "<<i->coefficient<<"x^"<<i->exponent;
}
}
}
}
//out<<"\n";
return out;
n = n->next;
}
private:
void copy(const Polynomial &p) {
for(Term *l=p.head; l!=nullptr; l=l->next) addTerm(l->exponent, l->coefficient);
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;
}

130
specker1n.cpp Normal file
View file

@ -0,0 +1,130 @@
#include <iostream>
#include <stdexcept>
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;
};

129
specker2n.cpp Normal file
View file

@ -0,0 +1,129 @@
#include <iostream>
#include <stdexcept>
#include <string>
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;
};

80
specker3n.cpp Normal file
View file

@ -0,0 +1,80 @@
#include <iostream>
#include <stdexcept>
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;
};