17
\$\begingroup\$

The scenario: You are a software designer working for a gov't-run company that designs license plates for cars and other vehicles. You've been asked to develop software that generates license plates. Before you got to work, your bosses laid down these ground rules.


A license plate cannot contain:

  • ASS
  • 666
  • 69<any number here>
  • <any number here>69
  • KKK
  • SHT

Rules and requirements:

  • License plate must be randomly generated.
  • Once a random license plate is generated, the same license plate cannot be generated again.
  • You must output at least 200 unique license plates. You can generate more if you want to.
  • You may store generated plates in a file to "remember" them.
  • The license plate contains 2 sections, one containing only three letters, and one containing only three numbers, separated by a dash, like this: 233-ADF or ADF-233.
  • You can only use numbers and capital letters.
  • License plates can be written to stdout, or a file.
  • Each "side" of a license plate will contain either three numbers or letters.
  • This is a , so shortest, most popular, answer wins. Winner will be chosen after seven days.

General rules

  • Answer should include, but not limited to, the following.
  • Language name.
  • Character count.
  • File size.
  • How the code is run.
  • The code itself.
  • Example: Python 234 chars or Python 23mb.

If I need to clarify any additional details, please mention it in the comments and I will add it to my post. Anyways, good luck, and generate me some appropriate license plates!


Update 1: Winner will be chosen slightly earlier.

Turns out I have to go on a trip soon, so I will be choosing a winner around 00:00 UTC, July 25. After the winner is chosen, you can still submit entires, just know that a winner has been chosen. Bai.


Update 2: Winners!

We have winners! Yay! Cheese and wine to everyone who participated! Here's who won.

  • 1st place: Àngel - Bash (95 characters)
  • 2nd place: Martin Büttner - Mathematica (182 bytes)
  • 2nd place: Emilio M Bumachar - Pyg (92 ?)
  • 2nd place: Peter Taylor - Golfscript (98 characters)
  • 3rd place: Mark Thomas - Ruby (127 characters)

Wow, three second place ties. Wow. The competition is over, but feel free to submit entries if you want to. Bai!


\$\endgroup\$
21
  • 2
    \$\begingroup\$ "Once a random license plate is generated, the same license plate cannot be generated again." What about non-random licence plates? \$\endgroup\$ Jul 19, 2014 at 18:33
  • 4
    \$\begingroup\$ The obvious way to do this (and probably the way it works in real life) is to generate the numbers in order. \$\endgroup\$ Jul 19, 2014 at 18:34
  • 5
    \$\begingroup\$ "Randomly generated" is imprecise. I presume you mean "uniformly selected at random from the unused legal licence plates" rather than, say, uniformly selected at random from the legal licence plates beginning AAA- \$\endgroup\$ Jul 19, 2014 at 20:00
  • 1
    \$\begingroup\$ please tell how many digits should be in every plate, and what characters are valid - it varies from country to country \$\endgroup\$ Jul 20, 2014 at 17:55
  • 15
    \$\begingroup\$ I'm now somewhat tempted to write a program to generate random license plates that contain some obscene or otherwise inappropriate string not found in your list. \$\endgroup\$ Jul 20, 2014 at 19:32

24 Answers 24

12
\$\begingroup\$

bash (95 chars)

Save the script as m in a folder in your PATH with execute bit set.

Run as bash m. The plates are stored in file p

l(){ tr -dc $1</dev/urandom|head -c3;};egrep -ve"ASS|666|69|KKK|SHT" -fp>>p<<<`l 0-9`-`l A-Z`;m

This is equivalent to running the following:

# Print three random numbers and three random letters
echo $(tr -dc 0-9 < /dev/urandom | head -c3)-$(tr -dc A-Z < /dev/urandom | head -c3) |

# Print only plates not matching the blacklist or any line of p
# Append the plates ton p
egrep -v -e "ASS|666|69|KKK|SHT" -f p >> p

# Execute itself again
m 

Caveat: The final m should actually be exec m (+5 chars) in order to avoid leaving processes waiting for completion (but you can have thousands without much problem)

Credit goes to http://www.cyberciti.biz/faq/linux-random-password-generator/ for the idea of using tr -dc

