# How many states do I border?

When I was younger, I had a big map of the US tacked up on my wall across from my bed. When I was bored, I would stare at that map and think about stuff. Stuff like the four-color-theorem, or which state bordered the most other states. To save younger me some brainpower in counting, you are going to invent a time machine and tell me how many states border the input. Because time is finicky, this needs to be as short as possible.

Given one of the 50 US states, either by its full name or by its postal abbreviation, as found on this page (archive.org mirror), return the number of states it borders. The following is a mapping of all inputs for full state names to the number of states adjacent, found on this website.

Missouri, Tennessee -> 8
Arkansas, Idaho, Illinois, Iowa, Nebraska, New York, Oklahoma, Pennsylvania, South Dakota, Utah, Wyoming -> 6
Arizona, Georgia, Massachusetts, Michigan, Minnesota, Nevada, New Mexico, Ohio, Virginia, West Virginia -> 5
Alabama, Indiana, Kansas, Maryland, Mississippi, Montana, North Carolina, Oregon, Texas, Wisconsin -> 4
California, Connecticut, Delaware, Louisiana, New Hampshire, New Jersey, North Dakota, Rhode Island, Vermont -> 3
Florida, South Carolina, Washington -> 2
Maine -> 1


# The Rules

• Your program can either handle the full state name or the postal code - it cannot use a combination.
• You can specify the case of the input, but you cannot remove whitespace in the input.
• You do not have to handle Washington, D.C., or anything that is not one of the 50 states.
• The number of states bordered does not include the input state.
• This is , so shortest answer in bytes wins.

While I know this may just be whoever has the best compression or finds the best regex pattern per number, if I get too many of those answers, I'll award a bounty to an answer that generates a map of the US and uses that to calculate the number of bordering states.

• inb4 Mathematica Built-in – James Aug 20 '17 at 0:20
• @DJMcMayhem uh oh (sounds good at first, but see the update...) – Stephen Aug 20 '17 at 0:23
• @StepHen Oh no, I've been ousted! I was working on answer just now that incorporates this... ;) – notjagan Aug 20 '17 at 0:27
• Related – geokavel Aug 20 '17 at 0:36
• May we handle D.C./include it in our counts if we so please? – notjagan Aug 20 '17 at 0:37

# Jelly, 73 65 bytes

