[Question]
  [
My first code golf post, apologies for any mistakes...
# Context
In rock climbing ([bouldering specifically](https://en.wikipedia.org/wiki/Grade_(bouldering))), the V/Vermin (USA) climbing grades start at 'VB' (the easiest grade), and then go 'V0', 'V0+', 'V1', 'V2', 'V3', 'V4', 'V5' etc. up to 'V17' (the hardest grade).
# Task
You will take as input a list/array of climbing grades and you have to to return or print a list/array of the grades sorted from easiest to hardest.
If the input is empty, return an empty data structure; otherwise the input will always be a valid.
# Test cases
```
Input | Output
[] |  []
['V1'] |  ['V1']
['V7', 'V12', 'V1'] | ['V1', 'V7', 'V12']
['V13', 'V14', 'VB', 'V0'] |  ['VB', 'V0', 'V13', 'V14']
['V0+', 'V0', 'V16', 'V2', 'VB', 'V6'] | ['VB', 'V0', 'V0+', 'V2', 'V6', 'V16']
```
This is a [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") challenge.
  
[Answer]
# [Python 2](https://docs.python.org/2/), ~~58~~ 54 bytes
```
lambda x:sorted(x,key=lambda y,B10=0:eval(y[1:]+'10'))
```
[Try it online!](https://tio.run/##LYrLCoMwEEX3fsXskqCUjH0HsvEjZtN2kaJSaapiQjFfn47QxTD3nnvmFF/TWOfe3rN3n2frYDVhWmLXyrV6d8n@aaoa1Fab7uu8TDc0j1KgFkrlYAUhAuEB6AhUA52ANHdODb89H5MrEAvIxpnnkuPmAG0zk4vYhdkPUaqimJdhjNDLoPIP "Python 2 – Try It Online")
## How it works
```
y         y[1:]+'10'   eval(y[1:]+'10')
=======================================
VB        B10          0  (a variable we defined)
V0        010          8  (an octal literal)
V0+       0+10         10
V1        110          110
V2        210          210
...       ...          ...
V17       1710         1710
```
[Answer]
## JavaScript (ES6) / Firefox, 53 bytes
```
a=>a.sort((a,b)=>(g=s=>parseInt(s,32)%334+s)(a)>g(b))
```
### Test cases
For Firefox:
```
let f =
a=>a.sort((a,b)=>(g=s=>parseInt(s,32)%334+s)(a)>g(b))
console.log(JSON.stringify(f([])))
console.log(JSON.stringify(f(['V1'])))
console.log(JSON.stringify(f(['V7', 'V12', 'V1'])))
console.log(JSON.stringify(f(['V13', 'V14', 'VB', 'V0'])))
console.log(JSON.stringify(f(['V0+', 'V0', 'V16', 'V2', 'VB', 'V6'])))
```
For Chrome or Edge (+4 bytes):
```
let f =
a=>a.sort((a,b)=>(g=s=>parseInt(s,32)%334+s)(a)>g(b)||-1)
console.log(JSON.stringify(f([])))
console.log(JSON.stringify(f(['V1'])))
console.log(JSON.stringify(f(['V7', 'V12', 'V1'])))
console.log(JSON.stringify(f(['V13', 'V14', 'VB', 'V0'])))
console.log(JSON.stringify(f(['V0+', 'V0', 'V16', 'V2', 'VB', 'V6'])))
```
### How?
We apply 3 successive transformations that lead to lexicographically comparable strings.
```
s     | Base32 -> dec. | MOD 334 | +s
------+----------------+---------+---------
"VB"  |           1003 |       1 | "1VB"
"V0"  |            992 |     324 | "324V0"
"V0+" |            992 |     324 | "324V0+"
"V1"  |            993 |     325 | "325V1"
"V2"  |            994 |     326 | "326V2"
"V3"  |            995 |     327 | "327V3"
"V4"  |            996 |     328 | "328V4"
"V5"  |            997 |     329 | "329V5"
"V6"  |            998 |     330 | "330V6"
"V7"  |            999 |     331 | "331V7"
"V8"  |           1000 |     332 | "332V8"
"V9"  |           1001 |     333 | "333V9"
"V10" |          31776 |      46 | "46V10"
"V11" |          31777 |      47 | "47V11"
"V12" |          31778 |      48 | "48V12"
"V13" |          31779 |      49 | "49V13"
"V14" |          31780 |      50 | "50V14"
"V15" |          31781 |      51 | "51V15"
"V16" |          31782 |      52 | "52V16"
"V17" |          31783 |      53 | "53V17"
```
[Answer]
## [Husk](https://github.com/barbuz/Husk), 5 bytes
```
ÖiÖm±
```
[Try it online!](https://tio.run/##yygtzv7///C0zMPTcg9t/P//f7RSmIG2kg6QBBGGZiDSCEQ4gQgzpVgA "Husk – Try It Online")
The results are printed one per line, but internally this is a function that takes and returns a list of strings.
## Explanation
This is surprisingly similar to [Martin's Retina answer](https://codegolf.stackexchange.com/a/137157/32014).
First we do `Öm±`, meaning "order by mapping is-digit".
This puts `VB`, `V0` and `V0+` in the correct order, since they are compared as `[0,0]`, `[0,1]` and `[0,1,0]`.
Next we do `Öi`, meaning "order by integer value".
Given a string, `i` returns the first sequence of digits occurring in it as an integer, or 0 if one is not found.
The three strings above are all mapped to 0 and the sort is stable, so they will be in the correct order in the output.
[Answer]
## [Retina](https://github.com/m-ender/retina), 14 bytes
```
B
!
O`
!
B
O#`
```
[Try it online!](https://tio.run/##FYotFoAwDIN9bsFDYigbf7YXmIveBAKD4HH/kok0afK913c/LcIxoFQdRxlrBM1Ay@AKLuAGzvqVXJYkNScowETsmifFzoB9VnP8 "Retina – Try It Online")
### Explanation
```
B
!
```
Replace `B` with `!` so that the lexicographic order of grades puts `VB` (or then `V!`) in front of all the numeric grades.
```
O`
```
Sort all input lines lexicographically. This doesn't give the right result but it does order `V! < V0 < V0+` correctly.
```
!
B
```
Turn `V!` back into `VB`.
```
O#`
```
Sort the lines numerically. Retina simply looks for the first decimal number in a string to determines its sort key. If there is no number (such as for `VB`), it sets the value to `0`. That means all of `VB`, `V0` and `V0+` have the same sort key. But Retina's sort is stable and we've already put them in the correct relative order.
[Answer]
# [V](https://github.com/DJMcMayhem/V), 3 bytes
```
Úún
```
[Try it online!](https://tio.run/##K/v///Csw7vy/v8PM9DmCjPmCjPhCjPgCjPkCnPiCjPiCjPlCjMDcs0B "V – Try It Online")
## How does it work?
```
ú   # Sort on...
 n  #   the first decimal number on the line
```
This command is *almost* a valid solution, since every line that *can't* be sorted by numbers (AKA, `VB`) will be placed at the beginning, without the order changed. However, since it's only looking at numbers, it can't distinguish between `V0` and `V0+`. Since Vim uses a stable sort, whichever of these came first will remain first after sorting it. So...
```
Ú   # Sort lexicographically (will place 'V0' before 'V0+')
 ú  # Sort by...
  n #   The first number on the line
```
[Answer]
# C#, ~~121~~ ~~83~~ ~~82~~ 83 bytes
*Saved **39** bytes thanks to TheLethalCoder and LiefdeWen*
```
a=>a.OrderBy(x=>x[1]>65?-1:x=="V0+"?0.5:int.Parse(x.Remove(0,1)))
```
[Try it online!](https://tio.run/##TU@xasMwFNz1FQ9NMnWEPaRDXCmQ0kJLS0ML6RAyqPZLENgSleTUIfjbXcU4pbc97u7dXelnjTV2aL02B/g4@YBNQf5f/EWb74KQslbewxrOBCJ8UEGXcLS6glelDfPBRc92B8odfDKpLnhsTXl3ZVN4enMVOqweTNugU181TqSUsI9SEECu3kEJqfhoWJ1YJ2S3zXfydr6c5YtOCLrJbugy4/OFNoGvlfPIOv6OjT0iy9I8SZIhFod7a7ytkX86HTCuwaksf7axOE1peglmBn/gb8UZ6CanKYwZ0MdXxdiqJ/3wCw "C# (Mono) – Try It Online")
Bytecount includes `using System.Linq`.
---
**How?**
* Gets an array of strings as input.
* If the input is equal to `VB`, set the value to -1, if it's equal to `VB0+`, set the value to 0.
* Order the input based on the number value that comes after the `V`.
Might be a bit of a hack, but it works! :)
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~52 42~~ 41 bytes
```
->x{[?B,0,"0+",*1..17].map{|a|"V#{a}"}&x}
```
[Try it online!](https://tio.run/##FYrLCsIwFER/5RJR1MaQ66u6UKEfMZvSRVx0VyhqsZLm2@N0MczrvIbnL7e3vLuPsX5U1lvjC2O36pyWjetCH6cwGSxiSCatxpT74fOWtl5@11AV6FFwEuwFZ4FnZ6poB4rLVUBASZS8C8aZEcw3l8umyX8 "Ruby – Try It Online")
### How it works:
Turn the problem around, produce the full sorted list, then get the intersection with our input.
Thanks Lynn for saving 1 byte.
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), 16 bytes
Port of [Python answer](https://codegolf.stackexchange.com/a/137152/48934) by OP.
```
o|hx"B00+"tN+3st
```
[Test suite](http://pyth.herokuapp.com/?code=o%7Chx%22B00%2B%22tN%2B3st&test_suite=1&test_suite_input=%5B%5D%0A%5B%27V1%27%5D%0A%5B%27V7%27%2C+%27V12%27%2C+%27V1%27%5D%0A%5B%27V13%27%2C+%27V14%27%2C+%27VB%27%2C+%27V0%27%5D%0A%5B%27V0%2B%27%2C+%27V0%27%2C+%27V16%27%2C+%27V2%27%2C+%27VB%27%2C+%27V6%27%5D&debug=0).
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~17~~ ~~13~~ 8 bytes
```
Σþï}„VB†
```
[Try it online!](https://tio.run/##MzBNTDJM/f//3OLD@w6vr33UMC/M6VHDgv//o9XDDLTVdRSAFJg0NANTRmDSCUyaqccCAA "05AB1E – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 9 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
Ḋv-.F+LµÞ
```
A monadic link taking a list of lists of characters and returning the sorted list.
**[Try it online!](https://tio.run/##y0rNyan8///hjq4yXT03bZ9DWw/P@3@4PcvhUdOaR4371NWzgKSOwv//6mEG2uo6CkAKTBqagSkjMOkEJs3UAQ "Jelly – Try It Online")** (the footer formats the result nicely)
### How?
```
Ḋv-.F+LµÞ - Link: list of lists of characters
       µÞ - sort by key:
Ḋ         -   dequeue (remove the 'V' from the item)
  -.      -   literal -0.5
 v        -   evaluate as Jelly code with argument -0.5
          -   ...this means `VB` and `V0+` become -0.5
          -      (to binary and addition respectively)
          -      while others become their literal numbers
    F     -   flatten
     +L   -   add the length of the item
          -   ...'VB', 'V0', 'V0+', 'V1', 'V2'... -> 1.5, 2, 2.5, 3, 4, ...
```
[Answer]
# [Haskell](https://www.haskell.org/), 55 bytes
```
f l=['V':x|x<-"B":"0":"0+":map show[1..17],_:y<-l,x==y]
```
[Try it online!](https://tio.run/##y0gszk7Nyfn/P00hxzZaPUzdqqKmwkZXyUnJSskAhLWVrHITCxSKM/LLow319AzNY3XirSptdHN0KmxtK2P/5yZm5tkWFGXmlaikRSuFAdXrKAApMGloBqaMwKQTmDRTiv0PAA "Haskell – Try It Online")
[Answer]
~~To kick things off here is my Python 3 solution...~~ Apologies, posted this too soon against convention, now re-posting...
# [Python 3](https://docs.python.org/3/), ~~69~~ 67 bytes
```
lambda l:sorted(l,key=lambda x:'B00+'.find(x[1:])+1or int(x[1:])+3)
```
[Try it online!](https://tio.run/##TY5NDoMgEEb3nIIdEEkD2tiEhI2H6MaysFFSU/wJsNDTU4Q2lQWPeTNkvnX3r2WugpaPYLrp2XfQCLdYP/TY0Pewy6/dBGoYK9BFj3OPt5YLRQq@WDjO/ldWJPjBeQclbAGMp1U0E905@r9viMJoyoxTg1dZXROadLNTP@7PKk3VCeVptkZKAaBjqiNHjJboRPq/2iOqxociBIQP "Python 3 – Try It Online")
[Answer]
# [Swift 3](https://swift.org/blog/swift-3-0-released/), 102 bytes
```
var r={String((Int($0,radix:32) ?? 992)%334)+$0};func f(l:[String]){print(l.sorted(by:{r($0)<r($1)}))}
```
This is a function. You can call it as such:
```
f(l:["V0","VB","V13","V0+"])
```
**[Try it online!](http://swift.sandbox.bluemix.net/#/repl/5981c1ec94c9c15dc3f62e5e)**
---
# How does this work?
This is basically a port of the [amazing Javascript answer by @Arnauld](https://codegolf.stackexchange.com/questions/137151/sort-the-climbing-grades/137159#137159), but optimized for Swift.
It maps each of the values to lexicographically orderable Strings as shown in the table below:
```
Initial String -> Result
V1  ->  325V1
V10 ->  46V10
V11 ->  47V11
V12 ->  48V12
V13 ->  49V13
V14 ->  50V14
V15 ->  51V15
V16 ->  52V16
V17 ->  53V17
V2  ->  326V2
V3  ->  327V3
V4  ->  328V4
V5  ->  329V5
V6  ->  330V6
V7  ->  331V7
V8  ->  332V8
V9  ->  333V9
V0+ ->  324V0+
V0  ->  324V0
VB  ->  1VB
```
---
# Code Explanation
* `String((Int($0,radix:32) ?? 992)%334)` - Converts each String from a base-32 Number to Decimal. In case the value is "V0+", the call to `Int(_:radix:)` will return nil, and we take the value of "V0", 992. We additionally take the result of `mod 334`, and finally convert it to String.
* `+$0` - Adds the current value to the String created above. For instance, if the String is `V9`, the function above returns `333` and we add `V9`, resulting in `333V9`.
* `var r={...}` - Declares a variable `r` to an anonymous closure, because it saves lots of bytes since it's used twice.
* `func f(l:[String])` - Defines a function `f` with a parameter `l`, a list of Strings.
* `print(l.sorted(by:{r($0)<r($1)}))` - Prints the result of sorting the given list, with the key being the variable `r` defined above.
[Answer]
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), 45 bytes
```
param($a)'B',0,'0+'+1..17|%{"V$_"}|?{$_-in$a}
```
[Try it online!](https://tio.run/##K8gvTy0qzkjNyfn/vyCxKDFXQyVRU91JXcdAR91AW13bUE/P0LxGtVopTCVeqbbGvlolXjczTyWx9v///w4a6mFANToKQApMGpqBKSMw6QQmzdQ1AQ "PowerShell – Try It Online")
Uses the same process as [G B's Ruby answer](https://codegolf.stackexchange.com/a/137173/42963) to construct the full argument list in sorted order, then select out those that are `-in` the input list.
[Answer]
# Google Sheets, 142 bytes
```
=ArrayFormula(If(A1="","",Sort(Transpose(Split(A1,",")),Transpose(IfError(Find(Split(A1,","),"VBV0V0+"),Value(Mid(Split(A1,","),2,3))+9)),1)))
```
Input is a string in `A1` with each entry separated by a comma.  
Output is the formula's cell plus the `n-1` cells below it where `n` is the number of entries in `A1`.
[![Result](https://i.stack.imgur.com/J37Hh.png)](https://i.stack.imgur.com/J37Hh.png)
It's a long, messy formula so let's unpack it.
* `If(A1="","",~)` fixes the null input. Without this, an empty input returns a `#VALUE!` error because the `Split` function doesn't work on empty inputs.
* `Transpose(Split(A1,","))` splits `A1` at the commas and transposes it into a column because the `Sort` function only works on columns.
* `Transpose(IfError(Find(),Value()+9))` is breaks into these pieces:
	+ `Find(Split(A1,","),"VBV0V0+")` tries to find each parameter in that string. These first three are the only ones that must be sorted as strings so we use `Find` to get their sort order.
	+ `Value(Mid(Split(A1,","),2,3))+9` gets the numerical value of the grade. This only matters for V1 and higher so they sort numerically just fine. The `+9` at the end is to ensure V1 comes after V0+ since its `Find` value would be `5`. Technically, then, only `+5` is required but it costs me no more bytes to make extra double sure it sorts correctly.
	+ `IfError(Find(~),Value(~))` returns the `Find` value if the string was found (i.e., the grade is VB, V0, or V0+). If it can't be found, it returns the numerical value of the grade plus nine.
	+ `Transpose(IfError(~))` again turns it into a column so `Sort` can use it.
* `Sort(Transpose(Split(~)),Transpose(IfError(Find(~),Value(~)+9)),1)` wraps it all up by sorting the split input using the custom sort order ascending.
* `ArrayFormula(~)` wraps the entire thing so it returns the results as an array instead of just returning the first value in that array. This is what causes the formula in one cell to fill the cells below it, too.
[Answer]
# Bash + coreutils, 21
```
tr B .|sort -V|tr . B
```
[GNU `sort`'s `-V`ersion sorting mode](https://www.gnu.org/software/coreutils/manual/html_node/Details-about-version-sort.html#Details-about-version-sort) almost does what we want. Switch the `B` for a `.` and we're done.
[Try it online](https://tio.run/##FUs7DoAgFNt7ircbifhDVw7RXSc3E2Dk7s@atGn6u6/6uLdi2UKvb2k2sssGy@6MG3iCcQGzZBJ38JAIP1dQUK7FDKpMoE7ToFJBTB8).
[Answer]
# [Haskell](https://www.haskell.org/), ~~90~~ ~~84~~ ~~83~~ 61 bytes
```
import Data.List
f"VB"=[]
f(_:'1':[a])='X':[a]
f x=x
sortOn f
```
[Try it online!](https://tio.run/##y0gszk7Nyfn/PzO3IL@oRMElsSRRzyezuIQrTSnMSck2OpYrTSPeSt1Q3So6MVbTVj0CzOBKU6iwreBKty0GavLPU0j7n5uYmWdbUJSZV6KSHq0UZqCtpKMApMCkoRmYMgKTTmDSTCn2PwA "Haskell – Try It Online")
`f` is a function that converts climbing grades to strings that can be compared. If converts `VB` to be the empty string so it gets the highest priority, it then replaces `V1` with `X` in strings that are three long to lower the priority of `V10`-`V17`. For the remainder we do nothing.
To sort the list we use `Data.Lists`'s `sortOn` function (as suggested by Lynn) to create a point-free function.
[Answer]
# [R](https://cran.r-project.org/), 45 bytes
```
l=paste0('V',c('B','0','0+',1:17));l[l%in%x]
```
### How does this work?
* Assign the correctly ordered vector of grades to 'l';
	+ Use 'paste0' instead of 'paste' to avoiding making a 'sep=""' argument;
* Index 'l' based on matches of 'l' in your input vector of mixed, unsorted grades.
[Answer]
**Python2, 77 bytes**
```
sorted(input(),key=lambda s:float(s[1:].replace("B","-1").replace("+",".5")))
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~17~~ 11 bytes
```
fØD
ṢÇÞÇV$Þ
```
[Try it online!](https://tio.run/##y0rNyan8/z/t8AwXroc7Fx1uPzzvcHuYyuF5/w@3H530cOeM//@j1cMMtNV1FIAUmDQ0A1NGYNIJTJqpxwIA "Jelly – Try It Online")
[Answer]
# [TXR Lisp](http://nongnu.org/txr): 45 bytes
```
(op sort @1 :(ret`@(mod(toint @1 32)334)@1`))
```
Run:
```
1> (op sort @1 :(ret`@(mod(toint @1 32)334)@1`))
#<interpreted fun: lambda (#:arg-01-0168 . #:rest-0167)>
2> [*1 ()]
nil
3> [*1 (list "V0+" "V0" "V16" "V2" "VB" "V6")]
("VB" "V0" "V0+" "V2" "V6" "V16")
```
[Answer]
# [Perl 5](https://www.perl.org/), 56 + 1 (-a) = 57 bytes
```
map{$i=$_;s/V//;$a[/B/?0:/^0/?length:$_+2]=$i}@F;say"@a"
```
[Try it online!](https://tio.run/##LYxPC4IwHEC/yrAJhdhvE/SgLMVDt66/S39kkJXMnGxeROqjtxZ0ezx4b2xNn7pVqMRTjouFGsCItwXk69N1A4iUe7GjzavaF1bOVC2eb9oQq81EVDvbULlfSztBm8KXAAWVR38qWQ4XBmXfDvfpkdMmSs6Cdv9TUMnAOWQRQUaQZwQTgjXB7KPHqdODdfEh3TLOXCy/ "Perl 5 – Try It Online")
]