5 kyu

Don't Eat the Last Cake!

562 of 1,779SagePtr

Description:

Welcome Warrior! Let's play a game!

You've gotten challenged by a lot of kata, now it's time for you to challenge the kata!

In a room is a table with a pile of cakes. One of these cakes is poisoned. Every turn, we will take cakes from this pile and eat them, leaving the last one to be the poisoned cake. Whoever eats the poisoned cake will die. The poisoned cake is clearly marked, so you do not have to guess. Rather you need to rely on logic to save you.

The rules are simple:

  1. Do not eat the last cake. It's obivious that the poisoned cake will be the last to be eaten, so, DON'T EAT THE LAST CAKE. Try to make your opponent eat it.

  2. When it is your turn, you can only take one, two or three cakes. The same rules apply to your opponent on their turn. You cannot skip your move, so choose wisely how many cakes to eat. Both opponents will be able to see how many cakes the other eats on each turn.

  3. You cannot copy your opponent's previous move; likewise they cannot copy yours. If your opponent takes one cake, next move you can only choose between two and three. If you take three cakes, your opponent can only choose one or two. This doesn't effect the first move, only subsequent ones.

  4. If one of the players has no valid moves (ie. one cake left and previous move was one cake), that player will skip their turn. Then the other player will be forced to eat the last cake. This is the ONLY case of turn skipping.

  5. You can choose whether or not to go first. This decision is key to victory, so don't hurry, choose wisely!

Task of this kata:

To solve this kata, you should write class called Player. This class has one constructor and two other functions:

class Player {
  // called at the beginning of each game. Parameter: a number of cakes on the table
  constructor(cakes) {
  }
  // called after the constructor. Must return true if you want to move first, false is you want to move after your opponent
  // Parameter: number of cakes on the table left (same as in constructor)
  firstmove(cakes) {
  }
  // called before each of your moves. First parameter: number of cakes left on the table. Second parameter: amount of cakes took by your opponent last move. Must return 1, 2 or 3 depending of how much cakes you want to take.
  move(cakes, last) {
  }
}
class Player {
  // called at the beginning of each game. Parameter: a number of cakes on the table
  constructor(cakes: number) {
  }
  // called after the constructor. Must return true if you want to move first, false is you want to move after your opponent
  // Parameter: number of cakes on the table left (same as in constructor)
  firstmove(cakes: number): boolean {
  }
  // called before each of your moves. First parameter: number of cakes left on the table. Second parameter: amount of cakes took by your opponent last move. Must return 1, 2 or 3 depending of how much cakes you want to take.
  move(cakes: number, last: number): number {
  }
}
class Player
  # called at the beginning of each game. Parameter: a number of cakes on the table.
  constructor: (cakes) ->
  
  # called after the constructor.
  # Parameter: number of cakes on the table left (same as in constructor).
  # Must return true if you want to move first, false is you want to move after your opponent.
  firstmove: (cakes) -> 

  # called before each of your moves.
  # First parameter: number of cakes left on the table.
  # Second parameter: amount of cakes took by your opponent last move.
  # Must return 1, 2 or 3 depending of how much cakes you want to take.
  move: (cakes, last) ->
  
class Player
  # called at the beginning of each game. Parameter: a number of cakes on the table.
  def initialize(cakes)
  end
  # called after the constructor.
  # Parameter: number of cakes on the table left (same as in constructor).
  # Must return true if you want to move first, false is you want to move after your opponent.
  def firstmove(cakes)
  end
  # called before each of your moves.
  # First parameter: number of cakes left on the table.
  # Second parameter: amount of cakes took by your opponent last move.
  # Must return 1, 2 or 3 depending of how much cakes you want to take.  
  def move(cakes, last)
    last == 1 ? 2 : 1 # I'm not greedy
  end
end
class Player:
  # called at the beginning of each game. Parameter: a number of cakes on the table.
  def __init__(self, cakes):
  
  # called after the constructor.
  # Parameter: number of cakes on the table left (same as in constructor).
  # Must return true if you want to move first, false is you want to move after your opponent.
  def firstmove(self, cakes): 

  # called before each of your moves.
  # First parameter: number of cakes left on the table.
  # Second parameter: amount of cakes took by your opponent last move.
  # Must return 1, 2 or 3 depending of how much cakes you want to take.
  def move(self, cakes, last):
  
<?php
class Player
{
  // Called at the beginning of each game.
  // Parameter: a number of cakes on the table.
  function __construct(int $cakes)
  {
  }
  // Called after the constructor.
  // Parameter: number of cakes on the table left (same as in constructor).
  // Must return true if you want to move first, false is you want to move after your opponent.
  public function firstmove(int $cakes): bool
  {
  }
  // Called before each of your moves.
  // First parameter: number of cakes left on the table.
  // Second parameter: amount of cakes took by your opponent last move.
  // Must return 1, 2 or 3 depending of how much cakes you want to take.
  public function move(int $cakes, int $last): int
  {
  }
}
public class Player {
  Player(int cakes) {
    // called at the beginning of each game. Parameter: a number of cakes on the table
  }
  
