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\$ – Gabriele D'Antona Dec 6 '15 at 17:50
  • \$\begingroup\$ @mınxomaτ: I don't know if chars=1 byte in every programming language. \$\endgroup\$ – Gabriele D'Antona Dec 6 '15 at 18:41
  • \$\begingroup\$ @mınxomaτ: ok, changed to "shortest amount of bytes". \$\endgroup\$ – Gabriele D'Antona Dec 6 '15 at 18:54
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 Dec 5 '15 at 20:06
  • \$\begingroup\$ @DavidCarraher Are you sure? It works on 10.1.0... \$\endgroup\$ – LegionMammal978 Dec 5 '15 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 Dec 6 '15 at 1:17
  • \$\begingroup\$ @DavidCarraher Perhaps Compress functionality changed in 10.2? \$\endgroup\$ – LegionMammal978 Dec 6 '15 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\$ – Gabriele D'Antona Dec 6 '15 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\$ – Tom Carpenter Dec 6 '15 at 17:56
  • \$\begingroup\$ Your solution transposed to Python (with zlib.compress) is around 2.500 bytes. You should try it :) \$\endgroup\$ – Gabriele D'Antona Dec 6 '15 at 18:29
  • \$\begingroup\$ @friol managed to get it to work after a bit of messing, knocked over 1000 bytes off the code! \$\endgroup\$ – Tom Carpenter Dec 6 '15 at 18:39
  • \$\begingroup\$ Still my solution in Python using your approach is 2644 bytes. \$\endgroup\$ – Gabriele D'Antona Dec 6 '15 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\$ – Gabriele D'Antona Dec 7 '15 at 18:01
  • \$\begingroup\$ Woops. Should probably specify that \$\endgroup\$ – Dylan Madisetti Dec 7 '15 at 18:02
  • \$\begingroup\$ Yeah the zlib encoding goes screwy in 3 \$\endgroup\$ – Dylan Madisetti Dec 7 '15 at 18:03
0
\$\begingroup\$

Long "demo" answer in Python, 3755 chars

def f(c):
    import zlib
    import base64
    s=zlib.decompress(base64.b64decode('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')).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\$ – Tom Carpenter Dec 5 '15 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 Dec 5 '15 at 20:05
  • \$\begingroup\$ Fixed. Unfortunately, code has grown to 3,5kb... \$\endgroup\$ – Gabriele D'Antona Dec 5 '15 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, privacy policy and cookie policy

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