I've been developing some programs involving me fetching a vector from a url using Alpha-2 country codes (such as GET /jp.svg for Japan). Except, oh no! All the country data on my computer uses Alpha-3! That just won't do...

The task is simple: Take an Alpha-3 country code (e.g. UKR) and return its Alpha-2 equivalent (e.g. UA). And because my hard drive is smaller than the Vatican (and because this is ), the program must be as small as possible.

Codes can be found here
and below.

[["AFG", "AF"],["ALA", "AX"],["ALB", "AL"],["DZA", "DZ"],["ASM", "AS"],["AND", "AD"],["AGO", "AO"],["AIA", "AI"],["ATA", "AQ"],["ATG", "AG"],["ARG", "AR"],["ARM", "AM"],["ABW", "AW"],["AUS", "AU"],["AUT", "AT"],["AZE", "AZ"],["BHS", "BS"],["BHR", "BH"],["BGD", "BD"],["BRB", "BB"],["BLR", "BY"],["BEL", "BE"],["BLZ", "BZ"],["BEN", "BJ"],["BMU", "BM"],["BTN", "BT"],["BOL", "BO"],["BIH", "BA"],["BWA", "BW"],["BVT", "BV"],["BRA", "BR"],["VGB", "VG"],["IOT", "IO"],["BRN", "BN"],["BGR", "BG"],["BFA", "BF"],["BDI", "BI"],["KHM", "KH"],["CMR", "CM"],["CAN", "CA"],["CPV", "CV"],["CYM", "KY"],["CAF", "CF"],["TCD", "TD"],["CHL", "CL"],["CHN", "CN"],["HKG", "HK"],["MAC", "MO"],["CXR", "CX"],["CCK", "CC"],["COL", "CO"],["COM", "KM"],["COG", "CG"],["COD", "CD"],["COK", "CK"],["CRI", "CR"],["CIV", "CI"],["HRV", "HR"],["CUB", "CU"],["CYP", "CY"],["CZE", "CZ"],["DNK", "DK"],["DJI", "DJ"],["DMA", "DM"],["DOM", "DO"],["ECU", "EC"],["EGY", "EG"],["SLV", "SV"],["GNQ", "GQ"],["ERI", "ER"],["EST", "EE"],["ETH", "ET"],["FLK", "FK"],["FRO", "FO"],["FJI", "FJ"],["FIN", "FI"],["FRA", "FR"],["GUF", "GF"],["PYF", "PF"],["ATF", "TF"],["GAB", "GA"],["GMB", "GM"],["GEO", "GE"],["DEU", "DE"],["GHA", "GH"],["GIB", "GI"],["GRC", "GR"],["GRL", "GL"],["GRD", "GD"],["GLP", "GP"],["GUM", "GU"],["GTM", "GT"],["GGY", "GG"],["GIN", "GN"],["GNB", "GW"],["GUY", "GY"],["HTI", "HT"],["HMD", "HM"],["VAT", "VA"],["HND", "HN"],["HUN", "HU"],["ISL", "IS"],["IND", "IN"],["IDN", "ID"],["IRN", "IR"],["IRQ", "IQ"],["IRL", "IE"],["IMN", "IM"],["ISR", "IL"],["ITA", "IT"],["JAM", "JM"],["JPN", "JP"],["JEY", "JE"],["JOR", "JO"],["KAZ", "KZ"],["KEN", "KE"],["KIR", "KI"],["PRK", "KP"],["KOR", "KR"],["KWT", "KW"],["KGZ", "KG"],["LAO", "LA"],["LVA", "LV"],["LBN", "LB"],["LSO", "LS"],["LBR", "LR"],["LBY", "LY"],["LIE", "LI"],["LTU", "LT"],["LUX", "LU"],["MKD", "MK"],["MDG", "MG"],["MWI", "MW"],["MYS", "MY"],["MDV", "MV"],["MLI", "ML"],["MLT", "MT"],["MHL", "MH"],["MTQ", "MQ"],["MRT", "MR"],["MUS", "MU"],["MYT", "YT"],["MEX", "MX"],["FSM", "FM"],["MDA", "MD"],["MCO", "MC"],["MNG", "MN"],["MNE", "ME"],["MSR", "MS"],["MAR", "MA"],["MOZ", "MZ"],["MMR", "MM"],["NAM", "NA"],["NRU", "NR"],["NPL", "NP"],["NLD", "NL"],["ANT", "AN"],["NCL", "NC"],["NZL", "NZ"],["NIC", "NI"],["NER", "NE"],["NGA", "NG"],["NIU", "NU"],["NFK", "NF"],["MNP", "MP"],["NOR", "NO"],["OMN", "OM"],["PAK", "PK"],["PLW", "PW"],["PSE", "PS"],["PAN", "PA"],["PNG", "PG"],["PRY", "PY"],["PER", "PE"],["PHL", "PH"],["PCN", "PN"],["POL", "PL"],["PRT", "PT"],["PRI", "PR"],["QAT", "QA"],["REU", "RE"],["ROU", "RO"],["RUS", "RU"],["RWA", "RW"],["BLM", "BL"],["SHN", "SH"],["KNA", "KN"],["LCA", "LC"],["MAF", "MF"],["SPM", "PM"],["VCT", "VC"],["WSM", "WS"],["SMR", "SM"],["STP", "ST"],["SAU", "SA"],["SEN", "SN"],["SRB", "RS"],["SYC", "SC"],["SLE", "SL"],["SGP", "SG"],["SVK", "SK"],["SVN", "SI"],["SLB", "SB"],["SOM", "SO"],["ZAF", "ZA"],["SGS", "GS"],["SSD", "SS"],["ESP", "ES"],["LKA", "LK"],["SDN", "SD"],["SUR", "SR"],["SJM", "SJ"],["SWZ", "SZ"],["SWE", "SE"],["CHE", "CH"],["SYR", "SY"],["TWN", "TW"],["TJK", "TJ"],["TZA", "TZ"],["THA", "TH"],["TLS", "TL"],["TGO", "TG"],["TKL", "TK"],["TON", "TO"],["TTO", "TT"],["TUN", "TN"],["TUR", "TR"],["TKM", "TM"],["TCA", "TC"],["TUV", "TV"],["UGA", "UG"],["UKR", "UA"],["ARE", "AE"],["GBR", "GB"],["USA", "US"],["UMI", "UM"],["URY", "UY"],["UZB", "UZ"],["VUT", "VU"],["VEN", "VE"],["VNM", "VN"],["VIR", "VI"],["WLF", "WF"],["ESH", "EH"],["YEM", "YE"],["ZMB", "ZM"],["ZWE", "ZW"]]


  • Your answer must work with all countries and territories
  • You may not fetch any data from the internet.
  • Standard loopholes apply.
  • This is , so the shortest code in bytes in each language wins.
