You are playing balls and cows with your friends. The rules of the game are as follows:
Write a secret number and ask your friend to guess what the number is. Every time a friend guesses, you will give him a hint containing the following information:
Guess how many digits in the number belong to the number and the exact position (called "Bulls", bull),
How many digits belong to numbers, but the position is wrong (called "Cows"). In other words, how many non bull numbers in this guess can be converted into bull numbers by rearrangement.
Give you a secret number Secret and friends guess the number Guess, please return to your friend's guess.
The format of the prompt is "xAyB", x is the number of bulls, y is the number of cows, A is the number of bulls, and B is the number of cows Represents A cow.
Please note that both secret numbers and numbers guessed by friends may contain duplicate numbers.
Example 1:
Input: secret = "1807", guess = "7810"
Output: "1A3B"
Explanation: the numbers and positions are connected by '' for (bulls). If the numbers are right and the positions are wrong (cows), they are marked in bold italics.
"1807"

"7810"
Example 2:
Input: secret = "1123", guess = "0111"
Output: "1A1B"
Explanation: the numbers and positions are connected by '' for (bulls). If the numbers are right and the positions are wrong (cows), they are marked in bold italics.
"1123" "1123"
 or 
"0111" "0111"
Note that only one of the two mismatched ones will be counted as a cow (the number is guessed right and the position is wrong). By rearranging non bull numbers, only one 1 can become a bull number.
Example 3:
Input: secret = "1", guess = "0"
Output: "0A0B"
Example 4:
Input: secret = "1", guess = "1"
Output: "1A0B"
Tips:
1 <= secret.length, guess.length <= 1000
secret.length == guess.length
secret and guess consist only of numbers
Idea 1:
Dictionary + zipper method
Record the number and the position of occurrence in the dictionary, and calculate the values of A and B after traversing guess
1 class Solution: 2 def getHint(self, secret: str, guess: str) > str: 3 maps = {} 4 length = len(secret) 5 bull_mask = [False] * length 6 A = 0 7 B = 0 8 for i in range(length): 9 key = secret[i] 10 if key in maps: 11 maps[key].append(i) 12 else: 13 maps[key] = [i] 14 15 # bulls 16 for i in range(length): 17 guess_ch = guess[i] 18 if guess_ch in maps and i in maps[guess_ch]: 19 A += 1 20 maps[guess_ch].remove(i) 21 bull_mask[i] = True 22 23 # cows 24 for i in range(length): 25 guess_ch = guess[i] 26 if not bull_mask[i] and guess_ch in maps and maps[guess_ch]: 27 B += 1 28 maps[guess_ch].pop() 29 return format(f"{A}A{B}B")
Idea 2:
Considering that there are only 10 occurrences of numbers, you can simplify the dictionary into an array
A number corresponds to the number of cows After excluding the bull, min(guess the number of times the number appears, and the number of times the number appears in secret)
1 class Solution2: 2 def getHint(self, secret: str, guess: str) > str: 3 A = 0 4 B = 0 5 cnt_secret = [0] * 10 6 cnt_guess = [0] * 10 7 8 for i in range(len(secret)): 9 guess_ch = guess[i] 10 secret_ch = secret[i] 11 # bulls 12 if guess_ch == secret_ch: 13 A += 1 14 # cows 15 else: 16 cnt_secret[ord(secret_ch)  ord('0')] += 1 17 cnt_guess[ord(guess_ch)  ord('0')] += 1 18 for s, g in zip(cnt_secret, cnt_guess): 19 B += min(s, g) 20 return f"{A}A{B}B"