Identifying Custom Australian Licence Plates
In case this saves anyone some time, here’s a quick bit of regex and Python code for identifying if a given licence plate is standard or custom (personalised) in a given state.
I can’t promise that this logic is correct or up to date. Some of the rules used are a bit more general than they need to be. I also tended to ignore rules before 1970. The rules come from:
- https://en.wikipedia.org/wiki/Vehicle_registration_plates_of_Australia
- https://www.vicroads.vic.gov.au/registration/number-plates/general-issue-number-plates
import re
# Takes a pattern like xxxddd (for three letters followed by three numbers)
# and converts it to regex. Other characters are left as is in the regex
# pattern string. This is helpful for states like SA in which every modern
# licence plate begins with an "S".
def match_plate_pattern(plate, pattern):
pattern = pattern.replace('x','[A-Za-z]').replace('d','[0-9]')
return(re.fullmatch(pattern, plate))
licence_plate_patterns = {
"VIC": ["dxxdxx", # current car
"xxxddd", # old car
"dxdxx", # current motorcycle
"xxddd"], # old motorcycle
"NSW": ["xxddxx", # current car
"xxxddx", # old car
"xxxdd"], # motorcycles
"QLD": ["dddxxx", # current car
"dddxxd", # future car
"dddxx"], # motorcycles
"SA": ["Sdddxxx", # current car
"dddxxx", # old car
"Sddxxx", # current motorcycles
"ddxxx"], # old motorcycles
"WA": ["1xxxddd", # current style plates
"xxxddd", # old style plates before 1978
"dxxddd", # old style plates 1978--1997
"1ddxxx"], # current motorcycles (1997 onwards)]
"TAS": ["xddxx", # current style plates
"xxdddd", # old style plates 1970--2008
"xxxddd", # old style plates 1954--1970
"xxddd", # motorcycles
"xdddx"], # motorcycles
"ACT": ["xxxddx", # current style plates
"xxxddd", # future style plates
"xdddd"], # motorcycles
"NT": ["xxddxx", # current style plates
"dddddd", # future style plates
"xdddd", # current motorcycles
"ddddd"] # old motorcycles 1979--2011
}
def plate_type(plate, state):
# remove anything that isn't a letter or number
plate = re.sub(r'[\W_]+', '', str(plate))
plate_matches = [match_plate_pattern(plate, pattern) for pattern
in licence_plate_patterns[state]]
if plate == "":
return("no_plate")
elif any(plate_matches):
return("standard_plate")
else:
return("custom_plate")
And some Victorian examples:
plate_type("ABC-123", "VIC")
#> 'standard_plate'
plate_type("XY123", "VIC")
#> 'standard_plate'
plate_type("1AB-2CD", "VIC")
#> 'standard_plate'
plate_type("HOTROD", "VIC")
#> 'custom_plate'
The image at the top of this page is in the public domain.
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.1.0 (2021-05-18)
#> os macOS Big Sur 11.3
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_AU.UTF-8
#> ctype en_AU.UTF-8
#> tz Australia/Melbourne
#> date 2021-07-18
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date lib source
#> cachem 1.0.4 2021-02-13 [1] CRAN (R 4.1.0)
#> callr 3.7.0 2021-04-20 [1] CRAN (R 4.1.0)
#> cli 2.5.0 2021-04-26 [1] CRAN (R 4.1.0)
#> crayon 1.4.1 2021-02-08 [1] CRAN (R 4.1.0)
#> desc 1.3.0 2021-03-05 [1] CRAN (R 4.1.0)
#> devtools 2.4.0 2021-04-07 [1] CRAN (R 4.1.0)
#> digest 0.6.27 2020-10-24 [1] CRAN (R 4.1.0)
#> downlit 0.2.1 2020-11-04 [1] CRAN (R 4.1.0)
#> ellipsis 0.3.2 2021-04-29 [1] CRAN (R 4.1.0)
#> evaluate 0.14 2019-05-28 [1] CRAN (R 4.1.0)
#> fansi 0.4.2 2021-01-15 [1] CRAN (R 4.1.0)
#> fastmap 1.1.0 2021-01-25 [1] CRAN (R 4.1.0)
#> fs 1.5.0 2020-07-31 [1] CRAN (R 4.1.0)
#> glue 1.4.2 2020-08-27 [1] CRAN (R 4.1.0)
#> htmltools 0.5.1.1 2021-01-22 [1] CRAN (R 4.1.0)
#> hugodown 0.0.0.9000 2021-05-16 [1] Github (r-lib/hugodown@97ea0cd)
#> jsonlite 1.7.2 2020-12-09 [1] CRAN (R 4.1.0)
#> knitr 1.33 2021-04-24 [1] CRAN (R 4.1.0)
#> lattice 0.20-44 2021-05-02 [1] CRAN (R 4.1.0)
#> lifecycle 1.0.0 2021-02-15 [1] CRAN (R 4.1.0)
#> magrittr 2.0.1 2020-11-17 [1] CRAN (R 4.1.0)
#> Matrix 1.3-3 2021-05-04 [1] CRAN (R 4.1.0)
#> memoise 2.0.0 2021-01-26 [1] CRAN (R 4.1.0)
#> pkgbuild 1.2.0 2020-12-15 [1] CRAN (R 4.1.0)
#> pkgload 1.2.1 2021-04-06 [1] CRAN (R 4.1.0)
#> png 0.1-7 2013-12-03 [1] CRAN (R 4.1.0)
#> prettyunits 1.1.1 2020-01-24 [1] CRAN (R 4.1.0)
#> processx 3.5.2 2021-04-30 [1] CRAN (R 4.1.0)
#> ps 1.6.0 2021-02-28 [1] CRAN (R 4.1.0)
#> purrr 0.3.4 2020-04-17 [1] CRAN (R 4.1.0)
#> R6 2.5.0 2020-10-28 [1] CRAN (R 4.1.0)
#> Rcpp 1.0.6 2021-01-15 [1] CRAN (R 4.1.0)
#> remotes 2.3.0 2021-04-01 [1] CRAN (R 4.1.0)
#> reticulate 1.20 2021-05-03 [1] CRAN (R 4.1.0)
#> rlang 0.4.11 2021-04-30 [1] CRAN (R 4.1.0)
#> rmarkdown 2.8 2021-05-07 [1] CRAN (R 4.1.0)
#> rprojroot 2.0.2 2020-11-15 [1] CRAN (R 4.1.0)
#> sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 4.1.0)
#> stringi 1.6.1 2021-05-10 [1] CRAN (R 4.1.0)
#> stringr 1.4.0 2019-02-10 [1] CRAN (R 4.1.0)
#> testthat 3.0.4 2021-07-01 [1] CRAN (R 4.1.0)
#> usethis 2.0.1 2021-02-10 [1] CRAN (R 4.1.0)
#> vctrs 0.3.8 2021-04-29 [1] CRAN (R 4.1.0)
#> withr 2.4.2 2021-04-18 [1] CRAN (R 4.1.0)
#> xfun 0.22 2021-03-11 [1] CRAN (R 4.1.0)
#> yaml 2.2.1 2020-02-01 [1] CRAN (R 4.1.0)
#>
#> [1] /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/library