Python solves digital baseball games

Posted by ryeman98 on Fri, 14 Jan 2022 04:42:41 +0100

The number baseball game is played in this way: first, a thinks of a four digit number in his mind, such as 3092. If it is less than four digits, it is supplemented by 0. For example, 12 is considered to be 0012. This number is called the target. B guesses the number. The method is like this. He first randomly says a number to a, such as 5382. A tells B how many balls and strikes there are in 5382. The so-called ball means that several numbers in 5382 appear in the target. Because the numbers 3 and 2 have appeared, there is ball=2. The so-called strike means that several positions in the two balls are correct. For example, in the above example, the number 2 is in the correct position, so strike=1. B will then analyze it and guess a number. A will tell B what ball and strike are equal to respectively. This process is repeated until B guesses the goal. Note that strike is always less than or equal to ball. Here is an example:

A: I have a four digit number
 B: 0115
 A: ball=1,strike=0
 B: 5623
 A: ball=0,strike=0
 B: 1798
 A: ball=1,strike=1
 B: 8088
 A: ball=3,strike=1
 B: 4088
 A: you guessed right!

The goal of this section is to write a program for human beings to make questions and computers to guess. When you see this problem, you can easily think of such an idea. When you guess 5382 that ball=2 and stripes = 1, it means that the shape of the target is like 5 * 3 *, 5 * * 3, * 35 *, * 3 * 5, 58 * *, 5 * * 8. Write down all these possible patterns, then randomly select one of them, such as * 35 *, and then randomly spell out a data, such as 1359, so that humans can inform the comparison results, and then update the above patterns with the results. This process is complicated. In fact, we also have a simple way of thinking: reverse thinking + data structure.

The so-called reverse thinking means that we do not try to establish the target model, but conversely, eliminate the impossible model. For example, if you guess that 5382 gets b2s1, exclude the 10000 numbers from 0 to 9999 that are not b2s1 compared with 5382. The result of this is certain, not as many patterns obtained by positive thinking are uncertain.

The data structure of reverse thinking is A list candidates containing 10000 numbers from 0 to 9999, and each number is represented by A list containing 4 numbers. For example, 123 is represented by [0, 1, 2, 3]. First, the computer randomly selects A number A from the candidates to guess. After human beings tell the values of ball and strike, the program deletes some numbers from the candidates. The results after comparing these numbers with A are different from the above ball and strike. Then the computer randomly selects A number from the simplified candidates and repeats the above process until B guesses the number.

It can be seen that as long as an appropriate data structure is established - even if the data structure is very simple - the difficulty of the problem can be solved. The code is as follows:

Python solves digital baseball games

# File: p04_03_ball_strike.py
import random

def get_candidates(num=4):  # Get all 4-bit candidates
    return [to_list(i, num) for i in range(int(10**num))]

def to_list(n, num):  # Convert the number n to a list of num digits
    result = []
    for _ in range(num):
        result.insert(0, n % 10)
        n //= 10
    return result

def get_balls_strikes(goal, guess): # Get the result after comparing two numbers
    balls = 0
    goal_copy = goal.copy()
    for digit in guess:
        if digit in goal_copy:
            balls += 1
            pos = goal_copy.index(digit)
            goal_copy[pos] = -1  # Fill in - 1 for each number found

    strikes = 0
    for d1, d2 in zip(guess, goal):  # Bitwise comparison
        if d1 == d2:
            strikes += 1
    return balls, strikes

def guess(candidates):  # Select a number at random from the candidate numbers
    return candidates[random.randint(0, len(candidates)-1)]

def extract(candidates, guess, balls, strikes):
    # Delete impossible candidates
    for i in range(len(candidates)-1, -1, -1):
        bs, ss = get_balls_strikes(candidates[i], guess)
        if ss != strikes or bs != balls:  # If the comparison results do not match
            del candidates[i]

def to_str(digit_list):
    return ''.join([chr(ord('0') + d) for d in digit_list])

if __name__ == '__main__':
    num = 4
    goal = input('Please enter a target, one at most%d Bit positive integer:' % num)
    goal = to_list(int(goal), num)
    candidates = get_candidates()
    guesses = 0
    while True:
        g = guess(candidates)
        guesses += 1
        print("I guess:", to_str(g))
        if g == goal:
            break
        balls, strikes = get_balls_strikes(goal, g)
        print("\tballs =", balls, "strikes =", strikes)
        extract(candidates, g, balls, strikes)
    print('Yes, I guess%d second' % guesses)

The results of program operation are as follows:

Please enter the target, a positive integer of up to 4 digits: 3450
 I guess: 5848
	balls = 2 strikes = 0
 I guess: 4553
	balls = 3 strikes = 1
 I guess: 4365
	balls = 3 strikes = 0
 I guess: 3574
	balls = 3 strikes = 1
 I guess: 3450
 You guessed right. I guessed five times

 

 

Topics: Python data structure