[Question]
  [
You probably know the game mastermind:
The player tries to guess a code of 4 slots, with 8 possible colors - no duplicates this time.
Let's call those colors A through H, so possible solutions could be ABCD or BCHD.
Each time you place a guess, the game master will respond with two information: how many slots you got right, and how many colors you got right but in the wrong place.
Some examples:
```
If the code is ABCD
and your guess is ACHB
the response 12: the color A is correctly placed, the two colors B&C are in the wrong place.
Code is ABCD
you guess EFGH
response is 00
Code is ABCD
you guess ABCD
response is 40
A full representation would be:
ABCD04,DCBA40
or
ABCD00,EFGH22,EFHG13,HFGE40
A partial game does not contain the final solution, 
nor necessarily enough data to define a unique solution.
ABCD00,EFGH22,EFHG13
An example for an invalid partial game would be:
ABCD03,EFGH02: This would require that 5 colors are present
```
In essence, all games that cannot have a solution are invalid. The gamemaster made a mistake.
**Your task**
Never trust a game master. Your task is to write a program that takes a partial or full game description and validates whether such a game state is possible.
* Expect that no game description is longer than 8 attempts.
* Expect that the gamemaster can make a mistake on the very first turn, e.g. ABCD41
* The player can make an "invalid" guess to gain further information, e.g. AAAA to check if there is an A at all. Such a game is still valid, you only evaluate the gamemaster's responses. In such a case, exact hit takes precedence over near-misses, for code ABCD it's AAAA10, not AAAA14.
* You can format the input and output in whatever way you see fit, including replacing the colors by digits etc.
* Any pre-generated hashtable counts towards the total number of bytes.
* You know the loophole thing.
**The shortest code wins.**
Additional test cases:
```
 - ABCD11,ACEG02,HGFE11,CCCC10,CDGH01 => valid
 - ABCD01,EFGH03,CGGH11,HGFE21 => valid
 - ABCD22,EFGH01,ACDE11 => invalid
 - ABCD02,EFGH01,AABB21,AEDH30 => invalid
 - ABCD03,DCBA02 => invalid 
 - ABCD32 => invalid
```
You can generate any number of valid cases by [playing the game.](https://www.webgamesonline.com/mastermind/index.php)
Invalid solutions are hard to come up with. If you find invalid combinations that first slipped through your code, please comment it below for your fellow golfers.
**Bonus:**
Bonus points if you come up with a solution that uses a significantly different approach than generating and traversing all possible permutations.
  
[Answer]
# JavaScript (ES6), ~~116 112~~ 107 bytes
Expects an array of entries in the following format: `[[a,b,c,d], "XY"]`, where `a` to `d` are integers in `[0..7]`, `X` is the number of correct digits and `Y` is the number of near-misses.
Returns **0** or **1**.
```
f=(a,n)=>n>>12?0:!a.some(([a,x])=>!a.every(o=(d,i)=>o[x-=d^(v=n>>i*3&7)?a.includes(v):10,v]^=1)|x)|f(a,-~n)
```
[Try it online!](https://tio.run/##dZDBTtwwEIbvPIW5ELt4jZMsqkSVRVkn69w4cEyDZCXO1ihrL3GIFgE99gH6iH2RZbJUoogyh7E8880/v32rRuXr3myHmXWN3u/bBCtqSbKwi0UYXfKLY8W822iMS0V3FTSgoEfdP2CX4IYaqLhyN0uaGzwmMGS@xCdfyaVixtbdfaM9HslFyOlY3SQhedqRpxY2zH5asu/13b3pNQ5aHxDWa9WsTKevH2yNOWGDux56Y9eYML/tzICD7xaw1vW5qn9gj5IFejxCSKEE4Q0kzzZqgM5Zmc6K6nH@zNjZmhCobl/pEpWMMc98Z2qNOUVzUh269dQN0qXI8pUsArDe6N1Vi2tCKPLlvEKncJxXqCLfYGPtrHedZp1b4w27dcbiAIG1rWpy2@B4ToAP0J9fvyGfIngvgblnsp82hCFNRS55RAu5yuEmIOB/RCYLHk5GRtWZ5mhieUgnQzymQsoC2GkkCtHfeMdG0Ss7yWegi94HsMb@o/xGp8tlBEeeFTH/jI5pJpYpj9B/441GBzz@hPsoLqQQYEWmEsSpSOFDoo/0gX0B "JavaScript (Node.js) – Try It Online")
### Commented
```
f = (                     // f is a recursive function taking:
  a,                      //   a[] = input
  n                       //   n = 12-bit counter, initially undefined, to
) =>                      //       describe all possible codes
n >> 12 ?                 // if n = 4096:
  0                       //   stop the recursion
:                         // else:
  !a.some(([a, x]) =>     //   for each entry [a, x, y] in a[], with a[] =
                          //   guess, x = correct digits and near-misses:
    !a.every(o =          //     we use the object o to keep track of the
                          //     digits that were already extracted from n,
                          //     in order to discard invalid codes
      (d, i) =>           //     for each value d at position i in a[]:
      o[                  //
        x -=              //       update x:
          d ^ (           //         compare d with ...
            v =           //         ... v which is defined as ...
              n >> i * 3  //         ... the next 3-bit digit extracted from n
              & 7         //
          ) ?             //         if d is not equal to v, decrement x if ...
            a.includes(v) //           ... v appears elsewhere in a[]
          :               //         else:
            10,           //           subtract 10 from x
        v                 //       actual index in o to ...
      ] ^= 1              //       ... mark this digit as used; or yield 0
                          //       and exit every() if it was already used
    )                     //     end of every(); the iteration fails if it's
    | x                   //     falsy or x is not equal to 0
  )                       //   end of some()
  | f(a, -~n)             //   do a recursive call with n + 1
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 47 bytes
```
⊙ＥＸ⁸¦⁴Ｅ⁴§α﹪÷ιＸ⁸λ⁸∧⬤ι⁼№ιλ¹⬤θ⁼Ｉ…⮌λ²ΣＥι∨⁼ν§λξ∧№λνχ
```
[Try it online!](https://tio.run/##RU7LCsIwEPyV0NMGImjpoeApRC09iKJH8RDagIE10bSp9utjUl972WUeO9NcpGusxBD2TpseuBlhK2@wtw/loGSkoIwkoGCE97Vp1RNkRGzr0UJt@pUedKtAM/KzII2ektK0uGmBIyZ@ffcSOxDWxxydZIwsJk3k739edj2IsUElLvYGBzUo1ylI6jypj/46NYwfdg4@JvNvh4w8v8nvrIiYlDWn31mGcDplohJinmcsq3jFp0PwzXqRZ@dzmA34Ag "Charcoal – Try It Online") Link is to verbose version of code. Brute-force, but only takes a second or so on TIO. Outputs a Charcoal boolean, i.e. `-` for truthy, nothing for falsy. Explanation:
```
⊙ＥＸ⁸¦⁴Ｅ⁴§α﹪÷ιＸ⁸λ⁸
```
Generate all possible codes including duplicates, and see if any of them satisfies the following.
```
∧⬤ι⁼№ιλ¹
```
Check that the code contains no duplicates, and...
```
⬤θ
```
... check whether all of the guesses satisfy the following.
```
⁼Ｉ…⮌λ²
```
Get the result of the guess and check that it equals the following.
```
ΣＥι
```
Map over each character of the code.
```
∨⁼ν§λξ
```
Check whether it's an exact match.
```
∧№λνχ
```
Check whether it's misplaced.
~~60~~ ~~46~~ 44-byte version for a version that allows duplicates in the code:
```
⊙ＥＸ⁸¦⁴Ｅ⁴§α﹪÷ιＸ⁸λ⁸⬤θ⁼Σλ⁺×⁹ΣＥι⁼ν§λξΣＥα⌊⟦№ιν№λν
```
[Try it online!](https://tio.run/##RY5LC8IwEIT/SuhpAxFUPCieQtTSg1DQW@kh2IIL28Q@4uPXx8Rq3Ut2PmZ2crnq7mI1eZ93aAaQ5gVHfYPcPuoO1oKtuGARrASTQ2aq@gk6EFs5spCZYYd3rGpAwaYI8ZBZcx4fSQStYPvWaerh5BqgQHNyPZyxqXvYCBZprMDJZ/5lJNiTj7d@vtiPBpsgC2Vd@HVImmAYBUVR8u9svS@KRKVKzZeJSFKZys@i5GG/WCZl6Wd3egM "Charcoal – Try It Online") Link is to verbose version of code. Brute-force, so takes a few seconds on TIO for falsy cases. Outputs a Charcoal boolean, i.e. `-` for truthy, nothing for falsy. Explanation:
```
⊙ＥＸ⁸¦⁴Ｅ⁴§α﹪÷ιＸ⁸λ⁸
```
Generate all possible codes including duplicates, and see if any of them satisfies the following.
```
⬤θ
```
Check whether all of the guesses satisfy the following.
```
⁼Σλ⁺
```
Extract the result of the guess (when passed a string which contains non-digits, `Sum` looks for embedded integer(s) and takes their sum rather than their digital sum) and check that it equals the sum of the following:
```
×⁹ΣＥι⁼ν§λξ
```
Count 9 for each exact match.
```
ΣＥα⌊⟦№ιν№λν
```
Count each match (whether exact or misplaced).
Edit: I had inadvertently calculated 4⁸ instead of 8⁴, so the code was taking 16 times longer than it needed to.
[Answer]
## Python3, ~~304~~ 140 bytes
```
lambda l:any(all(sum((x in t)+9*(x==y)for x,y in zip(p,t))==int(t[4:])for t in l)for p in permutations('ABCDEFGH',4))
from itertools import*
```
Lambda expecting input in the form of an array. [Try it online!](https://tio.run/##RY7BboQgEIbvPsXcFramQdykrYkHRBffoe2BTbUlQSCIifblLeihXGbm//5/BreFH2vKV@f3sf7YtZweXxJ0Jc2GpNZoXiaEVlAGAn56u6K1rjc8Wg9rviX1Vznk8oBxXSsTUHi/VZ8HD4nqo3WpdYOfliCDsmZGF9bwtruL/pLfMM5GbydQYfDBWj2Dmpz14bqnrEpZL833gEgOL7gC59OhESnjloDw8@y0ihXjPS0tCmC8E4RCL@5dnHh8BQHeip4UWbKQAtJpUgIXoo@W5KQno/RkaUsb42fgX2RNQ2Pp2r4kJyuh5Q0j9JhKmnHBeQwIJqIInMVP0D8)
Or 156 bytes as a full python program with textual input/output:
```
from itertools import*
l=input()
print(any(all(sum((x in t)+9*(x==y)for x,y in zip(p,t))==int(t[4:])for t in l.split())for p in permutations('ABCDEFGH',4)))
```
[(try it online)](https://tio.run/##RY/BboQgFEX3fsXLbAZaM0GcpO0kLBAd/IemCzOlLQkCQUy0P29BF2VD3r333Lzn1/jjbP3qw/Zwn4qdTqdNj96FCDqqEJ0zEwwT6MIwbf0cES580Daiwa5oMAZN84jQAtpCxM9vT2hhbMVfLsBSrln91R75MmLMWMbi@/X2sfsxu@YyeaNT6y75LOmLV2Gc4xC1sxM680a03V325/KKMd7ShkXO6pwNg/1WiJTwgm@gFvVA@Qq8ZaaqgItOEgq9vHdpEulVBEQre1IVOUIqyM2kBiFlnyI5SQ@P0sPLLW3CD@Bf5E1D09e1fU0Or4ZWNJzQfappIaQQCZBcJhEET0vQPw)
Could save 2 bytes by replacing `'ABCDEFGH'` with `range(8)`, but then input should be in the form `012311,024602,765411,222210,236701`.
**History of edits:** move `r=[0,1,2,3]` outside of function and remove `[]` to save 3 bytes; remove `()` around `return` value to save 2 bytes; replace `def f(p,t):` with `lambda p,t:` to save about 8 bytes; replace `[...].count(True)` with `sum(...)` to save 5+3=8 bytes; remove intermediary variable `m` to save 5 bytes; use `:=` in a much better way to get rid of the nested `lambda` and the awkward `(,,)[-1]` and save 26 bytes; [@Arnauld](https://codegolf.stackexchange.com/users/58563/arnauld) fixed a mistake with the rules of mastermind and golfed it down to 221 bytes; @Arnauld did some magic with the booleans and ints to golf it to 185; replace `for i in range(4)` with `for x,y in zip(p,t)` to save 7 bytes; save 10 bytes by replacing `(lambda l:...)(input())` with `l=input() ...`; @Arnauld saves 8 bytes by replacing `t.count(x)and 1+9*(x==y)` with `(x in t)+9*(x==y)` (which is also easier to understand in my opinion) plus 3 bytes by requiring whitespace-separated input to replace `.split(',')` with `.split()`, @Arnauld saves 1 byte by replacing `import itertools as i` with `from itertools import*`; @Arnauld removed 16 bytes by making it a lambda instead of a full python program
**Less compact, more readable version**
```
import itertools as i
r=0,1,2,3
def f(p,t):
    correct = [p[i]==t[i] for i in r]
    misplaced = [t.count(p[i]) and not correct[i] for i in r]
    return sum(correct) * 10 + sum(misplaced) == int(t[4:])
def z(line):
    return any(all(f(p,t) for t in line.split(',')) for p in i.permutations('ABCDEFGH',4))
print(z(input()))
```
* `f(p,t)` is `True` if combination `p` passes test `t`. `p` is a size-4 array which might not contain duplicates (eg `ABCD`). `t` is a size-6 array which might contain duplicates (eg `CCCC10`).
* `z(line)` is `True` if there exists at least one legal combination `p` which passes all tests `t`; tests are described by the comma-separated string `line`.
[Answer]
# [R](https://www.r-project.org/) + gtools, ~~130~~ 125 bytes
```
function(l)any(apply(permutations(8,4),1,function(c)all(sapply(l,function(g)g[[2]]==c(x<-sum(c==el(g)),sum(c%in%el(g))-x)))))
```
[Try it online!](https://tio.run/##hZNNb@IwEIbv@RUWqwpbSnfzAZRWm0MIIRx6atkTQsgYL0R1PmQ7FVD1t7O2gVIWAnMa@533mbET8y1LZxzzNVzIomACWRkWkvIszedTsqTkLdj@rXIi0yKHDOF8DXFZsjUsVU0lsd4XsGu3kO3aX4UEYcag2FWy4/4CLcZjbzIJAgJXv@9FlUESBJQpAdlmdZfmd7v1/Qrp2Gb4jU7TvKzklKVCBl@wFfqwgAq2a7M6tlnvFR2boMq1DwrJRclSCdd2s4nQscANMizJEm7G7lNrYj/Ho1H88nos4FRWXB1eQzaujcXPNJd0QblytJ86E7SHfSLr07IkFVITT4aGBDbCXtR33YbdCKM4cTyVDJNBbHYiFa6jk34ydNwGQuAHeMcsnRucV4dztDkeKI@vzUkyNDjN9c4ofh3F8w6U3XR9PZQxp/nR3qod4tQe9nqeSeL@0HfOOe1ajj5DP@qFCvjdBYytU2fzvfMeDxeLVbjO/7fSrS31T6cIgCyAeRCg5JTQOc0JBbxi1HAeL3GiJIrM9SRhEpokCtUn974Nobghz3HF5k0BdD2gK5yVe6rr1IzXO/wlOJuli6qoBCBYUBvMCrkE75QL/S4BJoSWEs8Uzjp72NB00JDRy5/4suxdl30tD8Ln1xq9dUNv39A7N/SH6@N1b9gfr9td56CDX3vM9h8 "R – Try It Online")
Colours are represented by digits 1..8. Returns 'TRUE' for valid games and 'FALSE' for invalid gamemaster responses.
**Commented:**
```
mastermind_check=function(l)            # l=list of lists of [guess,response]
 any(                                   # do any of...
  apply(permutations(8,4),1,            # all possible codes...
   function(c)all(                      # produce all valid responses for...
    sapply(l,                           # every [guess,response] pair...
     function(g)                        # using this function to define valid response:
      all(g[[2]]==c(                    # - both of these must be the same:
        x<-sum(c==el(g)),               #   - response[1] == sum of correct cols in correct pos
        sum(c%in%el(g))-x               #   - response[2] == sum of correct cols in any pos
      )                                 #                    minus response[1]
)))))                                   # ...?
```
---
# [R](https://www.r-project.org/), 114 bytes
```
function(l){while(T)T=!all(y<-sample(1:8,4),sapply(l,function(g)g[[2]]==c(x<-sum(y==el(g)),sum(y%in%el(g))-x)));1}
```
[Try it online!](https://tio.run/##hZRLb@IwFIX3@RUeUIUtpW0e0NdMFiGkYdEVZVYVQm7wEKuOiWKnhVb8dmqbV1vI4JWTe87n45vY5SrHQpIyp3wyTjOSvgSrfxVPJZ1xyNDHW0YZgUM0DH5hxuDiz7nAeaFeuXc3dhvZAhcFW0Bm70xTNH168kajIEjhXMmrHC6CgDBVUHL9dEb52fr5fI4Q@u0uVYgXMqa8qOSYUSGDHW2OPiygBluvM9@vs9hU9HgPKq59UMhSFIxKuLBbLYT2AjfIsUwz@P7k3rVH9kM8HMaDx72gJLIq1Y415N21sbigXJIpKZWjc3c1QhvYEllLy5JESE38FhqmsBF2o57rNuxGGMWJ46lJP7mPzZtIDdfRk17Sd9wGQqAJXjGjE4Pz6nCONsf3yuNrc5L0DU5zvQOKX0fxvC1lna6nQxkz5Xt7uzbEd3vY7XpmEvf6vnPI6dRy9B56UTdUwK8uYGxXdTbfO1zj@qhYDdf52ZWbWqn/PUUA5AyYUwCKkqRkQnhKQFkxYji3xzhREkWmPUmYhGYSheqTe19CKG5YclyxSUsArQdkbk7R@kdyauJ1t38Jzp/ptJpVAqRYEBs8z2QGXkkp1DkQAKcpKSR@VjirCfhMEiAzLLeburwPHx5j4xTgjTKmJSDDTF4AMCD57FXryWbDlE9Bq9lSTcAlTtXFsOuIUlvWz8sCmg3ojMPB3/h42duVm@CowNcCk7JO0T6p6JxUXO0VR@vXp2LenADc/r8NrrOtA0i5ajldf04ELjfU1Sc "R – Try It Online")
Stochastic function that checks random codes until it finds one that could satisfy the gamemaster responses, at which point it halts and returns `1`.  
Halting is assured in finite time for all valid gamemaster responses.  
If gamemaster response is invalid, function never halts.
]