“U[“Ȥ“!÷2“®Ɓ⁵]StƁ}K“ʂÞiƬ¦.ÞrÆu“4œ(°fWg?Ʋd“Ɠ©“Œb‘i³OS%168¤$€Tµ’6L?  Try it online! Builtins? Who needs those? (ʂÞiƬ on the ground in disgust). Takes input as full name, such as "Idaho". How it Works “U[“Ȥ“!÷2“®Ɓ⁵]StƁ}K“ʂÞiƬ¦.ÞrÆu“4œ(°fWg?Ʋd“Ɠ©“Œb‘i³OS%168¤$€Tµ’6L?
“U[“Ȥ“!÷2“®Ɓ⁵]StƁ}K“ʂÞiƬ¦.ÞrÆu“4œ(°fWg?Ʋd“Ɠ©“Œb‘                   The literal list of code-page index lists  [[85, 91], [154], [33, 28, 50], [8, 143, 133, 93, 83, 116, 143, 125, 75], [167, 20, 105, 152, 5, 46, 20, 114, 13, 117], [52, 30, 40, 128, 102, 87, 103, 63, 153, 100], [147, 6], [19, 98]]
€        On each sublist:
¤            Evaluate the hash value:
³                     Input
O                   Character values
S                  Sum.
%                 Modulus.
168              168
i                     Does the sublist contain that nilad?
T       Get the sublist which does contain that nilad.
?  If
L     Length.
Then
’        Return the index - 1
Else
6      Return 6

• What process did you use to get that list? – Scott Milner Aug 20 '17 at 2:13
• @ScottMilner I ran OS%168 on each of the states, which directly yielded the list. I found the constant 168 by brute-forcing all possibilities less than 250, checking each of them for being able to actually differentiate between different numbers of borders. 168 worked (among a few others) and had the added benefit of only having to hard-code 48 values because of collisions. – fireflame241 Aug 20 '17 at 2:17

# Mathematica, 112 111 bytes

-5 byte thanks to Mark S. and LegionMammal978!

-22 bytes (and noticing a problem with the output) thanks to ngenisis!

Tr[1^Entity["AdministrativeDivision",#~StringDelete~" "]@"BorderingStates"]+Boole@StringMatchQ[#,"Il*"|"Mic*"]&


Of course, there's a Mathematica builtin for it. Includes D.C. in the count.

• This feels dirty, but AdministrativeDivision is so amazingly long that you'd save a byte with Length[x="AdministrativeDivision"~Entity~StringDelete[" "]@#~ToExpression[x<>"Data"]~"BorderingStates"]& – Mark S. Aug 20 '17 at 14:13
• ToExpression can be replaced with Symbol, if I remember correctly. – LegionMammal978 Aug 20 '17 at 17:40
• Also you don't need to use AdministrativeDivisionData, just pass "BorderingStates" as an argument to the entity; e.g. Entity["AdministrativeDivision","Alaska"]["BorderingStates"] – ngenisis Aug 21 '17 at 20:29
• @ngenisis I applied a fix to the first problem; fortunately, due to your suggestions, it didn't add that many bytes. The latter problem you mentioned regarding D.C. is not an issue as I asked OP whether this was valid and the response was yes. – notjagan Aug 21 '17 at 21:54
• @notjagan You can also use Tr[1^...] in place of Length@... to save another byte. – ngenisis Aug 21 '17 at 22:05

# JavaScript (ES6), 115 113 bytes

Edit: saved 2 bytes by borrowing 2 more string optimizations from Step Hen Python answer. I missed them on my initial attempt.

Takes postal codes as input.

s=>('7KYCO8MOTN0AKHI1ME2FLSCWA3CACTNDELANHNJRIVT4ALWINCKSMDMSMTXOR5GAZOHMANMIMNVWVA'.match('.\\D*'+s)||'6')[0][0]


### How?

A non-RegExp argument passed to the .match() method is implicitly converted to a RegExp object. So, we're testing the regular expression /.\D*{{input}}/ on our encoded string. This is matching a digit(1), followed by 0 to N non-digit characters, followed by the input.

For instance: if the input is "NH" (New Hampshire), the matched string will be "3CACTNDELANH". We simply keep the first character of this string, or return "6" by default if there was no match.

(1): The . is actually matching any character, but the string is built in such a way that what is found before a group of letters is always a digit.

### Demo

let f =

s=>('7KYCO8MOTN0AKHI1ME2FLSCWA3CACTNDELANHNJRIVT4ALWINCKSMDMSMTXOR5GAZOHMANMIMNVWVA'.match('.\\D*'+s)||'6')[0][0]

const o = {
8:['MO', 'TN'],
7:['CO', 'KY'],
6:['AR', 'ID', 'IL', 'IA', 'NE', 'NY', 'OK', 'PA', 'SD', 'UT', 'WY'],
5:['AZ', 'GA', 'MA', 'MI', 'MN', 'NV', 'NM', 'OH', 'VA', 'WV'],
4:['AL', 'IN', 'KS', 'MD', 'MS', 'MT', 'NC', 'OR', 'TX', 'WI'],
3:['CA', 'CT', 'DE', 'LA', 'NH', 'NJ', 'ND', 'RI', 'VT'],
2:['FL', 'SC', 'WA'],
1:['ME'],
0:['AK', 'HI']
};

for(let n = 8; n >= 0; n--) {
o[n].forEach(s => {
let res = f(s);
console.log(s + ' -> ' + res + ' ' + (res == n ? 'OK' : 'FAIL'));
});
}

# Hash version, 115 bytes

Same input format.

s=>04436303035050063062750600644408${6e7}503600300540410005207058036442600400000650035[parseInt(s,33)%589%180%98]  ### Demo let f = s=>04436303035050063062750600644408${6e7}503600300540410005207058036442600400000650035[parseInt(s,33)%589%180%98]

const o = {
8:['MO', 'TN'],
7:['CO', 'KY'],
6:['AR', 'ID', 'IL', 'IA', 'NE', 'NY', 'OK', 'PA', 'SD', 'UT', 'WY'],
5:['AZ', 'GA', 'MA', 'MI', 'MN', 'NV', 'NM', 'OH', 'VA', 'WV'],
4:['AL', 'IN', 'KS', 'MD', 'MS', 'MT', 'NC', 'OR', 'TX', 'WI'],
3:['CA', 'CT', 'DE', 'LA', 'NH', 'NJ', 'ND', 'RI', 'VT'],
2:['FL', 'SC', 'WA'],
1:['ME'],
0:['AK', 'HI']
};

for(let n = 8; n >= 0; n--) {
o[n].forEach(s => {
let res = f(s);
console.log(s + ' -> ' + res + ' ' + (res == n ? 'OK' : 'FAIL'));
});
}

• You could save a lot of bytes by btoaing that String – Downgoat Aug 21 '17 at 5:21
• OHMAN this is beautiful. – Steve Bennett May 11 '20 at 14:26

# Python 3, 168154153 137 bytes

lambda s:[i for i,S in enumerate('AKHI ME FLSCWA CACTLANHNJNDERIVT ALWINCKSMDMSMTXOR MAZOHGANMIMNVWVA A KYCO MOTN'.split())if s in S]or 6


Try it online!

-4 bytes thanks to isaacg

-10 bytes thanks to ETHProductions

-1 byte thanks to notjagen

Saved some more bytes by defaulting to six, as other answers have done.

TIO includes tests. Takes input as postal code. Generates a list of the state names as strings for each set, squished together where possible (for example, WVVA is stored as WVA). The lambda function gets the index in the list whose string contains the input. There may be a way I don't know about the golf the body of the function. Outputs as a list containing an integer - add [0] to the end of the lambda to output as integer.

• Also, you only use l once, so you might as well inline it. – isaacg Aug 20 '17 at 2:31
• @ETHproductions yep, thanks – Stephen Aug 20 '17 at 2:52
• @isaacg thanks, dunno why I didn't see that – Stephen Aug 20 '17 at 2:52
• -1 byte by rearranging Texas's position. – notjagan Aug 20 '17 at 2:55
• @notjagan thanks, missed that – Stephen Aug 20 '17 at 3:01

# V, 143 bytes

çourüee/C8
çdoüke/C7
çrküI„sn]üebüOkünnsüSDüUüwy/C6
çzüg„ot]üttüinnüvaüxiüOh/C5
çbüdiüKüMáû5}üNCüOüTüWi/C4
ç^[CDLNRV]/C3
ç[FSW]/C2
çM/C1
ñlS0


