[Question]
  [
Players of the traditional board game Go measure their skill in a [system of ranks](https://en.wikipedia.org/wiki/Go_ranks_and_ratings):
* Players new to the game are ranked 30th *kyū* (written `30k`) and progress **counting down** to 1st *kyū* (written `1k`). These are considered the *student* ranks.
* A player may promote from 1st *kyū* to 1st *dan* rank (written `1d`), and then progress **counting up** to 7th *dan* rank (written `7d`). These are the *master* ranks.
* Exceptionally skilled players past `7d` may promote to the 1st *professional dan rank* `1p`, and progress **counting up** to 9th *professional dan* rank (written `9p`). This is the highest rank.
In short: ranks are ordered `30k < 29k < ··· < 1k < 1d < 2d < ··· < 7d < 1p < 2p < ··· < 9p`.
# Task
Given two strings among {`30k`, …, `1k`, `1d`, …, `7d`, `1p`, …, `9p`} as input, output the **higher** rank of the two. (If they are equal, simply output either input.)
(As usual, [I/O is flexible](https://codegolf.meta.stackexchange.com/q/2447/3852) — your answer may be a function or a full program, reading input in any reasonable fashion and producing output in any reasonable fashion.)
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"): the objective is to minimize your code's byte count.
# Test cases
(Format: `input1 input2 output`.)
```
29k 9k    9k
21k 27k   21k
6d 1p     1p
5d 17k    5d
1k 1d     1d
1d 1d     1d
1d 2d     2d
9p 1d     9p
2d 30k    2d
1p 1k     1p
1d 1p     1p
1p 2d     1p
7p 8p     8p
30k 30k   30k
```
  
[Answer]
# JavaScript (ES7), 58 bytes
Takes the two strings in currying syntax `(a)(b)`.
```
a=>b=>(g=s=>parseInt(s)*'_dp'.search(s[1])**3)(a)>g(b)?a:b
```
[Try it online!](https://tio.run/##jdDdCoIwHIfh865iZ9uEsv/E0mB23DVExHRqpehw0u2b34WKdOSQh5ff9hJvoYPiqcptlsuwingluOdzj8Rcc0@JQoeXrCSaGvguFd7pUBTBg@gr3KhhWJQI6sXEp2dx8qsgz3Sehrs0j0lEMHMTTAnCzYci00TITTZTA43B7DiY@sfEIHyQbQfU0AE1M3ZjMIwdZMuZgW4PyLGzYOTfho2GzY2rJh13vpm1m619stKBvpOs3B3@eJ@@8928YI6dccaOMzXd2N/N9an6AA "JavaScript (Node.js) – Try It Online")
### How?
The helper function **g()** translate the input string **s** into a score.
1) We look for **s[1]** into the string **"\_dp"**. This gives:
* **1** for a *dan* rank **"xd"**
* **2** for a *professional dan* rank **"xp"**
* **-1** for a *kyū* rank **"xk"** or **"xxk"** because **s[1]** is either **"k"** or a digit
2) We cube this result, which leaves **1** and **-1** unchanged but gives **8** for a *professional dan* rank.
3) We multiply by the decimal part of the rank.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~11~~ 10 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
Inspired to go back to the drawing board by Arnauld!
```
⁾kNyv9FµÞṪ
```
A monadic link accepting a list of strings\* (as described) which yields the highest rank found.
* Also works with numbers other than two.
**[Try it online!](https://tio.run/##y0rNyan8//9R475sv8oyS7dDWw/Pe7hz1f///6PVDQvUddTNU9RjAQ "Jelly – Try It Online")** Or see a [test-suite](https://tio.run/##y0rNyan8//9R475sv8oyS7dDWw/Pe7hz1f@Hu7foPNyx6XC7isqjpjXu//8bWWYrWGZzGRlmKxiZZ3OZpSgYFnCZAkkgByhmmMJlmAIljVK4LAtAbKMUBWMDoDSQkw2WLgCxgdLmBQoWBVxAOZA8AA "Jelly – Try It Online").
### How?
Sorts by a key function and returns the rightmost (i.e. a maximum).
The key function first changes any **k** to become an **N** using the dyadic atom `y`, translate, with the two-character list `⁾kN` (Jelly code for `['k','N']`) and then evaluates the string as a monad with an argument of nine (by use of the code `v9`).
In Jelly:
* `N` is a monadic atom which negates its input
	+ so the code `9 30N` does not actually use the nine and results in the integer `-30`
* `d` is a dyadic atom which yields the result of a Python divmod of two values - the pair of the results of integer division and modulo
	+ so the code `9 7d` results in \$\lfloor \frac 7 9 \rfloor\$ paired with \$7 \pmod 9\$ which is `[0,7]`
* `p` is a dyadic atom which performs a Cartesian product, which includes implicit 1-indexed range-ification of its inputs
	+ so the code `9 p3` yields the Cartesian product of `[1,2,3]` and `[1,2,3,4,5,6,7,8,9]` which is `[[1,1],[1,2],...,[1,9],[2,1],[2,2],...,[2,9],[3,1],[3,2],...,[3,9]]`
Once such evaluations have been performed using the strings to be compared we need to be able to compare the results; since ints are not comparable with lists we need to wrap the negated values in a list, but since the ordering would still work after the `p` lists are flattened (e.g. `[[1,1],[1,2],...]` -> `[1,1,1,2]`) we can use the single-byte monadic atom `F` applied to all evaluations.
A table of the inputs to their key-value is as follows:
```
in    ⁾kNy    ⁾kNyv9F
30k   30N     [-30]
29k   29N     [-29]   
...
 2k    2N     [-2]
 1k    1N     [-1]
 1d    1d     [0,1]
 2d    2d     [0,2]
 ...
 6d    6d     [0,6]
 7d    7d     [0,7]                                 
 1p    1p     [1,1,1,2,...,1,9]
 2p    2p     [1,1,1,2,...,1,9,2,1,...,2,9]
 ...
 8p    8p     [1,1,1,2,...,1,9,2,1,...,7,9,8,1,...,8,9]
 9p    9p     [1,1,1,2,...,1,9,2,1,...,7,9,8,1,...,8,9,9,1,...,9,9]
```
Code commentary:
```
⁾kNyv9FµÞṪ - Link: list of lists of characters
       µÞ  - sort by (Þ) the monadic link to the left (µ):
⁾kN        -   two-char list = ['k', 'N']
   y       -   translate the current string (change 'k's to 'N's)
     9     -   literal nine
    v      -   evaluate (the left) as Jelly code with the input as given on the right (9)
      F    -   flatten the result
         Ṫ - tail (get the rightmost, and hence (a) maximum)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 14 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
OṪ|8-2*×ṖV$µÞṪ
```
A monadic link accepting a list of strings\* (as described) which yields the highest rank found.
\* Also works with numbers other than two.
**[Try it online!](https://tio.run/##y0rNyan8/9//4c5VNRa6RlqHpz/cOS1M5dDWw/OAQv///49WNyxQ11E3T1GPBQA "Jelly – Try It Online")** Or see a [test-suite](https://tio.run/##y0rNyan8/9//4c5VNRa6RlqHpz/cOS1M5dDWw/OAQv8f7t6i83DHpsPtKiqPmta4//9vZJmtYJnNZWSYrWBkns1llqJgWMBlCiSBHKCYYQqXYQqUNErhsiwAsY1SFIwNgNJATjZYugDEBkqbFyhYFHAB5UDyAA "Jelly – Try It Online").
### How?
Sorts by a key function and returns the rightmost (i.e. a maximum).
The letters \$k\$, \$d\$, and \$p\$ have ordinals \$107\$, \$100\$, and \$112\$ respectively. In binary \$107\$ has the eight bit set while the others do not, hence bitwise OR-ing with 8 we get 107, 108, and 120 respectively - these are now in the order required to sort the classes they identify.
The amateur ranks are in descending order so to complete our key function we could concatenate our class-identifier with the number given in the string, negating if the string ends in \$k\$ (e.g. `'7k'` -> `[107,-7]` while `7p` -> `[120,7]`). In the code this requires storing the class-identifier and exponentiating minus one for the multiplication - `OṪ|©8-*×ṖV$®,µÞṪ` - which is \$16\$ bytes.
To improve upon this we can use minus two instead and multiply the elements together, which may be achieved with a single multiplication.
```
OṪ|8-2*×ṖV$µÞṪ - Link: list of lists of characters
           µÞ  - sort by (Þ) the monadic link to the left (µ):
O              -   ordinals
 Ṫ             -   tail
   8           -   literal eight
  |            -   bitwise OR
    -2         -   literal minus two
      *        -   exponentiate
          $    -   last two links as a monad (of the current list of characters):
        Ṗ      -     pop (get all but rightmost character)
         V     -     evaluate as Jelly code (gets the number)
       ×       -   muliply
             Ṫ - tail (get the rightmost)
```
Table of the key-function's action...
```
in    ṖV$  OṪ   OṪ|8       OṪ|8-2*×ṖV$
30k   30   107  107       -4867778304876400901747340308643840 = ((-2)^107)*30
29k   29   107  107       -4705519028047187538355762298355712 = ((-2)^107)*29
...
 2k    2   107  107        -324518553658426726783156020576256 = ((-2)^107)*2
 1k    1   107  107        -162259276829213363391578010288128 = ((-2)^107)*1
 1d    1   100  108         324518553658426726783156020576256 = ((-2)^108)*1
 2d    2   100  108         649037107316853453566312041152512 = ((-2)^108)*2
 ...
 8d    8   100  108        2596148429267413814265248164610048 = ((-2)^108)*8
 9d    9   100  108        2920666982925840541048404185186304 = ((-2)^108)*9
 1p    1   112  120     1329227995784915872903807060280344576 = ((-2)^120)*1
 2p    2   112  120     2658455991569831745807614120560689152 = ((-2)^120)*2
 ...
 8p    8   112  120    10633823966279326983230456482242756608 = ((-2)^120)*8
 9p    9   112  120    11963051962064242856134263542523101184 = ((-2)^120)*9
```
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~30~~ ~~28~~ ~~25~~ 23 bytes
```
,0&)Uw'k'-tUw6*+qw*w]<G
```
[Try it online!](https://tio.run/##y00syfn/X8dATTO0XD1bXbcktNxMS7uwXKs81sb9/391wwJ1LnXzFHUA "MATL – Try It Online")
*(-2 bytes thanks to Luis Mendo)*  
*(another -3 bytes replacing `v&X>` with `>`, this time based on Luis Mendo's answer)*  
*(-2 bytes using `&)` syntax)*
### Explanation:
* Subtract 'k' from the last character (gives n = -7, 0, 5 for 'd', 'k', 'p' respectively).
* Compute v = n^2+6n-1 (gives 7, -1, 54 respectively).
* Multiply that value v by the actual rank number (so k levels get negative products, d levels go from 7 to 49, p levels from 54 and above).
* Do that for both input strings, compare the products
* Get the input string corresponding to the greater product
---
Alternate, more straightforward method: :
### 23 bytes
```
,0&)Uwo'dpk'1L6^XE*w]<G
```
[Try it online!](https://tio.run/##y00syfn/X8dATTO0PF89pSBb3dDHLC7CVas81sb9/391I9NsdS518xR1AA "MATL – Try It Online")
```
,              % Do this twice (once for each input):
0&)            % Split the input into number, last letter
U              % str2num i.e. Convert '21' to 21
wo             % Bring the letter out and change it to numeric (its ASCII code)
'dpk'          % Push the array 'dpk'
1L6^           % Push [1 2 1j] and raise to ^6, giving [1 64 -1]
XE             % Find the letter in 'dpk', replace it with its corresponding 
               %  number from the second array (d=1, p=64, k=-1)
*              % Multiply the number part by this
w              % Switch to bring out the other input to top
]              % End loop
               % Stack has [second input's value, first input's value]
<              % Is second input < first input? 1 or 0
G              % Retrieve the corresponding input: 1 for 1st input,
               %  0 for last (2nd) input
```
---
[Answer]
# [Haskell](https://www.haskell.org/), ~~73~~ 71 bytes
```
r(x,"k")=0-x
r(x,"d")=x
r(x,"p")=x+7
p=r.head.reads
a#b|p a<p b=b|0<1=a
```
[Try it online!](https://tio.run/##bY7fS8MwEMff81ccmYMEu9JWtG4sPongg@iDb05GSiIt/RXSqh3sf6/XdHNFB@G4@/C5by6VTa6Loi9r9VloeJJZxUosnHyn2mpCstLUtoVX3bX@i82q9uOI7mUr/Ye6UDIpNGut/NK20VveW9Z5NKdcBIuOuEHhcGjN0F7GxAjrp1oq32JpiJwlewNybSARyT5Yh0L2wx2wWsHjMzBO3CTg9x9gG8zbcVjcgXGHAZ03gA/BvNlUFDrYwQV0M5TeCACj0TKnHlCsHBB4SEJHohjRSG7UAEK8Ew7O9Uji09a4FKqTE6rzJJqQpfnrRM65CibJo5P/S57cMzrT5NiR24kzZB6jkbyT/gc "Haskell – Try It Online")
As usual for me, just a straight forward implementation rather than anything particularly golf-y. The "(#)" function takes two ranks as strings and returns the larger one. Works only with exactly the format specified in the question.
(I've also tried a version using `comparing` and `maximumBy` but that ended up being 3 bytes longer - damn you `base` and your occasionally human readable function names!)
(Applied suggestions by Amphibological and Lynn)
[Answer]
# [Python 2](https://docs.python.org/2/), 54 bytes
```
lambda s:max(s,key=lambda x:(int(x,27)%9-3)*int(x,26))
```
[Try it online!](https://tio.run/##fY1BDsIgEADvvqIXA5iayDYWadKXqAcMNhpsJbYH@noU6KEB4mWTnZ3s6Hl6vAewXXuxL9HfpCjGphcGj6W6z@2CTIOfw4RNCYxs@b4iu2WtCbH645YOnxFwhcoC/eaVkM2KU8@BxYdaOk51hI8BJ3p4Q2WM5R8MMeY6a4O3q0PSDLrKN3XWTprM41Nsu1o2ylbf7Rc "Python 2 – Try It Online")
Using [Arnauld's method](https://codegolf.stackexchange.com/a/168155/20260). The mapping `int(x,27)%9-3` only depends on 
the last letter of `x`, since all digits but the last one contribute a multiple of `9`. It takes:
```
'k' -> -1
'p' -> 1
'd' -> 4
```
This is barely enough margin for the multiplier for `1p` to beat `7d`, the highest dan rank, when interpreted in base 26.
I found this by brute-forcing expressions of this form and a few others.
---
# [Python 2](https://docs.python.org/2/), 64 bytes
```
lambda s:max(s,key=lambda x:(ord(x[-1])|8,int(x,36)^-('k'in x)))
```
[Try it online!](https://tio.run/##fc3fCoMgGIfh811FZ/qBwTTWP@hKWoOGi4XLpDow2L27lYMNlZ148Hwv/tS63EfJTFedzaMdrryN5nJoNZ6JuK3Vh3SJx4ljXce0gWdOerlgTZIULjFGAvUy0gBg1LQdOlwjVghEIvR@G4DDj9PdWeYeUr45VQ6fLHu5/YZyl/kfZi4XKlizvU6O3qbNRXhTBWtvM9s5d@tt7TtqXg "Python 2 – Try It Online")
[Answer]
# [R](https://www.r-project.org/), 73 bytes
```
function(v)v[rank(as.double(chartr('dp','.0',sub('(.+)k','-\\1',v))))][2]
```
[Try it online!](https://tio.run/##bYxBDoIwEEX3XmSmEQmtUWThSYBFaSUaTGkK9Pq1rdGCcRaTvPdnvnH91fWLEvNjVGiJrQ1XA/Ipl@PSPW8o7tzMBkFqyCAvIJuWDgHzPRm8ODQNhcwSP23NWtejQGBViPwiZPcWNAhWJnOWXlD95VPk1UH8oDKx/MMscaW3OQv5sVgVxoPhp1Bv81VhGfiS8tD1aXQv "R – Try It Online")
* I had to use `as.double` instead of `strtoi` since the latter doesn't handle spaces/points and I couldn't think of another valid character to replace `d`
* -1 byte using `rank` instead of `order`, since they are equal when there are only two elements
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 13 bytes
This is quite different from my [other Jelly answer](https://codegolf.stackexchange.com/a/168173/58563), so I'm posting this separately.
Takes input as a list of two (or more) strings.
```
“kNdHp0”yVµÞṪ
```
[Try it online!](https://tio.run/##y0rNyan8//9Rw5xsvxSPAoNHDXMrww5tPTzv4c5V/w@3P2pa4/3/fzSXgkK0upFltrqOOpCI1QFyDEEcI3MIzywFyDEsALNNwWyoBFiVYQqEnYLGNoKwLQsQ4kYgcWMDqGawRDaS5gKEOFSzOYhtAREH6YPq5ooFAA "Jelly – Try It Online")
### Commented
```
“kNdHp0”yVµÞṪ
“kNdHp0”       - literal string
        y      - translate each rank character into a Jelly instruction/symbol:
                   'k' -> 'N' = negate
                   'd' -> 'H' = halve
                   'p' -> '0' = a literal zero
         V     - evaluate as Jelly code
                 examples:
                   '21k' -> '21N' -> -21
                   '7d'  -> '7H'  -> 3.5  (*)
                   '3p'  -> '30'  -> 30
          µÞ   - sort the input using all of the above
            Ṫ  - return the second entry
(*) we don't really need to halve these values, but we do want to get rid of 'd'
```
[Answer]
# Julia 0.7 ~~100~~ 93 bytes
It is not the most efficient way, (contrast @sundar's [Julia 0.6 answer](https://codegolf.stackexchange.com/a/168154/4397))
but it is nice because it is purely numeric.
Also uses dispatch (though sadly only once)
```
!z=(-z%2+.9)z*z
s(x,y,z)=(10x+y)*!z
s(x,z)=x*!z
~r=s(Int[r...]...)
a|b=[a,b][argmax(.~[a,b])]
```
Very similar code works in 0.6 [Try it online](https://tio.run/##ldBBa8MgFAfwu5/CCgNtM6mOtc1BGNtp991CDmaRzmULpVpIpfSrZ0YtrAfpJsSnjx//8Pw8fGm5GseZE/je3fEFLYmbO2DwUBwLRwRmy2FxJPNZ7PnOMJ3Pe2Hwa2@rPaW09h8B8tSIShZNXem@/ZYDpudwJfV4MLrfwmdpFH1TxoIn63ejLEQvH@q9g9oi2Kit7gG8XgFCxMsOwRNEUxEi1JxkUfJ1olMjY1dtoGwXpa8Z@JjgJdPfMzL9nbUpMg/b/0GeIM/CcneVWGan4THxYdndimQpsrv1QOyvL5kSL9Pk4TrCTUrcZGEY4/c40wGovh1/AA)
### How:
The trick is all in the `!(z)` function.
It maps the UTF-8 value:
* for `k` into a negative number, so it sorts backwards
* for `d` into a positive number
* for `p` into a larger positive number
As shown:
```
julia> !(Int('k'))
-1144.8999999999996
julia> !(Int('d'))
9000.0
julia> !(Int('p'))
11289.6
```
### Test results
```
julia> @testset "Check it" begin
               @test "29k" | "9k" == "9k"
               @test "21k" | "27k" == "21k"
               @test "6d" | "1p" == "1p"
               @test "5d" | "17k" == "5d"
               @test "1k" | "1d" == "1d"
               @test "1d" | "1d" == "1d"
               @test "1d" | "2d" == "2d"
               @test "9p" | "1d" == "9p"
               @test "2d" | "30k" == "2d"
               @test "1p" | "1k" == "1p"
               @test "1d" | "1p" == "1p"
               @test "1p" | "2d" == "1p"
               @test "7p" | "8p" == "8p"
               @test "30k" | "30k" == "30k"
       end
Test Summary: | Pass  Total
Check it      |   14     14
Test.DefaultTestSet("Check it", Any[], 14, false)
```
[Answer]
# [Haskell](https://www.haskell.org/), 64 bytes
```
r[(n,[c])]=n*(gcd(fromEnum c)28-3)
g=r.reads
a%b|g a>g b=a|1>0=b
```
[Try it online!](https://tio.run/##XU9db4IwFH3vr7ghM2mlMMFsihHf9itYH0pBJEBtCsYs4bePlZZM40tzPu45vffC@6Zs22nSGZY0E4ywVK5xJQp81tfuS946ECTeB1uCqlSHuuRFj/gqHyvgpwrylI/RaZPmk@ay6SGFrL9c7yB932u8UR6DbLuhcRKGEWPg@0924ewoDHevlvq3EsaQ4rW2zZjTnMAI/KDhGEAvuNSADwQyBu57CvnsaIbu@iorEzrX7VCaqW8XDk5glof3FAyxxQgNZT@4fi9OGo965iHUkGgm8c6xz8KQSFn8YfFi2KmocLh4wbHDiXro8axvN0vYGs1TWD30Jbyb8d7pc25JM9TxWpq9la7lAG@A7c0UOq4A36S4af0DeEUI2AvJ9CvOLa/6KRBK/QE "Haskell – Try It Online")
The expression `gcd(fromEnum c)28-3` maps the character to a multiplier
```
k -> -2
d -> 1
p -> 25
```
The idea was to take their character values `[107,100,112]` and choose `28` to have increasingly large factors in common with them, made easy but the first one 107 being prime. This method saves 2 bytes over explicitly [writing out a mapping](https://tio.run/##XU9rb4IwFP3eX3HTzATGYxazMdT6R1izlIdIwFoKxizht4@Vlkzjl@Y87jm998T7pmzbaeqwxDTZdbjAlOw6@KYQEKRSR/i5y6h47SBHFVWhKnnRI77Kxgr4oYKM8pEc1jSbFBdNDxTS/nS5gfA83OBR7IN0s/ajJAwJY@B5D3ZhbRKG8bMl/62EMSR5rUyzw/3MhRH4VsE@gD7nQoGzdSFlYL/3IZsdxdBNXUSlQ8e6HUo99WXDwQH08vBGQRNTjNBQ9oPtx1HSYB/rx/U1ITOJYss@Ck2INPjd4MUwU6SwuHjCkcWJvOvRrG/WS9gYzUNY3vUlHM/40@pzbkkzdOa10HtLVYsBXsAxN/tw5hKcq8ivSv2As3JdMBe6029@bHnVT0Eu5R8).
The built-in [`reads`](http://hackage.haskell.org/package/base-4.12.0.0/docs/Text-Read.html#v:reads) is used to separate the number and rank.
```
Prelude> reads "25k" :: [(Int, String)]
[(25,"k")]
```
(Actually, the direct splitting [from Sara J](https://codegolf.stackexchange.com/a/182564/20260) is one byte shorter, giving [63 bytes](https://tio.run/##XU/JboMwEL3zFSOUSHZZGkBtQhRy61ekPgxLCAIcyyaKKvHtpcZGTZSL9ZZ5zzMXVG3VddNUg8pkhSVpeDOAom@kLkpyltf@i9/6VYdqVuNdkFAH1/lYAx5ryDMco@MmyyeJvFWQwUldrnfgnue27sgPwSnZ@HEahhFj4HlPdmntKAy3r5b4t1LGHIGNNM0E/ZzCCLiXcAhAFcglkD2FEwP7vQ/57Ejm3OWV1zp0brqh0lPfNhwcQS8P7xloYoodZ6jUYPvdOG1d39UP9TWJZhJvLfssNYmEwR8GL4aZikqLyxccW5yKhx7PerJZwsZon8LioS/h7Yx3Vp9zS5o5PTZc7y1kwwdYATE3@9CjAHLjxU3KHyBrSsFcSKff4txhraagEOIP).)
The take-the-bigger-one step takes an annoying number of bytes in my solution. I tried other approaches like iterating over ranks in decreasing order and taking the first one that's an element of `[a,b]`, but they turned out longer.
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~28~~ 27 bytes
```
,w'kdp'X{'*-1 . *8'YbYXU]>G
```
[Try it online!](https://tio.run/##y00syfn/X6dcPTulQD2iWl1L11BBT0HLQj0yKTIiNNbO/f9/dSPLbHUudSABAA) Or [verify all test cases](https://tio.run/##y00syfmf8F@nXD07pUA9olpdS9dQQU9By0I9MikyIjTWLt79v0vIf3Ujy2x1LnUwYWQIJs1BpFkKkDAsABKmYBZYECxvmIJJGIEIywIUrrFBNswIJH0FMAKsxhzEsiiAqwaRAA).
### Explanation
```
,                % Do twice
  w              %   Swap. Takes implicit input
  'kdp'          %   Push this string
  X{             %   Split chars: gives cell array {'k', 'd', 'p'}
  '*-1 . *8'     %   Push this string
  Yb             %   Split at whitespace: gives cell array {'*-1', '.', '*8'}
  YX             %   Regexprep: replaces 'k' by '*-1', 'd' by '.', 'p' by '*8'
  U              %   Convert to number: evaluates string
]                % End
>                % Greater than? Gives a result r which is 0 or 1
G                % Push r-th input (modularly: 0 is last, 1 is first)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 16 bytes
Takes input as a list of two strings.
```
OṪ²²%90’’×ṖV$µÞṪ
```
[Try it online!](https://tio.run/##y0rNyan8/9//4c5VhzYd2qRqafCoYSYQHZ7@cOe0MJVDWw/PA0r9P9z@qGmN9///0VwKCtHqRpbZ6jrqQCJWB8gxBHGMzCE8sxQgx7AAzDYFs6ESYFWGKRB2ChrbCMK2LECIG4HEjQ2gmsES2UiaCxDiUM3mILYFRBykD6qbKxYA "Jelly – Try It Online") (all test cases)
### How?
The ASCII code \$c\$ of the rank character is converted to a multiplier \$m\$ with the following formula:
$$m=(c^4 \bmod 90)-2$$
Which gives:
```
 char. | ASCII | **4       | mod 90 | -2
-------+-------+-----------+--------+----
  'k'  |   107 | 131079601 |      1 | -1
  'd'  |   100 | 100000000 |     10 |  8
  'p'  |   112 | 157351936 |     76 | 74
```
### Commented
```
OṪ²²%90’’×ṖV$µÞṪ
OṪ²²%90’’        - process the rank character        takes a string, e.g. '28k'
O                - get ASCII codes                   --> [50, 56, 107]
 Ṫ               - pop                               --> 107
  ²²             - square twice                      --> 131079601
    %90          - modulo 90                         --> 1
       ’’        - decrement twice                   --> -1
          ṖV$    - process the decimal part
          Ṗ      - remove the last character         --> '28'
           V     - evaluate as Jelly code            --> 28 (integer)
         ×       - multiply                          --> -28
             µÞ  - sort input using all of the above
               Ṫ - return the second entry
```
### Alternate formula
For 16 bytes as well, we can use:
$$m=((c-1)^9 \bmod 64)-1$$
```
OṪ’*9%64’×ṖV$µÞṪ
```
[Try it online!](https://tio.run/##y0rNyan8/9//4c5VjxpmalmqmpkA6cPTH@6cFqZyaOvheUCJ/4fbHzWt8f7/P5pLQSFa3cgyW11HHUjE6gA5hiCOkTmEZ5YC5BgWgNmmYDZUAqzKMAXCTkFjG0HYlgUIcSOQuLEBVDNYIhtJcwFCHKrZHMS2gIiD9EF1c8UCAA "Jelly – Try It Online")
[Answer]
# JavaScript (ES6), ~~55~~ 54 bytes
-1 byte thanks to @Shaggy
```
a=>b=>(s=x=>parseInt(x)*~-{p:9,d:2}[x[1]])(a)>s(b)?a:b
```
[Try it Online!](https://tio.run/##jdDdCoIwGIDh8y7Doy0q2qL8gdlx1yAeTKdRig4nIUTdurF9QjImdbKPwcO7nzt/cJV3N9lvm1YUY8lGzuKMxUixgcWSd6q4ND0a8Pq9fcoo3IiIvpIhIWmKEcexQhk@8ygb87ZRbV3s6vaKSuTRsPIw8vTKmBkrWxAjqA/EbG1zEpoQaYQeNjgCmBp6Zws4hQhIuID4C1AA1AHovOACoZyBUC4VDvtqMUEgUS3@BPn1VVCYnuECvgEBFAIHMPf7XtPM8QM)
## Explanation
```
a=>b=>
  (s=x=>                 // Function s(x), that converts x to a "score", where a higher
                         // rank gets a higher score by
    parseInt(x)*         //   taking the integer part of x and multiplying it by
    ~-{p:9,d:2}[x[1]])  //   ~-9 (8) if it is a professional rank, ~-2 (1) if it is a dan
                         //   rank and ~-undefined (-1) if it is a kyū rank by looking up
                         //   the second character of the string
  (a)>s(b)               // Compare s(a) and s(b)
    ?a:b                 //   and return the one with the biggest score
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~52~~ 46 bytes
```
->s{s.max_by{|x|(5-x[-1].ord*5%8)*x.to_i(26)}}
```
Straightforward port of xnor's answer.
[Try it online!](https://tio.run/##lYtLDoIwGIT3nuLfGFpSGlvDa6EXMYYABSXF0NCSlABnr0W9gJvJzHwz41TNzkVXvWj6Km1RzctqVxRH9haxOx1GEcbHDIeWmqHoEE/wtrn28t/h8GiMplr1nUEBCTBtyvoJ@w/UZDS0tC77HtnvBG/geC4hl4QzCTyVJBHAFIm9@uA7JggTP@WC5Gr3XMD55LEP8oPV7j1OFWSKeLZzAHgD "Ruby – Try It Online")
*EDIT: -6 bytes by realizing I could have used a Proc*
[Answer]
# [C# (Visual C# Compiler)](http://www.mono-project.com/docs/about-mono/releases/5.0.0/#csc), ~~136~~ 135 bytes
```
a=>b=>{string c=a.PadLeft(3,'0'),d=b.PadLeft(3,'0');int x=c[2]-d[2];return(x==0?c.CompareTo(d)*(c[2]=='k'?-1:0)>0:x==5|x>9|x==-7)?a:b;}
```
[Try it online!](https://tio.run/##nY9Pa4QwEMXvforgxaSoqMvWqo0eFnrawkILPZQeYhJLcDeKyRbLrp/d@ufUpQftHGbCm/nx8qhyqKI9PRKlwMG4GGAopYkWFHxVgoFnIiREkzwvx3r5Vpqf3KezpI9KN0J@2n9q80xTUADcE5zmOL3MGqCYuAfC9rzQcGNbnoVshvMbKRFSgxbT9@DDYUNLGq7PjYQtxl5G3V11qknDXyvI0B0crzC2Sitz/NhDqRcPZ9trm0bX4eGEKCNxnnR9Ytzm2FVSVUfuvjVC872QHBbQDKLSRNAcO0qWEf5EBOFy5J6NhF8vBrYTsMJh/pPPlgPsX0CwHIjqlQ7B5LDxVqSeLcq1qeuVDitShxPwsNxhyvs7dmd0Rv8D "C# (Visual C# Compiler) – Try It Online")
-1 Byte thanks to TheLethalCoder
**Expanation:**
```
static void Main()
{
    System.Func<string, System.Func<string, string>> f =
        a => b =>
        {
            string c = a.PadLeft(3, '0'),
                d = b.PadLeft(3, '0');      //Pad the input with leading '0' to be 3 characters long
            int x = c[2] - d[2];            //Calculate the difference of the letter characer (the character at index 2) as integer
            return                          //return ...
                (x == 0 ?                   //if the letter of the inputs is the same...
                c.CompareTo(d)              //  compare the padded strings resulting in a positive number if the first input is greater or a negative number if the first input is lower 
                    * (                     //  multiply the result by...
                    c[2] == 'k' ? -1 : 0    //  if the letter is 'k' then -1 else 0
                    ) > 0                   //  check if the result is greater than 0
                :                           //else (the letters are not the same)
                x == 5 | x > 9 | x == -7    //  check if the letter difference was 5 (input p and k) or 12 (> 9, input p and d) or -7 (input d and k)
                ) ? a : b;                  //  then return the first input else return the second input.
        }
    ;
    System.Console.WriteLine(f("29k")("9k"));
    System.Console.WriteLine(f("21k")("27k"));
    System.Console.WriteLine(f("6d")("1p"));
    System.Console.WriteLine(f("5d")("7k"));
    System.Console.WriteLine(f("1k")("1d"));
    System.Console.WriteLine(f("1d")("1d"));
    System.Console.WriteLine(f("1d")("2d"));
    System.Console.WriteLine(f("9p")("1d"));
    System.Console.WriteLine(f("2d")("30k"));
    System.Console.WriteLine(f("1p")("1k"));
    System.Console.WriteLine(f("1d")("1p"));
    System.Console.WriteLine(f("1p")("2d"));
    System.Console.WriteLine(f("7p")("8p"));
    System.Console.WriteLine(f("30k")("30k"));
}
```
[Answer]
# Perl, ~~46~~ 38 bytes
```
s/p/0/g;s/\w*k/-$&/g;/ /;$_=@F[$`<=$']
```
Run as `perl -pae '...'`. Takes input from stdin, space-separated on one line. 
Performs a couple of substitutions to make comparison "easier". The regexp substitutions essentially amount to replacing `p` with a trailing zero and `k` with a leading negative sign. So `10k` becomes `-10` (so the ordering is reversed) and `3p` becomes `30` (so that `p` is above everything else). Then it's just a simple numerical comparison.
Thanks to DomHastings for the `$`` / `$'` suggestion, which shaved off 8 bytes.
[Answer]
# [R](https://www.r-project.org/), ~~65~~ 62 bytes
```
`+`=paste0;max(ordered(scan(,""),c(30:1+"k",1:7+"d",1:9+"p")))
```
[Try it online!](https://tio.run/##bYzRCoIwFIbvewo5N57DlrhFmVbvomwKIelQAyF69uWkmkY3O3zf/@/vbBWct0F1b9RwbRsc6dGrolm5KIpotDnLL6bohzI@3YoR206XXanRtZEDEFe4izPBoAYusoSBdjdlYICI7HNTocJQpnXIw@khegvhhEy8OehJCPPl/cyLwvxDaM/6D0vPqVnn0uW7eDE4F@qfQbPOF4OJ46PP3dZn0b4A "R – Try It Online")
This comes in a bit shorter than the previous R answers, and makes good use of R's statistics functionality :-)
*-3 bytes thanks to [Robin Ryder](https://codegolf.stackexchange.com/users/86301/robin-ryder)'s suggestion to use* `ordered` *instead of* `factor`
Takes input from stdin (although the TIO link restructures slightly for ease of testing). Casts the input ranks into an *ordered* `factor` of all ranks, then takes the max.
Output looks like:
```
[1] MAX_RANK
46 Levels: 30k < 29k < 28k < 27k < 26k < 25k < 24k < 23k < 22k < ... < 9p
```
[Answer]
# Java 8, ~~128~~ ~~122~~ 121 bytes
```
a->b->g(a)<g(b)?b:a;float g(String s){return("kdp".indexOf(s.charAt(s.length()-1))-.9f)*new Byte(s.replaceAll(".$",""));}
```
-6 bytes thanks to *@SaraJ*.
[Try it online.](https://tio.run/##jZNBT8MgGIbv/gpCPIC1ZJ3RuXWrmQdvxoNH3YEVWlmRkvarupj99gndnNpU4wXIw/u9b4GvK/7Cw5UotqnmdY1uuTLvRwitHGYNKM2yxqSgSsNu9ovpPVTK5Kf/0uzmJEEZmm15mCzDJCecTnOypFfLCY8zXXJAOdkJUU3fKwlNZQguhMVMGSHf7jJSs/SJV3NwCy1NDk@EhhGlIRtn9MTIV3S9Buk2K2k1T@Vca4LZMT7FmNJ4s3Unss1SqxTVwMFNL6US6Nkddh/8sECc@oMjBLIGgofjwlW7gcbfaeTpcNTBF8LRyP6E5y3sSluDSHSg@A0OO3Bse5RDrzwbdJNaadGXZHuU3aSRh5cdpQ85RLX8fl2DfGZlA8y6iwRtyL4iKyviAFKzs0GsklkUqzCk7VZvmQpwMUE48K/p25BQlrfQP2HHMYqRms5GbgyCvy1Fn6X41XL8D0vbZ2n3lht/Ld@brL24XZMxxg5d1mP99T/Nq4qvawblrs79MAGePMKP1Ixxa/Wa8IfBgh7W0eLzMzbbDw) (See the bottom of the output in the TIO-links to see the mapped values.)
**Explanation:**
```
a->b->                       // Method with two String parameters and String return-type
  g(a)<g(b)?                 //  If the mapped value of `a` is smaller than `b :
   b                         //   Return input `b` as result
  :                          //  Else:
   a;                        //   Return input `a` as result
float g(String s){           // Separated method with String parameter and float return-type
                             // (This method maps all possible Strings to a value)
 return("kdp".indexOf(       //   Take the (0-based) index in the String "kdp"
    s.charAt(s.length()-1))  //   of the last character
    -.9f)                    //   After we've subtracted 0.9
  *(                         //  And multiply it with:
    new Byte(                //   Convert the String to an integer
     s.replaceAll(".$",""));}//   After we've removed the trailing character
```
[Answer]
# [Haskell](https://www.haskell.org/), ~~75~~ ~~70~~ 68 bytes
```
g k=read(init k)*(abs(fromEnum(last k)*2-209)-8)
a?b|g a>g b=a|1>0=b
```
[Try it online!](https://tio.run/##dZI9b4MwGIR3fsUJdbALSIGqTahqOnVrp45RBrt2EsSnwCgZ8t@pMYGkUbOcXj8@n0@y97zNVJ73RSW7XOGLpyUOe9WofoeMNYpLkpapRkYfCRct2TZV8VF2Bcl5a2kURIuYBivq8Hdx2oEnOwjGT2GyYKLXyrg4BNSxVj9aSQc4gRgrBWMzBQP3PNeH63nCDAiSYfxzqNKm1iFt1R2zDR2WZDr2ep1hdqjrOEOh1iSsTSZA3CjOXN@dhPoTDgcSLa2GVxsv0pCwHmWmz5ZatxlnbENCOcqFyrs0OstM43ryxlfXWdvTIrsxj7Wym27hv40tiOQNXQ50dZaZjjddlFq@cZxi@C0M2yqXDUiSUJBG6a4pQSjFuu70t24@Szxg/gdH@/y@8I8Ub4Hl7ab/BQ "Haskell – Try It Online")
`-5 bytes` thanks to @Laikoni  
`-2 bytes` thanks to @ASCII-only
[Answer]
# [Python 2](https://docs.python.org/2/), 61 bytes
Uses Arnauld's algorithm.
```
lambda c:max(c,key=lambda i:'_dp'.find(i[-1])**3*int(i[:-1]))
```
[Try it online!](https://tio.run/##fY3dCsIgHEfve4rd6WRFOmpN2JOsCJtJYlsSu2hPb34EhUo3wu/8Dx69zLfHRIzojubOxgtnxUBH9oJDpa5L90GSgjPXYCPkxKHs1/hUIlQjOc12UTdLo59uCtgD0ipQFcC@lq9@OPacNPFhzx3HOsK7gBM9fIN5jPkfTGLc6qxNvF1vk2bQVb6ps3bSbDw@xLarfaPmDQ "Python 2 – Try It Online")
---
### Previous answer, 73 bytes
```
lambda c:max(c,key=lambda i:('dp'.find(i[-1]),int('-'*('k'in i)+i[:-1])))
```
[Try it online!](https://tio.run/##fY1BDoIwEEX3nqK7abUYWyMICSdBF0glTiq1MSzk9JUWE00hbmbx/ss8O/S3h5GuLU/uXncXVZOm6OoXbbi@DuUHYUFBWdi2aBTFKhFnxtH0FBJYU9CAhiDbYFX4hTFnn35taQUy18AJjHccVj9cBC6zeEiV58JG@DDhmT69ESrG6g@WMc7toi2Dvd/NmpOul5t20Z41s4CPse1r36h7Aw "Python 2 – Try It Online")
[Answer]
# [Julia 0.6](http://julialang.org/), ~~75~~ ~~71~~ 65 bytes
```
S->S[indmax((s->parse(s[1:end-1])*(search("_dp",s[2])-1)^3).(S))]
```
[Try it online!](https://tio.run/##DcpRCoQgEADQq8R8zUQGFgQF2yX8FAtJI6MVcQq6vbvv@53PFexQ9k9RYlY6RPe1LyKLOdnMHlnLyUcnpKEa2du8HQirS9Cw7gwJSUtPLSoiU1IO8b4i7qih@48KRgeGqCo/ "Julia 0.6 – Try It Online")
*(-4 bytes, parse in 0.6 auto detects it as Int)*
*(-6 bytes, use `(search("_dp",s[2])-1)^3)` based on Arnauld's JS answer, instead of `((c=cmp(s[end],'k'))^2*6+4c-1)`)*
[Answer]
# [Retina 0.8.2](https://github.com/m-ender/retina/wiki/The-Language/a950ad7d925ec9316e3e2fb2cf5d49fd15d23e3d), 29 bytes
```
O$^`.+((k)|(.))
$3$&$*1$2
1G`
```
[Try it online!](https://tio.run/##K0otycxL/P/fXyUuQU9bQyNbs0ZDT1OTS8VYRU1Fy1DFiMvQPeH/f8tsLssCLvNsLvMULvMCAA "Retina 0.8.2 – Try It Online") Accepts any number of ranks and outputs the highest. Explanation:
```
O`
```
Sort the lines...
```
$
```
... using the specified key...
```
^
```
... in reverse order.
```
.+((k)|(.))
$3$&$*1$2
```
The key is created from the input line as follows: a) the (professional) dan rank letter b) the rank in unary c) the kyū letter (where applicable). Since this is a reverse sort, the professional dan rank `p` sorts before the dan rank `d` and the kyū rank which starts with `1` because the kyū letter is left at the end. Within the ranks the (professional) dan ranks sort in descending order due to the length of the unary string, however the trailing `k` for the kyū ranks causes them to sort in ascending order.
```
1G`
```
Select the first line, which is now the greatest rank.
[Answer]
# J, 39 bytes
```
[`]@.(<&(".@}:((*_1&^)+]*0=2&|)a.i.{:))
```
[Try it online!](https://tio.run/##dc7LCsIwEAXQfb9icNEm1YYmUvvAQkFw5cqt1AfWonZh9uq316QZLYEYCMlwuMO99xMWtFAWEMAMYijUjRistpt1vzvWFSNLn0xY9S4ICQ/c39NpHcal8F/0xG7sWVDaU@9yvj4gyLsAIrVI6E87zCiCf4kbEql6AZC5NLpoBtQjjJo0RhNUE/1lUXGxHl3auFTYKmzNsZV@/2eFyc5juxVmOWY7u5W0W0m3SlerDDU1mtnZoYbm4TP28tTpPw "J – Try It Online")
## explanation
```
[`]@.(<&(".@}: ((* _1&^) + ] * 0 = 2&|) a. i. {:))    entire phrase
[`]@.(<&(       assign a rank number            ))
      <&                                              "less than" of the ranks of the left and right args
                                                      ie, return 1 if right arg rank is bigger
[`]@.                                                 if so, return right arg.  otherwise left
                                                      breaking down the rank number part now...
        (       assign a rank number            )
        (".@}: ((* _1&^) + ] * 0 = 2&|) a. i. {:)
        (".@}:                                  )     everything but last char, convert to number
        (                               a. i. {:)     index within ascii alphabet of the last char
                                                      these become the left and right args to what follows...
        (      ((* _1&^) + ] * 0 = 2&|)         )
        (      (           ] * 0 = 2&|)         )     the right arg * "is the right arg even?"
                                                      because only 'k' is odd (107), this will be 0 for 'k'
                                                      and will be 100 for 'd' and 112 for 'p'
        (      ((* _1&^)              )         )     left arg (number of go rank) times _1 raised
                                                      to the ascii index.  this will swap the sign
                                                      for k only, hence producing a valid rank function
```
[Answer]
# [Python](https://docs.python.org/), 59 bytes
```
lambda s:max(s,key=lambda x:(-2)**(ord(x[-1])|8)*int(x,26))
```
An unnamed function accepting an iterable of strings which returns a maximal one by Go rank. Works much like [my Jelly answer](https://codegolf.stackexchange.com/a/168185/53748) (just uses the whole string evaluated as an integer in base 26 to save bytes).
**[Try it online!](https://tio.run/##XY/NDoIwEITP@hS9dZdUQ0vkL/FJxAOmEA0CDfSAUZ4d6U@C8bL7zezOYdRL3/suWupzsTzL9iZLMuZtOcHImup19taUw0FgEEA/SJguB37FT4rBo9MwMREjLnU/EF2Nmjw6AkBF1lBG14FsFdwIkTgVy1VwZflk2R/sF5eO5R8Lx5nafGH8KPRhe2h@wmrzfTgxnDrf5Hwa8/1ODaYLffO50G9hRjjT41qqLTXUYJohI4HduHwB "Python 3 – Try It Online")**
[Answer]
# [Perl 6](https://github.com/nxadm/rakudo-pkg), 35 bytes
```
*.max: {{+TR/pd/0 /}(S/(.+)k/-$0/)}
```
[Try it online!](https://tio.run/##VY3NasMwEITveopBmCDVrmWp5McxoQ/QQ6HtsRfHUiEoTtTk0BjjZ3fXVQKpENr9dmZHwZ32i7HtZm4zPuRtfVmj79OPNxWsKqAG8a5EnkqvHpNCyWGsWN92SOoMU9nG0lRM0IgwaSQ2yJtjuxXq8ydVsmLnugNPanKvyYpn8GzmRFyQMuN4feG4IBV3U7hv8soBX8cTuCk96NIpPTPawywnoo4tLHSYFCpsTvCnYG4Z2bSNCoH9DyaCsawMN6UMjMZPhb8qlKv9LVrf/0PdNYBgGbCKyiqwaTsm0Mvz/e7gztX4Cw "Perl 6 – Try It Online")
A rather different approach to all this search-and-cube stuff. Essentially string replacement: `...k -> -...`, `p -> 0`, `d` deleted. Thus newbies get a minus score, dans get their rank and pros get rank\*10. Using the WhateverStar gets us a closure, and `max` takes a comparator function. 
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 12 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
Σ'pK°.Vyþ*}θ
```
`.V` (evaluate as 05AB1E code) is inspired by [*@Arnauld*'s similar approach in his Jelly answer](https://codegolf.stackexchange.com/a/168211/52210).
Input as a list of two (or more) of the valid strings.
[Try it online](https://tio.run/##yy9OTMpM/f//3GL1Au9DG/TCKg/v06o9t@P//2gl4wIlHSWTbKVYAA) or [verify all test cases](https://tio.run/##yy9OTMpM/V9Waa@k8KhtkoKSfeX/c4vVC7wPbdALqzy8T6v23I7/Ov@jo5WMLLOVdJSARKwOkGMI4hiZQ3hmKUCOYQGYbQpmQyXAqgxTIOwUNLYRhG1ZgBA3AokbG0A1gyWykTQXIMShms1BbAuIOEgfVHcsAA).
**Explanation:**
```
Σ           # Sort the (implicit) input-list by:
 'pK       '#  Remove "p"
    °       #  Take 10 to the power this string
            #  (if the string is not a valid number, the string remains unchanged)
     .V     #  Evaluate the string as 05AB1E code
       yþ*  #  Multiply it with just the digits of the string
}θ          # After the sort: pop and push the last element
            # (which is output implicitly as result)
```
* `k` pops a list and an item, and pushes the index of the item in the list. Since the stack doesn't contain a list, `"30k"` through `"1k"` will always result in `-1`. Multiplied by their number, it will be the range \$[-30,-1]\$.
* `d` checks if a number is non-negative (`>= 0`). Since this is truthy for all, `"1d"` through `"7d"` will always result in `1`. Multiplied by their number, it will be the range \$[1,7]\$.
* Removing `p` and using `°` will use 10 to the power \$a\$ if \$a\$ is a valid number, otherwise \$a\$ remains the same. So if \$a\$ is `"2k"` or `"2d"`, it will remain `"2k"` or `"2d"` after using `°`, but `"2"` (since we've removed the `p`) with `°` will become `100`. Multiplied by their number, `"1p"` through `"9p"` will be the list \$[10, 200, 3000, 40000, 500000, 6000000, 70000000, 800000000, 9000000000]\$.
[See all mapped values here.](https://tio.run/##yy9OTMpM/W9s4KOefWh1kLmPesqh1YdWW/qoF4Doskp7JYVHbZMUlOz/V6oXeB/aoBdWeXif1n@d/wA)
[Answer]
# [Scala](http://www.scala-lang.org/), 307 61 54 bytes
Great thanks to **Kevin Crujissen** and **ASCII-only** for their work on this answer, that got it down ~250b.
Some algorithm optimization for ordering function of 61b answer.
```
l=>l.maxBy(s=>s.init.toInt*(math.abs(s.last*2-209)-8))
```
Test cases here: [Try it online!](https://tio.run/##jdFPa4MwGAbwez9F8JR0rTQZrTqw0B0GO@y0Y90hNXZztTGYbLSMfXYX/0Ghee1OCg8/n5dHnfKC1@XuM0sNeuG5RNnJZFJotFHqZ4LQN6/Q/gE9fcnU5KWk201V8fP21VS5fH@bof4lrot4XfhHfno8Yx2vtZ/L3PimfJZmio/cfPh8p7H2C67NlM3ZIiLzkJBaWW4Kib09br@ME49Fh8SbocRrnoSgGHl3Q9qENrORTcjEpWmvWeDitOU2g/xKdJyqa70SDaYKssvBuqqXHYabh8OpuMbd2VSAVoxY8T/LQMtAGym4N1LjvazvvV@4flRbbCPw6qHZgWnXfLi5lgLXUrd6nWup8bWC3oaO3qC1IdjbrgTO1Qx1sddv/Qc "Scala – Try It Online")
# Old 61 bytes answer
```
l=>l.maxBy(s=>(s.init.toInt+s.last)*(math.abs(s.last-105)-3))
```
The trick is to compute distance between `rank letter` and `i` (char code `105`). Then we use this distance as a score (*dan* = 5, *kyu* = 2, *pro* = 7) that we multiply by the rank number. Then we take the maximum on input array using the scoring function.
[Try it online too!](https://tio.run/##jZFPa8IwGIfvforQUzK1mEitHVRwh8EOO@1od4hN3TprGppsKGOfvUv/wcC8daeE/HjyvPxenfKC1@X@I0sNeua5RNnZZFJotFXqe4LQF6/Q4R49fsrU5KWku21V8cvuxVS5fHudof4S10W8KfwTPz9csI43WPu5zI1vyidpptovuDbkDp@4eff5XuPuZU4XAZkvCamV/cUUEnsH3Apw4rHomHgzlHjNSQiKkTcd0ia0mY1sQiYumvY0C104bXGbQfxKdDhV1/RKNDBVEBsMrEsddDBsHgan4hruxqYCZMUIK/7HMpBlIBsp2BupcS/rvcuFa1Gt2Ebg1IPZAdPOfLzZlgLbUre8zrbUeFthz64d3rBl16C3bQmsqynqT18/9S8 "Scala – Try It Online")
[Answer]
# [PHP](https://php.net/), ~~100~~ 98 bytes
(-2 bytes by changing function declaration)
```
<?function f($v){return(strpos('!!dp',$v[1])-1)**3*$v;};list(,$a,$b)=$argv;echo f($a)>f($b)?$a:$b;
```
To run it:
```
php -n <filename> <rank1> <rank2>
```
Example:
```
php -n go_rank.php 1p 7d
```
Or [Try it online!](https://tio.run/##Fc1NCsMgEEDhqzQwEEfMQrII1LY5SOlC8w9FBzVuSq/eabJ5y@/RSsy3ft79kLfgL7OAgp845T16kXKkkERdVSPVCspTv7DRKGUroZiveW8pCwVWgcM72LgUMw1rOBGLj6MOe7BXcIaZNXE3/gKdm8SN/wM "PHP – Try It Online")
---
# [PHP](https://php.net/) (7.4), 74 bytes
```
$g=fn($v)=>(strpos(__dp,$v[1])-1)**3*$v;$f=fn($a,$b)=>$g($a)>$g($b)?$a:$b;
```
[Try it online!](https://tio.run/##fZFta4MwEIC/51cc5UAj2dqkdK1zrj/ESdFGKwg1NOKXsd/uzuiyF0bz4XI8eXJ3JKYx48vRUMRLWl9DHHj6Gtr@Zjobnk7aCBwymfMHyaNoG@GQYO28QmBJKl4o5W4r@RGLZyyTEfvK9hZSyFgWqLgNBAQUcxCwXkPcTlQ6qvaEHSVA@EkThUCaL1kaoruFenmniboKRLV3HdV3qPJUTTQ2f9x46qZmd7vxo7kKi9v@mkz@O@/ifndzdD/Tg3cPE53aiJ/dKGN5wljd3ari3EC4vGZhwWUc3hnQqs5NB1jPx9mGLs8ZfRY8wurtukrYx/gJ "PHP – Try It Online")
---
# How?
Similar to [Arnauld's approach](https://codegolf.stackexchange.com/a/168155/81663), but in PHP. I'm using a function to convert each rank to a numeric value and compare and output the one with higher value.
The rank value comes from input string's second character position in `!!dp`, reduced by one and then powered to 3 and multiplied by the integer part of input string.
So for example, position of second character of `1p` which is `p` in `!!dp` is 3, reduced by one and powered to 3 it will be 8. So integer part of all `*p` ranks will be multiplied by 8. This means `1p = 8`, `2p = 16`, ..., `9p = 72`.
For all `*d` ranks, the integer part will be multiplied by 1 (or simply no multiplication). This means `1d = 1`, ..., `7d = 7`.
And for all `*k` and `**k` ranks, position of second character in `!!dp` will be equal to `false` which is equal to 0 (no explicit), reduced by one and powered by 3, means that the integer part will be multiplied by -1. This means `30k = -30`, ..., `1k = -1`.
This is my first ever golf attempt, not sure how bad it is!
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 95 91 bytes
Thanks to ceilingcat for the suggestion.
```
#define _(s)(strtol(s,&u,0)+(*u^15)*8)*~-(*u&2)
f(s,t,u)char*s,*t,*u;{puts(_(s)<_(t)?s:t);}
```
[Try it online!](https://tio.run/##XY9Rb4IwFIXf@RUNJqatdYEuTh3i/oDZ254IGtaCNjIgtPXFsL/O2goL20t7v3POPcllyzNj/UxUrNQ8BzupuKifLnvvj1SKT6P1M54XosrBCUoEpWpVXUJJ5poEaAGxPoYrhDcIfy8NzCnyCuMqohG7ZC2WBCuCdXRvtJLQVuxOUKE3@apQ1PU2A7BM0vjuAeDT7dUnvn0chZboesAXbihsHrByMFouGPIB@H@gA2ybiWNF/zkYG5x1nTY0E2dsWFvYDI5b/q14/zgciH26yPNEpcBXJipoh6w9M/K4FJv5hoA9dhCESQMgCmhTe4qAm25JmBL30xRFJpCXMgdF3UIRy8gsiUXssiIJUiJM2qS6/gc "C (gcc) – Try It Online")
[Answer]
# Excel VBA, 129 bytes
An anonymous VBE Immediate window function that takes input in range `A1:A2` and outputs to the console.
```
[B:B]="=SUBSTITUTE(A1,""p"",10)":[C1:C2]="=LEFT(B1,LEN(B1)-1)*-1^IFERROR(FIND(""k"",B1)>0,0)":?[INDEX(A:A,MATCH(MAX(C:C),C:C,0))]
```
### Explaination
```
[B:B]="=SUBSTITUTE(A1,""p"",10)"                            ''  Convert inputs to numerics 
                                                            ''  by appending 10 to rank if 
                                                            ''  is a professional dan rank
                                                            ''
[C1:C2]="=LEFT(B1,LEN(B1)-1)*-1^IFERROR(FIND(""k"",B1)>0,0)"''  Remove rightmost char; If 
                                                            ''  the rank is kyū, then mult
                                                            ''  by -1
                                                            ''
?[INDEX(A:A,MATCH(MAX(C:C),C:C,0))]                         ''  Find the max, return the 
                                                            ''  corresponding input
```
]