Input/Output may be a string, list of characters, or list of character codes. Text case does not matter

Test Cases


USA -> US     # United States
AUS -> AU     # Australia
BIH -> BA     # Bosnia and Herzegovina
ISL -> IS     # Iceland
FSM -> FM     # Micronesia
SYC -> SC     # Seychelles


UMI -> UM     # US Minor Outlying Islands
SPM -> PM     # Saint Pierre and Miquelon
GUF -> GF     # French Guiana
ATF -> TF     # French Southern Territories
HKG -> HK     # Hong Kong
IOT -> IO     # British Indian Ocean Territory
  • 4
    \$\begingroup\$ Wish I could compare the size of my hard drive to the size of a country! :P \$\endgroup\$
    – Noodle9
    Commented May 2, 2022 at 9:32
  • \$\begingroup\$ Is fetching data from the Mathematica builtin libraries permitted? \$\endgroup\$
    – Romanp
    Commented May 2, 2022 at 15:23
  • \$\begingroup\$ Builtins, yes! I kind of figured Mathematica had a builtin for it, haha \$\endgroup\$
    – Komali
    Commented May 2, 2022 at 15:34
  • \$\begingroup\$ What a coincidence, my hard drive is also smaller than the Vatican. @Noodle9 \$\endgroup\$ Commented May 3, 2022 at 15:33
  • 7
    \$\begingroup\$ @Noodle9: (2.7in ⋅ 3.96in) / ( 44 ha ) ~ 1,57E-8. So one 2.5'' HDD has an area of approximately 16 nanovatican. \$\endgroup\$ Commented May 4, 2022 at 13:11

8 Answers 8


JavaScript (Node.js), 253 bytes

Saved 1 byte thanks to @MatthewJensen

