5
\$\begingroup\$

Italian zipcodes are 5-digit numbers. Each number is linked to a province. There are 4610 zipcodes and 110 provinces (as of 2015) in Italy.

Given the list of zipcodes and the related province (in this file - Gist here) write a function (any language would be fine) that, accepting in input an Italian zipcode, writes out the related province. For unknown zipcodes (for example '99999'), the result should be "XX" ('unknown zipcode').

This is , so the function with the shortest amount of bytes wins.

Rules: you can't use Internet resources, files (including the list of zipcodes-provinces of before, even if you can include the list, but then that would count as chars in your source file), built-ins or libraries/modules that provide a mapping from zipcodes to provinces or any other external entity in your function.

Some test cases:

f("00185")="RM"

f("00014")="XX"

f("86071")="IS"

f("20020")="MI"

f("08010") can be "OR" or "NU" (they share the same zipcode)

Happy coding!

\$\endgroup\$
3
  • \$\begingroup\$ @mınxomaτ: done. \$\endgroup\$
    – friol
    Commented Dec 6, 2015 at 17:50
  • \$\begingroup\$ @mınxomaτ: I don't know if chars=1 byte in every programming language. \$\endgroup\$
    – friol
    Commented Dec 6, 2015 at 18:41
  • \$\begingroup\$ @mınxomaτ: ok, changed to "shortest amount of bytes". \$\endgroup\$
    – friol
    Commented Dec 6, 2015 at 18:54

5 Answers 5

3
\$\begingroup\$

Mathematica, 2973 bytes

