Abbreviate that US state!

50

6

Given one of the 50 U.S. state names on the left as input, output its two-letter postal code as shown to the right:

Alabama         AL
Alaska          AK
Arizona         AZ
Arkansas        AR
California      CA
Colorado        CO
Connecticut     CT
Delaware        DE
Florida         FL
Georgia         GA
Hawaii          HI
Idaho           ID
Illinois        IL
Indiana         IN
Iowa            IA
Kansas          KS
Kentucky        KY
Louisiana       LA
Maine           ME
Maryland        MD
Massachusetts   MA
Michigan        MI
Minnesota       MN
Mississippi     MS
Missouri        MO
Montana         MT
Nebraska        NE
Nevada          NV
New Hampshire   NH
New Jersey      NJ
New Mexico      NM
New York        NY
North Carolina  NC
North Dakota    ND
Ohio            OH
Oklahoma        OK
Oregon          OR
Pennsylvania    PA
Rhode Island    RI
South Carolina  SC
South Dakota    SD
Tennessee       TN
Texas           TX
Utah            UT
Vermont         VT
Virginia        VA
Washington      WA
West Virginia   WV
Wisconsin       WI
Wyoming         WY

Rules

  • Input and output are both case sensitive. You many not output e.g. Al for Alabama.
  • You may assume the input is one of the 50 state names shown above.
  • You may not access the internet or use built-in state data (looking at you, Mathematica).

Separate lists of inputs and outputs can be found in this snippet (please don't run it, it's just for compressing the post):

Alabama
Alaska
Arizona
Arkansas
California
Colorado
Connecticut
Delaware
Florida
Georgia
Hawaii
Idaho
Illinois
Indiana
Iowa
Kansas
Kentucky
Louisiana
Maine
Maryland
Massachusetts
Michigan
Minnesota
Mississippi
Missouri
Montana
Nebraska
Nevada
New Hampshire
New Jersey
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

AL
AK
AZ
AR
CA
CO
CT
DE
FL
GA
HI
ID
IL
IN
IA
KS
KY
LA
ME
MD
MA
MI
MN
MS
MO
MT
NE
NV
NH
NJ
NM
NY
NC
ND
OH
OK
OR
PA
RI
SC
SD
TN
TX
UT
VT
VA
WA
WV
WI
WY

(Non-scoring) Brownie points if you can also take District of Columbia as input and produce DC, Virgin Islands, etc etc.

Scoring

This is , so the shortest code in bytes in each language wins.

(Originally proposed by ETHProductions)

Steve Bennett

Posted 2017-05-26T05:32:57.937

Reputation: 1 558

1Related (another challenge about US states) – Mego – 2017-05-26T06:37:08.583

11For those curious to know Mathematica's approach: Entity[a="AdministrativeDivision",{#,"UnitedStates"}]@EntityProperty[a,"StateAbbreviation"]& – DavidC – 2017-05-26T07:05:31.870

12@BetaDecay Questions that are closed as off-topic are not useful dupe targets. – Mego – 2017-05-26T07:08:48.893