Expects a string in upper case. Returns an array of 2 characters.


Try it online!

Or 250 bytes with unprintable characters:

Try it online!



We categorize the Alpha-2 codes into 4 groups:

  1. Codes made of the first two letters of the Alpha-3 code, e.g. AFGAF (156 entries).
  2. Codes made of the 1st and last letters of the Alpha-3 code, e.g. ATGAG (71 entries).
  3. Other codes whose 1st letter is the 1st letter of the Alpha-3 code, e.g. UKRUA (12 entries).
  4. Codes whose 1st letter is not the 1st letter of the Alpha-3 code, e.g. CYMKY (8 entries).

Initial lookup

We first test whether the input belongs to either group 3 or group 4 by looking for its position i into the following lookup string (without the spaces), divided by 3:

\_____________________________/ \_____________________________________________/
            group 4                                 group 3

First letter

For the first letter, we attempt to get:

"TKKYKGPR"[i] // lookup string for group 4

If this is undefined, we use the first letter of the input.

Second letter

For the second letter, we attempt to get:

"FMYTPSMSXQYJAOEWELIA"[i] // lookup string for groups 4 and 3

If this is undefined, we need to figure out whether we should use the 2nd or 3rd letter of the input.

We apply the following hash function to the input string:

q = parseInt(s, 36) * 5 % 1601

and test whether we can reach exactly \$0\$ by subtracting the ASCII codes minus \$32\$ of the corresponding data string from q:


This is encoding the entries that belong to group 2.

For instance, parseInt("JAM", 36) is \$25006\$, which leads to:

$$q=(25006\times 5)\bmod 1601=125030\bmod 1601=152$$

Using the first four characters Z&:^ of the data string, we find out that this is the sum of:


which means that "JAM" belongs to group 2 and the correct answer is "JM".

  • \$\begingroup\$ You can save a byte by removing c \$\endgroup\$ Commented May 2, 2022 at 20:25
  • \$\begingroup\$ @MatthewJensen RIght. It's not re-used anymore. Thanks! \$\endgroup\$
    – Arnauld
    Commented May 2, 2022 at 20:32

05AB1E, 238 219 bytes

¨I2ιн.•LS’αPñΔ•.•„Rà´θ≠…āñ©B—‚Ls¿ºÄ¿α>°%»^cýαƒ¸AbŒΓÝ€I†„{rʒKÓÎƶÿ}ιUƶ–ΔΓ5`Δ9Λº½P.÷ü)–\ÎÇÕ¡â"‚0’₁Ýá+_.n¯₅Èg«J¡þ&м£ñ:‡‘÷&´”тε?ʒ^÷δ“ ¥ΔàHÌAiìb0SĀ'WDî>ηOāß7|^î‘€'òê®ćM2¤γù£Œ∞Néä_}àŒ@‹Ó•3ôIlk₄%©èIнì.•TŠ+º°•2ô®èI¦)®•rá÷•₃в‹Oèu

Try it online or verify all test cases.


There are five possible groups:

  1. Those for which the first character is removed
  2. Those for which the middle character is removed
  3. Those for which the last character is removed
  4. Those for which the last two characters are replaced with a different character, but the first character remains unchanged
  5. Those for which all three characters are replaced with two different characters

My program does three steps:

1. Generate the five possible results above (in the order 1,2,4,5,3), and put them in a list:

¨            # (1) Remove the last character from the (implicit) input-string
I            # (2) Push the input-string again
 2ι          # Uninterleave it into two parts: "abc" → ["ac","b"]
   н         # Only leave the first part
.•LS’αPñΔ•   # (4) Push compressed string "aaeeijloqwxy"
  ...        # See step 2 below
     è       # Modular 0-based index the result of step 2 into this string
      Iн     # Push the first character of the input-string
        ì    # Prepend it in front of the indexed character
.•TŠ+º°•     # (5) Push compressed string "kykmkprs"
        2ô   # Split it into parts of size 2: ["ky","km","kp","rs"] 
          ®  # Push the index of step 2 again
           è # Modular 0-based index it into this list
I            # (3) Push the input-string again
 ¦           # Remove its first character
)            # Wrap all five results on the stack into a list

Try just step 1 online.

2. Check in which group the input belongs:

.•„Rà´θ≠…āñ©B—‚Ls¿ºÄ¿α>°%»^cýαƒ¸AbŒΓÝ€I†„{rʒKÓÎƶÿ}ιUƶ–ΔΓ5`Δ9Λº½P.÷ü)–\ÎÇÕ¡â"‚0’₁Ýá+_.n¯₅Èg«J¡þ&м£ñ:‡‘÷&´”тε?ʒ^÷δ“ ¥ΔàHÌAiìb0SĀ'WDî>ηOāß7|^î‘€'òê®ćM2¤γù£Œ∞Néä_}àŒ@‹Ó•
            "# Push compressed string "atfmytspmsgscymcomprksrbatagnbalablrbihukrestirlsvnbenisrmacabwagoandarearmatgautbdibgdbhsblzbrbbrncafchlchncodcogcokcpvdnkeshflkfrofsmginglpgnqgrdgrlgufguyirqjamkazkorlbrlbymafmdgmdvmexmltmnemnpmozmtqniupakpcnplwpngpolprtprypyfsenslbslvsursvksweswzsyctcdtkmtunturtuvurywlf"
  3ô         # Split it into parts of size 3: ["atf","myt",...,"wlf","esh"]
    I        # Push the input-string
     l       # Convert it to lowercase
      k      # Get its index in this list (or -1 if not found)
       ₄%    # Modulo-1000 to convert the -1 to 999
         ©   # Store it in variable `®` (without popping)

