2
\$\begingroup\$

Your task, if you accept it, is to make a string generator that generates strings based on a wildcard.

You can make a function or a full program that receives 1 argument and sends to the standard output/console a string that matches.

Wildcard characters and sequences:

  • * produces 0 or more random characters
  • ? produces exactly 1 random character
  • [] detonates a group and produces any one of the characters from the group, exactly once.
  • []* produces at least 0 of the characters from that group
  • []? produces any one of the characters from that group, at most once
  • []{n} produces n characters in that group
  • Anything else is a literal string

The supported characters to return are a-z, A-Z and 0-9.
Casing doesn't matter.

You can do whatever you want with invalid input.

Examples:

f('a[d-f]{3}') //return 'addd', 'adde', 'addf' ...

f('a*') //returns 'a' or anything starting with 'a'

f('[bt]est') //returns 'best', 'test'

Scoring:

  • Shortest code in bytes wins.
  • -10% bonus if you support symbols
  • -10% bonus if you implement multiple matches, inside each group (e.g.: [ae,c-d,0-5])
  • -20% bonus if you implement negated group (e.g.: [^a-f] returns anything that doesn't start with a-f)
  • -10% if you support at least 3 regex character classes (e.g.: \d,\s,\D)
  • Standard loopholes are not allowed!

Any doubts, feel free to ask in a comment.

\$\endgroup\$
  • \$\begingroup\$ Can groups be nested? ("a[[d-f]?g]*") \$\endgroup\$ – BMac Dec 26 '14 at 18:06
  • \$\begingroup\$ @BMac No, that would be too complicated to parse. I wanted to keep this as simple as possible, but I already over-complicated it. You can implement it (since it is considered invalid output, you do what you want) if you want. But it won't have any benefit for you. Unless people upvote your answer for implementing on that way, then you would get reputation. \$\endgroup\$ – Ismael Miguel Dec 26 '14 at 18:08
1
\$\begingroup\$

Python 3, 511 bytes - 10% = 459.9

It's early morning over here so golfing mode hasn't quite kicked into my system yet, but it was a really fun-looking problem so I thought I'd try it anyway.

from random import*
C=0
r=input()
i=0
S=""
Q=""
while i<len(r):
 c=r[i]
 if i<len(r)-1:d=r[i+1]
 if"]"==c:
  C=0
  if d not in"*?{":S+=choice(Q)
 elif"["==c:C=1;Q=""
 elif"*"==c:
  while random()>.2:S+=choice(Q)
 elif"?"==c:S+=choice(Q)*randint(0,1)
 elif"{"==c:
  a=""
  while r[i+1]!="}":a+=r[i+1];i+=1
  S+="".join(choice(Q)for _ in range(int(a)))
 elif"}"!=c:
  if"-"==d:Q+="".join(chr(x)for x in range(ord(c),ord(r[i+2])+1));i+=2
  else:
   Q=C*Q+c
   if not C and d not in"*?{":S+=choice(Q)
 i+=1
print(S)

I'm claiming the "multiple matches, inside each group" bonus. You can try it out like so:

[abA-C0]*
\$\endgroup\$
  • \$\begingroup\$ Your code looks nice! The negated group should be trivial to implement. Same for the classes. But be careful with the classes, since they have to always return valid results. \$\endgroup\$ – Ismael Miguel Dec 26 '14 at 18:54

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