; license plates
(define rand #f)
(define randint #f)
(let ((two31 #x80000000) (a (make-vector 56 -1)) (fptr #f))
(define (mod-diff x y) (modulo (- x y) two31)) ; generic version
; (define (mod-diff x y) (logand (- x y) #x7FFFFFFF)) ; fast version
(define (flip-cycle)
(do ((ii 1 (+ ii 1)) (jj 32 (+ jj 1))) ((< 55 jj))
(vector-set! a ii (mod-diff (vector-ref a ii) (vector-ref a jj))))
(do ((ii 25 (+ ii 1)) (jj 1 (+ jj 1))) ((< 55 ii))
(vector-set! a ii (mod-diff (vector-ref a ii) (vector-ref a jj))))
(set! fptr 54) (vector-ref a 55))
(define (init-rand seed)
(let* ((seed (mod-diff seed 0)) (prev seed) (next 1))
(vector-set! a 55 prev)
(do ((i 21 (modulo (+ i 21) 55))) ((zero? i))
(vector-set! a i next) (set! next (mod-diff prev next))
(set! seed (+ (quotient seed 2) (if (odd? seed) #x40000000 0)))
(set! next (mod-diff next seed)) (set! prev (vector-ref a i)))
(flip-cycle) (flip-cycle) (flip-cycle) (flip-cycle) (flip-cycle)))
(define (next-rand)
(if (negative? (vector-ref a fptr)) (flip-cycle)
(let ((next (vector-ref a fptr))) (set! fptr (- fptr 1)) next)))
(define (unif-rand m)
(let ((t (- two31 (modulo two31 m))))
(let loop ((r (next-rand)))
(if (<= t r) (loop (next-rand)) (modulo r m)))))
(init-rand 19380110) ; happy birthday donald e knuth
(set! rand (lambda seed
(cond ((null? seed) (/ (next-rand) two31))
((eq? (car seed) 'get) (cons fptr (vector->list a)))
((eq? (car seed) 'set) (set! fptr (caadr seed))
(set! a (list->vector (cdadr seed))))
(else (/ (init-rand (modulo (numerator
(inexact->exact (car seed))) two31)) two31)))))
(set! randint (lambda args
(cond ((null? (cdr args))
(if (< (car args) two31) (unif-rand (car args))
(floor (* (next-rand) (car args)))))
((< (car args) (cadr args))
(let ((span (- (cadr args) (car args))))
(+ (car args)
(if (< span two31) (unif-rand span)
(floor (* (next-rand) span))))))
(else (let ((span (- (car args) (cadr args))))
(- (car args)
(if (< span two31) (unif-rand span)
(floor (* (next-rand) span))))))))))
(define licenses (make-vector 17576 (list)))
(define (hash license)
(define (c->i c)
(- (char->integer (char-upcase c)) 65))
(let loop ((cs (string->list license))
(e 2) (s 0))
(if (negative? e) s
(loop (cdr cs) (- e 1)
(+ (* 26 s) (c->i (car cs)))))))
(define (adjoin license)
(when (not (license? license))
(vector-set! licenses (hash license)
(cons (substring license 3 6)
(vector-ref licenses (hash license))))))
(define (license? license)
(member (substring license 3 6)
(vector-ref licenses (hash license))))
(define (start-list half-license)
(sort string<? (vector-ref licenses (hash half-license))))
(define (create-random-data n)
(define (i->c i) (integer->char (+ i 65)))
(define (i->d i) (integer->char (+ i 48)))
(set! licenses (make-vector 17576 (list)))
(do ((n n (- n 1))) ((zero? n))
(adjoin (list->string
(cons (i->c (randint 26))
(cons (i->c (randint 26))
(cons (i->c (randint 26))
(cons (i->d (randint 10))
(cons (i->d (randint 10))
(list (i->d (randint 10))))))))))))
(display (license? "PLB123")) (newline)
(display (length (start-list "PLB"))) (newline)
(display (start-list "PLB")) (newline)
(display (apply max (map length (vector->list licenses)))) (newline)
(display (length (filter zero? (map length (vector->list licenses))))) (newline)
(display (apply + (map length (vector->list licenses)))) (newline)
Pages: 1 2 3
In Python
from collections import defaultdict class license_plates: # assumes plates of format ABC-123 def __init__(self): self.collection = defaultdict(lambda : defaultdict(lambda : defaultdict(list))) def __str__(self): result = "List of plates in license_plate collection:" for l1 in self.collection: for l2 in self.collection[l1]: for l3 in self.collection[l1][l2]: for n in self.collection[l1][l2][l3]: result+= "\n"+ l1+l2+l3+"-"+n return result def add_plate(self, plate): if len(plate) != 7 and all(plate[i] in string.letters for i in range(3)): raise else: self.collection[plate[0]][plate[1]][plate[2]].append(plate[4:7]) def print_plates_starting_with(self, start_letters): if start_letters and len(start_letters) < 4: d = self.collection for l in start_letters: d = d[l] print("Plates starting with:", start_letters) self.pretty_print_dict(start_letters, d) else: raise def pretty_print_dict(self, prefix, d): for key in d: # print('\t' * indent + str(key)) if isinstance(d[key], dict): self.pretty_print_dict(prefix+key, d[key]) else: for n in d[key]: print(prefix + key + '-' + n) lp = license_plates() lp.add_plate('ABC-123') lp.add_plate('ABH-666') lp.add_plate('AQC-987') lp.add_plate('DEF-000') print(lp) lp.print_plates_starting_with('A') lp.print_plates_starting_with('AB') lp.print_plates_starting_with('D') lp.print_plates_starting_with('X') # output: # List of plates in license_plate collection: # DEF-000 # AQC-987 # ABH-666 # ABC-123 # Plates starting with: A # AQC-987 # ABH-666 # ABC-123 # Plates starting with: AB # ABH-666 # ABC-123 # Plates starting with: D # DEF-000 # Plates starting with: X # [Finished in 0.2s]MUMPS V1
LICPLATE ;New routine N CT,I,PLATES ; Add plates to array ; F I="PLB-123","PLB-666","PLB-987","PLC-000" D . S PLATES(I)="" ; Is PLB-123 member of the array? W !,"PLB is ",$S($D(PLATES("PLB-123")):"",1:"not"),"a member of the array." ; ; How many license plates begin with 'PLB'? ; S I=$O(PLATES("PLB"),-1) ; Start immediately before entries starting with 'PLB' F CT=0:1 S I=$O(PLATES(I)) Q:I'?1"PLB".E W !!,CT," plate",$S(CT'=1:"s",1:"")," begin with 'PLB'." ; ; What is the list of license plates that begin with the 'PLB' ; W !!,"List of license plates that begin with 'PLB':" S I=$O(PLATES("PLB"),-1) ; Start immediately before entries starting with 'PLB' F S I=$O(PLATES(I)) Q:I'?1"PLB".E W !,I Q --- D ^LICPLATE PLB is a member of the array. 3 plates begin with 'PLB'. List of license plates that begin with 'PLB': PLB-123 PLB-666 PLB-987MUMPS V1
Correction LICPLATE ;New routine N CT,I,PLATES ; Add plates to array ; F I="PLB-123","PLB-666","PLB-987","PLC-000" D . S PLATES(I)="" ; Is PLB-123 member of the array? W !,"PLB-123 is ",$S($D(PLATES("PLB-123")):"",1:"not"),"a member of the array." ; ; How many license plates begin with 'PLB'? ; S I=$O(PLATES("PLB"),-1) ; Start immediately before entries starting with 'PLB' F CT=0:1 S I=$O(PLATES(I)) Q:I'?1"PLB".E W !!,CT," plate",$S(CT'=1:"s",1:"")," begin with 'PLB'." ; ; What is the list of license plates that begin with the 'PLB' ; W !!,"List of license plates that begin with 'PLB':" S I=$O(PLATES("PLB"),-1) ; Start immediately before entries starting with 'PLB' F S I=$O(PLATES(I)) Q:I'?1"PLB".E W !,I Q --- D ^LICPLATE PLB is a member of the array. 3 plates begin with 'PLB'. List of license plates that begin with 'PLB': PLB-123 PLB-666 PLB-987Using SQLite.
import sqlite3 as db import random import string def create_random_plates(): 'fill the database with some license plates' with db.connect("license2.db") as DB: cur = DB.cursor() cur.execute('CREATE TABLE LicensePlates(Id INT, Chr TEXT)') for i in range(100000): c = "".join(random.sample(string.ascii_uppercase, 3)) n = "".join(random.sample(string.digits, 3)) cur.execute("""INSERT INTO LicensePlates Values({}, "{}-{}")""".format(i+1, c, n)) def find_pattern(pattern): 'pattern for SQL LIKE' with db.connect("license2.db") as DB: cur = DB.cursor() cur.execute("""SELECT * FROM LicensePlates WHERE Chr LIKE '{}' ORDER BY Chr""".format(pattern)) return cur.fetchall() create_random_plates() # find all plates starting with PLB and with 5 in middle of number for plate in find_pattern("PLB-_5_"): print(plate[1]) """ PLB-451 PLB-652 PLB-756 PLB-956 """I used this shell program to generate a list of license plate numbers:
#!/bin/bash
NUM_TIMES=100000
for ((i == 0 ; i < NUM_TIMES ; i++)); do
HEAD=$(head -c 3 < /dev/urandom | tr --complement 'A-Z' 'A-ZA-ZA-ZA-ZA-ZA-ZA-ZA-Z')
TAIL=$(head -c 3 < /dev/urandom | tr --complement '0-9' '0-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-9')
echo $HEAD-$TAIL
done
Then I piped it through
sortanduniqto make a list with no duplicates intocleaned.txt.Then I can use this shell program to query in the 3 ways required (membership, prefix count, and prefix listing):
#!/bin/bash
case "$1" in
(member) # membership query #
<cleaned.txt grep --silent '^'"$2"'$'
if test "$?" -eq 0
then
echo "'$2' is a member of this set."
else
echo "'$2' is not a member of this set."
exit 1
fi
;;
(prefix) # prefix count #
COUNT=$(<cleaned.txt grep --count '^'"$2")
if test "$COUNT" -eq 0
then
echo "No license plates begin with '$2'."
exit 1
elif test "$COUNT" -eq 1
then
echo "1 license plate begins with '$2'."
else
echo "$COUNT license plates begin with '$2'."
fi
;;
(list) # prefix list #
<cleaned.txt grep '^'"$2"
if test "$?" -ne 0
then
echo "No license plates begin with '$2'."
exit 1
fi
;;
(*)
echo "unknown command - use 'member', 'prefix', or 'list'."
exit 1
;;
esac
edit of above comment:
#!/bin/bash
NUM_TIMES=100000
for ((i == 0 ; i < NUM_TIMES ; i++)); do
HEAD=$(head -c 3 < /dev/urandom | tr --complement 'A-Z' 'A-ZA-ZA-ZA-ZA-ZA-ZA-ZA-Z')
TAIL=$(head -c 3 < /dev/urandom | tr --complement '0-9' '0-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-90-9')
echo $HEAD-$TAIL
done
—
#!/bin/bash
case "$1" in
(member) # membership query #
<cleaned.txt grep --silent '^'"$2"'$'
if test "$?" -eq 0
then
echo "'$2' is a member of this set."
else
echo "'$2' is not a member of this set."
exit 1
fi
;;
(prefix) # prefix count #
COUNT=$(<cleaned.txt grep --count '^'"$2")
if test "$COUNT" -eq 0
then
echo "No license plates begin with '$2'."
exit 1
elif test "$COUNT" -eq 1
then
echo "1 license plate begins with '$2'."
else
echo "$COUNT license plates begin with '$2'."
fi
;;
(list) # prefix list #
<cleaned.txt grep '^'"$2"
if test "$?" -ne 0
then
echo "No license plates begin with '$2'."
exit 1
fi
;;
(*)
>&2 echo "unknown command - use 'member', 'prefix', or 'list'."
exit 1
;;
esac