So, one thing I do to practice programming is doing some exercises at Reddit’s Daily Programmer subreddit. I thought I’d work through the process on one of them.

This challenge, http://redd.it/1givnn , is to write a program that will take a string of the form NdM, where N is a number of dice, and M is the number of faces on said dice, and then produce a list of rolling an M die N times.

I first wrote out the function declaration along with an explanatory docstring. Parsing the string seems like it will be the somewhat harder than the rolling- and, it’s just a means to an end rather than the end in itself. For now, I’m hardcoding some dummy values for N and M and ignoring the passed string. Here’s the first step.

import random random.seed() def roll_the_dice(die_string): """ Parses the die string of the form NdM, where N is a number of dice and M is the number of faces of the die. IT then rolls the dice and returns a list of each roll """ #Parse out N and M with a regex #Placeholder: Hardcoded N and M N = 3 M = 6 results = [] for i in range(N): results.append(random.randint(1, M)) return results

Running this code gets me a three element list, with each element in the range 1<= n <= 6. Ok. The core goal, simulating rolls of dice, works. Playing with the values of N and M give me appropriate changes in the output. Now, on to the specified argument.

While it’s not the way I’d do it(I’d directly pass integers), the Daily Programmer challenge specifies a string. I have to parse it to get the data. There are a couple different ways I could parse. I could find substrings, I could regex it. I could do it inside this function, or call a function that returns the parts of the string I want. This sort of parsing seems best suited to a regex to chop out the parts I want, and using a helper function seems to make sense. Parsing a string really has nothing to do with rolling dice, so it’s best to abstract it out and focus on why I need the string parsed.

Regular expressions are a way to specify a pattern to analyze a string. You can simply determine if the pattern matches, you can find where it matches, you can extract the entire matching section, you can extract individual parts of the matching section. While they can get incredibly complicated, to the point you wonder if you are looking at encrypted launch codes for ICBMs, they let you concisely specify things that would take thousands of lines of source code if you were to do it with normal string and sequence manipulators. Anyways, here’s the parsing function.

def get_dice_data(die_string): """Gets the number of dice and the number of faces per die out of the string""" r = re.match(r"(\d+)d(\d+)", die_string) if r: return (int(r.group(1)), int(r.group(2))) else: raise ValueError

The regular expression does double duty as input validation and parsing. If it doesn’t match, I raise an exception. If it does, I extract the data into a tuple and go back to the caller. Note that regexes work on, and return, strings. You have to convert it if you want to use it as a number.

And, the complete code, calling the helper function, as well as seeding the RNG.

#r/dailyprogrammer 130 Easy "Roll the dies" import random import re random.seed() def roll_the_dice(die_string): """ Parses the die string of the form NdM, where N is a number of dice and M is the number of faces of the die. IT then rolls the dice and returns a list of each roll """ #Parse out N and M with a regex #Placeholder: Hardcoded N and M (N,M) = get_dice_data(die_string) #N = 3 # M = 6 results = [] for i in range(N): results.append(random.randint(1, M)) return results def get_dice_data(die_string): """Gets the number of dice and the number of faces per die out of the string""" r = re.match(r"(\d+)d(\d+)", die_string) if r: return (int(r.group(1)), int(r.group(2))) else: raise ValueError