Misère Nim

Sort by

recency

|

30 Discussions

|

  • + 0 comments

    Rust best solution

    If you’re looking for solutions to the 3-month preparation kit in either Python or Rust, you can find them below: my solutions

    fn misere_nim(s: &[i32]) -> String {
        //Time complexity: O(n)
        //Space complexity (ignoring input): O(1)
        let mut xor_sum = 0;
        let mut exist_column_over_1 = false;
        for &number in s {
            xor_sum ^= number;
            if number > 1 {
                exist_column_over_1 = true;
            }
        }
    
        if exist_column_over_1 {
            if xor_sum == 0 {
                return String::from("Second");
            } else {
                return String::from("First");
            }
        } else {
            if s.len() % 2 == 0 {
                return String::from("First");
            } else {
                return String::from("Second");
            }
        }
    }
    
  • + 0 comments

    This is seems to be a bad problem, because I don't see how you can deduce that during the interview (different from the magic square, where you can build all the possible squares). I've also added solution to normal nim as a reference Python best solution

    If you’re looking for solutions to the 3-month preparation kit in either Python or Rust, you can find them below: my solutions

    def normal_nim(s):
        # Here, the last player to move wins (last player to remove last stones)
        initial_xor_sum = 0
        for pile in s:
            initial_xor_sum ^= pile
    
        # In case the initial state is xor_sum equal to 0, any move player 1 makes will
        # change the xor_sum to not 0. As long as player 2 moves to make the xor_sum
        # back to 0, player 1 can never wins
        if initial_xor_sum == 0:
            return "Player 2"
        else:
            return "Player 1"
    
    
    # Function to a find a winnable move in a nim-game
    def move_to_zero_xor(s):
        xor_sum = 0
        for number in s:
            xor_sum ^= number
    
        if xor_sum == 0:
            return "XOR of all numbers is already 0"
        # Proof that there is always a move that makes the xor_sum from not 0 to 0
        # Let S be the xor of all numbers but the one I'll change, which is x.
        # S^x = xor_sum
        # S^x' = 0 =>  x' = S => x'^x = xor_sum => x^xor_sum = x'
        # To prove that always exist x' < x, just look for the highest bit in xor_sum
        # look for a number that has that bit as well, x' won't have. This way,
        # I can guarantee there will be a number that works and that x' < x.
    
        copy_xor_sum = xor_sum
        highest_bit = 0
        while copy_xor_sum > 1:
            copy_xor_sum = copy_xor_sum >> 1
            highest_bit += 1
    
        base_10 = 1 << highest_bit
        for number in s:
            if (number & base_10) == base_10:
                print(f"Move from number {number} to number {xor_sum ^ number}")
    
    
    def misere_nim(s):
        # Although less obvious than normal nim, the logic is similar. But there is an edge-case
        # As long your next move will not change all columns to be 1, forcing oponent
        # into xor_sum = 0 is a winning move. If all columns are 1, odd columns is a
        # winning move to your oponent and even columns is winning move to you
        xor_sum = 0
        columns_one = 0
        exist_non_one_column = False
        for number in s:
            if number == 1:
                columns_one += 1
            else:
                exist_non_one_column = True
            xor_sum ^= number
    
        if exist_non_one_column:
            if xor_sum==0:
                return "Second"
            else:
                return "First"
        else:
            if columns_one%2==0:
                return "First"
            else:
                return "Second"
    
  • + 0 comments
    def misereNim(s):
        if all(x == 1 for x in s):
            if len(s) % 2 == 1:
                return "Second"
            else:
                return "First"
        else:
            balance = 0
            for val in s:
                balance ^= val
            if balance == 0:
                return "Second"
            else:
                return "First"
    
  • + 1 comment

    If you're familiar with Nim-Sum, this problem will be very easy; otherwise, it's incredibly difficult. This type of problem should be used to test well-read individuals, not programmers.

        let allOnes = true;
        
        for (let stone of stones) {
            xorSum ^= stone;
            if (stone > 1) {
                allOnes = false;
            }
        }
        
        if (allOnes) {
            return stones.length % 2 === 0 ? "First" : "Second";
        } else {
            return xorSum === 0 ? "Second" : "First";
        }
    
  • + 0 comments

    def misereNim(s):

    xor = reduce((lambda x, y: x ^ y), s)
    if max(s) == 1:
        return "First" if xor == 0 else "Second"
    else:
        return "Second" if xor == 0 else "First"