7@DavidC You can save 20 bytes: Entity["AdministrativeDivision",{#,"UnitedStates"}]@"StateAbbreviation"& :) – ngenisis – 2017-05-26T18:28:42.273

1How is this a Kolmogorov complexity question? I thought this tag is for constant output – Felix Dombek – 2017-05-26T18:59:09.810

@ngenisis, nice shortcut (that I was not aware of)! – DavidC – 2017-05-26T19:20:00.810

Would've been more interesting if you had included territories and federate states. ;) – jpmc26 – 2017-05-26T22:57:55.370

@FelixDombek It's more about efficiently generating a set of data, even if not all of it is output. – Esolanging Fruit – 2017-05-27T00:44:33.767

@FelixDombek https://codegolf.meta.stackexchange.com/a/9909/45941

– Mego – 2017-05-27T07:07:54.063

2Offer extra credit for including the other 12 two-character codes in the complete official list of US postal abbreviations: AA (ARMED FORCES AMERICAS), AE (ARMED FORCES EUROPE), AP (ARMED FORCES PACIFIC), AS (AMERICAN SAMOA), DC (DISTRICT OF COLUMBIA), FM (FEDERATED STATES OF MICRONESIA), GU (GUAM), MH (MARSHALL ISLANDS), MP (NORTHERN MARIANA ISLANDS), PR (PUERTO RICO), PW (PALAU), VI (VIRGIN ISLANDS). – joe snyder – 2017-05-27T15:47:45.487

1Also, this is a code-golf, while the proposed duplicate was a pop-con – John Dvorak – 2017-05-27T17:28:55.550

2Yeah this is not a dupe. – Christopher – 2017-05-27T18:27:16.570

Also the question listed as a dupe is closed as off topic where this one clearly isn't off topic. – Ian Miller – 2017-05-28T01:00:00.867

2Heh, I only just noticed that someone actually closed this as a dupe. FFS. – Steve Bennett – 2017-05-28T01:22:00.180

@joesnyder I've made clearer in the challenge that non-scoring Brownie points are available for all of those extensions. It says in the guidelines somewhere that bonus points are generally discouraged. Also this isn't my challenge. Also, I prefer this tighter challenge. – Steve Bennett – 2017-05-28T01:23:44.453

Answers

25

Javascript, 124 117 bytes

(saved 7 bytes thanks to hvd)

x=>/.+[A-Z]|A..[sz]k?|M.ss.s?|M[io]n?t?|Nev?|[AFIOUW][^o]|T..|.+/.exec(x)[0].replace(/(.).*(.)/,'$1$2').toUpperCase()

Explanation:

  • The regexp finds a match with the first and last letters the two letters of the abbreviation
  • First part matches states with more than two words (including District of Columbia)
  • Second part matches Alaska and Arizona
  • Third part matches Massachusets, Mississippi and Missouri
  • Fourth part matches Michigan, Minnesota and Montana
  • Fifth part matches Nebraska and Nevada
  • Sixth part matches all remaining states abbreviated to their first two letters, with a special case to exclude Iowa
  • Seventh part matches all remaining states abbreviated to their first and third letters
  • Eighth part matches everything else, which are abbreviated to their first and last letters
  • Then it is just a case of stripping of those letters and capitalising
  • Also matches Puerto Rico and American Samoa, but not Guam, Marianas islands or US Virgin Islands

HP Williams

Posted 2017-05-26T05:32:57.937

Reputation: 381

Wow, this is great! +1! – NoOneIsHere – 2017-05-26T15:00:55.497

3Nice! Some more opportunities: the initial [A-Z] is not necessary since the input is known to be valid. The Iowa special case can be shortened to [AFIOUW][^o] to exclude it, leaving it for the final .+. – hvd – 2017-05-26T15:23:28.883

1Your regex machinery is so efficient compared to mine...wish there was a way to make it work with my shorter regex. But they're constructed on such different principles. – Steve Bennett – 2017-05-26T15:36:52.843

@SteveBennett interesting that you had Missouri as the oddball, whereas I had trouble with Montana. – HP Williams – 2017-05-26T15:52:37.200

1Well there are quite a few that are weird in their own ways. There's a nice collection that match both the "first and last" and "first two" rules (Colorado, Delaware, California...), but then Mississippi (MS) ruins it. – Steve Bennett – 2017-05-26T16:26:08.237

I think you missed something in your last edit; the regex is currently not valid (the + at the beginning throws an error). – ETHproductions – 2017-05-26T16:31:16.827

Yeah, it should be .+ at the start of the regex. I think you did have that when testing, since your byte count is right for that. – hvd – 2017-05-26T16:57:47.877

Mine is down to 113, with the help of your idea of using regex conditionals instead of looping. – Steve Bennett – 2017-05-27T07:04:59.423

Mine is down to 108, but if you use slice instead of replace in yours, yours becomes 105: f=s=>s[0]+/.+[A-Z]|A..[sz]k?|M.ss.s?|M[io]n?t?|Nev?|[AFIOUW][^o]|T..|.+/.exec(s)[0].slice(-1).toUpperCase() – Steve Bennett – 2017-05-27T22:31:26.843

Oh look, I golfed you down to 102: s=>s[0]+/.+[A-Zz]|Alask|M.ss.s?|M[io]n?t?|Nev?|[AFIOUW][^o]|Te.|.+/.exec(s)[0].slice(-1).toUpperCase() – Steve Bennett – 2017-05-27T23:10:06.733

1101: s=>s[0]+/.+[A-Zz]|Nev?|.*sk|M.ss.s?|M[io]n?t?|[AFIOUW][^o]|Te.|.+/.exec(s)[0].slice(-1).toUpperCase() Can we get to 100? :) – Steve Bennett – 2017-05-27T23:12:05.857

Whoa, now down to 94. See my answer. – Steve Bennett – 2017-06-01T05:49:02.990

23

Javascript, 137 135 134 132 113 110 108 101 99 94 93 92 bytes

This is based on HP Williams solution, with some improvements outside the regex, and a couple of tweaks within it.

s=>s[0]+
/.*( .|z)|...s.s?|T..|M[i-t]+|[AFINOUW][^o]v?|.*/
.exec(s)[0].slice(-1).toUpperCase()

(Linebreaks for readability only)

Commentary for the regex:

.*( .|z)|      // Two-or-three word states, plus Arizona
...s.s?|       // Mississippi, Missouri, Massachussetts, Alaska, and (non-harmfully) Kansas
M[i-t]+|       // Montana, Minnesota, Michigan
[AFINOUW][^o]v?|  // All the other first-two-letter states, avoiding Iowa, plus Nevada
T‌​..|           // Tennessee, Texas
.+             // Everything else is first-and-last

Pointless alternative regex (same length):

/...(a$|z|s.s?|.* .)|M[i-t]+|T..|[AFINOUW].v?|.*/  

History

94

s=>s[0]+/.*( .|z)|...s.s?|M[io]n?t?|[AFIOUWN][^o]v?|T..|.*/
.exec(s)[0].slice(-1).toUpperCase()

99

s=>s[0]+/.*( .|z|l.*k)|T..|M.ss.s?|M[io]n?t?|[AFIOUWN][^o]v?|.*/
.exec(s)[0].slice(-1).toUpperCase()

101

s=>s[0]+/.+[A-Zz]|Nev?|.*sk|M.ss.s?|M[io]n?t?|[AFIOUW][^o]|T‌​e.|.+/
.exec(s)[0].sl‌​ice(-1).toUpperCase(‌​)

108

 s=>s[0]+/MI(N|SSO|S)|[CDGHKLPV].*|.* .|.*[XZV]|.*?N[NTE]|.*(SK|D$|WA)|../
.exec(s.toUpperCase())[0].slice(-1)

110

s=>s[0]+/MI(N|SSO|S)|[CGHKLPV].*|.* .|.*[XZV]|.*?N[NTE]|.*(SK|[ED]$|WA)|../
.exec(s.toUpperCase())[0].slice(-1)

113

s=>s[0]+/^MI(N|SSO|S)|^[CGHKLPV].*|.*?( .|[XZV])|.*?N[NTE]|.*(SK|[ED]$|WA)|../
.exec(s.toUpperCase())[0].slice(-1)

132

s=>(S=s.toUpperCase(),' ._SSO_^MI[NS]_^[CGHKLPV].*_.V_N[TNE]_SK_[ED]$_WA_Z_X_..'
.split`_`.some(p=>s=S.match(p)),S[0]+s[0].slice(-1))

134

s=>' ._SSO_^MI[NS]_^[CGHKLPV].*_.V_N[TNE]_SK_E$_D$_WA_Z_X_..'.split`_`
.map(p=>s=(z=s.toUpperCase().match(p))?s[0]+z[0].slice(-1):s)&&s

135

s=>' ._SSO_^MI[NS]_LASK_^[CGHKLPV].*_NT_EN_[DE]$_WA_.[XVZ]_..'.split`_`
.map(p=>s=(z=s.toUpperCase().match(p))?s[0]+z[0].slice(-1):s)&&s

137

s=>' ._OWA_SSO_ONT_^MI[NS]_LASK_^[CGHKLPV].*_EN_[DE]$_.[XVZ]_..'.split`_`.
map(p=>s=(z=s.toUpperCase().match(p))?s[0]+z[0].slice(-1):s)&&s

Steve Bennett

Posted 2017-05-26T05:32:57.937

Reputation: 1 558

This is just insane, I wish I could upvote again. – ETHproductions – 2017-06-01T00:35:30.377

Don't look now! 99! – Steve Bennett – 2017-06-01T02:59:18.707

start="94">

  • Totally crazy. I discovered this optimisation (...s.s? captures Mississippi, Missouri, Massachussetts and Alaska) by accident. I was actually in the process of moving the .*sk fragment to somewhere else, and the tests just happen to ran and passed, while the fragment wasn't present anywhere. Easiest 5 character gain ever!
  • < – Steve Bennett – 2017-06-01T05:22:23.073

    Wow, and I just realised that ...s.s? is also inadvertently matching Kansas, and is, by miracle, still giving the right result. – Steve Bennett – 2017-06-01T05:31:45.583

    And one more character with M[onti]+. So weird: if the state starts with M, then the second letter is the last in a sequence of at least one o, n, t, or i. A very weird way to capture Michican, Minnesota, or Montana. – Steve Bennett – 2017-06-01T06:35:02.927

    One more! M[i-t]+ – Steve Bennett – 2017-06-01T06:37:22.070

    Doesn't help, but just noticed that [^GHKMPV] is the same length as [AFINOUW] – Steve Bennett – 2017-07-04T00:57:15.903

    20

    JavaScript (ES6), 156 136 bytes

    s=>s[0]+'.KT..N.VEA.XVL.H.TZ.AA..I.EADATO.JTISRDIYOI.DALA.Y.KE.C.D.R.YAS.NM...C.L...N'[parseInt(s.split` `.join``,36)%359%248*8%99*3%83]
    

    Demo

    let f =
    
    s=>s[0]+'.KT..N.VEA.XVL.H.TZ.AA..I.EADATO.JTISRDIYOI.DALA.Y.KE.C.D.R.YAS.NM...C.L...N'[parseInt(s.split` `.join``,36)%359%248*8%99*3%83]
    
    ;[
      "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho",
      "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi",
      "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "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"
    ]
    .map(s => console.log(s, '-->', f(s)))

    Arnauld

    Posted 2017-05-26T05:32:57.937

    Reputation: 111 334

    1Is this bruteforced to be optimal using this method? – ASCII-only – 2017-05-26T08:10:03.343

    2@ASCII-only This is bruteforced on arbitral ranges, so it's only guaranteed to be optimal for X MOD[50-1000] MOD[50-1000] MOD[50-100]. But the .slice(1) was a mistake. Currently running again on the whole string. – Arnauld – 2017-05-26T08:13:46.300

    2Could you explain to a newb what this does? – Hankrecords – 2017-05-26T10:17:58.517

    1@Hankrecords Sure, will do. (But I'm in a train with limited Internet access right now.) – Arnauld – 2017-05-26T11:12:07.680

    Damn, my hand-crafted solution is one byte longer :/ – Steve Bennett – 2017-05-26T13:43:31.077

    1now mine is 135! – Steve Bennett – 2017-05-26T14:30:49.790

    1

    @Hankrecords This one has become more complex than I wanted it to be. You may want to have a look at this one, which is using the same principle (a hash function generating an index into a lookup table) but with a simpler formula and a simpler dataset. Does that make sense?

    – Arnauld – 2017-05-27T18:55:16.850

    17

    Jelly, 75 bytes

    ³Oḅ⁹%⁽qġ%14ị⁽"wB¤Ḥ
    “¿ØƈṢḍw÷S=)µZṂ÷ĿæÆɱ»Ḳiµ%2+3¢⁸?
    e“\B“½ƈN»ȧ5ȯÇ’
    i⁶ȯÇ‘ịṭḢŒu
    

    Try it online!

    ...or see a test suite - Note a small change had to be made to run the full program for multiple inputs in one go (I swapped out the program input atom, ³, for a recall from register, ®, one and set the register to each state name in turn).

    How?

    Calculates the index to use for the second character of the postal code, appends it to the first character and uppercases the result.

    First finds the index of a space character (or 0 if not found);

    Else checks if it is Alaska or Missouri (yielding 5 for k or o);

    Else finds the index of the input state in the list Arizona Minnesota Mississippi Nevada Montana Texas Tennessee (or 0 if not found) - if so it takes that index mod 2 plus 3 (for z n s v t x n);

    Else converts the string to ordinals, converts that from base 256, finds the remainder of that after dividing by 29487, finds the remainder of that after dividing by 14 and uses that to index into the binary representation of 9620 and doubles the result - yielding 0 for states that use their final letter and 2 for those that use their second letter.

    All but the very first case are incremented, and the resulting value is decremented (upping the space index found by one).

    i⁶ȯÇ‘ịṭḢŒu - Main link: state string
     ⁶         - space character
    i          - first index (of a space character in the state) or 0 if not found  (n-1 or 0)
       Ç       - call link 3 as a monad  (get n-1 in other cases)
      ȯ        - logical or  (yielding n-1)
        ‘      - increment   (yielding n)
         ị     - index into the state string (get the nth character)
           Ḣ   - head the state string (get the first character)
          ṭ    - tack
            Œu - convert to uppercase
               - implicit print
    
    e“\B“½ƈN»ȧ5ȯÇ’ - Link 3: n-5 or ... : state string
     “\B“½ƈN»      - ["Alaska","Missouri"]
    e              - exists in? (1 if so, 0 if not)
              5    - 5
             ȧ     - logical and
                Ç  - call link 2 as a monad
               ȯ   - logical or
                 ’ - decrement
    
    “¿ØƈṢḍw÷S=)µZṂ÷ĿæÆɱ»Ḳiµ%2+3¢⁸? - Link 2: n = 3 or n = 4 or ... : state string
    “¿ØƈṢḍw÷S=)µZṂ÷ĿæÆɱ»           - "Arizona Minnesota Mississippi Nevada Montana Texas Tennessee"
                        Ḳ          - split at spaces
                         i         - first index of state string in that list or 0
                          µ        - monadic chain separation (call that i)
                                 ? - if: 
                                ⁸  -   link's left argument, i
                                   - then:
                           %2      -   mod 2
                             +3    -   plus 3  - odd entries to 4: AriZona, MisSissippi, MonTana, TenNessee
                                   -            even entries to 3: MiNnesota, NeVada, TeXas
                                   - else:
                               ¢   -   call link 1 as a nilad
    
    ³Oḅ⁹%⁽qġ%14ị⁽"wB¤Ḥ - Link 1 ...n=2 or n=0: no arguments
    ³                  - program's 1st input    e.g. Iowa          or Ohio
     O                 - cast to ordinals            [73,111,119,97]  [79, 104, 105, 111]
       ⁹               - 256
      ḅ                - convert from base           1232041825       1332242799
         ⁽qġ           - 29487
        %              - modulo                      15991            20139
            %14        - modulo 14                   3                7
                    ¤  - nilad followed by link(s) as a nilad:
                ⁽"w    -   9620                     V       V
                   B   -   convert to binary = [1,0,0,1,0,1,1,0,0,1,0,1,0,0]
               ị       - index into                  0                1
                     Ḥ - double                      0                2
                       -   ...0th index of Iowa is 'a', 2nd of Ohio is 'h'
    

    Jonathan Allan

    Posted 2017-05-26T05:32:57.937

    Reputation: 67 804

    1This is the longest Jelly I've ever seen =) – caird coinheringaahing – 2017-05-27T08:13:46.713

    11

    Python 2, 191 bytes

    lambda s:s[0]+("KZD"*5+"HNTD"*5+"AYY"*4+"__L_O_VTA_I__A_T_RS_KA__S_"+"MOO"*5+"I_C_"+"AE"*6+"_I_D__A_"+"EDL"*5+"HV_A"+"IR"*7+"XC"*6+"E____N__YJ_YT___L")[reduce(lambda a,x:a+ord(x)^24,s,0)%174]
    

    Try it online!

    Uses a simple hash function to find the second character of the abbreviation.

    ASCII-only

    Posted 2017-05-26T05:32:57.937

    Reputation: 4 687

    11

    Python 2, 94 90 bytes

    lambda s:s[0]+s[(19**9*0x4710b8f6019c1b61deca10eef13b1>>hash(s)%8199472%52*3&7)+1].upper()
    

    Try it online

    (Only Python 2 because Python 3 hashes are not stable and also you can't hash a string without turning it into bytes.)

    Works with all 50 states, plus as a bonus District of Columbia and Puerto Rico.

    It would be possible to save one byte by writing the number in base-36: int("5clu7x0aixb0pelmpugv5iiibphrpf",36). I'm waiting to see if I can think of a more creative solution.

    Update:

    Since there are 12 unused digit positions in the hash, there are 236 possible numbers which will work. It seemed reasonable to believe that one of them would have a prime factor with a large exponent. For any given prime and exponent, finding a value is quite fast; I managed to find one with a factor of 199, reducing the size of the expression needed to represent the number by four bytes.

    This is basically the same procedure as my C answer but using Python. Since the base hash function is different, I had to find a different reduction function, which turns out to be mod 52 instead of mod 54. But the biggest savings over C come from the possibility of using bignums to encode the vector, and of course the fact that the standard for Python seems to be that it's ok to use a lambda literal instead of a complete program.

    rici

    Posted 2017-05-26T05:32:57.937

    Reputation: 601

    10

    Retina, 113 81 80 77 70 68 bytes

    M1!`.+[A-Zz]|...s.s?|M[io]n?t?|[AFIOUWN][^o]v?|T..|.*
    \B.*(?=.)
    
    T`l`L
    

    Try it online! Includes all 51 test cases. Saved 32 bytes by appropriating @JörgHülsermann's regex that finds the second letter (with a tweak to support DC; edit: saved 1 byte thanks to @JörgHülsermann). Saved 3 bytes by switching to @SteveBennett's regex from his comment to @HPWilliam's answer. Saved 7 9 bytes thanks again to @SteveBennett. The other letters are then deleted and the string uppercased.

    Neil

    Posted 2017-05-26T05:32:57.937

    Reputation: 95 035

    Very nice, wouldn't have thought you could get a set of fully removable strings. – colsw – 2017-05-26T09:18:41.623

    @ConnorLSW e was the most troublesome, really. – Neil – 2017-05-26T09:19:37.223

    @JörgHülsermann Thanks for the return favour! – Neil – 2017-05-27T20:50:31.107

    @JörgHülsermann Oh, so I'll be able to save another byte then? – Neil – 2017-05-27T21:27:04.897

    Wow, nice. I'm certainly learning a lot about regexes :) It's still counterintuitive to me to have the [v] before the [P], and yet Pennsylvania handles correctly. And looking at it, I'm confused that Indiana doesn't become ID. – Steve Bennett – 2017-05-28T10:04:37.103

    1Wait, Indiana does become ID. You can probably fix it just by adding $ after the d. (You might want to use automatic testing - I have a script that constantly checks all 50 cases.) – Steve Bennett – 2017-05-28T10:07:00.887

    @SteveBennett Oops. JörgHülsermann has since rolled back his edit too. Meanwhile it turns out that I accidentally counted two invisible characters that Stack Exchange inserted into your comment to HPWilliam's answer, so now represents a correct 3-byte saving! – Neil – 2017-05-28T20:17:46.090

    You can save more bytes by using my newer ridiculous 51 character regex. /.+[A-Zz]|...s.s?|M[io]n?t?|[AFIOUWN][^o]v?|T..|.*/ – Steve Bennett – 2017-06-01T05:48:15.397

    @SteveBennett Impressive! – Neil – 2017-06-01T08:55:06.447

    Shaved 4 more characters off! .*( .|z)|...s.s?|T..|M[i-t]+|[AFINOUW][^o]v?|.* – Steve Bennett – 2017-06-02T05:42:11.537

    @SteveBennett I see M[i-t]+ saves 2 bytes but I don't see anything else saved... – Neil – 2017-06-02T07:52:09.563

    Sorry, miscounted. – Steve Bennett – 2017-06-02T08:27:53.417

    8

    PHP>=7.1, 113 Bytes

    <?=($a=$argn)[0],ucfirst(preg_match('#[vxz]| .|owa|lask|[CGHKLPV].*|ssi?.|n(n|t|[de]$)#',$a,$t)?$t[0][-1]:$a[1]);
    

    Online Version

    The strikes are match through a earlier beginning match before

    ([vxz]) matches Arizona, Nevada, New Mexico, Pennsylvania, Texas,

    (.) (one space before) matches New Hampshire, New Jersey, New Mexico, New York, North Carolina, North Dakota, Rhode Island, South Carolina, South Dakota, West Virginia

    [CGHKLPV].*(.) matches California, Colorado, Connecticut, Georgia, Hawaii, Kansas, Kentucky, Louisiana, New Hampshire, North Carolina, Pennsylvania, South Carolina, Vermont, Virginia, West Virginia

    ow(a) match Iowa

    las(k) match Alaska

    ssi?(.) matches Massachusetts, Mississippi, Missouri, Tennessee

    n(n|t|[de]$) matches Connecticut, Kentucky, Maine, Maryland, Minnesota, Montana, Pennsylvania, Rhode Island, Tennessee, Vermont

    No match for these states so we take the first two letters Alabama, Arkansas, Delaware, Florida, Idaho, Illinois, Indiana, Michigan, Nebraska, Ohio, Oklahoma, Oregon, Utah, Washington, Wisconsin, Wyoming

    First time that I am use this Regex Subpatter ?| with allows to store the backreferences in one.

    Support the District of Columbia

    Replace (.) with ([^o]) +3 Bytes

    Try it online!

    PHP, 150 Bytes

    <?=($t=preg_replace("#.\K\w+ |las|ri|nec|eorgi|awa|ow|[aio]ni?|e(?=n|v|x)|ntuck|ouisi|a?in|arylan|issi?|nnsylv|erm|irg#","",$argn))[0],ucfirst($t[1]);
    

    Try it online! Testcases

    Jörg Hülsermann

    Posted 2017-05-26T05:32:57.937

    Reputation: 13 026

    3Isn't n|t| a byte shorter than [nt]|? – Neil – 2017-05-27T18:18:44.690

    @Neil Yes it is. I have not realize it. Thank You – Jörg Hülsermann – 2017-05-27T18:55:52.110

    7

    C, 945 937 718 711 660 616 bytes

    Saved 219 bytes thanks to ASCII-only.

    struct{int*a,b;}m[]={"laba",76,"lask",75,"rizo",90,"rkan",82,"alif",65,"olor",79,"onne",84,"elaw",69,"lori",76,"eorg",65,"awai",73,"daho",68,"llin",76,"ndia",78,"owa",65,"ansa",83,"entu",89,"ouis",65,"aine",69,"aryl",68,"assa",65,"ichi",73,"inne",78,"issi",83,"isso",79,"onta",84,"ebra",69,"evad",86,"ew H",72,"ew J",74,"ew M",77,"ew Y",89,"orth",67,"orth",68,"hio",72,"klah",75,"rego",82,"enns",65,"hode",73,"outh",67,"outh",68,"enne",78,"exas",88,"tah",84,"ermo",84,"irgi",65,"ashi",65,"est ",86,"isco",73,"yomi",89};
    i;char b[99];main(){gets(b);putchar(*b);for(;m[i].a;i++)if(!strncmp(m[i].a,b+1,4))puts(&m[i].b);}
    

    Newline unnecessary, only for display purposes. Takes the state as input. Try it online!

    How it works:

    • struct{int*a,b;}m[]=... declares a map m with two values - a four-byte string and one character. This is used in the comparison loop, which compares the second through fifth indexes with char*a in the map.
    • gets(b) reads a string b. This will be the state to abbreviate.
    • putchar(*b) prints the first character of that string, since each abbreviation starts with the first letter of the state.
    • for(;m[i].a;i++) loops through each value of the map. (This might be able to be shortened.)
    • if(!strncmp(m[i].a,b+1,4)) compares the current map value to the second through fifth characters of b (the state to abbreviate). This is because the only differences are in the first five characters, but we've already printed the first character.
    • puts(&m[i].b); prints the second letter of the abbreviation (if the state name matches with the current map value), and a newline.

    MD XF

    Posted 2017-05-26T05:32:57.937

    Reputation: 11 605

    This seems to produce wrong output for the North/South states. – Felix Dombek – 2017-05-26T15:43:30.883

    7

    PHP, 887 854 bytes

    <?=array_combine(['Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Delaware','Florida','Georgia','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas','Kentucky','Louisiana','Maine','Maryland','Massachusetts','Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','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'],['AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA','HI','ID','IL','IN','IA','KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','OH','OK','OR','PA','RI','SC','SD','TN','TX','UT','VT','VA','WA','WV','WI','WY'])[$argv[1]];
    

    Try it online!

    First timer, hooray!

    Ivanka Todorova

    Posted 2017-05-26T05:32:57.937

    Reputation: 171

    1

    This way a little golfed In the Array are the values with space or where the second letter is correct removed. And $argv[1] is replaced with $argn http://sandbox.onlinephpfunctions.com/code/cbc4cb03939742a6541dabc042ba2e0cb808356f

    – Jörg Hülsermann – 2017-05-26T20:20:24.507

    @JörgHülsermann thanks a lot! I really enjoy your answers here on codegolf in php! – Ivanka Todorova – 2017-05-26T20:22:41.137

    I am only a little light against other people here. The learning effort is good if someone finds an improvement. I hope that you answer more questions in the future – Jörg Hülsermann – 2017-05-26T20:31:21.567

    6

    C, 148 141 bytes

    main(){char s[99];gets(s);printf("%c%c\n",*s,s["-2-1--561-1-62--642138364---4142--1416--67-7131-111-7-246"[*(int*)(s+1)%663694%57]-48]&95);}
    

    *(int*)(s+1) considers the second through fifth character of the input to be an integer; that integer is then hashed into 0-56 using the hash i%663694%57. The hashed value is then looked up in a vector of offsets which represent the location of the second letter of the abbreviation. I chose those particular four bytes because (1) Missouri and Mississippi first differ in the fifth character and (2) some states have only four characters In C you can use the the NUL terminator byte, but nothing beyond that is reliable. (This hashes both Norths to the same value, as well as both Souths. But that doesn't matter because the associated offset is 6 for all of these.)

    As it happens, that particular hash yields the correct position for the second letters of the abbreviations of District of Columbia, Puerto Rico and "Virgin Islands" (typed that way, not as "US Virgin Islands", because the algorithm insists that the first character of the abbreviation be the first character of the name).

    The constants 663694 and 57 were found with an automated test; 57 was the smallest hash range I found. (The first version used 380085 and 63, but when I extended the test range I found the new one.) It seems that a slightly smaller hash exists if a code is added for "use the last character in the name"; unfortunately, C syntax for selecting the last character is too wordy to make that helpful.

    There are only 8 different offsets, so they could have been stored in a 171-bit (3*57) lookup table with three bits per entry. But I couldn't think of a way to insert those bits efficiently into the program. Hex-encoding would require about one character per four bits, plus the 0x prefixes. I couldn't do better than 151 bytes, which is much longer than the string version. If the 171 bits could somehow be inserted as raw octets, they would occupy 22 bytes, so there might be a solution, but reading a file is clunky.

    rici

    Posted 2017-05-26T05:32:57.937

    Reputation: 601

    4

    Actually, 181 bytes

    2"OHCALAGAMAWVFLNVILMNMOMIRINCDEMTMEINWANYTXORNEOKIDAZNMUTNDMDVAKYSDPAARWYNHIAMSALNJAKTNHIKSVTWICOSCCT"╪"âäà♠îÉæô↨→←∟♣áíå*,▓/12│┤94▼╛?DE╞G╚╠╬ST╒WXßb;Θoq╙|⌂"♂┘Z⌠i≈┐⌡MXO;rR5♀ⁿ*:236@%└
    

    This solution expects input as a quoted string.

    Try it online!

    Explanation

    This solution utilizes the same hashing strategy as my Python 3 solution. For brevity, I am going to omit the explanation of how the hash is computed and why it was chosen (go read the other answer if you want that bit).

    Also for brevity, I'm going to be leaving out the contents of the very long strings, since otherwise the explanation would be unreadable.

    2"..."╪"..."♂┘Z⌠i≈┐⌡MXO;rR5♀ⁿ*:236@%└
    2"..."╪                                state abbreviations (push the long string, split into length-2 chunks)
           "..."♂┘                         hash values for the state names (a string of CP437-encoded characters, converted to their CP437 ordinals)
                  Z                        zip the two lists
                   ⌠i≈┐⌡M                  for each pair:
                    i                        flatten the pair
                     ≈                       convert hash value to int
                      ┐                      store abbreviation at the register numbered by the hash value
                         X                 discard the now-empty list
                          O                convert input string to list of ASCII ordinals
                           ;rR             range(len(ordinal_list)), reversed
                              5♀ⁿ          5**i mapped over that range
                                 *         dot product of powers of 5 and ordinal list
                                  :236@%   mod by 236
                                        └  push value in that register
    

    Mego

    Posted 2017-05-26T05:32:57.937

    Reputation: 32 998

    3

    Python 3, 230 bytes

    lambda s:chr(s[0])+'IA%%L!NOI!M%!E.N!Y.XR.Z$D.I!.D$DA.D%!.HA!LJ%.N%‌​$T.I%!C!T!.HAAT$.A!.‌​VL.V%$CE%%AEK%.T$!.Y‌​.A!.R.Y$O.S%!.K$!.S'‌​.replace('%','$$').r‌​eplace('$','!!').rep‌​lace('!','..')[sum(c‌​*5**i for i,c in enumerate(s[::-1]))%236-5]
    

    Try it online!

    Input is expected as a bytes object (a byte string, rather than a Unicode string).

    Thanks to Johnathon Allan for an absurd amount of bytes

    Explanation

    Each state name is hashed to an integer a by applying the hash a = sum(o*5**i) % 236 (where o is a character's ASCII ordinal and i is its index in the string, counting back from the end). The modulus 236 was chosen because it is the smallest modulus that causes all hash values to be distinct for the 50 US state names. These hashes are then mapped to the state abbreviations, and the resulting dictionary (compressed using string substitution) is used to look up the abbreviation given a state name (hashing it to get the appropiate key).

    Mego

    Posted 2017-05-26T05:32:57.937

    Reputation: 32 998

    Save 179 bytes with lambda s:chr(s[0])+'.....IA................L..NOI..M..........E.N..Y.XR.Z....D.I...D....DA.D...........HA..LJ.........N............T.I..........C..T...HAAT.....A...VL.V............CE................AEK.........T.......Y.A...R.Y....O.S...........K.......S'[sum(c*5**i for i,c in enumerate(s[::-1]))%236] – Jonathan Allan – 2017-05-26T10:58:24.773

    ...and another 51 on top of that with lambda s:chr(s[0])+'IA%%L!NOI!M%!E.N!Y.XR.Z$D.I!.D$DA.D%!.HA!LJ%.N%$T.I%!C!T!.HAAT$.A!.VL.V%$CE%%AEK%.T$!.Y.A!.R.Y$O.S%!.K$!.S'.replace('%','$$').replace('$','!!').replace('!','..')[sum(c*5**i for i,c in enumerate(s[::-1]))%236-5] – Jonathan Allan – 2017-05-26T11:46:31.503

    I'm surprised that counting backwards costs fewer bytes than a hash function that counts forwards -- but I can't find one with a little playing – Chris H – 2017-05-26T15:41:12.400

    1@ChrisH I thought I found one, but the compressed string is more expensive. – Mego – 2017-05-26T16:14:49.367

    2

    ///, 619 608 bytes

    /2/~M//@/~South //1/~North //!/~New //~/\/\///Alabama/AL~Alaska/AK~Arizona/AZ~Arkansas/AR~California/CA~Connecticut/CT~Delaware/DE~Florida/FL~Georgia/GA~Hawaii/HI~Idaho/ID~Illinois/IL~Indiana/IN~Iowa/IA~Kansas/KS~Kentucky/KY~Louisiana/LA2aine/ME2aryland/MD2assachusetts/MA2ichigan/MI2innesota/MN2ississippi/MS2issouri/MO2ontana/MT~Nebraska/NE~Nevada/NV!Hampshire/NH!Jersey/NJ!Mexico/NM!York/NY1Carolina/NC1Dakota/ND~Ohio/OH~Oklahoma/OK~Oregon/OR~Pennsylvania/PA~Rhode Island/RI@Carolina/SC@Dakota/SD~Tennessee/TN~Texas/TX~Utah/UT~Vermont/VT~Virginia/VA~Washington/WA~West Virginia/WV~Wisconsin/WI~Wyoming/WY/
    

    Try it online!

    Since there is no other way of taking input in ///, it goes at the end of the program. Just append the desired input to the program.

    Saved 11 bytes by making more replacements, as recommended by @SteveBennett

    Comrade SparklePony

    Posted 2017-05-26T05:32:57.937

    Reputation: 5 784

    There's probably some patterns you can replace multiple times at once, like "New " and "akota". Annoying that you can't do much smarter like removing sections of state names, because converting the remaining character to uppercase is so expensive... – Steve Bennett – 2017-05-27T05:48:17.270

    @SteveBennett Edited, thanks! – Comrade SparklePony – 2017-05-27T12:13:58.203

    2

    Python 2, 131 125 bytes

    lambda s:s[0]+'CLLKARADEZVAK.T..DETTH.NSAHY...ID.D..O..Y.IRE.X..NALINC.VJM.SY.T..AAOI'[int(s[0]+s[-2:],36)%386%334%181%98%70]
    

    Try it online!

    ovs

    Posted 2017-05-26T05:32:57.937

    Reputation: 21 408

    2

    Ruby, 106 103 bytes

    ->s{s[0]+(s=~/ /?$'[0]:s[(j="()6>P_ac;?.O}AFLKMrS".index((s.sum%136%95+32).chr))?j>7?j/4:-1:1]).upcase}
    

    If the input contains a space, the second output letter is the one after the space. Else...

    Hash the sum of all characters in the input to obtain a character whose index in the magic string indicates the index of the second output letter in the input string, according to the formula j>8?j/4:-1 (-1 means the end.). If the hash gives a character that is not in the magic string, second letter is second letter of input.

    As an explanation of the magic string, the hash characters and the letter indexes they encode are below. Note that Delaware appears even though the second letter would do - this is because its hash code clashes with Kentucky. Fortunately the last letter of Delaware is the same as the second.

    Letter(index)
    Last  (-1)  (-MD    )-VA    6-GA-LA  >-DE-KY    P-PA    _-CT    a-KS    c-VT
    3rd    (2)  ;-TN    ?-MN    .-TX     O-NV
    4th    (3)  }-MS    A-IA    F-MT     L-AZ
    5th    (4)  K-MO    M-AK    r-ME     S-HI 
    

    Ungolfed in test program

    a="Alabama
    Alaska
    Arizona
    Arkansas
    California
    Colorado
    Connecticut
    Delaware
    Florida
    Georgia
    Hawaii
    Idaho
    Illinois
    Indiana
    Iowa
    Kansas
    Kentucky
    Louisiana
    Maine
    Maryland
    Massachusetts
    Michigan
    Minnesota
    Mississippi
    Missouri
    Montana
    Nebraska
    Nevada
    New Hampshire
    New Jersey
    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".split($/)
    
    f=->s{                                                            #String argument s.
      s[0]+(                                                          #Return character s[0] +
        s=~/ /?$'[0]:                                                 #if s contains a space, 1st character after space, ELSE
          s[(j="()6>P_ac;?.O}AFLKMrS".index((s.sum%136%95+32).chr))?  #if (sum of ascii codes, mod 136 mod 95 +32).chr in the magic string
            j>7?j/4:-1:                                                 #return s[j/4] if j>7 else return s[-1] ELSE
          1]                                                          #if not in the magic string, return s[1].
      ).upcase                                                        #Convert the second character to uppercase if needed.
    }
    
    
    a.map{|i|p [i,f[i]]}
    

    Level River St

    Posted 2017-05-26T05:32:57.937

    Reputation: 22 049

    1

    TAESGL, 386 bytes

    B=«ōďā,AL,ņćđ,AK,ķċđ,AZ,ćōē,AR,ďċđ,CA,ĭāď,CO,ŕĭ,CT,ćđēą,DE,ĕŕ,FL,īĭ,GA,ńāē,HI,ćĉďą,ID,ĭċď,IL,ľđā,ţ,ńĕĕ,IA,ķő,KS,ŏĝ,KY,ŏĕĕ,LA,ŏđć,ME,ņāē,MD,ńđā,MA,īđą,MI,ļēď,MN,ŕğ,MS,ňė,MO,ććĕĉ,MT,ćċćĉ,NE,ŕēď,NV,ň ćŋā,NH,ň ĩēđ,NJ,ň ğĕċ,NM,ň ĉĝ,NY,ćņ ġĉă,NC,ćņ ńċą,ND,ĩēą,OH,ŋĺ,OK,ļķ,OR,ĺđď,PA,ĉĉğ đēā,RI,ōċ ġĉă,SC,ōċ ńċą,SD,ňďą,TN,ċĕď,TX,ōđą,UT,ćđāā,VT,ğğ,VA,ďĉē,WA,ĉĉć ğğ,WV,ľēđ,WI,ĉĩĕ,WY»Ĵ",";B[BĪA)+1
    

    Interpreter

    Very simple compression of the state names, added into an array with the abbreviations.

    Tom

    Posted 2017-05-26T05:32:57.937

    Reputation: 3 078

    1

    Japt, 383 bytes

    The compression of the first string may be improvable by experimenting with the order of the letters.

    g +`lkzÇUaidlnyaÀÍ¥evhjmycdhkÎödnxttaaviy`g`alabaµ
    Ã2ka
    iza
    kÂ6s
    Öâfnia
    åªv
    ¬nש
    Ü.Ø
    fÓQ»
    gegia
    °ii
    i»
    ÅJno
    Äa
    Å0
    kÂ6s
    kÀ_cky
    lia
    Úpe
    æ¯À
    ÚUaÖ³etts
    Úòig
    ·nÌta
    æ«7ppi
    æ¬
    Úa
    ßka
    va»
    w mp¢i
    w jÀ y
    w ´xi¬
    w yk
    Íh ÖÚ¦na
    Íh »kota
    oo
    oklaÊá
    eg
    pnsylvia
    r¸ Ó
    Ñh ÖÚ¦na
    Ñh »kota
    âÊte
    x
    ©ah
    vÚ
    virgia
    Øgn
    ØÙ virgia
    æÈ;n
    wyÇg`·bUv) u
    

    Try it online

    Shaggy

    Posted 2017-05-26T05:32:57.937

    Reputation: 24 623

    1

    Mathematica, 138 140 134 Bytes

    +2 bytes - found a mistake (needed array offset of 1 not 0)

    -6 bytes - found a better hash

    #~StringTake~1<>"R_ATE__IN_COI_J_I_SLNAT_Y_Y_HKOAE__SAA_DDLM_RVAH_XDTVA__I_N_EA_T_DY_C_KZL"~StringTake~{1+Hash@#~Mod~89866736~Mod~73}&

    Similar to others it takes the name and takes the first letter. Then it applies the default Mathematica hash then applies two modulus to it "Hash@#~Mod~89866736~Mod~73" to get a unique number for each state. This value is then looked up in a string to generate the second letter.

    Can probably be golfed more but the search space is huge for Mathematica to find. Duplicated second letters weren't considered in the hash search. _ characters represent wasted values in the string. In theory you could get the string down to only 19 characters but finding the custom hash to produce that would be a nightmare.

    Ian Miller

    Posted 2017-05-26T05:32:57.937

    Reputation: 727

    1

    Perl 5, 150 148 bytes (147 + 1)

    This is by no means optimal, but it does its job. Needs -n command line flag.

    s/las//;s/ai?n//;s/[oie]n|ri//;s/e([vx])/$1/;s/issi?//;s/(.).+ /\1/;/(.)(.)/;/^([^W]).*(?:[cogavn][wiku]|[ir][ys][li]|rm)([adyti])$/;print uc"$1$2"
    

    Silvio Mayolo

    Posted 2017-05-26T05:32:57.937

    Reputation: 1 817

    0

    Python 2, 152 bytes

    lambda s:s[0]+'.NY.SDS...O.DT..RT.AAYJZE.K.I.X.TI.EL.CMI..E.NA..L....TH.......O....DAAC..VNH.YAI.RVDA..L....A'[int(s.replace(' ','')[1:],36)%358%235%95]
    

    Try it online!

    A port of Arnauld's answer.

    ASCII-only

    Posted 2017-05-26T05:32:57.937

    Reputation: 4 687