  boolean firstMove(int cakes){
    // called after the constructor.
    // Parameter: number of cakes on the table left (same as in constructor)
    // Must return true if you want to move first, false is you want to move after your opponent
  }
  int move(int cakes, int last){
    // called before each of your moves.
    // First parameter: number of cakes left on the table.
    // Second parameter: amount of cakes took by your opponent last move.
    // Must return 1, 2 or 3 depending of how much cakes you want to take.
  }
}
-- actually, forget that class, it's useless. just define

firstMove :: Int -> Bool  -- Must return True if you want to move first, False if you want to move after your opponent
                          -- Parameter: number of cakes initially on the table

move :: Int -> Int -> Int -- Must return 1, 2 or 3 depending on how many cakes you want to take
                          -- First parameter: number of cakes currently on the table
                          -- Second parameter: number of cakes your opponent took last move ( or 0, only for the very first move of any game )

Each test is a different game and different instance of the Player class. You should not worry about calling functions, you should only watch the number of cakes on the table and decide on every move how many to take, and decide who moves first.

Write your Player class and beat your opponent! You must figure out a strategy that can guarantee you a victory.

Your implementation should not crash or do invalid moves if used as the second player (without an option to choose the fisrt move). If you are forced to lose, do it with dignity.

Example:

class Player {
  constructor(cakes) {
    // Not sure if you need one
  }
  // Decide who moves first - player or opponent (true if player)
  firstmove(cakes) {
    // I wish to move first
    return true;
  }
  // Decide your next move
  move(cakes, last) {
    // I'm not greedy
    return last == 1 ? 2 : 1;
  }
}
export class Player {
  constructor(cakes: number) {
    // Not sure if you need one
  }
  // Decide who moves first - player or opponent (true if player)
  firstmove(cakes: number): boolean {
    // I wish to move first
    return true;
  }
  // Decide your next move
  move(cakes: number, last: number): number {
    // I'm not greedy
    return last == 1 ? 2 : 1;
  }
}
class Player
  constructor: (cakes) ->
  
  # Decide who moves first - player or opponent (return true if player)
  firstmove: (cakes) -> 
    true # I want to move first
    
  # Decide your next move (return 1, 2 or 3)
  move: (cakes, last) ->
    if last is 1 then 2 else 1 # I'm not greedy
class Player
  # Constructor
  def initialize(cakes)
  end
  # Decide who moves first - player or opponent (return true if player)
  def firstmove(cakes)
    true # I want to move first
  end
  # Decide your next move (return 1, 2 or 3)
  def move(cakes, last)
    last == 1 ? 2 : 1 # I'm not greedy
  end
end
class Player:
    # Constructor
    def __init__(self, cakes):
        pass
    # Decide who moves first
    def firstmove(self, cakes):
        # I wish to move first
        return True
    # Decide your next move
    def move(self, cakes, last):
        #I'm not greedy
        return 1 if last != 1 else 2
<?php
class Player
{
  // Class constructor
  function __construct(int $cakes)
  {
    // Not sure if you need one
  }
  // Decide who moves first - player or opponent (true if player)
  public function firstmove(int $cakes): bool
  {
    // I wish to move first
    return true;
  }
  // Decide your next move
  public function move(int $cakes, int $last): int
  {
    // I'm not greedy
    return $last == 1 ? 2 : 1;
  }
}
public class Player {
  Player(int cakes) {
  }
  // Decide who moves first - player or opponent (return true if player)
  boolean firstMove(int cakes) {
    // I wish to move first
    return true;
  }
  // Decide your next move (return 1, 2 or 3)
  int move(int cakes, int last) {
    // I'm not greedy
    return last == 1 ? 2 : 1;
  }
}
-- Decide who moves first - player or opponent (return True if player)
firstMove :: Int -> Bool
firstMove cakes = True -- I wish to move first

-- Decide your next move (return 1, 2 or 3)
move :: Int -> Int -> Int
move cakes    1 = 2
move cakes last = 1 -- I'm not greedy

Example of game:

12 cakes on the table. You decide to move first.

You eat 1 cake, 11 cakes left.

Opponent eats 3 cakes, 8 cakes left.

You eat 2 cakes, 6 cakes left.

Opponent eats 1 cake, 5 cakes left.

You eat 3 cakes, 2 cakes left.

Opponent has no winning choice. If he eats 2 cakes, he will lose. If he eats 1 cake, you will be left in stalemate situation, and he will again eat 1 cake and lose.

You win.

Puzzles

Stats:

CreatedMay 27, 2014
PublishedMay 27, 2014
Warriors Trained13587
Total Skips5262
Total Code Submissions42818
Total Times Completed1779
JavaScript Completions589
CoffeeScript Completions19
Python Completions562
Ruby Completions168
Java Completions491
Haskell Completions14
TypeScript Completions22
PHP Completions10
Total Stars650
% of votes with a positive feedback rating92% of 256
Total "Very Satisfied" Votes225
Total "Somewhat Satisfied" Votes21
Total "Not Satisfied" Votes10
Ad
Contributors
  • SagePtr Avatar
  • jhoffner Avatar
  • alchemy Avatar
  • xcthulhu Avatar
  • TellowKrinkle Avatar
  • JohanWiltink Avatar
  • flaco Avatar
  • bidouille Avatar
Ad