Try just step 2 online.

3. Use that to index into the quintuplet of possible results:

®            # Push the index of step 2 again
 •rá÷•       # Push compressed integer 3503691
      ₃в     # Convert it to base-95 as list: [4,8,20,91]
        ‹    # Check for each if its larger than the index
         O   # Sum to get the amount of truthy values
          è  # Use that to index into the result-quintuplet of step 1
           u # Uppercase it for the potential lowercase characters
             # (after which the result is output implicitly)

Try just (the first portion of) step 3 online.

See this 05AB1E tip of mine (sections How to compress strings not part of the dictionary?, How to compress large integers?, and How to compress integer lists?) to understand why .•LS’αPñΔ• is "aaeeijloqwxy"; .•TŠ+º°• is "kykmkprs"; .•„Rà´θ≠…āñ©B—‚Ls¿ºÄ¿α>°%»^cýαƒ¸AbŒΓÝ€I†„{rʒKÓÎƶÿ}ιUƶ–ΔΓ5`Δ9Λº½P.÷ü)–\ÎÇÕ¡â"‚0’₁Ýá+_.n¯₅Èg«J¡þ&м£ñ:‡‘÷&´”тε?ʒ^÷δ“ ¥ΔàHÌAiìb0SĀ'WDî>ηOāß7|^î‘€'òê®ćM2¤γù£Œ∞Néä_}àŒ@‹Ó• is "atfmytspmsgscymcomprksrbatagnbalablrbihukrestirlsvnbenisrmacabwagoandarearmatgautbdibgdbhsblzbrbbrncafchlchncodcogcokcpvdnkeshflkfrofsmginglpgnqgrdgrlgufguyirqjamkazkorlbrlbymafmdgmdvmexmltmnemnpmozmtqniupakpcnplwpngpolprtprypyfsenslbslvsursvksweswzsyctcdtkmtunturtuvurywlf"; •rá÷• is 3503691; and •rá÷•₃в is [4,8,20,91].


Wolfram Language (Mathematica), 115 bytes (uses builtin libraries)

Turns out there's a builtin for everything! There was a restriction against using internet connectivity, so I'm not sure if the builtin data is allowed, but if so, it's the shortest.


This code doesn't work right on TIO due to using Mathematica's libraries. Also takes quite a while to run, but it does work for every test case, although I did have to hardcode in the three cases seen in the If statement.

(Don't) try it online!

Here's a cloud notebook with the code: https://www.wolframcloud.com/obj/romanp/Published/CountryCodeConvert

It should eventually return the correct values, but if it doesn't, you can copy the code and test it either in the cloud on a smaller test case or in a personal installation.


Charcoal, 241 bytes


Try it online! Link is to verbose version of code. Explanation (with compressed lookup tables redacted to ⪪”...”³):


If the country is one of CYM, COM, PRK or SRB, then output KY, KM, KP or RS respectively, otherwise:


If the country is one of ATF, MYT, SPM or SGS, then output the second and third letters, otherwise:


Output the first letter.


If the country is one of ALA, ATA, BLR, BEN, BIH, MAC, EST, GNB, IRL, ISR, SVN or UKR, then output the respective letter from XQYJAOEWELIA, otherwise:


Output either the second or third letter of the input appropriately.


R + countrycode, 76 74 bytes (using library)

Edit: -2 bytes thanks to pajonk


Try it at rdrr.io

Seemingly the R 'countrycode' library is more comprehensive than Mathematica's "CountryCode" builtin, although still not perfect and requiring "ANT" to be hard-coded.

  • 2
    \$\begingroup\$ "if" should do instead of ifelse (but you'll need to Vectorize or sapply in the test suite) \$\endgroup\$
    – pajonk
    Commented May 3, 2022 at 15:44
  • \$\begingroup\$ @pajonk - Yes, you're right, and the test output is much nicer like that (and no warning): thanks a lot! \$\endgroup\$ Commented May 3, 2022 at 15:50
  • \$\begingroup\$ Impressive! "iso3c"/"iso2c" are also significantly shorter than "UNCode"/"CountryCode", which shaves a few. \$\endgroup\$
    – Romanp
    Commented May 3, 2022 at 17:14
  • \$\begingroup\$ About half the resources I've found classify the Dutch Antilles (AN/ANT) as their respective territories (CW/CUW for Curaçao and BQ/BES for all the others), which is why that has to be hardcoded in. Nice answer! \$\endgroup\$
    – Komali
    Commented May 4, 2022 at 13:11

Perl 5 -MLocale::Country -pl, 48 bytes


Try it online!

The ANT->AN mapping isn't in Perl's list, so it's hardcoded.

  • \$\begingroup\$ Makes sense to use the builtins! You can save a few bytes using a glob too (removed examples to fit link in comment): Try it online! \$\endgroup\$ Commented May 19, 2022 at 13:59
  • 1
    \$\begingroup\$ @DomHastings That's slick. I never thought about using a glob that way. \$\endgroup\$
    – Xcali
    Commented May 20, 2022 at 2:36

Whython, 370 bytes


Attempt This Online!



Vyxal, 217 bytes


Try it Online! or Run all the test cases or Try it on every country code

Port of 05AB1E.


                # ^ full program
Ṫ               # Remove the last character of the (implicit) input
 ⁰              # Push the input again
  y             # Uninterleave, push a[::2] and a[1::2] to the stack
   _            # Pop so a[1::2] is removed. Stack: a[:-1], a[::2]
    «⌐ƈḣAɾǑP«   # Push compressed string "aaeeijloqwxy"
                # Push compressed string "atfmytspmsgscymcomprksrbatagnbalablrbihukrestirlsvnbenisrmacabwagoandarearmatgautbdibgdbhsblzbrbbrncafchlchncodcogcokcpvdnkeshflkfrofsmginglpgnqgrdgrlgufguyirqjamkazkorlbrlbymafmdgmdvmexmltmnemnpmozmtqniupakpcnplwpngpolprtprypyfsenslbslvsursvksweswzsyctcdtkmtunturtuvurywlf"
3ẇ              # Split into chunks of 3: ["atf", "myt", "spm", ..., "ury", "wlf"]
  ⁰ɽ            # Push the input and lowercase it
    ḟ           # Find its index in the list (-1 if not found)
     k1%        # Modulo 1000 to convert -1 to 999
        :£      # Store in the register without popping
          i     # Index this into the string pushed earlier ("aaeeijloqwxy")
           ⁰h   # Push the first character of the input
             p  # Prepend it
«∞τjḊ§«         # Push compressed string "kykmkprs"
       2ẇ       # Split into chunks of two
         ¥      # Push the contents of the register
          i     # Index this into the list
           ⁰Ḣ   # Push the input without the first character
W               # Wrap these five values on the stack into a list
 ¥              # Push the contents of the register
  »?Ṫ4»         # Push compressed integer 4082091
       ₁τ       # Convert to base 100 list: [4, 8, 20, 91]
         <      # For each item, is the register (pushed earlier) less than it?
          ∑     # Sum this to get the amount of integers that the register is less than
           i    # Index this into the list pushed earlier
            ⇧   # Uppercase

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.