How many states do I border?

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.


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

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'));
  });
}