Number Plate Golf: Parsing See Also: Recognition

Introduction

You've now been taken off the speed camera development team (let's face it, your code is nowhere near production code standards) and are now working on a program to extract information about the car from the number plates. Of course, you've caught the code golf bug and want to write the program in as few bytes as possible.

Challenge

Given a valid, British number plate, display information about the car's registration.

You only have to support number plates registered between 2001 and 2051 (inclusive).

Internet access is disallowed.

The input will be given as a string.

Number Plates

British number plates are ordered like so:



Area code

A table with all of the area code mnemonics which you need to support can be found here.

For the letter X, you only need to output Personal Export due to multiple areas being covered by the same mnemonic.

You must output the DVLA office name.

Age Identifier

Similarly, a table with all of the age identifiers which you need to support can be found here.

If the identifier is in the range Y to 50 inclusive, you must output:

1/3/[Year] to 31/8/[Year]


Likewise, if the identifier is in the range 51 to 00 inclusive, you must output:

1/9/[Year] to [28/29]/2/[Year + 1]


You should support leap years.

Examples

WK94 FRS

Truro, 1/9/2044 to 28/2/2045


CB16 BTD

Bangor, 1/3/2016 to 31/8/2016


BD51 SMR

Birmingham, 1/9/2011 to 29/2/2012


XAY EEA

Personal Export, 1/3/2001 to 31/8/2001


Scoring

The shortest code in bytes wins
Ruby, 629 bytes
s=gets
p=c=0
'PETeRborOuGh
NORWich
IPSwicH
BIRMiNGHam
CARdiff
SWANsea
BAngOr
CHEsTer
SHREWsbURY
CHELmSFOrd
NOTTInGHAm
LInCOlN
MAIDStone
BRIgHtON
BOURNEMoUth
PORTSMoUth
ISLE OF WIGHt
PORtSmOUtH
BOREHAMwoOD
NORTHAmPton
WIMBLeDoN
BOREHAMwOoD
SIdcup
MANChESTer
NEWCAstle
STOcKtON
oXFOrd
PReStON
CArlISlE
ReADIng
GLAsGoW
EDINBUrGh
DUNdEe
ABERDEen
INvErNEsS
WORcESTer
EXeTeR
TRUro
BRiStoL
PERSONAL eXPOrt
LeEds
SHEFFiElD
BEVERLEY'.split($/).map{|w|c&lt;s[0,2].to_i(35)&amp;&amp;p=w;d=0;w.bytes{|b|d+=d+b/95};c+=d}
y=(?1+s[2,9]).to_i-1
puts p.capitalize+&quot;, 1/%d/20%02d to %d/%d/20%02d&quot;%[z=3+y%100/50*6,1+y%=50,z&lt;4?31:y%4==2?29:28,(z+5)%12,1+y+z/9]

The first two letters are interpreted as a base 35 number and then looked up to find the correct town. The quantity of addresses assigned to each town is encoded (run-length encoding) in the captialization of each town in binary, where uppercase=0 and lowercase=1.
In order to handle the Y age indicator for the first half of 2001, a 1 is prepended to the age. Thus 1 Y is interpreted by .to_i as 1, and 1 02 is interpreted as 102. 1 is subtracted (to handle the wraparound for 2050) and taken modulo 100 to decide which half of the year we are in. It is then taken modulo 50 (and the 1 added on again) to find the year.