\$\endgroup\$
2
  • \$\begingroup\$ Is it to me or the uniqueness requirement is missing? \$\endgroup\$ Jul 20, 2014 at 16:48
  • 1
    \$\begingroup\$ @Cristian-Ciupitu: The grep -v is excluding both the blacklist and the list of plates we already generated (grep is expecting p to contain one pattern per line, but as the plates don't contain regular expression metacharacters, they only match themselves). We only generate one or zero plates per iteration, so after each iteration the full (updated) list of plates to exclude will be read by grep. :D \$\endgroup\$
    – Ángel
    Jul 20, 2014 at 18:03
7
\$\begingroup\$

PYG - 92

Pe(Se(Re.sub(".*(666|69|ASS|KKK|SHT).*","",J(RSm(STuc*3,3)+[j]+RSm(STd*3,3)))for j in'-'*K))

Now able to select uniformly from all unused plates, keeping to OP's specs, while being shorter by 1 more character.

It's theoretically possible that the list of 999 plates will contain enough repetitions so that the trimmed set will be less than 200. But the odds of that are infinitesimally small. In ten trials, the lowest length I got was 994.

EDIT: changed 999 to K (which is pyg for 1000), to save two chars at the advice of bitpwner.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Did you filter out the disallowed values? Don't see any KKK or 666 anywhere. \$\endgroup\$
    – Vectorized
    Jul 20, 2014 at 3:52
  • 5
    \$\begingroup\$ @bitpwner: I use only the digits from 0 to 5 and letters from A to J, so the disallowed values cannot occur. \$\endgroup\$ Jul 20, 2014 at 9:54
  • \$\begingroup\$ Very clever! Nobody ever said those others had to be used. Nice. \$\endgroup\$ Jul 20, 2014 at 20:37
  • 1
    \$\begingroup\$ OP agreed to the randomness being "uniformly selected at random from the unused legal licence plates". See comments in question. Unless your definition of uniform means uniform from any range. And you can change 999 to K, saving u 2 chars. \$\endgroup\$
    – Vectorized
    Jul 21, 2014 at 1:20
  • 3
    \$\begingroup\$ Not sure I'd count output as random if there's valid plates that are impossible to generate... \$\endgroup\$
    – Alconja
    Jul 21, 2014 at 1:33
5
\$\begingroup\$

Mathematica, 182 bytes

Ugh, this is long

l={};While[Length[l=Union@Pick[l,StringFreeQ[l,"ASS"|"666"|"69"|"KKK"|"SHT"]]]<200,AppendTo[l,RandomSample[FromCharacterCode/@{48+9~(r=RandomInteger)~3,65+25~r~3}]~Riffle~"-"<>""]];l

Ungolfed

l = {};
While[
  Length[
    l = Union@
      Pick[l, StringFreeQ[l, "ASS" | "666" | "69" | "KKK" | "SHT"]]
  ] < 200,
  AppendTo[l, 
   RandomSample[
      FromCharacterCode /@ {48 + 9~(r = RandomInteger)~3, 
        65 + 25~r~3}]~Riffle~"-" <> ""]
  ];
l

Pretty straight-forward. Generates random plates, and filters out duplicates and forbidden ones until 200 are found.

\$\endgroup\$
5
\$\begingroup\$

GolfScript (98 chars)

260{3?}:^~,{.10^+`-3>'-'+\10^/26^+26base(;{65+}%+.-1%}%{'ASSKKKSHT66669'3/{1$\?)!},*},{,^^rand}$n*

This generates all possible licence plates in a random order using some ugly base conversion followed by filtering. There are a lot of them, so don't expect it to execute quickly, but the question didn't place any constraints on execution time.

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6) - 213

It can probably be improved. Tested on Firefox Console.

Change that alert to a console.log() if you want to test

r=x=>~~(Math.random()*x)+'';l=x=>[...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'][r(26)];a=[];while(a.length<200)p=r(10)+r(10)+r(10)+'-'+l()+l()+l(),!/ASS|666|69|KKK|SHT/.test(p)&&a.indexOf(p)<0&&a.push(p);a.forEach(x=>alert(x))
\$\endgroup\$
6
  • \$\begingroup\$ Wow, that has to be the longest single line of code I've ever seen. \$\endgroup\$ Jul 20, 2014 at 0:51
  • 2
    \$\begingroup\$ @DatEpicCoderGuyWhoPrograms you obviously haven't seen my 400+ char single-line JS regex ;) \$\endgroup\$ Jul 20, 2014 at 5:38
  • \$\begingroup\$ @eric_lagergren That sounds like it would have been a pain to write... \$\endgroup\$ Jul 20, 2014 at 14:28
  • 3
    \$\begingroup\$ @DatEpicCoderGuyWhoPrograms You can write it over multiple lines then remove the unnecessary whitespaces. There are multiple online services who offer that + other shortening (replacing function /var etc. names) to reduce js file sizes and subsequently save bandwidth. \$\endgroup\$
    – SBoss
    Jul 21, 2014 at 9:04
  • 1
    \$\begingroup\$ @DatEpicCoderGuyWhoPrograms optimize afterwards. I figure out how to correctly solve the problem, then I try and find shortcuts, and then I finally optimize my code :P a lot simpler \$\endgroup\$ Jul 21, 2014 at 17:01
4
\$\begingroup\$

Ruby — 136 133 129 characters

Hideous. Think there's room for improvement, though. Just drop the code in irb or pry and hit enter to run:

f=->*t{[0,1,2].map{t.sample}*''}
g=->l{(a=f[*?A..?Z]+?-+f[*?0..?9];l|=[a]if/69|666|ASS|SHT|KKK/!~a)until l.size>199;l}
puts g[[]]
\$\endgroup\$
4
\$\begingroup\$

Ruby, 127 chars

My attempt at a "readable" Ruby version:

a=[]
until a.size==200 do
  p="#{rand(899)+100}-#{('A'..'Z').to_a.sample(3).join}"
  a<<p unless p=~/69|666|ASS|SHT|KKK/
end
puts a
\$\endgroup\$
1
  • \$\begingroup\$ Note that this generates compliant license plates, but won't generate the entire set of possible plates (as with most of these answers). That doesn't seem to be a requirement. \$\endgroup\$ Jul 21, 2014 at 15:31
4
\$\begingroup\$

Python 2.7 - 258 chars

I'm not a professional programmer or anything, so I'd say I'm satisfied with the result.

import random as o
r=o.randint
t,j,k=[],0,""
b=["SHT","KKK","ASS","69","666"]
for i in range(200):
 l,j=b[0],b[4]
 while any(w in l for w in b):
  l,j="",""
  for i in range(3):
   l+=chr(r(65,90))
   j+=str(r(0,9))
 t.append(l+'-'+j)
print "\n".join(set(t))

Filesize is 4.0 K, run with python file.py !

\$\endgroup\$
12
  • \$\begingroup\$ Shouldn't that pass be a continue? You can also save some chars by indenting with a 1 space instead of 4. \$\endgroup\$ Jul 20, 2014 at 16:36
  • \$\begingroup\$ Also for i in range(0,200): could be replaced with for i in range(200):. \$\endgroup\$ Jul 20, 2014 at 16:53
  • \$\begingroup\$ @CristianCiupitu I couldn't get it to do the full 200 when using continue.. But pass did the trick. Plus, it's shorter. And when I tried for i in range(200), it only did 199 ^^ I counted them afterwards by making a duplicates variable and putting duplicates += 1 before pass and counting the occurrences for - in the list/string. \$\endgroup\$
    – Adam
    Jul 20, 2014 at 19:34
  • \$\begingroup\$ @CristianCiupitu range(200) worked after all - the 4 spaces in the code block are actually \t and replacing them by 1 space didn't change the character count... Thanks for the suggestions! \$\endgroup\$
    – Adam
    Jul 20, 2014 at 19:45
  • 1
    \$\begingroup\$ A user suggested in a suggested edit to simply remove if k in t: pass, as it does nothing. \$\endgroup\$
    – Doorknob
    Jul 20, 2014 at 22:12
3
\$\begingroup\$

Python - 208

Hi heres my stab at license plate generation. This solution is similar to @bitpwner's solution but without the string module and instead of a list for the license plate I chose to use a set and its also allows numbers first.

import random as r,re
f=r.randint
l=lambda x:chr(f(65, 90))if x else`f(0,9)`
d=set()
while len(d)<200:
 k=f(0,1);j=1-k;c=l(k)+l(k)+l(k)+'-'+l(j)+l(j)+l(j)
 if not(re.search("666|69|ASS|KKK|SHT",c)):d.add(c)

Sample output:

set(['DQJ-641', '086-QRY', '981-GAZ', 'UHN-718', '114-VMI', 'GLO-887',  ...
\$\endgroup\$
3
\$\begingroup\$

Python, 252 bytes

Here's my contribution. I'm impressed with it, but I know others have done better with python.

from random import randint as r
f=()
while len(f)<200:
 t=str(r(0,999))
 if not("666" in t or "69" in t):
  u=''.join(chr(r(65,90)) for _ in [1,2,3])
  if not("KKK" in u or "SHT" in u or "ASS" in u):f+=("%s-%s"%(t.zfill(3),u),)
 f=tuple(set(f))
print f
\$\endgroup\$
2
\$\begingroup\$

Python - 165

Those imports...

import random as r,re
j="666|69|ASS|KKK|SHT"
t=r.randint
while len(j)<2e3:
 exec"x="+"chr(t(0,25)+65)+"*3+"'-'"+"+`t(0,9)`"*3
 if not re.search(j,x):print x;j+='|'+x

If there is a need to begin randomly with either numbers or alphabets, which I don't think is really needed, then 190.

import random as r,re
j="666|69|ASS|KKK|SHT"
t=r.randint
while len(j)<2e3:
 exec"x="+"chr(t(0,25)+65)+"*3+"'-'"+"+`t(0,9)`"*3
 x=x[::r.choice((-1,1))]
 if not re.search(j,x):print x;j+='|'+x
\$\endgroup\$
4
  • \$\begingroup\$ Chars or bytes? \$\endgroup\$ Jul 19, 2014 at 23:19
  • \$\begingroup\$ May I suggest PYG? gist.github.com/Synthetica9/9796173 \$\endgroup\$ Jul 20, 2014 at 1:28
  • \$\begingroup\$ I count 208 chars, and does your solution allow numbers first? \$\endgroup\$
    – Willem
    Jul 20, 2014 at 5:27
  • \$\begingroup\$ @willem The four spaces for indentation are actually tabs, and alphabets first only. \$\endgroup\$
    – Vectorized
    Jul 20, 2014 at 5:39
2
\$\begingroup\$

PHP 341 324 320

Was the best I could do.

<?$a="p";$b=fopen($a,'a+');while($c<200){$d=rand(100,999);$e='';for($f=0;$f<3;++$f)$e.=chr(rand(65,90));$g=(rand(1,2)==1)?"$d-$e":"$e-$d";$h=array('ASS','666','69','kkk','SHT');$i=1;foreach($h as $j)!preg_match("/$j/",$g)?:++$i;if($i==1){$k=fread($b,filesize($a));if(!strpos($k,$g)){fwrite($b,$g);echo"$g<br />";++$c;}}}

To run the code just save as a .php file and browse to it on any web server. It will attempt to create the blacklist file p.txt if it does not exist already. However you may need to define it with a full server path if you do not have root access.

The code itself is here pre golfification:

<?
// create random plate
// check it does not break rules
// check is not on all time blacklist file
// Add to blacklist file
// Output to screen

// open file handle
$file = "p"; // filename and path if not root access
$fh = fopen($file, 'a+');

// do 200
while($x<200) {

    // get random number
    $rand_number = rand(100,999);
    
    // get random letters
    $letters = '';
    for($y=0; $y<3; ++$y) $letters .= chr(rand(65,90));
    
    
    // mix up combination
    $string = (rand(1,2)==1) ? "$rand_number-$letters" : "$letters-$rand_number";
    
    // assume is ok
    $ok = 1;

    // Set checks to be excluded on new plates.
    $checks = array('ASS','666','69','kkk','SHT');
    
    // do the exclusions
    foreach ($checks as $check) !preg_match("/$check/", $string) ? : ++$ok;


    // if all ok, check is not on the blacklist
    if($ok == 1) {

        // read blacklist
        $blacklist = fread($fh, filesize($file));
        
        // if not on blacklist, add it to file, echo it to output, increment counter
        if (!strpos($blacklist, $string)) {
            fwrite($fh, $string);
            echo "$string<br />";
            ++$x;
        }
    }
}

Was as short as I could get it :-(

Sample Output

XWU-888
PUD-534
355-QXG
WDE-402
113-QID
362-YBW
TBK-594
939-XDT
148-ARZ
838-ICY
723-ZDA
.... does exactly 200 new plates.

EDIT: tidied up a couple of if statements to use short form.

\$\endgroup\$
3
  • \$\begingroup\$ If the plates do not have to be mixed up - ie can be numbers then letters only, I could lose this line $string = (rand(1,2)==1) ? "$rand_number-$letters" : "$letters-$rand_number"; \$\endgroup\$ Jul 20, 2014 at 17:33
  • 1
    \$\begingroup\$ You could use a single-character filename (e.g., p instead of p.txt) and save yourself 4 characters, too. \$\endgroup\$
    – Mark
    Jul 21, 2014 at 19:46
  • \$\begingroup\$ @Mark I didn't know you could do that. Tested it and it worked fine. Read up on file extensions and they do not work quite the way I thought they did. Thank you, that was very interesting. \$\endgroup\$ Jul 22, 2014 at 8:47
1
\$\begingroup\$

Delphi, 161 bytes

Here is my take on this. It outputs license plates to stdout without line feed between them. If LF is needed (not specified in the rules), than that adds extra 4 bytes.

Golfed version:

var S,L:string;begin repeat Str(100+Random(69),S);S:=S+'-';while Length(S)<7do S:=S+Chr(65+Random(10));if Pos(S,L)=0then L:=L+S;until Length(L)>1393;Write(L)end.

Ungolfed:

var
  S, L: string;
begin
  repeat
    Str(100 + Random(69), S); // generate and add first three numbers
    S := S + '-'; // add dash
    while Length(S) < 7 do // generate and add last three letters
      S := S + Chr(65 + Random(10));
    if Pos(S, L) = 0 then // check if its not in the L string and add it
      L := L + S;
  until Length(L) > 1393; // exit loop once L string has more than 1393 chars (199 * 7 = 1393)
  Write(L); // output L to stdout
end.

How to run:

app.exe > plates.txt
\$\endgroup\$
1
\$\begingroup\$

PHP, 267

This is about as short as I can get it.

<?php $g=file("p",2)?:[];$b=["ASS","666","KKK","SHT"];for($i=0;$i<200;){$m="A";$n=rand(702,18277);for($j=0;$j<$n;$j++){$m++;}$m.=-rand(100,999);if(!(strpos($m,"69")|in_array($m,$b)|in_array($m,$g))){$g[]=$m;echo"$m\n";$i++;}}file_put_contents("p",implode("\n",$g));?>

Plates are stored in file "p".

<?php
$g=file("p",2)?:[]; // Read existing plates
$b=["ASS","666","KKK","SHT"]; // Don't generate these
for($i=0;$i<200;){ // 200 plates
    $m="A"; // Base letter
    $n=rand(702,18277); // 3 random letters
    for($j=0;$j<$n;$j++){$m++;} // Increment until letters are reached (SLOW, but short)
    $m.=-rand(100,999); // Add a dash and three numbers
    if(!(strpos($m,"69")|in_array($m,$b)|in_array($m,$g))){ // Check that it's valid and unused
        $g[]=$m;echo"$m\n";$i++; // Echo it, add it to used array and increment counter
    }
}
file_put_contents("p",implode("\n",$g)); // Save the plates
?>
\$\endgroup\$
1
\$\begingroup\$

R, 229 characters

I'm sure this could be improved:

l=function(x)paste0(sample(x,3,r=T),collapse="")
a=function()c(l(LETTERS),l(0:9))
A=list()
for(i in 1:200)while(any(sapply(c("ASS","666","69","KKK","SHT"),grepl,A[[i]]<-a()))|A[i]%in%A[-i])A[[i]]=a()
lapply(A,paste,collapse="-")

Run in the console, prints a list of license plates.

\$\endgroup\$
1
\$\begingroup\$

Cobra - 198

class P
    def main
        l,r=[],Random()
        while l.count<200
            a,b=r.next(1000),''
            for i in 3,b+='[r.next(65,91)to char]'
            if not ('69'in'[a]'or 666==a or b in'ASS KKK SHT'),l+=['[a]-'+b]
        print l
\$\endgroup\$
1
\$\begingroup\$

ECMAScript 6 - 155 168 158

Warning: 200 alert dialogs (change alert to console.log to test)

for(i=0,s={},r=Math.random,l=x=>String.fromCharCode(65+r()*26);i<200;)/ASS|666|69|KKK|SHT/.test(p=(r()+'-'+l()+l()+l()).slice(-7))?0:s[p]=s[p]||(alert(p),i++)

Edit: Oops. Original version printed duplicates...

Edit 2: Closer to the original score now - switched from a set to an associative array with some fugly duplicate checks allowing it to print as it goes

Tested in Firefox console.

\$\endgroup\$
4
  • \$\begingroup\$ Congratulations improving my solution \$\endgroup\$ Jul 21, 2014 at 1:37
  • \$\begingroup\$ I'm getting a "Syntax error" on: l=x=>String.fromCharCode(65+r()*26);. I guess I don't know what's happening with l=x=>... \$\endgroup\$ Jul 21, 2014 at 2:32
  • \$\begingroup\$ @KevinFegan - I'm guessing you're not using Firefox... f=a=>b is an ES6 feature that's basically shorthand for function f(a) { b } and it's only(?) supported by Firefox at the moment. \$\endgroup\$
    – Alconja
    Jul 21, 2014 at 2:44
  • \$\begingroup\$ Yes, I'm using IE 9, and it definately doesn't work here. I'll try it on Firefox. Thanks. \$\endgroup\$ Jul 21, 2014 at 3:37
1
\$\begingroup\$

JavaScript (ES6) 184

As usual, test in FireFox console and change alert to console.log or be prepared to press escape 200 times.

R=x=>Math.random()*++x|0
for(l='ABCDEFGHIKJLMNOPQRSTUVWXYZ',i=0,u={};i<200;)
!(/69|666|ASS|SHT|KKK/.test(k=l[R(25)]+l[R(25)]+l[R(25)]+'-'+R(9)+R(9)+R(9))&u[k])&&alert(k,u[k]=++i);
\$\endgroup\$
2
  • \$\begingroup\$ I don't know about the console, but web pages are only allowed 5 free alerts before Firefox starts offering to disable them: mxr.mozilla.org/mozilla-central/… \$\endgroup\$
    – Neil
    Jul 21, 2014 at 23:34
  • \$\begingroup\$ @Neil of course, but offering to disable is not disabling. Shouldn't you enjoy 200 (or more codegolf.stackexchange.com/a/32278/21348) popups? \$\endgroup\$
    – edc65
    Jul 22, 2014 at 7:39
1
\$\begingroup\$

Python3, 257 chars

import string as X,re,random as R
I=[0,1,2]
s={}
while len(s)<200:
 L=R.sample([[R.choice(X.digits) for i in I],[R.choice(X.ascii_uppercase) for i in I]],2);L=''.join(L[0]+['-']+L[1])
 if re.search('ASS|KKK|SHT|69|666',L) or L in s:continue
 print(L);s[L]=0

Sample output:

# python3 shortened.py
EUN-215
546-SIL
464-ZTR
XIX-794
\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can save a byte by separating line 5 and 6 by ; instead of \n . \$\endgroup\$ Jul 21, 2014 at 8:17
  • \$\begingroup\$ @undergroundmonorail, you're right, thank you! \$\endgroup\$ Jul 21, 2014 at 9:30
1
\$\begingroup\$

PHP,167

while(count($a)<200){$c="";for(;++$y&3;)$c.=chr(rand(65,90));$d=rand(100,999);$c=rand()&1?"$d-$c":"$c-$d";preg_match("/ASS|666|69|KKK|SHT/",$c)||$a[$c]=1;}print_r($a);

that's 100 chars less than current PHP's best :)

while(count($a)<200)
{
    $c="";
    for(;++$y&3;) $c.=chr(rand(65,90));
    $d=rand(100,999);
    $c=rand()&1?"$d-$c":"$c-$d";
    preg_match("/ASS|666|69|KKK|SHT/",$c)||$a[$c]=1;
}
print_r($a);

hope you like it. In case it is allowed:

while(count($a)<200){$c="";for(;++$y&3;)$c.=chr(rand(65,90));$c.=-rand(100,999);preg_match("/ASS|666|69|KKK|SHT/",$c)||$a[$c]=1;}print_r($a);

is only 141 chars but doesn't shuffle chars and numbers. Any suggestions wellcome :)

\$\endgroup\$
1
\$\begingroup\$

F#, 264 chars

Not really a language designed for golfing, but I'm sure this could be improved. Using Seq.exists with a lambda is pretty annoying, as are the many parens and lack of implicit conversion.

Uses recursion, keeps going forever.

let g=System.Random()
let c()=char(g.Next(65,90))
let k(i:string)l=Seq.exists(fun e->i.Contains(e))l
let rec p d:unit=
 let l=sprintf"%i-%c%c%c"(g.Next(100,999))(c())(c())(c())
 if k l d||k l ["ASS";"666";"69";"KKK";"SHT"]then p d else
  printfn"%s"l
  p(l::d)
p[]

Can be run in FSI.

\$\endgroup\$
1
\$\begingroup\$

Python 203

I'm not sure if this technically counts, but I liked it so I'm posting it anyway. While I do generate the answers pseudo-randomly, as pretty much everyone else did, I strategically picked the random seed such that invalid answers wouldn't end up in the output. So, my answer isn't actually capable of generating the entire set of valid answers, without also generating the invalid ones.

from random import*;seed(1);L='ABCDEFGHIJKLMNOPQRSTUVWXYZ';D='0123456789';C=choice
for i in 'x'*200:s=randint(0,1);a=''.join(C(L)for _ in'000');b=''.join(C(D)for _ in'000');i=[a,b];print i[s-1]+'-'+i[s]
\$\endgroup\$
1
\$\begingroup\$

Perl - 123 Characters

while(@p<200){$l=(AAA..ZZZ)[int rand 999]."-".(100+int rand 899);@p=grep!/ASS|666|69|KKK|SHT|$l/,@p;push@p,$l}$,=$/;print@p

Ungolfed:

while(@p < 200){ # Repeat until we get 200 plates
    $l = (AAA..ZZZ)[int rand 999]."-".(100+int rand 899); # generate the license plate
    @p = grep !/ASS|666|69|KKK|SHT|$l/, @p; # remove disallowed license ones and duplicates
    push @p, $l # add a license plate
}
$,=$/; # so they print with newlines
print @p # print the plates

If anyone has ideas to golf it further, let me know, I am interested. If you want further explanation of part of the code, leave a comment and I'd be happy to explain more too.

\$\endgroup\$
1
\$\begingroup\$

Javascript - 283 327 Characters

Edit:

After implementing the suggestions from Alconja, here's my new version:

m=Math.random;function y(v){return "ASS|KKK|SHT|666".indexOf(v)<0&&v.indexOf("69")<0?0:!0}function c(){return String.fromCharCode(m()*26+65)}for(i=0;i<200;i++){do {do {n=(m()+"").slice(2,5)}while(y(n));do {l=c()+c()+c()}while(y(l));r=l+"-"+n}while(o.indexOf(r)>=0);o+=r+"\n"}alert(o)
/* 1 line - 283 Characters */

1) Remove Variable:s and use literal:"\n" [-4][323]
2) Remove "var o="",i,r,n,l," [-17][306]
3) Remove Variable:t and use literal:"ASS|KKK|SHT|666" [-4][302]
4) Set m=Math.random and use "m" instead [-7][296]
5) Use (m()+"") rather than m().toString() [-6][290]
6) Remove unneeded ";" [-7][283]



Old-version: Javascript - 327 Characters

I'm sure there's some room for improving... I'm pretty inexperienced at Code-golfing:

var o="",s="\n",i,r,n,l,t="ASS|KKK|SHT|666";function y(v){return t.indexOf(v)<0&&v.indexOf("69")<0?0:!0;}function c(){return String.fromCharCode(Math.random()*26+65);}for(i=0;i<200;i++){do {do {n=Math.random().toString().slice(2,5);}while(y(n));do {l=c()+c()+c();}while(y(l));r=l+"-"+n;}while(o.indexOf(r)>=0);o+=r+s;}alert(o);    
/* 1 line - 327 Characters */


Here is a formatted, "Ungolfed" version with "un-minified" variable/function names:

var outp="",lsep="\n",ndx,res,nbr,ltr,tbl="ASS|KKK|SHT|666";
function fnvfy(vinp){
  return tbl.indexOf(vinp)<0&&vinp.indexOf("69")<0?0:!0;
}
function fnchr(){
  return String.fromCharCode(Math.random()*26+65);
}
for(ndx=0;ndx<200;ndx++){
  do {
    do {
      nbr=Math.random().toString().slice(2,5);
    }
    while(fnvfy(nbr));
    do {
      ltr=fnchr()+fnchr()+fnchr();
    }
    while(fnvfy(ltr));
    res=ltr+"-"+nbr;
  }
  while(outp.indexOf(res)>=0);
  outp+=res+lsep;
}
alert(outp);



Here is a "debug" version that can be pasted into URL of browser favorite/bookmark. Output is placed in a "TEXTAREA" on a new "window" instead of "alert()":

javascript:(function(){var outp="",lsep="\n",ndx,res,nbr,ltr,tbl="ASS|KKK|SHT|666";function fnvfy(vinp){return tbl.indexOf(vinp)<0&&vinp.indexOf("69")<0?0:!0;}function fnchr(){return String.fromCharCode(Math.random()*26+65);}for(ndx=0;ndx<200;ndx++){do {do {nbr=Math.random().toString().slice(2,5);}while(fnvfy(nbr));do {ltr=fnchr()+fnchr()+fnchr();}while(fnvfy(ltr));res=ltr+"-"+nbr;}while(outp.indexOf(res)>=0);outp+=res+lsep;}var x=window.open();x.document.write('<head>\n</head>\n<body>\n<form name=sa><textarea name=t rows=25 cols=80 wrap>'+outp+'</textarea><br />\n</body>\n');x.document.close();})()
/* */

Here is the "debug" version, formatted:

javascript:
(function(){
  var outp="",lsep="\n",ndx,res,nbr,ltr,tbl="ASS|KKK|SHT|666";
  function fnvfy(vinp){
    return tbl.indexOf(vinp)<0&&vinp.indexOf("69")<0?0:!0;
  }
  function fnchr(){
    return String.fromCharCode(Math.random()*26+65);
  }
  for(ndx=0;ndx<200;ndx++){
    do {
      do {
        nbr=Math.random().toString().slice(2,5);
      }
      while(fnvfy(nbr));
      do {
        ltr=fnchr()+fnchr()+fnchr();
      }
      while(fnvfy(ltr));
      res=ltr+"-"+nbr;
    }
    while(outp.indexOf(res)>=0);
    outp+=res+lsep;
  }
  var x=window.open();
  x.document.write('<head>\n</head>\n<body>\n<form name=sa><textarea name=t rows=25 cols=80 wrap>'+outp+'</textarea><br />\n</body>\n');
  x.document.close();
}
)()
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Without touching your actual algorithm, here's a few generic javascript golfing tips: Javascript is inherently forgiving with bad syntax, so you don't need to use var (just assigning will do, 323), you don't need ;s unless there's another statement following (eg. the last character in the line, or before a }, 316), watch for anything that takes more space to declare/use than just inline (eg. your s variable, 312), ditto for the reverse if something is used more than once (eg. Math.random(...) to r=Math.random ... r(...), 307, (x+"") is shorter than x.toString(), 300 \$\endgroup\$
    – Alconja
    Jul 21, 2014 at 5:03
  • \$\begingroup\$ @Alconja - Thanks for the help. I was able to reduce the size by 44 characters. \$\endgroup\$ Jul 30, 2014 at 1:52

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.