[Question]
  [
It's the end of the year, you and your friends have just received your grades and ranks for the GOLF101 class. On a chat group, everyone sends their grade and rank to see who's got the best one.
**Problem:** someone is lying.
Here is an excerpt from the chat:
```
<A> I'm ranked 1 with a grade of 85.
<B> Ranked 3, got 50.
<C> Ranked 1st, prof. gave me 65/100.
<D> Got ranked second with 70/100
```
Obviously here, student C is lying (at least) on their rank; they can't be 1st with a grade of 65 since both A and D got a better grade.
There can also be cases where someone is lying but we can't know who, specifically.
```
Rank | Grade
-------------
  2     71
  1     80
  3     60
  2     70
```
Here, one of the two rank-2 students is lying (since two students can't have the same rank while having different grades) but we can't know which one.
# Challenge
Create a function or program that, when given a sequence of (rank, grade) tuples which contains exactly one *lie*, returns the index of the *lie* in the list or a sentinel value if is impossible to know.
A *lie* is a tuple that, when removed from the list, makes the list valid (i.e. without any conflicting ranks/grades).
A valid list contains **all the possible ranks starting from 1** (or 0 if you use 0-indexing), so the rank sequence `1 2 3` is valid while `2 3 4` is not. The only way to not have every possible rank is when there are equal grades, in which case you can get sequences like `1 2 2` or `1 2 3 3 3`.
Multiple tuples may have the same grade, in which case they will have the same rank, and other tuples' ranks will not be affected. Two tuples having the second-best grade will lead to the sequence `1 2 2 4 ...`.
The input format is not fixed, you may use whatever is easier to parse for your language (a 2D int array, a list of tuples, a list of strings containing space-separated ints). The logic is more important than the parser's implementation details.
The output format is not fixed either. The "index" returned may be 0-based or 1-based, and the sentinel value can be anything that is clearly distinguishable from an index (if you're using 1-based indexing, 0 is a valid sentinel value).
# Test Cases
```
Rank | Grade
-------------
  2     71
  1     80
  3     60
  2     70
```
**Output**: impossible to know
```
Rank | Grade
-------------
  1     85
  3     50
  1     65
  2     70
```
**Output**: third student
```
Rank | Grade
-------------
  1     85
  3     50
  1     65
  2     70
```
**Output**: third student
Additional cases, thanks to @tsh:
* `[(1, 100), (2, 60), (3, 90), (3, 90)]` -> invalid input because we can't remove a single item to get a valid list
* `[(1, 100), (1, 100), (2, 90), (3, 90)]` -> fourth (if we remove the third we get an invalid list with ranks [1, 1, 3])
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the lowest byte count for each language wins!
**EDIT:** printing multiple values is a valid sentinel as long as you specify it. 0-indexing for ranks is fine too.
  
[Answer]
# [J](http://jsoftware.com/), 49 47 22 bytes
```
[:I.1(-:\:~i.])/@|:\.]
```
[Try it online!](https://tio.run/##VY5RS4RAFIXf51ccFFaNHGcWtLogLAVBED30qhLizqohDjEjFIV/3Ua3fejhXi7nHr5z3hePByfkhADXECA3McfD6/PjUtATl2FMJc09r6Lk8EMlr5aIvdxz6OEIo4fJ9nrchNV9CP1Z5tJ3bhmGMt/54nvmCY/mq4RiKkoqLhjW5rwgnPC2R1WiYkw1ncYeOVrX4TZ1ZyrclaWQuBFsC7HK2H5sYbvawhvU2NoOvcGoLdRn3djhC@pjqgdYDenRGSox0853XAeSK1w4eCbO3P8OJ4r1ka2Wu7@1JZsuMDBT27oK6rg1QVMbxZZf "J – Try It Online")
-14 bytes after reading [xigoi's idea](https://codegolf.stackexchange.com/a/219540/15469) of comparing the first index matches to the ranks.
Thanks to tsh for a test case showing that we needed "length not equal to 1" rather than "length greater than 1" as the failure criterion.
Returns 0-based index if exactly one liar is found, and 0 or multiple values otherwise. Takes "length" by 2 matrix with 0-indexed rank list as left column, score list as right column.
* `1...\.]` For each 1-item outfix (list with item removed), apply the verb...
* `(...)/@|:` Transpose and put the verb in parens between the two rows, so that the rank list is its left arg, and the score list is its right arg.
* `-:\:~i.]` Does the rank list match `-:` the first index of the score list `i.]` within the score list sorted descending `\:~`? We now have a 0-1 list, where 1 indicates a liar.
* `[:I.` Return the indexes of all ones.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 15 bytes
```
ṙJṖZNÞiⱮḷ⁼ʋ/Ɗ€T
```
[Try it online!](https://tio.run/##y0rNyan8///hzpleD3dOi/I7PC/z0cZ1D3dsf9S451S3/rGuR01rQv4fbgdS//9Hc0VHW5jqGMbqRJsa6BgDKTMIz9xAxyg2VgcobW4IZOlEWxiAxc0gqmDSsQA "Jelly – Try It Online")
I'm pretty sure it works correctly with the multiple equal grades rule, but I'd appreciate a testcase for that.
Takes a list of [grade, rank]. Returns a 1-indexed list of all possible liars.
## Explanation
```
ṙJṖZNÞiⱮḷ⁼ʋ/Ɗ€T   Main monadic link
ṙ                 Rotate left by
 J                  all of [1..length]
             €    For each rotation
            Ɗ     (
  Ṗ                 Pop (remove the last pair)
   Z                Zip, change to a pair of [grades, ranks]
           /        Reduce by
          ʋ         (
     Þ                Sort the grades by
    N                   their negation
      iⱮḷ             Find the first index of each grade in the reverse-sorted grades
         ⁼            Is this equal to the list of ranks?
          ʋ         )
            Ɗ     )
              T   Find the indices where this is true
```
]