Uncompress@"1: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"~StringTake~{a=2FromDigits@#,a+1}&

Looking for a better way to compress this... Currently, it just uncompresses to this long string, and looks up the ZIP code in it.

\$\endgroup\$
4
  • \$\begingroup\$ This does not uncompress for me on Mathematica 10.2.0 \$\endgroup\$
    – DavidC
    Commented Dec 5, 2015 at 20:06
  • \$\begingroup\$ @DavidCarraher Are you sure? It works on 10.1.0... \$\endgroup\$ Commented Dec 5, 2015 at 22:53
  • \$\begingroup\$ It returns this StringTake[ Uncompress[ "1:eJzt3U3O47gRgOEAWecQc5OR1f4cI7alkd1Go5e5QO6/\ y7ALBVIUJdMSRUru9ynoh8UiWfKmMX+YP/77v+7+57/\ ++Y8fQ91VwrzZUZrw93PHgVYSC3cUypfLAQCQxvNhQp9jYeaHNeV6LnUyAADb1J3d8Mea6\ +dDVXYuR885TgEAYD++Og33fX7k6TnHKQAA7MflERel+3RtqxsAAMp7dH74OXcs77qyXM+\ lTgYAYJvak3+Nh50N12nWnR1W9qtC3disPz+\ VDVeGT39nDwAAtu8e0DxC4dfI098hT885TgEAYD9u3000nb6Zd31zo67k3nTmrTn9qvz7r\ 3Gb09+5k408Pec4BQCA/air+vzr0qhMPO/Puzz7l85JyFji106/nnGa7lWYmnBd/\ Cluh7ZPmZnza4W+I80+AAAsEfxb642bj3nX8dh+MRFa28/Zfud/3bzcer8/A"... \$\endgroup\$
    – DavidC
    Commented Dec 6, 2015 at 1:17
  • \$\begingroup\$ @DavidCarraher Perhaps Compress functionality changed in 10.2? \$\endgroup\$ Commented Dec 6, 2015 at 2:13
3
\$\begingroup\$

MATLAB, 3987 2827 2813

Not sure it is worth posting this given the enormity of it, but anyway:

b=java.io.ByteArrayOutputStream;org.apache.commons.io.IOUtils.copy(java.util.zip.InflaterInputStream(java.io.ByteArrayInputStream(typecast(org.apache.commons.codec.binary.Base64.decodeBase64(uint8('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')),'uint8'))),b);s=char(b.toByteArray)';
i=input('');h=@hex2dec;r=@reshape;t=cellfun(@(x){x(1:2),h(x(3:6)),h(r(x(7:end),2,[])')},strsplit(strtrim(regexprep(s,'([A-Z]{2,})',' $1'))),'Un',0);z='XX';for l=t
a=l{1};g=a{3};for g=r(a{3},2,[])
s=a{2}*10+g(1);e=s+g(2);if any(s:e==i);z=a{1};end
end
end;disp(z)

Yeah. Not really code golf material. Although much better now


After a bit of messing around, I managed to get MATLAB to directly access the Java Virtual Machine to be able to decompress a base64 encoded zip representation of the original data, which quite literally knocks 25% of the size of the code. I am being quite naughty here in that I don't block closing the InputStream and OutputStream during decompression, but who cares, it doesn't crash!.


After decompression, the zip codes are encoded in a format which is:

CCbbbboollooll...

Where CC is the two letter zip code. bbbb is a base (starting point) for this zip code which was divide by 10 and converted to hex so that only 4 characters are needed. For each base there is one or more ooll entries which is two hex numbers where oo is the offset from the base, and ll is the number of codes in the range minus 1.

All of the hex numbers are lower case, and all of the zip codes are upper case. This allows each entry to be separated based on whenever a two upper case letters appear (because the are only present as the first two letters in an entry).

Once each entry is split up, the hex numbers are parsed and converted into decimal, and we basically work through every entry to find a match.

The ranges for a given ooll pair are calculated as:

start = 10*dec(bbbb) + dec(oo)
end = start + dec(ll)

A new entry (CCbbbb) occurs at each point that the a new zip code appears. Some of the codes appear at more than one base address as there are some which are not all grouped together. Allowing multiple entries costs some bytes of CCbbbb headers, but it means that all of the lengths and ranges need only be 2 characters which saves quite a few.


Matlab is not good at encoding in different bases, so of the ideas I had for how to encode the data, this is the best I could think of. It turns out, that I can actually save quite a lot of bytes by resorting to directly accessing the Java Virtual Machine that Matlab is running to perform base64 decoding, followed by zip decompression. The input string was made by doing the reverse (compress then encode).

\$\endgroup\$
5
  • \$\begingroup\$ Hasn't Matlab got a "compression" function (like Python's zlib.compress)? \$\endgroup\$
    – friol
    Commented Dec 6, 2015 at 17:54
  • \$\begingroup\$ @friol nope - it can (de)compress a file, but not raw data. It may be possible to go really low level if the JVM has a compression function and call that directly. \$\endgroup\$ Commented Dec 6, 2015 at 17:56
  • \$\begingroup\$ Your solution transposed to Python (with zlib.compress) is around 2.500 bytes. You should try it :) \$\endgroup\$
    – friol
    Commented Dec 6, 2015 at 18:29
  • \$\begingroup\$ @friol managed to get it to work after a bit of messing, knocked over 1000 bytes off the code! \$\endgroup\$ Commented Dec 6, 2015 at 18:39
  • \$\begingroup\$ Still my solution in Python using your approach is 2644 bytes. \$\endgroup\$
    – friol
    Commented Dec 6, 2015 at 18:53
1
\$\begingroup\$

Python2.7 2645 2573

def X(n):
    import zlib,base64
    a=(ord(zlib.decompress(base64.b64decode("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"))[n])-48)*2
    return 'XXRMVTRIFRLTTRPGSSOTORNUCAOGCIVSTOAOCNSVVCBIATALGEIMSPMIMBVACOSOLCBGBSCRLOPVNOVBPCVETVBLUDPNTSGOPDVIVRTNBZBOMOREPRFEROMNFCRNRAFIPTARSIMSLUPILIGRPOANPUMCAPFMTEPECHAQBAFGBRLETAMTBTNACEBNAVSAPZCBISCSCZKRRCVVPATPAGCLENCTSRRGME'[a:a+2]

Each zip has it's own character, use that as indice to grab code.

Compressing the lookup didn't work well, slight decrease in hash length, but penalty in decoding. Instead adapted to take in strings and inlined. Slight improvement. A lot uglier. Mmm

2572

import zlib,base64;a=(ord(zlib.decompress(base64.b64decode("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"))[int(raw_input())]))*2;print("XXRMVTRIFRLTTRPGSSOTORNUCAOGCIVSTOAOCNSVVCBIATALGEIMSPMIMBVACOSOLCBGBSCRLOPVNOVBPCVETVBLUDPNTSGOPDVIVRTNBZBOMOREPRFEROMNFCRNRAFIPTARSIMSLUPILIGRPOANPUMCAPFMTEPECHAQBAFGBRLETAMTBTNACEBNAVSAPZCBISCSCZKRRCVVPATPAGCLENCTSRRGME"[a:a+2])

Some thoughts

Further optimization could include finding better arrangement of characters for compression. Limiting factor here is getting the data down.

This approach works fairly well since, since using only indices has inherently less entropy than trying to encode the entire zip. Given such long streaks of characters, the entire thing compresses pretty well. I initially tried compressing only the numbers of interest (so that I could implement a binary search) but ended up using more bytes than just the ordinal string I'm using here. There might be a smarter means of storing, but it's hard to beat the built-in compression.

I considered using a statistical approach, but it would be at best heuristic. A true functional representation would probably require just as many bytes if not more.

\$\endgroup\$
3
  • \$\begingroup\$ Works only with Python 2.7 for me (not 3). \$\endgroup\$
    – friol
    Commented Dec 7, 2015 at 18:01
  • \$\begingroup\$ Woops. Should probably specify that \$\endgroup\$ Commented Dec 7, 2015 at 18:02
  • \$\begingroup\$ Yeah the zlib encoding goes screwy in 3 \$\endgroup\$ Commented Dec 7, 2015 at 18:03
0
\$\begingroup\$

Long "demo" answer in Python, 3755 chars

def f(c):
    import zlib
    import base64
    s=zlib.decompress(base64.b64decode('eJxN2VtyIzkOBdAtJQnw9SmpXR7H2JZGUumj97+QIe4FCXV0V5xGMZlMvkmdPk/fp9/T9XQ7/e90Pz1Pr/Pp/Hn+On+ff8/X8/38OD/P/15Ol/Pl4/Kfy9fl+/J7uV7ul8flefn34/fP5c/Hn88/X39+/tw/Pz6vn/evn6/Hf+/fl++P76/v6/fz++/P+efy8/Hz9fP7c/15/Dx/T7/X37/Xz+v9+rydbpfbP7eP2+ft6/Z7u97ut+ft7+11+/d+ul/uH/eZ4f3n/nu/Pk6Pr8f1cXvcH4/H63l6fjx/nzOD5/35eL7+/vOaRX9dXh+vr9f9NRO8XkfPx3Gk+Z84y/zD2Q7pZGnHUck6EyiY0jiOQcrMgmmTBkuwBluwB4cxzf9LKE52KjI0yoGSgvOBBlrSAw9mPFadHfkac98JLIfibEfKoOcwA4Ic1FkPEdATaJ9/laygoEdHmzmaO4kacnbLDBS1kpNjPeY51D4fSG/MQQ3W4PxsIWcJj8VubQHqfEUmi1gZyBlt5PxjJWhW9WRP+xVdIjpW9K28KaPdQKuf5ER58Z4EVJnMIKLWAI1R6TutoLygCqoPrcu3ZTQ4eHiDJ49KRAvqAVGWd/ZmvNgTeHktgUSURZ9PdNSkv41fwWiJtGwA63SzU+xoR3EsqsdOoHnnoBJRtd5XD6/o+c0yvzQdXobhLc8o2o1Re0WadTPwQZnRLBEt/rbJitwQbRHtER07BxtDmVH7zMKo9Wt/sTb0EmuZZgOY7N0rCk1q5ZvwDwJZ1SCHDqnrsdQ4cAoq3/4Fc8ZoAfumPeZUjiyw7xwKkg9ONBiFxoGBTqKvG71koAQ16BlKSj6kQfZf42q3kjDZaCVL39GKQpLd6gzsqEkjc5gTWJI1y4FzwCQS7UpiMJB1P7aqOiXpHAwkKgrMadMbAMRUAWpE7RXZ2XZmrAfQRn0jW7AHR2Q2xKJz6HKerCTHPDl2tKBKjP5BMwtMpNaFjYIZHFQfqWlNmfNzq6cFBfOC8S2BNzcoQQ2WoD04O1dKnLmKE12VxFIHSiSwVSSRBVViXOtFSpi55sfOlu8+TBHFN5KCzmVcK1lPw3sfyOWZLDuBL2pGy0GdbaV9ywz1UEjWQxFM+pY1KJh3yLbJ+QwsdRMlJxveBnaMcqPXOhhv81oHS7Ci/9qiia5cyBwUVCqoaCGwBGuwBfvOYfh4s2LZsBjgGsc1YxyL0yboTNZIUCVYg4MdMK/9Q28ZQ3p2BTBzbzS5+oNmYYdwYsSCLBCJBRBkTYKsB1AjWiKzosG2M6uRoEaC2jbbEZSdb+eEdGSMY9TcpO2GKrimIKPP9jVj8JZCVqy4xpW2+uzHtOgas31axjiWAa6KmkSVNDIH2aNADZYg+4ORLX+0kjGktZCcd4z+tjIyNxjNOXaUTUtqsG8qaoGUiNqaRJZ4RYkE1os8QdUgJjHjWiRy7iiaklYlnUSVkMImAut+TPqmRg4lcrCKKs5I21JQgmW/oo0d7ZHWtov+ihHRweVrcmTuaUsevoM2rs9U4QFk0RYq0o8FKsdbWs5npH88WHYCxWIBNs7VQ9aKDmZ0OePqnlnyegeI+Q/0PRdYN7mogbq5CmlDBdXglIgWm2SakbsgMgfVkoMjEoxIMJRbOWPDx0/6V1h07a66KDcYTkw2MkTx4oGoPwb63sgoQQ1yJFsO/opahQt2JrlVAxVVbfRXgL4HN0pQ2YRFeAiqpH1wJyWi3JiTOH+SZedgfaCRNR6z8oqzLK7GqtK4SpO+gwY7erXROldy2jmLnOes5NHKzTRY8YrJt1fw40kJ8qAwlAvDIU6cHcH5bbMvgvP8NmchsOMIblz9twtG1twpGVdU9fAlCZSIcikH0QDOgrUS7DttYQcHOX5Vj7dXrHndKEF2r1IUQ2/2atDWiUIqBhmJYxTo24PJ1auHYmzOzRLI7RfZdgJ+v3E9ln3aKM62mTmGQJwOQO6CSHRsUHHxAZayHyt98e1tCX1njkFdQ4/U4MAoNGYcuUCRnYAfRI5NthBZItpWdO1AVIu/mMRnkujjIDecxrUAqla/+CCb9RTQtkeJFC5qIKra6DlIVo6hRGbZUW5ZSWw7QInHWOukRoKxoxjo4Nvb0OXmt4m2zksSkMsMiVoH2ddB1iRYZJObBuPaNDTtq++AKDqYIwHfRmJ0GVch2VmCGY0FdrS8MePaAvQTipHtCVrtVSdKZHx7BeqhOseOSkQlojzaN5uUOdmQBR3cyE0O2Te5epG6H2O+Ri+OLel+mUFiOQC5hJKKs7RR8PGg92BQ8NWTq1fXYsdWOziCLA6J4oB6BMt+jEPEuPp6LRyblfQdHijBihFglIjyLojsi2vLOrxdqhPTCpjRf8my0/J2BpR4jPmCeuwcNB7TeEzHJkcyqZs1cqg7utbjUapPFWSLqDUPyY0xyJ0uyTtHsK/H3vJNvl+vpfkFJskzrzGjsciyE3B+AHmkJetKu6ra6K/wQWGfCfKMA2ISA60BCsluQMpOK3XnwDMvmXcOJR7jrGFcE3+yNTEFJcj1wpgjAScm4xo4vA049uWHRLQEcSfGLaj6kfXwwUDi/Ab6hhrsK4e3t/mCDbJKms3lXANA3mKTXCGNuDF04vrcuEbWPNZ5W5BoCxIrL5h10y8dQN2P8T7VuMqr8/ydgz6SjfxFAWxBXk2BVsMFXFPm3HH6TQPIbgT6/GvUiJadma8MQ+qaQMi+o7yoITGJgTwokAObaSMHr3ENnFaLrzhki+jA0DNaV27g22NrX23khXbOdY1uEpMuyC0KyEFG1p2WpxmwRA6cVoyrWUptq0uBGC1ki+jg6Ku42Me5rfoGGVyZjbZHAIhfX0C/qQLbpqIjgiwZWRff8l193chuILaTSBgwoG+pQG5RJtf2trR9LgTRm41rNipNeLEEenTkpr5lNa56aq348de4XtFaxQRSQb8iJiXIxaf3Y23VQByUQOk7ahv1RhYUDqzcwIFjs+G6qfS+G9Pod3hGCfIGLttNJctAYvYC8UOhs+2o8ArUqJFWeX+W+q7qORy9E5ASUQwCkD3VL7nxD26rDrSxMXOvZRTusntfzdJLR7OIU7G9BbEbcw5sJYwVWzCw4fAOjmOnHZjiyb6iXn2gcM9V+/qREGT3BdmVyYqzP++zDr5kXY9p7jzHFmdjJn1fms2ojzy7puExjcSMT/JgDpYgdwqk7hwqGwvEb3PrfuhA/XTf1pHcuhs1ojxzkmNHi27WyKzmYGRW28phfaZ0vwgj+VsH6HekRlwAgWtDb/IGMHK2AkveCTiXkOhnYI0cKp4jx4qmeIW3PIiWn+tBHz3x12oj7mtICWoQv3+RNaLWFoz6B1Udh3eNyqG0oms5MEpQg+xeo47ks5FxDSe7a2LUuDqiDg6yAa5OkIZ61LjSjsFZLpPsGqQtLOBbWi8vyJznR1bP17gG75rYB7imqzy67yfJYt0dnHOf8y3tmtqMEtQg7h/+D74BxmY=')).decode("utf-8")
    c=int(c)
    i=220
    while i<len(s):
        p=int(s[i:i+3])
        x=int(s[i+3:i+8])
        g=int(s[i+8:i+11])
        if c>=x and c<=(x+g):
            return s[p*2:p*2+2]
        i+=11
    return'XX'

Data is packed in a base64-encoded and zlib-compressed string with the format:

pppcccccddd

where ppp is province index, ccccc is starting zipcode and ddd is delta. For example, zipcodes for "RM" province (Rome) would be:

08200010004 (from 00010 to 00013) 
08200015000 (from 00015 to 00015) 

and so on.

\$\endgroup\$
3
  • \$\begingroup\$ There appears to be a flaw here. In your example of Rome, '00014' is not in the text document you linked to. Would your code not output RM for this instead of XX? There are other examples of this as well - '00070' to '00118' aren't there either. \$\endgroup\$ Commented Dec 5, 2015 at 19:23
  • \$\begingroup\$ Many zip codes for an area cannot be described through an interval (a,b). The data are more complicated than that. \$\endgroup\$
    – DavidC
    Commented Dec 5, 2015 at 20:05
  • \$\begingroup\$ Fixed. Unfortunately, code has grown to 3,5kb... \$\endgroup\$
    – friol
    Commented Dec 5, 2015 at 20:16
0
\$\begingroup\$

Python 2, 2714

e='x\x9c5X\xcbr\xeb:\x0e\xdc\xeb[\xe4*\x91 Ar\xe9\xf8\xe6dR\x93\xc4\x1e\xdb\xc7\x8b\xfb\xff\x1f2\xdd\rd\x83\xa6(\x8a\x0f<\x1a\xa0\xde>j;\xcaq\xaaeG\xc3\xecd\x8eF9\x0e\xcaZNs{;\x8f\x83#\xcaN\xb4Sq6\xacF\x87\x8d\xc0VO\x95\xd8\x9b$\xc7p\x12HNB\xb4\xb2\xbd}YE\xf7NYO\x8dX\xb1\xb4\xd0\x03\xed8\rb\x0b\xc4\x1c\xdb\xdb\xcf\xac\xb1\x01\xa2I\xf6SYl\x18?\x9b1\xec\xdab\x9fcG\xc3\x0e\xc9zrb+\x18F\xc4w\xc2I\xd9\xb9\x06q\x9d\n\x87s\xc3-7\xdc\xb8\xe1\xc0\x86\x8d\x7f\x16\x9b\xa5\xe0cb\xc3\xd6\x81\x18\'4\xf5Ru\xc4\xa6\xa7fX\x908\xe2\x9b^N\x9d\xe8\x05K\x02G\xe2L\\\x1a\xb5\xec4\xb6\xb7\xe7\xf0\x03kA\x85\x8e\xbdH\x9ad\xdf\xde\xeeC\n\x1cR N:\xe2\xe8\x8f\xday\xf4\xdew4|\xca\x9a]F\xecq\x1c \x8e\x83\t\xfe\xb5\xc5\x91P\x80-~z\x7fo\xa1\\\x1cU\xda\xef\xc2!\x19z\xd1\x12\xf7\x8fE\x8b\x9e\xd6\xbe\x86\x9e\xcfmj\xc9\x9d\xc8S\x02\xeb!Y%\x1b\xf4\xd1\xa6\xc6^\xa6\x16\x9d;\x10\x06\x87m\xd0\xe8U\xb2I\xca\x8c\xebp\xbd\xf1\x8aO\x89017I\xa9S\x00q\x8a\xb6\xdd\xbf1\x1b\xb4\r\x95\x8e\x93\xcd\xbd\x0fh\xcb;\xcdQ\x16\xb6\x18\xa6\x83\xe1(\xbb\xa4K\x0e\xc9)\xb9\xe8\xdc\xf7\x9f6`\xd0\x1d\x92\xdb\x86l\'ax\xce\x98\xe19cv\x0b\xf4\xa2\xfe\xc5c]\x9b\xb4\x8e~`\xa3\n\xbaTq\xb0a\xd4U\xeb:\xff\xa7T\x8c\xc0:\xca\xa41\x8eJ!eWEP\xdd\xa5\xe4\x8f{\x9f1#\x913v)\xd7\x88\xb5b8\xd0\xd4\x0bw\x0b\xf4\x18\xdd\x0e\xc9\x1ac\xbb\xdei\xcf]&\xf8x/\xae\x99\x1d\xaa8l\x9eJ\xa1N\xa0\xdb\xe2\xa1[\xa0%\xb6\xc4_\xcd\xf1\xcc\xdb\xc7\xd5\xda1x(ke\x1c\xdb\xf5c\xd2M\xb42\x17\xa6h\xf0\xb0\xebs\xd0\xc6tR\xac\xb3\xd3)\xb6\xeb\x9d\xc7B\x9b\xd1{0r\x19\x9f\x10m_\x9c\x13\x94\xb2\x8e9!\x96<\x8c\xf3\xdf\xee\xcd\xd2\xc1\x8c:\x10Vi\x198\xa9uC|Kv\xe9\xdc\x8eF?\x00\xf6\x1e\xc3\xfa\x14*\xae\xadT\xdfn\xaf*/nP\xfc8\xe06P\xbc\xdc\xf9\xf6\x84\xa5\xe4T\xc4\x8ei\x80\xb5INJ#\xff\x10[\x8c\xb1\x05\xa9/\xff\xba\xbel;\xb0\xd2\xcaD\xee\x0fh5Q6\xf6\xf8\xe0\xdf\xd93\x1a\xba\xe8\xef`C\xfcI\xf4\x13\x95$\xbf\xb9]\xaa\xe2\x06\n\xab\n\xd6\xdby\x89\xe2\xb0\xf8\x12[\xadd\xab\x95l\xb5\x8e0\x1e\xb0\x97\xed\xf6A\x9b\xef\x10\x95\xa2Q8\xc5\xe4\x1a.\xb6\xdf\xe5\r\x0b\xd0\x16\xf7J\xa7\xe1@p\xe2\x00\xb8\x0er\x0c\xb2\xbd\x1fS\xc2\xa2\xbdv\xf9O\xba\x8f\xbc\xa7\x10\xdav\xfb\xc7"0\xc0\xe8\x9d\x1ak\xc4\xc6#\x9bX\xc9\x92\x95\xac\xc7\xb6\x81\x8c\xb3\xed\xf6\xee\xc1c;qH.\xce\xda\xe9\xfd|\xd6\x8a\xf9\xb5\xebk\x1c\xf3\xb3{F\x8d\xf3+\xcaE\x0b:\xed\x00\x05\xa0\xd1d> \x8fL\x84Q\xb5\xfd\xae\xfd\x8f\xed\xf6c\x06W\xdc)\xabd\xa3\x92\xd0X\xea\\\xea\\\xf4?"=\xc7L~z\xed\xd06&\xa7\r$\xe9|\xc0\x1a\x92|\xd2e\xbd\xf7\x9f\xd5\x92B\x99`\xb7\xef\xf75E\x87;\xb136W\x04-\x1b2\xefL\xf3\xce4\xefL\xf3\xce\x88M \x13\xca\xf6}\xf1\x1a\x1a r\x8fD\xc6\x0c\x10;\x10\x9a\xdeZ\x8bQ\xa4\x00\xa0\xf6\xf1V\x0f&7\x92\x11\x93\x9a\xd0\x98\x98\x80\xad\x88\xb7\x98\xc0\x84\x9e8\x12g\x8c\'\x1f~_\x9b"\x01j@\x03\x07\x02?\xa3\xd1\x98\xe9\x89\n\xc6rh\xe7M\xa1\xf0\xfd\xd3<b\x87H\x9e\x03\xc2\xd2P\'\x1a\x08\xeb*\x8c4\xe4\xfa\x02T\xaa\x93"\xb51\xbdKr\xa3\xa4\xa1\xaa\xc2\x03\xd2\xc5?h\x0c&&\xe0\x8c \xcah\xa9\x19-5\xa3\x85\xf5D\xa2\xd3\xa1\xbe\x9f\xa3g\xdc\r\x05\xe2\xf9\xde\xb3\x02\xe9\xd2o#\xaar\xe9\xd2\xef"b\xbbFl\x1a\x05G\x03[\x87~\x1f\xbd\x05\xff\x03\xe9\x15\x90&\xe9\'\xa1\x85\xec\x92pLy\xc7\xe7w\x99Y\xce\x94\x19\xd9\xa4\x88\xca\xff\xdc-t\x06\xc0\x04\xf0Q\xf5^\x9a\x98\x8d\xaa\x1b\x9c\x9f\xb2K*9\x0fUDC\x8c9\xe8\x05\xd1\xb7([\xd5\x93hrPEe\xfb\xf3\xdeZ\xe66V@\x89\x8b\x96j4m\'\x9aE?\xab\x85\xa6\xb9ZVZ@\x8dhCO\xda\xe0\xc7\x08\x86E-S\xf8\x9aR\xc5\xa3\\\xe1\xcfg\xa7awJR!qR\x85\x07\x973\xa2l\xd6\x0f)X\xc5\x9b\x0b#\xc4E\x87]\x06v\xe1\xa2\xb4|2=5\xd6\x0e\x7f\xbe\xdd\xc2\xdb]%\xdc jjg\xf1\x16\xcf\x9dQ\xf5s\xad\xb2\x00\xdcKI\x0b\x92u\x15K\x1b\xc9I)b!\x9a$]\x16\xd8\x0fI\xf5\xf9\x11}\xde\x12\x95|\xabl\xf9s\x9eG\x18\x93\xe8\xca\x05\x07cS\x1d\xc8\xa7L\xb0\xa4\x04e\xcf\xc39=q\x05\x0e\xc3\xf1\xa6\x8e>\xd3\xb7g\xfa\xf6\xd4q}\xfb\xfb\x8fY\xb8.Q\x84\x06\x82j\x8d\xec\xc5\r\xfc\xcd\x82c\xb2\xdb\x94\xae\x99\xaaXXP0f\xb5\xd3\xcbg\xa4"\xa5\x1a\xa8\xf1\xf2\x1fO\xd2%2\x04\x80 .HS2\xf4(M\xdc\xa3\x94\x07\xf6\x1c\xdd\xf9Vs^\xab\xc2\n\x9e\x89F\x93~*k@J\x93tI\x11@U0]~\x8a\xbei(d*\x8cO\xe9t\x05\xe2d%Q\xc8N\xac\xbe\xab\xca\x1bR\xebv\xf9Z\x96\xd4\xabc_\xde\xa6g"\x9d\xb1\x95\xf3oIB\x1d \x14eQ\x1eY9\x96\x82\x99\x10|n\xd2\x01)\x9a\x1e\xb0\xf8\xd5\x8a<\xbfx\xd2N\xe0\xf2*\\\xb3ne\xd9J\x01\xb5\xbd\xcf\xac\x16\x88\x1e\xda\xad\xfc\x8c8\xe2\x99\xb5\x86\x06\xb4\x1c\xd0\xa4\x80\xa9@\xb9\xfc;gp\xcf\x9cQ\x0fMy\xa1\x9e\x1b\xab\x13\xe2\x8a\xe7\xde\x02YWCF;\xbf\xf1\xa1\xb1\x9a\xf31\x83<\xb0\xea -\xd1\x03Fdl`O\x94\'\x135\xcc\xb5\xb9A\xeb\xc0KUE]\xee\xf5W\xad5\xd4\xfa\\\xc1\xa4\xd0G\x8f\xdd\x12\x07K\x83\xa5d\xbe2\x99/&\xf3\xed\xf1\xc8K\xc6\x88\x8b \x19J\xf7\xcaFO\xd7\x1a\x8f\xfb\xf24\xa5\x96x\xdcJ^.\x8a.\x17E\xd8%\xd5\'w$\xea*&\xb3\x14\xd9\x85c\x14,\xdb\xe3\x05\xa7\x19x;\xa2\xfa \x0eI\xdd&F\x94\xea\xc4\xa1\xc2y0\x89q\x007\xf0\xdf\xfb\x9c$\x14\xa8h\xc6\x9d\x10\xa8\xf4\tlE\xcafz||v\xe3\xbd\x0e.\x8aF\xd4\x93\x96\xf5\xa4Q\xd7\x81]\x92\x1e\xd4\xe5\xaa\x8fk\xb5\xcc\x03hTn\xa8\xc6\x8b\xf3l\x19=h4eM4\xba8\xa2\xb1\x803\xa2\x93\xac\x81\xe0\x8a\xa2\xc6:b\xc0b\x9dB\x9czN\xfahq\xc3\xfaz\x1f\x91e`\n\xad\xf6u\xa9\x06\x8e \xd9\x01\x99\x02+iT\x92\xb6\xa9"\xd3I\x8c\xd2Ad\xaa\xe7\x9e_\xf5\x96\xa8\xb7\x9e\xbd\x9e\xbd>\x02\xc7\x91h\xf15\xcb\xcd\xb1=_V\xc2\xca\xa6x\x81\x87\x99\xc2\xe1\xebZ\x9d\xda\xc7\x9c\x1et\x0e\x8c\xec\xee\xb9\x03\x9f=1\x8a\x17\xa75\x9e\xf7,\xc2{\x14\xed\x9d\xb5"\xf2z\xa4\xc6\x1e\xf5=\xc7=,\x13\xa1\xb5H\xfd\xa6\xbf#\x96\n\xb3\x96%l\x8bZ\x02\x88\xca\xfby[%+\x88\x15\xdb\xfc\xec\x83\x158%\xe3\xa6\x8f\xa8\xfc\xba\xb2t\xcf,\xddGx+Q\xb5\x81rr\x1fQ\xa2>\x7fl\xc6\x1d\xc5\xc4\xd6poS\xcaAt\xa1\x01\x83#1\xa11y\x116\x05\xf6\xf3Z\xe2\x9f\x08|\xfe`e\xd5\x843P\x95ya\xe9D\xfe\xd4_\x91\xa2\xc4Z\xd5\x98\n\xaa\x83\x0e\xd3\x85t\x94\x92y\xa6d\x9e)YC\x15\xd5P}\xfbz\xb6<\xb8\xb2\xfe\xd7\xdf\xde\xb3\xf6\xe9A\xa1]\xb5|\x11v\xc9Ai9\x86\xf5O\x0f>#jD\xd3\x08\xb8"d\xd7\x97H!\x90\x9e\xa3\x9cO:\xee\xbbg\xa5E\x9c\x94b\x04"\xeb1\xa0h\x85\xb8Nz\x8fY];}\x9eG\xcb\x1f!C\x1d\xafs-\x19\x02U6|\xbd\xd5\xc9\x10`\xf6\x8f\x80\xaf3]N\x01_\x85.\xa9w-\xc7\xf6\x1c\xeb\xaa\x95\x81z\x1aE\xd2$\xa3n\x98\x83U\x06&\x97\xb4\xf8z\xe9i)\xc8\xe6\xaau{]\x8a\x85K\x16\xdd\x8c\xc9HA(j\x88*\x81\xe0\xfc\xa2\xd0}\xbd\x9bJ+\xd3\xef;#VY\xc8T9\xd8\x11dh\xb2h\x15\xeaI\xdc\xc5\x15`\xff\xed\xfc\xb1\xea\xafG+\x11\xbf>\xcdC\xd7\xc0\xaa\xc8\xf4\xb0\xa21\xe5K\xd2\xceD\x9e\xce<\xfe\xb7\x01=G\r\xf92\xb0\x0bU\xf5>\xa6\xfa\xc1T\xce\xea\x9d\x05\x91\xf3\x9au\xfe*\xfd\xf7\x07\x06\xbdD\x7fvx\xa7\xe0\xdf\xb7(\xd2\xaf%)\xa2\x88"@\xdc2\xdb\xf9\xc7\xf3\xff%\xd1$\xbb\xe4\xd4M7\xfeT\xf9\x11\x94L$\xf3\x00[\\t\x19\x16.My\xfa\xbe\xebg\xe6\xf9\x7f>t\xbd\xe6?N\xce\xa0\xa4\xe1J\x1aHo\xae\xa4\x85\x82\xd1\x95*\xf9^\xbb\xb9\xb9\xf1?\x19$v\x0e\xe9Qz\x1e#qF\tz\xac(Q\xb5\xae\x91\xb1^w\xfbM\xd2\xc6$-\xc9#\x00\xf9\x07D\xc8\xab<\x90\x05\x83:\x9c\x85\x89\xe5\x0eLtb#\x99k$s\x8d\xd2\xe0T\x8f\x15U\x85\x92\xe7bT.f\x1bv`\xf6\xbe\xbd\x9e%\x9dN7L\x12\x87\x91U\x8c\x17\xf3P\xf4\xb3D\x04\xc1D\x19hE\x81\x16\x1d\xfa\xdbR"\xb4^\x93W[\xa6\xc8\xc5\x08\xe2\xdf>F\x90\xb0%\xf6\xa2\x7f\x82\x8c\x1a={\xfc#\xa4*\xce\xafi\xf9\x0b\xc5~\x0bV\xa5Rl}\xca\xe7\xff\x0f.\x98vx'.decode('zlib').split();d={}
for s in e:
 d[s[:2]]=[]
 for g in s[2:].split(','):
  f=g.split('-');d[s[:2]].append(int(f[0]))
  if len(f)>1:
   for k in range(int(f[1])):
    d[s[:2]].append(int(f[0])+k+1)
def f(s):
 for g in d:
  if int(s) in d[g]:return g
 return'XX'

Provinces and zipcodes are stored in a zlib encoded file with the following structure:

BG24010-21,24033-36,24100,24121-8

Initially build a dictionary filled with all the values, then look up the province.

\$\endgroup\$

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.