Try it online!

Hexdump:

00000000: e76f 7572 fc65 652f 4338 0ae7 646f fc6b  .our.ee/C8..do.k
00000010: 652f 4337 0ae7 726b fc49 8473 6e5d fc65  e/C7..rk.I.sn].e
00000020: 62fc 4f6b fc6e 6e73 fc53 8144 fc55 fc77  b.Ok.nns.S.D.U.w
00000030: 792f 4336 0ae7 7afc 6784 6f74 5dfc 7474  y/C6..z.g.ot].tt
00000040: fc69 6e6e fc76 61fc 7869 fc4f 682f 4335  .inn.va.xi.Oh/C5
00000050: 0ae7 62fc 6469 fc4b fc4d e1fb 357d fc4e  ..b.di.K.M..5}.N
00000060: 8143 fc4f fc54 fc57 692f 4334 0ae7 5e5b  .C.O.T.Wi/C4..^[
00000070: 4344 4c4e 5256 5d2f 4333 0ae7 5b46 5357  CDLNRV]/C3..[FSW
00000080: 5d2f 4332 0ae7 4d2f 4331 0af1 6c53 30    ]/C2..M/C1..lS0


I wrote this before I realized you could take the input as postal codes. I'm not sure if that's actually shorter or not :shrug:. This answer uses regex to search for certain states, and then change the input to a certain number if it matches. However, as the number of states we've tested against goes up, the smallest search we can use goes down. So for example, we can't search for C because that will match Colorado and California. (As well as Conneticut and The Carolinas) However, once we've tested for every state that has more than 3 bordering, we can just search for starts with C because it can't match a previous one anymore.

A few test cases might be wrong since I don't have the time to test all of them. Let me know if you find any incorrect outputs. :)

# JavaScript, 153 bytes

MO=TN=8;CO=KY=7;AZ=GA=MA=MI=MN=NV=NM=OH=VA=WV=5;AL=IN=KS=MD=MS=MT=NC=OR=TX=WI=4;CT=DE=LA=NH=NJ=ND=RI=VT=3;FL=WA=2;ME=1;AK=HI="0";alert(self[prompt()]||6)

Variable chaining. I'm sure there's a better way to do this though.

Thanks to a suggestion from someone from Discord the output defaults to 6, the most common number of bordered states. 183 bytes to 151 bytes.

