From 929c5f1912cbc92e9e6ab2cbb4a15e991b70e72e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 6 Apr 2017 16:49:53 +0200 Subject: [PATCH] Adding medium/hard puzzles & challenges... --- challenges/2013-05-28/README.md | 6 + challenges/2013-05-28/question1.php | 26 + challenges/2013-05-28/question2.php | 76 +++ challenges/2016-02-27-Coders-Strike-Back.cpp | 199 ++++++ challenges/2016-09-24-Hypersonic.cpp | 638 ++++++++++++++++++ challenges/2016-10-01-Accountant.cpp | 210 ++++++ challenges/2016-11-26-Fantastic-Bits.cpp | 372 ++++++++++ puzzles/easy/ascii-art.cpp | 2 +- puzzles/easy/horse-racing-duals.sh | 2 + puzzles/hard/bender-episode-2.cpp | 71 ++ puzzles/medium/bender-episode-1.cpp | 257 +++++++ puzzles/medium/conway-sequence.cpp | 69 ++ puzzles/medium/dont-panic-episode-1.cpp | 77 +++ puzzles/medium/last-crusade-episode-1.cpp | 109 +++ puzzles/medium/mayan-calculation.cpp | 131 ++++ puzzles/medium/scrabble.cpp | 91 +++ .../medium/shadow-of-the-knight-episode-1.cpp | 80 +++ .../medium/skynet-revolution-episode-1.cpp | 87 +++ puzzles/medium/stock-exchange-losses.cpp | 61 ++ puzzles/medium/teads-sponsored-contest.cpp | 74 ++ puzzles/medium/telephone-numbers.php | 29 + puzzles/medium/the-gift.cpp | 79 +++ .../medium/there-is-no-spoon-episode-1.cpp | 64 ++ puzzles/medium/winamax-battle.cpp | 121 ++++ 24 files changed, 2930 insertions(+), 1 deletion(-) create mode 100644 challenges/2013-05-28/README.md create mode 100644 challenges/2013-05-28/question1.php create mode 100644 challenges/2013-05-28/question2.php create mode 100644 challenges/2016-02-27-Coders-Strike-Back.cpp create mode 100644 challenges/2016-09-24-Hypersonic.cpp create mode 100644 challenges/2016-10-01-Accountant.cpp create mode 100644 challenges/2016-11-26-Fantastic-Bits.cpp create mode 100644 puzzles/hard/bender-episode-2.cpp create mode 100644 puzzles/medium/bender-episode-1.cpp create mode 100644 puzzles/medium/conway-sequence.cpp create mode 100644 puzzles/medium/dont-panic-episode-1.cpp create mode 100644 puzzles/medium/last-crusade-episode-1.cpp create mode 100644 puzzles/medium/mayan-calculation.cpp create mode 100644 puzzles/medium/scrabble.cpp create mode 100644 puzzles/medium/shadow-of-the-knight-episode-1.cpp create mode 100644 puzzles/medium/skynet-revolution-episode-1.cpp create mode 100644 puzzles/medium/stock-exchange-losses.cpp create mode 100644 puzzles/medium/teads-sponsored-contest.cpp create mode 100644 puzzles/medium/telephone-numbers.php create mode 100644 puzzles/medium/the-gift.cpp create mode 100644 puzzles/medium/there-is-no-spoon-episode-1.cpp create mode 100644 puzzles/medium/winamax-battle.cpp diff --git a/challenges/2013-05-28/README.md b/challenges/2013-05-28/README.md new file mode 100644 index 0000000..0b28f9d --- /dev/null +++ b/challenges/2013-05-28/README.md @@ -0,0 +1,6 @@ +2013-05-28 Challenge +==================== + +Language used: PHP +Tests: 100% +Rank: 23/614 diff --git a/challenges/2013-05-28/question1.php b/challenges/2013-05-28/question1.php new file mode 100644 index 0000000..e2210a4 --- /dev/null +++ b/challenges/2013-05-28/question1.php @@ -0,0 +1,26 @@ + 0) { + + } + +} + +function simplifySeq($sequences, $n = 0) +{ + if (1 == count($sequences)) { + return $sequences[0]; + } + + if ($n == count($sequences)) { + $base = array_pop($sequences); + $sequences[0] .= $base; + return simplifySeq($sequences); + } + + $base = array_pop($sequences); + $len = strlen($base); + + $mergeDone = false; + for ($l = $len; $l > 0; $l--) { + $part = substr($base, 0, $l); + foreach ($sequences as &$seq) { + $seqPart = substr($seq, -$l); + if ($seqPart == $part) { + $seq .= substr($base, $l); + $mergeDone = true; + break; + } + } + if ($mergeDone) { + break; + } + } + + if (!$mergeDone) { + array_unshift($sequences, $base); + return simplifySeq($sequences, $n+1); + } + + return simplifySeq($sequences); +} + +function cleanShortSeqs($seqs) +{ + $c = count($seqs); + for ($i = 0; $i < $c; $i++) { + foreach ($seqs as $j => $seq) { + if ($i != $j && strstr($seq, $seqs[$i])) { + unset($seqs[$i]); + break; + } + } + } + return array_values($seqs); +} + +$seqs = cleanShortSeqs($seqs); +$result = simplifySeq($seqs); +echo strlen($result); + diff --git a/challenges/2016-02-27-Coders-Strike-Back.cpp b/challenges/2016-02-27-Coders-Strike-Back.cpp new file mode 100644 index 0000000..86f53cb --- /dev/null +++ b/challenges/2016-02-27-Coders-Strike-Back.cpp @@ -0,0 +1,199 @@ +// Coders Strike Back Challenge - 2016-02-27 +// Xavier Morel - 2016-02-27 +// Ranking 543/2530 + +#include +#include +#include +#include + +using namespace std; + +#define M_PI 3.14159265358979323846 /* pi */ + +#define MAX_ANGLE 25 +#define CHECK_DISTANCE_CLOSE 200 +#define CHECK_DISTANCE 3000 +#define CHECK_DISTANCE_FAR 6000 + +#define SPEED_SLOW 50 +#define SPEED_MED 100 +#define SPEED_FAST 150 +#define SPEED_MAX 200 + +typedef struct s_Coords +{ + int x; + int y; +} Coords; + +typedef struct s_Pod +{ + Coords pos; + Coords vec; + int angle; + int nextCP; + + Coords tgt; // Target. + int speed; + string dbgMsg; +} Pod; + +Pod myPods[2]; +Pod enemyPods[2]; + +int getAngle(Coords a, Coords b) +{ + float rad = atan2(b.y - a.y, b.x - a.x); + int deg = (rad * 180 / M_PI); + return (deg + 360) % 360; +} + +Coords getTarget(int podNb, Coords cp) +{ + Coords tmp; + tmp.x = myPods[podNb].pos.x + myPods[podNb].vec.x; + tmp.y = myPods[podNb].pos.y + myPods[podNb].vec.y; + + tmp.x = cp.x - tmp.x; + tmp.y = cp.y - tmp.y; + + tmp.x = myPods[podNb].pos.x + tmp.x; + tmp.y = myPods[podNb].pos.y + tmp.y; + + return tmp; +} + +int getDistance(Coords a, Coords b) +{ + return (int) sqrt(((b.x - a.x) * (b.x - a.x)) + ((b.y - a.y) * (b.y - a.y))); +} + +int turnsToReach(int podNb, Coords cp) +{ + Coords pos = myPods[podNb].pos; + Coords speed = myPods[podNb].vec; + int turns = 0; + int prevDist = -1; + + int i = 0; + + while (i < 20) { + int dist = getDistance(pos, cp); + if (dist < 600) { + return turns; + } + + if (prevDist > -1 && prevDist < dist) { + return -1; + } + + pos.x += speed.x; + pos.y += speed.y; + + speed.x *= 0.85; + speed.y *= 0.85; + + if (speed.x < 5 && speed.y < 5) { + return -1; + } + + prevDist = dist; + turns++; + i++; + } + + return -1; +} + +void process(int podNb, Coords cp, Coords nextCP) +{ + Pod pod = myPods[podNb]; + + int angle = getAngle(myPods[podNb].pos, cp); + int dist = getDistance(myPods[podNb].pos, cp); + + myPods[podNb].tgt = getTarget(podNb, cp); + + if (((abs(angle - pod.angle) + 360) % 360) < MAX_ANGLE) { + if (dist > CHECK_DISTANCE) { + if (dist > CHECK_DISTANCE_FAR) { + myPods[podNb].speed = SPEED_MAX; + } else { + myPods[podNb].speed = SPEED_FAST; + } + } else { + int nextAngle = getAngle(pod.pos, nextCP); + if (((abs(nextAngle - pod.angle) + 360) % 360) < MAX_ANGLE) { + myPods[podNb].speed = SPEED_MAX; + } else { + int ttr = turnsToReach(podNb, cp); + if (ttr == 1) { + myPods[podNb].tgt = getTarget(podNb, nextCP); + myPods[podNb].speed = 0; + } else { + if (dist > CHECK_DISTANCE_CLOSE) { + myPods[podNb].speed = SPEED_MED; + } else { + myPods[podNb].speed = SPEED_SLOW; + } + } + } + } + } else { + myPods[podNb].speed = SPEED_SLOW; + } +} + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int laps; + cin >> laps; cin.ignore(); + int checkpointCount; + cin >> checkpointCount; cin.ignore(); + + Coords checkpoints[checkpointCount]; + + for (int i = 0; i < checkpointCount; i++) { + cin >> checkpoints[i].x; + cin >> checkpoints[i].y; + } + + // game loop + while (1) { + for (int i = 0; i < 2; i++) { + cin >> myPods[i].pos.x; + cin >> myPods[i].pos.y; + cin >> myPods[i].vec.x; + cin >> myPods[i].vec.y; + cin >> myPods[i].angle; + cin >> myPods[i].nextCP; + cin.ignore(); + } + + for (int i = 0; i < 2; i++) { + cin >> enemyPods[i].pos.x; + cin >> enemyPods[i].pos.y; + cin >> enemyPods[i].vec.x; + cin >> enemyPods[i].vec.y; + cin >> enemyPods[i].angle; + cin >> enemyPods[i].nextCP; + cin.ignore(); + } + + for (int i = 0; i < 2; i++) { + Coords cp = checkpoints[myPods[i].nextCP]; + Coords nextCP = checkpoints[(myPods[i].nextCP + 1) % checkpointCount]; + process(i, cp, nextCP); + cout << myPods[i].tgt.x << " " << myPods[i].tgt.y << " " << myPods[i].speed; + if (myPods[i].dbgMsg.size() > 0) { + cout << " " << myPods[i].dbgMsg; + } + cout << endl; + } + } +} diff --git a/challenges/2016-09-24-Hypersonic.cpp b/challenges/2016-09-24-Hypersonic.cpp new file mode 100644 index 0000000..e041467 --- /dev/null +++ b/challenges/2016-09-24-Hypersonic.cpp @@ -0,0 +1,638 @@ +// Hypersonic Challenge +// Xavier Morel - 2016-09-24 +// Ranking 1070/2715 (blehhh) + +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define ITEM_MAX_DISTANCE 10 +#define COMPUTATION_MAX_DISTANCE 50 + +#define TYPE_PLAYER 0 +#define TYPE_BOMB 1 +#define TYPE_ITEM 2 + +#define TILE_EMPTY '.' +#define TILE_BOX '0' +#define TILE_BONUS_BOMB '1' +#define TILE_BONUS_REACH '2' +#define TILE_WALL 'X' +#define TILE_BOMB 'B' +#define TILE_ITEM 'I' + +int width = 0; +int height = 0; + +class Coords { +public: + int x; + int y; + Coords() : x(-1), y(-1) {} + Coords(int x, int y) : x(x), y(y) {} + + Coords above() + { + return Coords(x, y - 1); + } + + Coords below() + { + return Coords(x, y + 1); + } + + Coords leftOf() + { + return Coords(x - 1, y); + } + + Coords rightOf() + { + return Coords(x + 1, y); + } + + inline void up() + { + --y; + } + + inline void down() + { + ++y; + } + + inline void left() + { + --x; + } + + inline void right() + { + ++x; + } + + inline bool isValid() + { + return x >= 0 && y >= 0 && x < width && y < height; + } +}; + +class Tile { +public: + int score; + char type; + bool danger; + bool reachable; + + Tile() : score(0), danger(false), reachable(false), type(TILE_EMPTY) {} + + inline bool isBox() + { + return (type == TILE_BOX || type == TILE_BONUS_BOMB || type == TILE_BONUS_REACH); + } + + inline bool isBlocking() + { + return !isFree(); + } + + inline bool isFree() + { + return (type == TILE_EMPTY || type == TILE_ITEM); + } + + inline bool isWalkable() + { + return isFree() && !isDanger(); + } + + inline bool isDanger() + { + return danger; + } + + inline bool isItem() + { + return (type == TILE_ITEM); + } + + inline bool isReachable() + { + return reachable; + } +}; + +class Board { +private: + vector> tiles; + +public: + Board() {} + + void reset() + { + // TODO ... + tiles.clear(); + } + + void addRow(string row) + { + vector row_tiles; + for (int i = 0; i < row.size(); i++) { + Tile tile; + tile.type = row.at(i); + row_tiles.push_back(tile); + } + + tiles.push_back(row_tiles); + } + + inline Tile get(Coords pos) + { + return tiles.at(pos.y).at(pos.x); + } + + void setBomb(Coords pos, int reach, int danger) + { + tiles.at(pos.y).at(pos.x).type = TILE_BOMB; + tiles.at(pos.y).at(pos.x).danger = true; + + for (Coords c = pos.leftOf(); c.isValid(); c.left()) { + // cerr << "See if I can set danger at " << c.x << " " << c.y << endl; + if (get(c).isFree()) { + // cerr << "Set danger at " << c.x << " " << c.y << endl; + tiles.at(c.y).at(c.x).danger = true; + } + else { + break; + } + } + for (Coords c = pos.rightOf(); c.isValid(); c.right()) { + // cerr << "See if I can set danger at " << c.x << " " << c.y << endl; + if (get(c).isFree()) { + // cerr << "Set danger at " << c.x << " " << c.y << endl; + tiles.at(c.y).at(c.x).danger = true; + } + else { + break; + } + } + for (Coords c = pos.above(); c.isValid(); c.up()) { + // cerr << "See if I can set danger at " << c.x << " " << c.y << endl; + if (get(c).isFree()) { + // cerr << "Set danger at " << c.x << " " << c.y << endl; + tiles.at(c.y).at(c.x).danger = true; + } + else { + break; + } + } + for (Coords c = pos.below(); c.isValid(); c.down()) { + // cerr << "See if I can set danger at " << c.x << " " << c.y << endl; + if (get(c).isFree()) { + // cerr << "Set danger at " << c.x << " " << c.y << endl; + tiles.at(c.y).at(c.x).danger = true; + } + else { + break; + } + } + } + + void setReachable(Coords pos) + { + tiles.at(pos.y).at(pos.x).reachable = true; + } + + void setItem(Coords pos) + { + tiles.at(pos.y).at(pos.x).type = TILE_ITEM; + } + + void setScore(Coords pos, int score) + { + tiles.at(pos.y).at(pos.x).score = score; + } + + inline bool isBox(Coords pos) + { + return get(pos).isBox(); + } + + inline bool isBlocking(Coords pos) + { + return get(pos).isBlocking(); + } + + inline bool isFree(Coords pos) + { + return get(pos).isFree(); + } + + inline bool isItem(Coords pos) + { + return get(pos).isItem(); + } + + inline bool isDanger(Coords pos) + { + return get(pos).isDanger(); + } + + inline bool isReachable(Coords pos) + { + return get(pos).isReachable(); + } + + inline bool isWalkable(Coords pos) + { + return get(pos).isWalkable(); + } +}; + +Board board; + +typedef struct { + Coords pos; + int id; + int param1; + int reach; +} Entity; + +typedef struct { + Coords pos; + int score = 0; + bool toBomb = false; + bool getToSafety = false; + bool fetchItem = false; +} Destination; + +bool checkBombLocation(Coords pos, int reach) +{ + int i; + cerr << "Checking bomb pos " << pos.x << " " << pos.y << endl; + Coords c, d; + for (c = pos.above(), i = 0; i < reach && c.isValid() && board.isFree(c); c.up()) { + d = c.leftOf(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + d = c.rightOf(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + if (c.isValid() && board.isFree(c)) { + d = c.above(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + for (c = pos.below(), i = 0; i < reach && c.isValid() && board.isFree(c); c.down()) { + d = c.leftOf(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + d = c.rightOf(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + if (c.isValid() && board.isFree(c)) { + d = c.below(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + for (c = pos.leftOf(), i = 0; i < reach && c.isValid() && board.isFree(c); c.left()) { + d = c.above(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + d = c.below(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + if (c.isValid() && board.isFree(c)) { + d = c.leftOf(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + for (c = pos.rightOf(), i = 0; i < reach && c.isValid() && board.isFree(c); c.right()) { + d = c.above(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + d = c.below(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + if (c.isValid() && board.isFree(c)) { + d = c.rightOf(); + if (d.isValid() && board.isWalkable(d)) { + cerr << "Could flee from " << c.x << " " << c.y << " to " << d.x << " " << d.y << endl; + return true; + } + } + + return false; +} + +class Game +{ +private: + int myId; + Entity players[4]; + + Destination currentObjective; + bool didntmove; + bool items_present; + +public: + string action; + + Game(int id) : myId(id) { + currentObjective.score = 0; + } + + void reset() + { + didntmove = false; + items_present = false; + action = ""; + } + + void addEntity(int entityType, Entity entity) + { + switch (entityType) { + case TYPE_PLAYER: + if (entity.id == myId) { + if (players[entity.id].pos.x == entity.pos.x + && players[entity.id].pos.y == entity.pos.y + && entity.param1 > 0 + ) { + didntmove = true; + } + } + players[entity.id] = entity; + break; + case TYPE_BOMB: + board.setBomb(entity.pos, entity.reach, entity.param1); + break; + case TYPE_ITEM: + board.setItem(entity.pos); + items_present = true; + break; + } + } + + int getPositionScore(Coords pos) + { + int score = 0; + int reach = players[myId].reach; + int i; + Coords c; + + for (c = pos, i = 0; c.isValid() && i < reach; c.left()) { + if (board.isBox(c)) { + score++; + break; + } + if (board.isBlocking(c)) { + break; + } + } + + for (c = pos, i = 0; c.isValid() && i < reach; c.right()) { + if (board.isBox(c)) { + score++; + break; + } + if (board.isBlocking(c)) { + break; + } + } + + for (c = pos, i = 0; c.isValid() && i < reach; c.up()) { + if (board.isBox(c)) { + score++; + break; + } + if (board.isBlocking(c)) { + break; + } + } + + for (c = pos, i = 0; c.isValid() && i < reach; c.down()) { + if (board.isBox(c)) { + score++; + break; + } + if (board.isBlocking(c)) { + break; + } + } + + return score; + } + + void computeReachableTiles() + { + Destination objective = currentObjective; + + list toProcess; + toProcess.push_back(players[myId].pos); + + bool shouldFindCover = false; + if (board.isDanger(players[myId].pos)) { + shouldFindCover = true; + } + + int i = 0; + + while (toProcess.size() > 0) { + i++; + Coords pos = toProcess.front(); + toProcess.pop_front(); + + cerr << "Pos " << pos.x << " " << pos.y << endl; + board.setReachable(pos); + int score = getPositionScore(pos); + cerr << "Score: " << score << endl; + board.setScore(pos, score); + + bool dangerous = board.isDanger(pos); + cerr << "Dangerous: " << (dangerous ? "yes" : "no") << endl; + + if (!dangerous) { + if (shouldFindCover) { // && !dangerous) { + if (!objective.getToSafety) { + cerr << "Get to any possible cover!" << endl; + objective.getToSafety = true; + objective.fetchItem = false; + objective.toBomb = false; + objective.pos = pos; + objective.score = 0; + } + } + + // if (!shouldFindCover || !dangerous) { + if (board.isItem(pos) && objective.fetchItem == false && i <= ITEM_MAX_DISTANCE) { + cerr << "Closeby item + (should be) no danger, go for it !" << endl; + objective.getToSafety = !dangerous; + objective.fetchItem = true; + objective.toBomb = false; + objective.pos = pos; + objective.score = 4; + } + + if (score > objective.score) { + if (checkBombLocation(pos, players[myId].reach)) { + cerr << "Better than current objective: go bomb it!" << endl; + objective.pos = pos; + objective.score = score; + objective.toBomb = true; + objective.fetchItem = false; + objective.getToSafety = false; + } + else { + cerr << "Nope that's too dangerous!" << endl; + } + } + } + + if (i > COMPUTATION_MAX_DISTANCE) { // dont go too far... + cerr << "Already computed " << i << " entries. Stop for now..." << endl; + break; + } + + pos.up(); + if (pos.isValid() && !board.isReachable(pos) && board.isFree(pos)) { + toProcess.push_back(pos); + } + pos.down(); // back to origin + + pos.down(); + if (pos.isValid() && !board.isReachable(pos) && board.isFree(pos)) { + toProcess.push_back(pos); + } + pos.up(); // back to origin + + pos.left(); + if (pos.isValid() && !board.isReachable(pos) && board.isFree(pos)) { + toProcess.push_back(pos); + } + pos.right(); // back to origin + + pos.right(); + if (pos.isValid() && !board.isReachable(pos) && board.isFree(pos)) { + toProcess.push_back(pos); + } + cerr << "#############" << endl; + } + + cerr << "Go to " << objective.pos.x << " " << objective.pos.y << endl; + + currentObjective = objective; + + // for (int i = 0; i < height; ++i) { + // for (int j = 0; j < width; ++j) { + // if (board.isReachable(Coords(j, i))) { + // cerr << "Reachable: " << j << " " << i << endl; + // } + // } + // } + + } + + void computeObjective() + { + //if (didntmove) { + // cerr << "Didnt move: special output" << endl; + // action = "BOMB 0 0 x_x"; + // return; + //} + + action = "MOVE "; + if ( + currentObjective.pos.x == players[myId].pos.x + && currentObjective.pos.y == players[myId].pos.y + ) { + if (currentObjective.toBomb) { + action = "BOMB "; + } + currentObjective.toBomb = false; + currentObjective.score = 0; + currentObjective.getToSafety = false; + currentObjective.fetchItem = false; + } + + action += to_string(currentObjective.pos.x); + action += " "; + action += to_string(currentObjective.pos.y); + } +}; + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int myId; + cin >> width >> height >> myId; cin.ignore(); + + Game game(myId); + + // game loop + while (1) { + board.reset(); + game.reset(); + + for (int i = 0; i < height; i++) { + string row; + cin >> row; cin.ignore(); + board.addRow(row); + } + + int entities; + cin >> entities; cin.ignore(); + for (int i = 0; i < entities; i++) { + Entity entity; + + int type; + cin >> type + >> entity.id + >> entity.pos.x + >> entity.pos.y + >> entity.param1 + >> entity.reach; + cin.ignore(); + game.addEntity(type, entity); + } + + game.computeReachableTiles(); + game.computeObjective(); + + cout << game.action << endl; + } +} diff --git a/challenges/2016-10-01-Accountant.cpp b/challenges/2016-10-01-Accountant.cpp new file mode 100644 index 0000000..dd32d33 --- /dev/null +++ b/challenges/2016-10-01-Accountant.cpp @@ -0,0 +1,210 @@ +// Accountant challenge +// Xavier Morel - 2016-10-01 +// Ranking 675/6214 + + +#include +#include +#include +#include + +using namespace std; + +typedef struct { + int x; + int y; +} Coords; + +typedef struct { + int id; + bool alive = true; + Coords pos; +} Data; + +typedef struct { + int id = -1; + bool alive = true; + int data_dist = 0; + int data_id = 0; + int player_dist = 0; + int life; + Coords pos; +} Mob; + +int getDistance(Coords a, Coords b) +{ + int xdiff = b.x - a.x; + int ydiff = b.y - a.y; + return std::sqrt((xdiff * xdiff) + (ydiff * ydiff)); +} + +class Environment { +public: + size_t data_count; + size_t mobs_count; + map data; + map mobs; + Coords player; + + std::string action; + + void initialization(std::istream &input) { + ; + } + + void reset() { + for (int i = 0; i < data.size(); i++) { + data[i].alive = false; + } + for (int i = 0; i < mobs.size(); i++) { + mobs[i].alive = false; + } + action = ""; + } + + void input(std::istream &input) { + input >> player.x >> player.y; input.ignore(); + input >> data_count; input.ignore(); + for (int i = 0; i < data_count; i++) { + Data node; + input >> node.id >> node.pos.x >> node.pos.y; input.ignore(); + data[node.id] = node; + } + + input >> mobs_count; input.ignore(); + for (int i = 0; i < mobs_count; i++) { + Mob mob; + input >> mob.id >> mob.pos.x >> mob.pos.y >> mob.life; input.ignore(); + computeDistances(mob); + // computeTurns(mob); + mobs[mob.id] = mob; + } + } + + void computeDistances(Mob &mob) + { + int closest = -1; + int distance = 999999; + + for (auto iter : data) { + Data datanode = iter.second; + if (datanode.alive) { + int dist = getDistance(datanode.pos, mob.pos); + if (dist < distance) { + distance = dist; + closest = datanode.id; + } + } + } + + mob.player_dist = getDistance(mob.pos, player); + mob.data_id = closest; + mob.data_dist = distance; + } + + int getDamage(int distance) + { + return 125000 / pow(distance, 1.2f); + } + + void applyVector(Coords &pos, Coords dest, int distance) + { + ; + } + + void computeTurns(Mob &mob) + { + int turnsToLive = 0; + int turnsToCap = 0; + + int life, distToData, distToPlayer; + Coords pos = mob.pos; + Coords destination = data[mob.data_id].pos; + + life = mob.life; + distToData = mob.data_dist; + distToPlayer = mob.player_dist; + + while (distToData > 500 || life > 0) { + life -= getDamage(distToPlayer); + + applyVector(pos, destination, 500); + distToData = getDistance(pos, destination); + distToPlayer = getDistance(pos, player); + + if (life > 0) { + turnsToLive++; + } + if (distToData > 500) { + turnsToCap++; + } + } + cerr << "Mob " << std::to_string(mob.id) << " turns:" << std::endl; + cerr << "To live: " << std::to_string(turnsToLive) << std::endl; + cerr << "To capt: " << std::to_string(turnsToCap) << std::endl; + } + + std::string moveOut(Mob menace) + { + int x, y; + + x = menace.pos.x > (player.x - 500) ? player.x - 750 : player.x + 750; + y = menace.pos.y > (player.y - 500) ? player.y - 750 : player.y + 750; + + return "MOVE " + std::to_string(x) + " " + std::to_string(y) + " HAAAAAAAaaaa"; + } + + void compute(void) { + Mob target; + + for (auto iter : mobs) { + Mob mob = iter.second; + + // Skip dead. + if (!mob.alive) { + continue; + } + + // Pick one enemy. + if (target.id < 0) { + target = mob; + continue; + } + + // Switch target if current is far and this one is close, or closer to a datanode. + if (target.player_dist > 3000 && (mob.player_dist < 3000 || mob.data_dist < target.data_dist)) { + target = mob; + continue; + } + + // Switch target if this one is closer to me than the current target... + if (mob.player_dist < target.player_dist) { + target = mob; + } + } + + if (target.player_dist < 2500) { + action = moveOut(target); + } else { + action = "SHOOT " + std::to_string(target.id) + " DIIIIIE"; + } + } + + void output(std::ostream &output) { + output << action << std::endl; + } +}; + +int main() +{ + Environment env; + + env.initialization(std::cin); + + while (1) { + env.reset(); + env.input(std::cin); + env.compute(); + env.output(std::cout); + } +} diff --git a/challenges/2016-11-26-Fantastic-Bits.cpp b/challenges/2016-11-26-Fantastic-Bits.cpp new file mode 100644 index 0000000..48c7583 --- /dev/null +++ b/challenges/2016-11-26-Fantastic-Bits.cpp @@ -0,0 +1,372 @@ +// Fantastic Bits challenge +// Xavier Morel - 2016-11-26 +// Ranking 2208/2399 (Almost had no time to really work on it. :/) + + +#include +#include +#include +#include + +#define MIN_X 0 +#define MAX_X 16001 +#define MIN_Y 0 +#define MAX_Y 7501 +#define GOAL_SIZE 4000 +#define POLE_RADIUS 300 +#define WIZARD_RADIUS 400 +#define SNAFFLE_RADIUS 150 +#define MAX_SNAFFLES 7 +#define GOAL_MIDDLE_TEAM0 Coords(0,3750) +#define GOAL_MIDDLE_TEAM1 Coords(16000,3750) +#define WIZARD_ENTITY_TYPE "WIZARD" +#define ENEMY_ENTITY_TYPE "OPPONENT_WIZARD" +#define SNAFFLE_ENTITY_TYPE "SNAFFLE" +#define BLUDGER_ENTITY_TYPE "BLUDGER" +#define LIMIT_MAX (0-1) + +// FINE TUNABLE: +#define LIMIT_ATK_ENEMY 5000 +#define LIMIT_GOAL_ENEMY 10000 +#define LIMIT_GOAL_BALL 7000 +#define MAX_DISTANCE_DEF_TO_GOAL 5000 + +#define THROW_SPEED_ATK "500" +#define THROW_SPEED_DEF "500" +#define MOVE_SPEED_ATK_TO_BALL "150" +#define MOVE_SPEED_DEF_TO_BALL "100" +#define MOVE_SPEED_DEF_TACKLE "100" +#define MOVE_SPEED_DEF_STANDBY "50" +#define MOVE_SPEED_DEF_TO_GOAL "100" + + class Coords + { + public: + int x; + int y; + Coords() : x(0), y(0) {} + Coords(int x, int y) : x(x), y(y) {} + + int getClosest(std::vector others, int limit) + { + int closestNb = -1; + int distance = LIMIT_MAX; + int curDist = 0; + if (limit == 0) { + limit = LIMIT_MAX; + } + + int i = 0; + for (Coords other : others) { + curDist = getDistance(other); + if (curDist < distance || distance == LIMIT_MAX) { + distance = curDist; + closestNb = i; + } + } + + if (curDist > limit && limit > 0) { + std::cerr << "Min distance: " << std::to_string(curDist) << std::endl; + return -1; + } + return closestNb; + } + + inline int getDistance(const Coords &other) const + { + std::cerr << "From " << write() << " to " << other.write() << std::endl; + return abs(x - other.x) + abs(y - other.y); + } + + std::string write() const + { + return std::to_string(x) + " " + std::to_string(y); + } + + inline bool operator!=(const Coords &other) const + { + return x != other.x || y != other.y; + } + + inline bool operator==(const Coords &other) const + { + return x == other.x && y == other.y; + } + + inline Coords operator+(const Coords &other) + { + return Coords(x + other.x, y + other.y); + } + + inline Coords operator-(const Coords &other) + { + return Coords(x - other.x, y - other.y); + } + + inline Coords operator*(int k) + { + return Coords(x * k, y * k); + } + + inline Coords operator*=(int k) + { + x *= k; + y *= k; + return *this; + } + + inline bool onTrajectory(const Coords &a, const Coords &b) const + { + + return true; + } + }; + +class Game +{ + int teamId; + + Coords goal; + Coords myGoal; + + std::vector wizards_pos; + std::vector wizards_vect; + std::vector wizards_state; + + std::vector enemies_pos; + std::vector enemies_vect; + std::vector enemies_state; + + std::vector snaffles_pos; + std::vector snaffles_vect; + + std::vector bludgers_pos; + std::vector bludgers_vect; + +public: + void setTeamId(int teamId) + { + if (teamId == 0) { + goal = GOAL_MIDDLE_TEAM1; + myGoal = GOAL_MIDDLE_TEAM0; + } + else { + goal = GOAL_MIDDLE_TEAM0; + myGoal = GOAL_MIDDLE_TEAM1; + } + } + + void reset() + { + wizards_pos.clear(); + wizards_vect.clear(); + wizards_state.clear(); + enemies_pos.clear(); + enemies_vect.clear(); + enemies_state.clear(); + snaffles_pos.clear(); + snaffles_vect.clear(); + bludgers_pos.clear(); + bludgers_vect.clear(); + } + + inline int getTeamId() + { + return teamId; + } + + void addWizard(Coords pos, Coords vect, bool state) + { + wizards_pos.push_back(pos); + wizards_vect.push_back(vect); + wizards_state.push_back(state); + } + + void addOpponentWizard(Coords pos, Coords vect, bool state) + { + enemies_pos.push_back(pos); + enemies_vect.push_back(vect); + enemies_state.push_back(state); + } + + void addSnaffle(Coords pos, Coords vect) + { + snaffles_pos.push_back(pos); + snaffles_vect.push_back(vect); + } + + void addBludger(Coords pos, Coords vect) + { + bludgers_pos.push_back(pos); + bludgers_vect.push_back(vect); + } + + std::string getOffensiveWizardAction() + { + Coords wiz_pos = wizards_pos.front(); + bool wiz_state = wizards_state.front(); + + if (wiz_state == true) { + // If I have a ball: fire it towards opponent goal. + return "THROW " + goal.write() + " " + THROW_SPEED_ATK; + } + else { + // If I don't: go toward the closest ball. + // TODO What about close-by enemies? + // TODO Should try and get to the ball closest to enemy goals? + int ballNb = -1; + + std::cerr << "ATK Closest enemy." << std::endl; + if (wiz_pos.getClosest(enemies_pos, LIMIT_ATK_ENEMY) > -1) { + std::cerr << "ATK Closest ball." << std::endl; + ballNb = goal.getClosest(snaffles_pos, LIMIT_MAX); + } + else { + std::cerr << "ATK Closest ball." << std::endl; + ballNb = wiz_pos.getClosest(snaffles_pos, LIMIT_MAX); + } + + if (ballNb > -1) { + Coords snaffle = snaffles_pos.at(ballNb); + return "MOVE " + snaffle.write() + " " + MOVE_SPEED_ATK_TO_BALL; + } + else { + return "MOVE 0 0 10 Stuck >_<"; + } + } + } + + std::string getDefensiveWizardAction() + { + Coords wiz_pos = wizards_pos.back(); + bool wiz_state = wizards_state.back(); + + if (wiz_state == true) { + // If I have a ball, fire it towards my buddy (?) or goal (?) + return "THROW " + wizards_pos.front().write() + " " + THROW_SPEED_DEF; + } + else { + // If I don't: + // If I'm far from my goals. + if (wiz_pos.getDistance(myGoal) > MAX_DISTANCE_DEF_TO_GOAL) { + return "MOVE " + myGoal.write() + " " + MOVE_SPEED_DEF_TO_GOAL; + } + + std::cerr << "DEF Closest enemy." << std::endl; + int enemyNb = wiz_pos.getClosest(enemies_pos, LIMIT_GOAL_ENEMY); + if (enemyNb > -1) { + // - If an opponent is close, get between him and the goal + // TODO ... + Coords enemy = enemies_pos.at(enemyNb); + return "MOVE " + enemy.write() + " " + MOVE_SPEED_DEF_TACKLE; + } + + // - If no opponents are close, + std::cerr << "DEF Closest ball." << std::endl; + int ballNb = wiz_pos.getClosest(snaffles_pos, LIMIT_GOAL_BALL); + if (ballNb > -1) { + // - if a ball is close-by, go fetch it and fire it away + Coords snaffle = snaffles_pos.at(ballNb); + return "MOVE " + snaffle.write() + " " + MOVE_SPEED_DEF_TO_BALL; + } + + // - if no balls are close, just stand by. + return "MOVE " + myGoal.write() + " " + MOVE_SPEED_DEF_STANDBY; + } + } + + std::string getWizardAction(int id) + { + if (id == 0) { + // First wizard: fetch ball and fire it towards opponent goals + return getOffensiveWizardAction(); + } + else { + // Second wizard: defend own goal. + return getDefensiveWizardAction(); + } + } +}; + + +class Environment +{ + Game game; + +public: + Environment() {} + + void initialization(std::istream &input) + { + int myTeamId; + input >> myTeamId; input.ignore(); + game.setTeamId(myTeamId); + } + + void reset() + { + game.reset(); + } + + void input(std::istream &input) + { + int entities; + input >> entities; + input.ignore(); + + for (int i = 0; i < entities; i++) { + int id; + std::string entityType; + Coords pos; + Coords vect; + int state; + + input >> id >> entityType >> pos.x >> pos.y >> vect.x >> vect.y >> state; + input.ignore(); + if (entityType == WIZARD_ENTITY_TYPE) { + game.addWizard(pos, vect, state == 1); + } + else if (entityType == ENEMY_ENTITY_TYPE) { + game.addOpponentWizard(pos, vect, state == 1); + } + else if (entityType == SNAFFLE_ENTITY_TYPE) { + game.addSnaffle(pos, vect); + } + else if (entityType == BLUDGER_ENTITY_TYPE) { + game.addBludger(pos, vect); + } + else { + std::cerr << "Wut ?! Unknown entity type: " << entityType << std::endl; + } + } + } + + void compute(void) + { + ; + } + + void output(std::ostream &output) + { + for (int i = 0; i < 2; i++) { + output << game.getWizardAction(i) << std::endl; + } + } +}; + + +/** + * Grab Snaffles and try to throw them through the opponent's goal! + * Move towards a Snaffle and use your team id to determine where you need to throw it. + **/ +int main() +{ + Environment env; + env.initialization(std::cin); + while (1) { + env.reset(); + env.input(std::cin); + env.compute(); + env.output(std::cout); + } +} diff --git a/puzzles/easy/ascii-art.cpp b/puzzles/easy/ascii-art.cpp index 7aad2da..c7bf38f 100644 --- a/puzzles/easy/ascii-art.cpp +++ b/puzzles/easy/ascii-art.cpp @@ -1,4 +1,4 @@ -// https://www.codingame.com/training/easy/ascii-art +// https://www.codingame.com/ide/puzzle/ascii-art // Xavier Morel - 2014-10-16 #include diff --git a/puzzles/easy/horse-racing-duals.sh b/puzzles/easy/horse-racing-duals.sh index 425b5be..e90c5aa 100644 --- a/puzzles/easy/horse-racing-duals.sh +++ b/puzzles/easy/horse-racing-duals.sh @@ -1,6 +1,8 @@ # https://www.codingame.com/ide/puzzle/horse-racing-duals # Xavier Morel - 2016-03-12 +# WIP: Only passing tests up to 55% : big performance issues, obviously... + read N for ((i=0; i +#include +#include +#include + +using namespace std; + +struct Room { + int nb; + int money; + int door1; + int door2; + + int cache_money = 0; +}; + +map rooms; + +int getMostMoney(int roomNb) +{ + int money1 = 0; + int money2 = 0; + if (rooms[roomNb].door1 > -1) { + money1 = getMostMoney(rooms[roomNb].door1); + } + if (rooms[roomNb].door2 > -1) { + money2 = getMostMoney(rooms[roomNb].door2); + } + + if (money1 > money2) { + rooms[roomNb].money += money1; + } else { + rooms[roomNb].money += money2; + } + rooms[roomNb].door1 = -1; + rooms[roomNb].door2 = -1; + + return rooms[roomNb].money; +} + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int N; + cin >> N; cin.ignore(); + for (int i = 0; i < N; i++) { + string door1; + string door2; + Room room; + cin >> room.nb >> room.money >> door1 >> door2; cin.ignore(); + if (door1 == "E") { + room.door1 = -1; + } else { + room.door1 = stoi(door1); + } + if (door2 == "E") { + room.door2 = -1; + } else { + room.door2 = stoi(door2); + } + rooms[room.nb] = room; + } + + cout << getMostMoney(0) << endl; +} diff --git a/puzzles/medium/bender-episode-1.cpp b/puzzles/medium/bender-episode-1.cpp new file mode 100644 index 0000000..e4c2d03 --- /dev/null +++ b/puzzles/medium/bender-episode-1.cpp @@ -0,0 +1,257 @@ +// https://www.codingame.com/ide/puzzle/bender-episode-1 +// Xavier Morel - 2016-03-15 + +#include +#include +#include +#include + +#define LOOP 0 +#define WEST 1 +#define NORTH 2 +#define EAST 3 +#define SOUTH 4 + +#define EMPTY ' ' +#define DIR_WEST 'W' +#define DIR_NORTH 'N' +#define DIR_EAST 'E' +#define DIR_SOUTH 'S' +#define WALL '#' +#define BRK_WALL 'X' +#define START '@' +#define END '$' +#define BEER 'B' +#define TELEPORTER 'T' +#define INVERTER 'I' + +using namespace std; + +vector map; + +struct Coords { + int x; + int y; + + Coords () : x(0), y(0) {}; + Coords (int x, int y) : x(x), y(y) {}; +}; + +struct Character { + Coords pos; + char dir = SOUTH; + bool boosted = false; + bool inverted = false; + int brkWalls = 0; + + void faceNextDirection(bool recursive_call) + { + if (inverted == true) { + if (!recursive_call) { + dir = WEST; + return; + } + if (dir == WEST) { + dir = NORTH; + } else if (dir == NORTH) { + dir = EAST; + } else if (dir == EAST) { + dir = SOUTH; + } else if (dir == SOUTH) { + dir = WEST; + } + } else { + if (!recursive_call) { + dir = SOUTH; + return; + } + if (dir == SOUTH) { + dir = EAST; + } else if (dir == EAST) { + dir = NORTH; + } else if (dir == NORTH) { + dir = WEST; + } else if (dir == WEST) { + dir = SOUTH; + } + } + } +}; + +vector getPositions(char type) +{ + vector res; + for (int x = 0; x < map.size(); x++) { + size_t y = 0; + while ((y = map[x].find_first_of(type, y)) != string::npos) { + res.push_back(Coords(x, y)); + y++; + } + } + return res; +} + +inline void clearCell(Coords pos) +{ + map[pos.x].at(pos.y) = EMPTY; +} + +char getCurrentCellType(const Character &bender) +{ + return map[bender.pos.x].at(bender.pos.y); +} + +Coords getNextCellPos(const Character &bender) +{ + Coords next = bender.pos; + switch (bender.dir) { + case NORTH: + next.x--; + break; + case SOUTH: + next.x++; + break; + case WEST: + next.y--; + break; + case EAST: + next.y++; + break; + } + return next; +} + +char getNextCellType(const Character &bender) +{ + Coords next = getNextCellPos(bender); + return map[next.x].at(next.y); +} + +char getDirection(Character &bender, bool recursive_call) +{ + char nextNode = getNextCellType(bender); + char dir = bender.dir; + if (nextNode == WALL) { + bender.faceNextDirection(recursive_call); + return getDirection(bender, true); + } else if (nextNode == BRK_WALL) { + if (bender.boosted == false) { + bender.faceNextDirection(recursive_call); + return getDirection(bender, true); + } + } + return dir; +} + +void teleportBender(Character &bender) +{ + vector poss = getPositions(TELEPORTER); + for (Coords pos : poss) { + if (bender.pos.x != pos.x || bender.pos.y != pos.y) { + bender.pos = pos; + break; + } + } + cerr << "Teleport couldnt find other teleporter ?! Wtf ?" << endl; +} + +vector getDirections(void) +{ + vector history; + Character bender; + vector dirs; + + // Get initial pos. + bender.pos = getPositions(START).front(); + clearCell(bender.pos); + + int turns = 0; + while (1) { + // Check current cell and proceed as necessary (Teleporter, Beer, Inverter, new direction, break wall, ...) + char currentCell = getCurrentCellType(bender); + switch (currentCell) { + case TELEPORTER: + teleportBender(bender); + break; + case BEER: + bender.boosted = bender.boosted ? false : true; + break; + case INVERTER: + bender.inverted = bender.inverted ? false : true; + break; + case DIR_NORTH: + bender.dir = NORTH; + break; + case DIR_SOUTH: + bender.dir = SOUTH; + break; + case DIR_WEST: + bender.dir = WEST; + break; + case DIR_EAST: + bender.dir = EAST; + break; + case BRK_WALL: // We should be boosted here... + if (!bender.boosted) { + cerr << "WTF ?! On a breakable wall but not boosted ?!" << endl; + } + clearCell(bender.pos); + break; + case END: + // YAY! + return dirs; + } + // Check for next direction. + char dir = getDirection(bender, false); + // Append next direction to the stack. + dirs.push_back(dir); + // Move to the next cell. + bender.pos = getNextCellPos(bender); + // Check history for doubles with current status. + // If loop: clean stuff + return vector(); + // Save current status to the history. + turns++; + + // Crappy check for loops, hehe... + if (turns > 200) { + return vector(); + } + } + + return dirs; +} + +int main() +{ + int H = 0; + int W = 0; + cin >> H >> W; cin.ignore(); + for (int i = 0; i < H; i++) { + string row; + getline(cin, row); + map.push_back(row); + } + + vector dirs = getDirections(); + if (!dirs.size()) { + cout << "LOOP" << endl; + return 0; + } + + for (int dir : dirs) { + switch (dir) { + case NORTH: + cout << "NORTH" << endl; + break; + case SOUTH: + cout << "SOUTH" << endl; + break; + case WEST: + cout << "WEST" << endl; + break; + case EAST: + cout << "EAST" << endl; + break; + } + } +} diff --git a/puzzles/medium/conway-sequence.cpp b/puzzles/medium/conway-sequence.cpp new file mode 100644 index 0000000..a705400 --- /dev/null +++ b/puzzles/medium/conway-sequence.cpp @@ -0,0 +1,69 @@ +// https://www.codingame.com/ide/puzzle/conway-sequence +// Xavier Morel - 2016-03-23 + +#include +#include +#include +#include + +using namespace std; + +vector line; + + +void computeNextLine() +{ + vector next; + + int curNb = 0; + int qty = 0; + + for (int n : line) { + if (curNb != n) { + if (curNb != 0) { + next.push_back(qty); + next.push_back(curNb); + } + curNb = n; + qty = 1; + } else { + qty++; + } + } + + if (curNb != 0) { + next.push_back(qty); + next.push_back(curNb); + } + + line = next; +} + +void printLine(ostream& out) +{ + bool first = true; + for (int n : line) { + if (first == false) { + out << " "; + } + out << n; + first = false; + } + out << endl; +} + +int main() +{ + int R; + cin >> R; cin.ignore(); + int L; + cin >> L; cin.ignore(); + + line.push_back(R); + + for (int i = 1; i < L; i++) { + printLine(cerr); + computeNextLine(); + } + printLine(cout); +} diff --git a/puzzles/medium/dont-panic-episode-1.cpp b/puzzles/medium/dont-panic-episode-1.cpp new file mode 100644 index 0000000..ac46cdd --- /dev/null +++ b/puzzles/medium/dont-panic-episode-1.cpp @@ -0,0 +1,77 @@ +// https://www.codingame.com/ide/puzzle/don't-panic-episode-1 +// Xavier Morel - 2016-03-14 + +#include +#include +#include +#include + +using namespace std; + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int nbFloors; // number of floors + + int width; // width of the area + int nbRounds; // maximum number of rounds + int exitFloor; // floor on which the exit is found + int exitPos; // position of the exit on its floor + + int nbTotalClones; // number of generated clones + int nbAdditionalElevators; // ignore (always zero) + int nbElevators; // number of elevators + cin >> nbFloors >> width >> nbRounds >> exitFloor >> exitPos >> nbTotalClones >> nbAdditionalElevators >> nbElevators; cin.ignore(); + + int floors[nbFloors]; + memset(floors, 0, nbFloors); + floors[exitFloor] = exitPos; + + for (int i = 0; i < nbElevators; i++) { + int elevatorFloor; // floor on which this elevator is found + int elevatorPos; // position of the elevator on its floor + cin >> elevatorFloor >> elevatorPos; cin.ignore(); + floors[elevatorFloor] = elevatorPos; + } + + // bool firstTurn = true; + + // game loop + while (1) { + int cloneFloor; // floor of the leading clone + int clonePos; // position of the leading clone on its floor + string direction; // direction of the leading clone: LEFT or RIGHT + cin >> cloneFloor >> clonePos >> direction; cin.ignore(); + + // Write an action using cout. DON'T FORGET THE "<< endl" + // To debug: cerr << "Debug messages..." << endl; + + int prevDestPos = (cloneFloor > 0 ? floors[cloneFloor - 1] : -1); + int destPos = floors[cloneFloor]; + cerr << "Clone " << clonePos << " " << destPos << endl; + + if (cloneFloor == -1 && clonePos == -1 && direction == "NONE") { + cerr << "no clone" << endl; + cout << "WAIT" << endl; + } else if ( + (clonePos == width - 1 && direction == "RIGHT") + || (clonePos == 0 && direction == "LEFT") + ) { + cerr << "avoid laser" << endl; + cout << "BLOCK" << endl; + } else if (prevDestPos != clonePos && ( + (clonePos > destPos && direction != "LEFT") + || (clonePos < destPos && direction != "RIGHT") + ) + ) { + cerr << "Not the right direction" << endl; + cout << "BLOCK" << endl; + } else { + cerr << "..." << endl; + cout << "WAIT" << endl; + } + } +} diff --git a/puzzles/medium/last-crusade-episode-1.cpp b/puzzles/medium/last-crusade-episode-1.cpp new file mode 100644 index 0000000..39c2524 --- /dev/null +++ b/puzzles/medium/last-crusade-episode-1.cpp @@ -0,0 +1,109 @@ +// https://www.codingame.com/ide/puzzle/the-last-crusade-episode-1 +// Xavier Morel - 2016-03-16 + +#include +#include +#include +#include + +using namespace std; + +#define FROM_LEFT 0 +#define FROM_TOP 1 +#define FROM_RIGHT 2 + +#define NOPE 0 +#define LEFT 1 +#define RIGHT 2 +#define BOTT 3 + +int types[14][3] = { + // LEFT TOP RIGHT + {NOPE, NOPE, NOPE}, // type 0 + {BOTT, BOTT, BOTT}, // type 1 + {RIGHT, NOPE, LEFT}, // type 2 + {NOPE, BOTT, NOPE}, // type 3 + {NOPE, LEFT, BOTT}, // type 4 + {BOTT, RIGHT, NOPE}, // type 5 + {RIGHT, NOPE, LEFT}, // type 6 + {NOPE, BOTT, BOTT}, // type 7 + {BOTT, NOPE, BOTT}, // type 8 + {BOTT, BOTT, NOPE}, // type 9 + {NOPE, LEFT, NOPE}, // type 10 + {NOPE, RIGHT, NOPE}, // type 11 + {NOPE, NOPE, BOTT}, // type 12 + {BOTT, NOPE, NOPE} +}; + +int getDir(int type, int pos) +{ + cerr << "Cell is of type " << type << " and entered from " << pos << endl; + return types[type][pos]; +} + +int main() +{ + int W; // number of columns. + int H; // number of rows. + cin >> W >> H; cin.ignore(); + int grid[H+1][W+1]; + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + int x; + cin >> x; + cerr << x << endl; + grid[i][j] = x; + } + cin.ignore(); + } + int EX; + cin >> EX; cin.ignore(); + + cerr << "Large: " << W << " Haut: " << H << endl; + for (int i = 0; i < H; i++) { + cerr << "|"; + for (int j = 0; j < W; j++) { + cerr << grid[i][j] << " "; + } + cerr << endl; + } + cerr << "----------" << endl; + + + // game loop + while (1) { + int XI; + int YI; + string pos_str; + int pos; + cin >> XI >> YI >> pos_str; cin.ignore(); + + if (pos_str == "TOP") { + pos = FROM_TOP; + } else if (pos_str == "LEFT") { + pos = FROM_LEFT; + } else if (pos_str == "RIGHT") { + pos = FROM_RIGHT; + } else { + cerr << "Unrecognized entrance..." << endl; + } + + cerr << "Cell at " << XI << "x" << YI << endl; + int dir = getDir(grid[YI][XI], pos); + cerr << "Dir: " << dir << endl; + switch (dir) { + case LEFT: + XI--; + break; + case RIGHT: + XI++; + break; + case BOTT: + YI++; + break; + default: + cerr << "WUT?" << endl; + } + cout << XI << " " << YI << endl; + } +} diff --git a/puzzles/medium/mayan-calculation.cpp b/puzzles/medium/mayan-calculation.cpp new file mode 100644 index 0000000..0e49ce1 --- /dev/null +++ b/puzzles/medium/mayan-calculation.cpp @@ -0,0 +1,131 @@ +// https://www.codingame.com/ide/puzzle/mayan-calculation +// Xavier Morel - 2016-03-15 + +#include +#include +#include +#include + +using namespace std; + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int L; + int H; + cin >> L >> H; cin.ignore(); + map nums; + for (int i = 0; i < H; i++) { + string numeral; + cin >> numeral; cin.ignore(); + for (int j = 0; j < 20; j++) { + if (!nums.count(j)) { + nums[j] = string(); + } + nums[j] += numeral.substr(j*L, L); + nums[j] += "\n"; + } + } + map term1; + int S1; + cin >> S1; cin.ignore(); + for (int i = 0; i < S1; i++) { + int numPow = floor(i/H); + string num1Line; + cin >> num1Line; cin.ignore(); + if (!term1.count(numPow)) { + term1[numPow] = string(); + } + term1[numPow] += num1Line; + term1[numPow] += "\n"; + } + + map term2; + int S2; + cin >> S2; cin.ignore(); + for (int i = 0; i < S2; i++) { + int numPow = floor(i/H); + string num2Line; + cin >> num2Line; cin.ignore(); + if (!term2.count(numPow)) { + term2[numPow] = string(); + } + term2[numPow] += num2Line; + term2[numPow] += "\n"; + } + string operation; + cin >> operation; cin.ignore(); + + // cerr << "Numbers:" << endl; + double number1 = 0; + double number2 = 0; + + for (int i = 0; i < 20; i++) { + // cerr << i << endl << nums[i] << endl; + for (int j = 0; j < term1.size(); j++) { + if (term1[j] == nums[i]) { + int pw = term1.size() - j - 1; + cerr << "Number1 += " << i << " * 20^ " << pw << endl; + number1 += i * pow(20.0, pw); + } + } + for (int j = 0; j < term2.size(); j++) { + if (term2[j] == nums[i]) { + int pw = term2.size() - j - 1; + cerr << "Number2 += " << i << " * 20^ " << pw << endl; + number2 += i * pow(20.0, pw); + } + } + } + // cerr << "term1:" << endl; + // for (int i = 0; i < term1.size(); i++) { + // cerr << term1[i] << endl; + // } + // cerr << number1 << endl; + + // cerr << "term2:" << endl; + // for (int i = 0; i < term2.size(); i++) { + // cerr << term2[i] << endl; + // } + // cerr << number2 << endl; + + cerr << number1 << operation << number2; + + double res = 0; + switch (operation.c_str()[0]) { + case '+': + res = number1 + number2; + break; + case '-': + res = number1 - number2; + break; + case '/': + res = number1 / number2; + break; + case '*': + res = number1 * number2; + break; + } + + cerr << " = " << res << endl; + + bool started_to_write = false; + for (int i = 64; i > 0; i--) { + double curPow = pow(20.0, i - 1); + if (curPow <= res) { + int curNb = floor(res / curPow); + cerr << "Current pow: " << curPow << " - nb: " << curNb << " = " << curPow * curNb << " (res " << res << ")" << endl; + res -= (curNb * curPow); + cout << nums[curNb]; + started_to_write = true; + } else if (started_to_write == true) { + cout << nums[0]; // endl should be included. + } + } + if (started_to_write == false) { + cout << nums[0]; + } +} diff --git a/puzzles/medium/scrabble.cpp b/puzzles/medium/scrabble.cpp new file mode 100644 index 0000000..6cd8d8e --- /dev/null +++ b/puzzles/medium/scrabble.cpp @@ -0,0 +1,91 @@ +// https://www.codingame.com/ide/puzzle/scrabble +// Xavier Morel - 2016-03-15 + +#include +#include +#include +#include + +using namespace std; + +typedef struct { + string w; + int val = 0; +} Word; + +Word getWord(string str) +{ + Word res; + res.w = str; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'q' || c == 'z';}) * 10; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'j' || c == 'x';}) * 8; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'k';}) * 5; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'f' || c == 'h' || c == 'v' || c == 'w' || c == 'y';}) * 4; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'b' || c == 'c' || c == 'm' || c == 'p';}) * 3; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'd' || c == 'g';}) * 2; + res.val += std::count_if(str.begin(), str.end(), [](char c) {return c == 'e' || c == 'a' || c == 'i' || c == 'o' || c == 'n' || c == 'r' || c == 't' || c == 'l' || c == 's' || c == 'u';}) * 1; + return res; +} + +bool checkLetters(string word, string available) +{ + // A bit redundant, but whatever. + for (char c : available) { + if (count(word.begin(), word.end(), c) > count(available.begin(), available.end(), c)) { + return false; + } + } + + return true; +} + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int N; + cin >> N; cin.ignore(); + vector dict; + + for (int i = 0; i < N; i++) { + string W; + getline(cin, W); + if (W.size() < 8) { + dict.push_back(getWord(W)); + } + } + string LETTERS; + getline(cin, LETTERS); + + cerr << "Letters: " << LETTERS << endl; + + Word *bestWord = 0; + for (Word word : dict) { + if (word.w.find_first_not_of(LETTERS) == string::npos) { + if (!checkLetters(word.w, LETTERS)) { + continue; + } + // Check for multiple letter occurrences... + if (bestWord == 0 || word.val > bestWord->val) { + cerr << "Word is best than stored one: " << word.w << endl; + if (bestWord != 0) { + delete bestWord; + } + bestWord = new Word(word); + } + } else { + cerr << "Word with invalid letters: " << word.w << endl; + } + } + + // filtering of dict: + // str.find_first_not_of(LETTERS) + + // Write an action using cout. DON'T FORGET THE "<< endl" + // To debug: cerr << "Debug messages..." << endl; + + cout << bestWord->w << endl; + delete bestWord; +} diff --git a/puzzles/medium/shadow-of-the-knight-episode-1.cpp b/puzzles/medium/shadow-of-the-knight-episode-1.cpp new file mode 100644 index 0000000..8ffb3d9 --- /dev/null +++ b/puzzles/medium/shadow-of-the-knight-episode-1.cpp @@ -0,0 +1,80 @@ +// https://www.codingame.com/ide/puzzle/shadows-of-the-knight-episode-1 +// Xavier Morel - 2016-03-14 + +#include +#include +#include +#include + +#define MIN 0 +#define MAX 1 + +using namespace std; + +typedef struct { + int x; + int y; +} Coords; + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int W; // width of the building. + int H; // height of the building. + cin >> W >> H; cin.ignore(); + int N; // maximum number of turns before game over. + cin >> N; cin.ignore(); + Coords pos; + Coords range[2]; + + range[MIN].x = 0; + range[MIN].y = 0; + range[MAX].x = W - 1; + range[MAX].y = H - 1; + + cin >> pos.x >> pos.y; cin.ignore(); + + while (1) { + string BOMB_DIR; // the direction of the bombs from batman's current location (U, UR, R, DR, D, DL, L or UL) + cin >> BOMB_DIR; cin.ignore(); + + if (BOMB_DIR == "U") { + range[MAX].y = pos.y - 1; + } else if (BOMB_DIR == "UR") { + range[MAX].y = pos.y - 1; + range[MIN].x = pos.x; + } else if (BOMB_DIR == "R") { + range[MIN].x = pos.x; + } else if (BOMB_DIR == "DR") { + range[MIN].y = pos.y; + range[MIN].x = pos.x; + } else if (BOMB_DIR == "D") { + range[MIN].y = pos.y; + } else if (BOMB_DIR == "DL") { + range[MIN].y = pos.y; + range[MAX].x = pos.x - 1; + } else if (BOMB_DIR == "L") { + range[MAX].x = pos.x - 1; + } else if (BOMB_DIR == "UL") { + range[MAX].y = pos.y - 1; + range[MAX].x = pos.x - 1; + } + + if (range[MAX].x != range[MIN].x) { + pos.x = ceil((range[MAX].x + range[MIN].x) / 2.0f); + } else { + pos.x = range[MIN].x; + } + + if (range[MAX].y != range[MIN].y) { + pos.y = ceil((range[MAX].y + range[MIN].y) / 2.0f); + } else { + pos.y = range[MIN].y; + } + + cout << pos.x << " " << pos.y << endl; // the location of the next window Batman should jump to. + } +} diff --git a/puzzles/medium/skynet-revolution-episode-1.cpp b/puzzles/medium/skynet-revolution-episode-1.cpp new file mode 100644 index 0000000..aa6ab9e --- /dev/null +++ b/puzzles/medium/skynet-revolution-episode-1.cpp @@ -0,0 +1,87 @@ +// https://www.codingame.com/ide/puzzle/skynet-revolution-episode-1 +// Xavier Morel - 2016-03-12 + +#include +#include +#include +#include + +using namespace std; + +typedef struct { + bool is_gateway = false; + vector links; +} Node; + +Node *nodes; + +void remove_link(int a, int b) +{ + for (auto it = nodes[a].links.begin(); it != nodes[a].links.end(); it++) { + if (*it == b) { + nodes[a].links.erase(it); + break; + } + } + + for (auto it = nodes[b].links.begin(); it != nodes[b].links.end(); it++) { + if (*it == a) { + nodes[b].links.erase(it); + break; + } + } + cout << a << " " << b << endl; +} + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int N, L, E; + cin >> N >> L >> E; cin.ignore(); + nodes = new Node[N]; + + for (int i = 0; i < L; i++) { + int N1, N2; + cin >> N1 >> N2; cin.ignore(); + nodes[N1].links.push_back(N2); + nodes[N2].links.push_back(N1); + } + + for (int i = 0; i < E; i++) { + int EI; + cin >> EI; cin.ignore(); + nodes[EI].is_gateway = true; + } + + // game loop + while (1) { + int SI; + cin >> SI; cin.ignore(); + + int a = 0; + int b = 0; + + for (int i : nodes[SI].links) { + cerr << "Check node " << i << endl; + if (nodes[i].is_gateway && nodes[i].links.size() > 0) { + a = SI; + b = i; + break; + } + } + + if (a == 0 && b == 0) { + for (int i = 0; i < N; i++) { + if (nodes[i].is_gateway && nodes[i].links.size() > 0) { + a = i; + b = nodes[i].links.back(); + break; + } + } + } + remove_link(a, b); + } +} diff --git a/puzzles/medium/stock-exchange-losses.cpp b/puzzles/medium/stock-exchange-losses.cpp new file mode 100644 index 0000000..6a4035e --- /dev/null +++ b/puzzles/medium/stock-exchange-losses.cpp @@ -0,0 +1,61 @@ +// https://www.codingame.com/ide/puzzle/stock-exchange-losses +// Xavier Morel - 2016-03-16 + +#include +#include +#include +#include + +using namespace std; + + + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int n; + cin >> n; cin.ignore(); + vector history; + int last_high = 0; + int last_low = 0; + int prev = 0; + for (int i = 0; i < n; i++) { + int v; + cin >> v; cin.ignore(); + + if (i == 0) { + last_high = v; + last_low = v; + continue; + } else { + if (v > last_high) { + if (last_high != last_low) { + history.push_back(last_high); + history.push_back(last_low); + } + last_high = v; + last_low = v; + } else if (v < last_low) { + last_low = v; + } + } + } + + if (last_high != last_low) { + history.push_back(last_high); + history.push_back(last_low); + } + + int max_loss = 0; + for (vector::iterator it = history.begin(); it != history.end(); it++) { + int loss = *min_element(it, history.end()) - *it; + if (loss < max_loss) { + max_loss = loss; + } + } + + cout << max_loss << endl; +} diff --git a/puzzles/medium/teads-sponsored-contest.cpp b/puzzles/medium/teads-sponsored-contest.cpp new file mode 100644 index 0000000..46c7bf3 --- /dev/null +++ b/puzzles/medium/teads-sponsored-contest.cpp @@ -0,0 +1,74 @@ +// https://www.codingame.com/ide/puzzle/teads-sponsored-contest +// Xavier Morel - 2016-03-17 + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +map> points; + +int findFarthestNode(int origin, int *distanceOut) +{ + int maxDistance = 0; + int farthestNode = 0; + vector> process; + + set discovered; + + process.push_back(pair(origin,0)); + while (process.size() > 0) { + pair node = process.back(); // node, distance + process.pop_back(); + discovered.insert(node.first); + + if (node.second > maxDistance) { + maxDistance = node.second; + farthestNode = node.first; + } + + for (int adjNode : points[node.first]) { + if (discovered.find(adjNode) == discovered.end()) { + process.push_back(pair(adjNode, node.second + 1)); + } + } + + } + + if (distanceOut != 0) { + *distanceOut = maxDistance; + } + + return farthestNode; +} + + + +int main() +{ + int n; + cin >> n; cin.ignore(); + int firstNode; + for (int i = 0; i < n; i++) { + int xi; + int yi; + cin >> xi >> yi; cin.ignore(); + points[xi].push_back(yi); + points[yi].push_back(xi); + if (i == 0) { + firstNode = xi; + } + } + + int distance; + int farNode = findFarthestNode(firstNode, &distance); + cerr << "Farthest node from origin is " << farNode << " with distance of " << distance << endl; + farNode = findFarthestNode(farNode, &distance); + cerr << "Farthest node from previous is " << farNode << " with distance of " << distance << endl; + + cout << ceil(distance / 2.0f) << endl; +} diff --git a/puzzles/medium/telephone-numbers.php b/puzzles/medium/telephone-numbers.php new file mode 100644 index 0000000..f861737 --- /dev/null +++ b/puzzles/medium/telephone-numbers.php @@ -0,0 +1,29 @@ + +#include +#include +#include +#include + +using namespace std; + +typedef struct { + int number; + int budget; + int resp; +} Ood; + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + int number; + cin >> number; cin.ignore(); + int total_price; + cin >> total_price; cin.ignore(); + int budget[number]; + int total_sum = 0; + cerr << "Price: " << total_price << " for " << number << " people." << endl; + for (int i = 0; i < number; i++) { + cin >> budget[i]; cin.ignore(); + total_sum += budget[i]; + cerr << "Budget " << i << ": " << budget[i] << " (Total: " << total_sum << ")" << endl; + } + + if (total_sum < total_price) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + int res[number]; + for (int i = 0; i < number; i++) { + res[i] = 0; + } + + int left = total_price; + while (left > 0) { + int eq_parts = left / number; + if (eq_parts == 0) { + eq_parts = 1; + } + cerr << "Each ood should pay " << eq_parts << " (left: " << left << ")" << endl; + for (int i = 0; i < number; i++) { + if (left == 0) { + break; + } + if (budget[i] >= eq_parts) { + cerr << "Ood " << i << " can pay (budget " << budget[i] << ")" << endl; + res[i] += eq_parts; + left -= eq_parts; + budget[i] -= eq_parts; + cerr << "-> Will pay total " << res[i] << " (budget left: " << budget[i] << ")" << endl; + } else { + cerr << "Ood " << i << " cant pay that much" << endl; + res[i] += budget[i]; + left -= budget[i]; + budget[i] = 0; + cerr << "-> Will pay total " << res[i] << " (budget left: " << budget[i] << ")" << endl; + } + } + } + + sort(res, res + number); + + for (int i = 0; i < number; i++) { + cout << res[i] << endl; + } +} diff --git a/puzzles/medium/there-is-no-spoon-episode-1.cpp b/puzzles/medium/there-is-no-spoon-episode-1.cpp new file mode 100644 index 0000000..af89761 --- /dev/null +++ b/puzzles/medium/there-is-no-spoon-episode-1.cpp @@ -0,0 +1,64 @@ +// https://www.codingame.com/ide/puzzle/there-is-no-spoon-episode-1 +// Xavier Morel - 2016-03-13 + +#include +#include +#include +#include +#include + +using namespace std; + +#define POS(x,y) ((width * y) + x) + +/** + * Don't let the machines win. You are humanity's last hope... + **/ +int main() +{ + int width; // the number of cells on the X axis + cin >> width; cin.ignore(); + int height; // the number of cells on the Y axis + cin >> height; cin.ignore(); + + char table[(width * height) + 1]; + + for (int i = 0; i < height; i++) { + string line; // width characters, each either 0 or . + getline(cin, line); + memcpy(table + (width*i), line.c_str(), width); + } + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (*(table + POS(x, y)) == '.') { + continue; + } + + int rightof = -1; + int below = -1; + + for (int t = x + 1; t < width; t++) { + if (*(table + POS(t, y)) == '0') { + rightof = t; + break; + } + } + + for (int t = y + 1; t < height; t++) { + if (*(table + POS(x, t)) == '0') { + below = t; + break; + } + } + + cout + << x << " " + << y << " " + << (rightof == -1 ? -1 : rightof) << " " + << (rightof == -1 ? -1 : y) << " " + << (below == -1 ? -1 : x) << " " + << (below == -1 ? -1 : below) << endl; + } + } +} diff --git a/puzzles/medium/winamax-battle.cpp b/puzzles/medium/winamax-battle.cpp new file mode 100644 index 0000000..85eb4a5 --- /dev/null +++ b/puzzles/medium/winamax-battle.cpp @@ -0,0 +1,121 @@ +// https://www.codingame.com/ide/puzzle/winamax-battle +// Xavier Morel - 2016-03-14 +// WIP : only passing tests up to 88%... + +#include +#include +#include + +using namespace std; + +int parseCard(string card) +{ + int num; + card = card.substr(0, card.size() - 1); + if (card == "J") { + num = 11; + } else if (card == "Q") { + num = 12; + } else if (card == "K") { + num = 13; + } else if (card == "A") { + num = 14; + } else { + num = stoi(card); + } + return num; +} + +void moveCards(list &winner, int card1, list &stack1, int card2, list &stack2) +{ + while (stack1.size() > 0) { + winner.push_back(stack1.front()); + stack1.pop_front(); + } + winner.push_back(card1); + while (stack2.size() > 0) { + winner.push_back(stack2.front()); + stack2.pop_front(); + } + winner.push_back(card2); +} + +void battleMove(list &stack, int card, list &cards) +{ + stack.push_back(card); + for (int i = 0; i < 3; i++) { + if (cards.size() == 0) { + break; + } + stack.push_back(cards.front()); + cards.pop_front(); + } +} + +int runSimulation(list &p1, list &p2) { + list stack1; + list stack2; + int turns = 0; + + while (p1.size() > 0 && p2.size() > 0) { + cerr << "Turn " << turns << ": " << p1.size() << " (" << stack1.size() << ") vs " << p2.size() << " (" << stack2.size() << ")" << endl; + + int first1 = p1.front(); p1.pop_front(); + int first2 = p2.front(); p2.pop_front(); + + if (first1 > first2) { + cerr << first1 << " > " << first2 << endl; + moveCards(p1, first1, stack1, first2, stack2); + turns++; + } else if (first1 < first2) { + cerr << first1 << " < " << first2 << endl; + moveCards(p2, first1, stack1, first2, stack2); + turns++; + } else { + // BATTLE + cerr << "Battle" << endl; + battleMove(stack1, first1, p1); + battleMove(stack2, first2, p2); + } + + } + + cerr << "END Turn " << turns << ": " << p1.size() << " (" << stack1.size() << ") vs " << p2.size() << " (" << stack2.size() << ")" << endl; + + return turns; +} + +/** + * Auto-generated code below aims at helping you parse + * the standard input according to the problem statement. + **/ +int main() +{ + list player1; + list player2; + + int n; // the number of cards for player 1 + cin >> n; cin.ignore(); + for (int i = 0; i < n; i++) { + string cardp1; // the n cards of player 1 + cin >> cardp1; cin.ignore(); + player1.push_back(parseCard(cardp1)); + } + + int m; // the number of cards for player 2 + cin >> m; cin.ignore(); + for (int i = 0; i < m; i++) { + string cardp2; // the m cards of player 2 + cin >> cardp2; cin.ignore(); + player2.push_back(parseCard(cardp2)); + } + + int turns = runSimulation(player1, player2); + + if (!player1.size() && !player2.size()) { + cout << "PAT" << endl; + } else { + int winner = (player1.size() > 0 ? 1 : 2); + cout << winner << " " << turns << endl; + } +}