A commenter pointed out that this fails for AK and HI, so I've added two bytes to fix the issue. 151 to 153 bytes.

• I'm pretty sure this fails for AK and HI because 0||6 evaluates to 6, which is incorrect output. – kamoroso94 Aug 20 '17 at 9:26
• @kamoroso94 I've updated my code, if you think there's a better fix let me know. – Eli Richardson Aug 20 '17 at 9:48

# 05AB1E, 78 72 bytes

.•n£þuγ{çâ/₁=èó[nK™ΩFîÀî˜Çʒ÷¿ηZ¬³ã®ÿΣÔ¢*5ŠÜ‚!¶Ö¾#}ê(Ûø‰¢þL[Æ₁cgIkö•s¡¬ð¢


Try it online!

.•n£þuγ{çâ/₁=èó[nK™ΩFîÀî˜Çʒ÷¿ηZ¬³ã®ÿΣÔ¢*5ŠÜ‚!¶Ö¾#}ê(Ûø‰¢þL[Æ₁cgIkö•
# Push the string: akhi me flscwa cactdelanhnjndrivt alinksmdmsncmtortxwi azgamamimnnvnmvaohwv idilianarenyokpnsdutwy kyco motn

s¡    # Split on input.
ð¢ # Count number of spaces.


This ONLY works because the order of the state abbreviations allows for NO state to occur in the overlap between states:

a[kh]i
me
f[ls][cw]a
c[ac][td][el][an][hn][jn][dr][iv]t
a[li][nk][sm][dm][sn][cm][to][rt][xw]i
a[zg][am][am][im][nn][vn][mv][ao][hw]v
i[di][li][an][ar][en][yo][kp][ns][du][tw]y
k[yc]o
m[ot]n


Took awhile to get the arrangement right... Then, by splitting on the input and counting the spaces in the first part, we get the correct result.

If I steal the "default to 6" from the other answers, I get 65 bytes:

# 05AB1E, 65 bytes

.•3θ0ÔÕ—ú^?D§:‚A†ǝλα“i›p‚ιCöΔƒñPŠ J€ŽãB»ΣUÆ¤ÆuhÃgŠ¦,Y²•s¡¬ð¢D9Qi6


Try it online!

• Took awhile to get the arrangement right -> oh, I think you could have copied it from my answer (if I'm reading this correctly) – Stephen Aug 23 '17 at 19:08
• @Stephen Well, I didn't get the idea from any other posts, if you look at the "sucky hashing algorithm" I was messing around with random ideas for hashing for like an hour then thought about the spaces, found I couldn't beat that implementation no matter how hard I tried. – Magic Octopus Urn Aug 23 '17 at 20:57
• @Stephen now that I read yours, I wish I had also thought about defaulting to 6 xD. – Magic Octopus Urn Aug 23 '17 at 20:59
• I didn't think of it, I saw it on this answer first, so feel free to take it :P – Stephen Aug 23 '17 at 21:07

# Retina, 106 105 bytes

MO|TN
8
CO|KY
7
AK|HI
0
ME
1
FL|WA
2
[CDLR].|N[HJD]|VT
3
.[CSX]|AL|IN|MD|MT|OR|WI
4
[GMV].|.[HMVZ]
5
..
6


Try it online! Did someone say regex? Edit: Saved 1 byte thanks to @Arnauld.

# JavaScript (ES6), 195 bytes

s=>/las|ii/[t='test'](s)?0:/ai/[t](s)?1:/Fl|Wa|S.*C/[t](s)?2:/fo|ct|de|ui|mp|er|^N.+ak/i[t](s)?3:/do|ck/[t](s)?7:/ur|ee/[t](s)?8:/iz|gi|ch|ev|xi|hi|es/[t](s)?5:/rk|ah|oi|ow|br|om|lv|ak/[t](s)?6:4


A series of regular expressions, which work on the state's full name.

Test cases:

var states = ['Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Delaware',
'Florida','Georgia','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas',
'Kentucky','Louisiana','Maine','Maryland','Massachusetts','Michigan','Minnesota',
'New Mexico','New York','North Carolina','North Dakota','Ohio','Oklahoma','Oregon',
'Pennsylvania','Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah',
'Vermont','Virginia','Washington','West Virginia','Wisconsin','Wyoming'];

let f=

s=>/las|ii/[t='test'](s)?0:/ai/[t](s)?1:/Fl|Wa|S.*C/[t](s)?2:/fo|ct|de|ui|mp|er|^N.+ak/i[t](s)?3:/do|ck/[t](s)?7:/ur|ee/[t](s)?8:/iz|gi|ch|ev|xi|hi|es/[t](s)?5:/rk|ah|oi|ow|br|om|lv|ak/[t](s)?6:4

for(i = 0 ; i <= 8 ; i++) {
s = []
states.forEach(st => f(st) == i && s.push(st))
console.log(i + ' bordering states: ' + s.join(', '))
}

# Jelly,  61  59 bytes

OP%⁽/r%101eÐ€“¿=“þ“(7“¡¦ðø,0@L“€ç÷<CMZa“Ø!)5HNV““1^“¥+‘Tȯ7’


A full program taking the full state name and printing the result (as a monadic link it either returns a list containing a single number or the number 6).

Try it online! or see a test suite.

### How?

“¿=“þ“(7“¡¦ðø,0@L“€ç÷<CMZa“Ø!)5HNV““1^“¥+‘


is a list of lists of code-page indices:

[[11,61],[31],[40,55],[0,5,24,29,44,48,64,76],[12,23,28,60,67,77,90,97],[18,33,41,53,72,78,86],[],[49,94],[4,43]]


and is shown as “ ... ‘, below:

OP%⁽/r%101eÐ€“ ... ‘Tȯ7’ - Main link: list of characters, stateName  e.g. Ohio
O                        - cast to ordinals                   [79,104,105,111]
P                       - product                                    95757480
⁽/r                   - base 250 literal                              12865
%                      - modulo by 12865                                3285
%101               - modulo by 101                                    53
“ ... ‘     - list of lists of code-page indices
eÐ€            - map: exists in?                 [0,0,0,0,0,1,0,0,0]
T    - truthy indices (if none yields an empty list)   [6]
ȯ7  - logical or with 7 (replace empty list with 7)   [6]
’ - decrement                                       [5]
- implicit print (Jelly's representation of a list of
-                 one item is just that item)       5


# Excel VBA, 177 154 147 Bytes

Anonymous VBE function that takes input, of the expected type String representing a state's postal code, from range [A1], and returns an Integer that represents the number of states that border that state.

For i=0To 8:r=r+IIf(Instr(1,Split("AKHI ME FLSCWA CACTLANHNJNDERIVT ALWINCKSMDMSMTXOR MAZOHGANMIMNVWVA | KYCO MOTN")(i),[A1]),i,0):Next:?IIf(r,r,6)


## Previous Versions

154 Bytes:

For Each s in Split("AKHI ME FLSCWA CACTLANHNJNDERIVT ALWINCKSMDMSMTXOR MAZOHGANMIMNVWVA | KYCO MOTN"):r=r+IIf(Instr(1,s,[A1]),i,0):i=i+1:Next:?IIf(r,r,6)


177 Bytes:

[2:2]=Split("AKHI ME FLSCWA CACTLANHNJNDERIVT ALWINCKSMDMSMTXOR MAZOHGANMIMNVWVA A KYCO MOTN"):[3:3]="=IfError(If(Find($A1,A2),Column(A3)),"""")":[B1]="=Sum(3:3)":?[If(B1,B1,6)]  Formatted for readability [2:2]=Split("AKHI ME FLSCWA CACTLANHNJNDERIVT ALWINCKSMDMSMTXOR MAZOHGANMIMNVWVA | KYCO MOTN") [3:3]="=IfError(If(Find($A1,A2),Column(A3)-1),"""")"
[B1]="=Sum(3:3)"
?[If(B1,B1,6)]


# Python 2, 363 218 bytes

lambda a:dict(WA=2,WI=4,WV=5,FL=2,NH=3,NJ=3,NM=5,NC=4,ND=3,RI=3,NV=5,CO=7,CA=3,GA=5,CT=3,OH=5,KS=4,SC=2,KY=7,OR=4,DE=3,HI=0,TX=4,LA=3,TN=8,VA=5,AK=0,AL=4,VT=3,IN=4,AZ=5,ME=1,MD=4,MA=5,MO=8,MN=5,MI=5,MT=4,MS=4).get(a,6)


Let's start out with the simple slightly optimized hardcoded answer. Takes postal code as input.

-145 bytes thanks to bfontaine.

• You can save almost 100 bytes by using dict(MO=8,TN=8,...) instead of {'MO':8,'TN':8,...}. You can then save almost 50 bytes by using .get(a,6) and removing those states that border 6 other states. I’m able to get down to 219 with those two tricks. – bfontaine Aug 20 '17 at 13:29
• @Mitch save some more by using space instead of . and doing split() (I think) – Stephen Aug 21 '17 at 12:39
• @Mitch do you even need the periods? Is there a method to split a list into groups of 2? – Magic Octopus Urn Aug 21 '17 at 16:34
• I believe you can save some more bytes using dict((i[0]+i[1],int(i[-1])) for i in zip(*[iter("WA2WI4WV5FL2...")]*3)). Also you could probably leave int out of that if it's allowed to have output as a string. – Izaak van Dongen Aug 22 '17 at 11:57
• Actually if you use unpacking you could do dict((a+b,int(c)) for a,b,c in zip(*[iter("WA2WI4WV5...")]*3)). Sorry, I'm a bit indecisive : D – Izaak van Dongen Aug 22 '17 at 12:02

# PowerShell, 187 bytes

param($a)$x=($b=" MO8TN8CO7KY7AZ5GA5MA5MI5MN5NV5NM5OH5VA5WV5AL4IN4KS4MD4MS4MT4NC4OR4TX4WI4CA3CT3DE3LA3NH3NJ3ND3RI3VT3FL2SC2WA2ME1").IndexOf($a);if($x+1){$b[$x+2];exit}6-6*($a-in'AK','HI')


Try it online!

I'm sure there's a better way to do this, but here's the approach I came up with.

Takes input $a and uses that to get the .IndexOf its occurrence in the long string of state/border combinations. Stores that into $x and the string into $b in the process. Then goes into an if statement that checks whether it found a match, and if so index to the digit and then exit. Otherwise, we're one of the 6 states or AK or HI, so we perform some logic to see whether $a is either of the 0 states, and subtract if necessary. In any case, that's left on the pipeline and output is implicit.

# Python 3, 729 733 bytes

Takes input as a postal abbreviation. This is my first attempt at a golfing challenge, and this is about the shortest I think I can get with this hellish approach. I know it's massive - come to think of it I'd probably have been better off with if-else statements, but after all of that time and effort I had to post it : D.

lambda s:sum((i-32)*96**j for j,i in enumerate(b'*g$<#?wP\\.=)kuDbk$yvv\\D:Nh:cd/Pj, e*[_yXGz6lR<$jMo0qUU*7(Dua3-ThO}iX6VWRYDv=<K$8mVbYK9ld);TFB/m\'NE3ow4./pUsI5yJrwYrM4@e6\\kHJ%q8NA3>fb!~-rtwsRW=RBni}Y7T^gD\\IoxzJf.%|1.&4*"$%Q+).|8p(vcJ]cLRGUyC2eF:<Q4!_)y\\<tr2A[z7re6OaR["2PRv\x7f,bRE [XrvtA<R<UlS23on?Byym&uy{XuB\x7fIMfh<y&waHElg-vk:4*on\x7f@?Ai5=2swfZSBF.PjkL{,|=,M<Bw"w,e@faKnmh\'xgg1#b4En\x7f+*\'g_ZRoeN*Q]mX\'>RoGc~ZP~e&{Hwo6bd<](hV)=l9#[f<Gj,#Ea!nJnL=9k"M,bP2PsP6(eJoGEU>GA?,BpS}"RzzdMRtL[cre;\\tld^xT\':pry\'Nu_*R}eYg_U!Ld{p7<f:95lD]OBMX(r"Jg\'|%Cq"Qy9g0aNrtYP9dnPRRr3\'yT(CE~\\&@5#tMLZ+a:V5NNXVp+Uy61s9$=Vb99(!ga7f7x}#=*]q.\x7f0R+f[*m:i^qe#D 8M&W\x7faGmCNCU9"~1Pj!]2r5 H>rYPqwfg4cFG*3-(z'))>>(5*int(s,36)-1850)&15
`

I just realised I'd taken the luxury of a three letter variable name - 4 bytes down, 400 to go!

• Welcome to PPCG! Sometimes simpler solutions are shorter, as shown by the other Python answers :P – Stephen Aug 21 '17 at 17:13
• Yeah, I love all the effort you put into this, considering your guilty pleasure is "making your code so concise it's illegible", you'll fit right in. – Adalynn Aug 21 '17 at 21:58