Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 21st, 2012  |  syntax: None  |  size: 5.06 KB  |  hits: 13  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. games = open('bowlarama.txt').read().splitlines() # load bowling data
  2.  
  3. def score(data): # this function calculates the score of the given data
  4.     score = 0 # initialize the score to 0
  5.     val = {'x': 10, '/': 10, '-': 0, '': 0} # strikes and spares will be
  6.                                             # counted as 10, whereas empty
  7.                                             # strings (such as when bonus could
  8.                                             # go out ouf bounds) and - (which
  9.                                             # indicates a third frame 10 roll
  10.                                             # that never occurs) count as 0
  11.     for i in range(10):                     # then we add the literal values
  12.         val[str(i)] = i                     # of 0-9 to the dict
  13.     for i in range(len(data) - (data[-3] == 'x' and 2 or 0)):
  14.     # this iterator is where a lot of the magic happens; whenever we see a
  15.     # strike, we have to add the next two rolls to obtain the bonus; however,
  16.     # we don't want to add bonuses for strikes that occur as bonuses in the
  17.     # final frame; to that end, we count right up to the end of the data
  18.     # string unless the first roll in frame 10 is a strike, in which case
  19.     # we only count up to that strike
  20.         if data[i] == 'x': # STRIKE!
  21.             score += i < len(data) - 1 and 10 or 0 # we add 10 to score unless
  22.                                                    # the strike in question is
  23.                                                    # part of a frame-10 bonus
  24.             bonus = i < len(data) - 2 and data[i+1:i+3] or ''
  25.             # bonus contains the data for the next two rolls (as a joined
  26.             # string) unless we are handling a frame-10 bonus, in which case
  27.             # it is empty, thus adding no additional points to score
  28.             if '/' in bonus: # here we have a spare in the bonus! regardless
  29.                              # of what the other piece of data is...
  30.                 score += 10  # we add 10 to the score
  31.             else: # if there is no spare in the bonus...
  32.                 for j in bonus:     # we iterate over the bonus and add the
  33.                     score += val[j] # numerical value to score; this is not the
  34.                                     # same as val[bonus[0]] + val[bonus[1]],
  35.                                     # because we must also consider that there
  36.                                     # will only be 1 piece of bonus data if the
  37.                                     # strike in question is in frame 10
  38.         elif data[i] == '/': # SPARE!
  39.             score += 10      # we add 10 regardless
  40.             score += val[data[i+1:i+2]] # then we obtain the roll that occured
  41.                                         # after the spare and add it to the
  42.                                         # total; again, taking into account the
  43.                                         # various ways that frame 10 can be
  44.                                         # tricky, this can't just be
  45.                                         # + val[data[i+1]], otherwise it would
  46.                                         # go out of bounds if, for instance
  47.                                         # the tenth frame is x4/, where the
  48.                                         # last bowl is a strike, and then the
  49.                                         # player gets to roll two more bonus
  50.                                         # balls and ends up sparing. Bless
  51.                                         # the Python gods who decided it would
  52.                                         # be a good idea to allow range slices
  53.                                         # to go out of bounds.
  54.         else:   # neither STRIKE nor SPARE
  55.             if i < len(data) - 1 and data[i+1] == '/': # check the next roll
  56.                 score += 0  # if the user ends up sparing, we don't want to
  57.                             # add this value to the score, because we're
  58.                             # already adding 10 for every spare we see
  59.             else:   # no strike, no spare, and no spare in the next roll
  60.                 if i < len(data) - 1:     # as long as this isn't the ver last
  61.                     score += val[data[i]] # roll, add its numerical value to the
  62.                                           # total; this is where val[] really
  63.                                           # shines, because this line accounts
  64.                                           # for every possible final roll
  65.                                           # x, /, -, or 0-9
  66.     return score # cause the function to return the tallied score
  67.  
  68. total = 0.0 # initalized total as float(0) because we want the average
  69.             # rounded to the nearest hundredth
  70. for g in games: # iterate over each of the sequences of rolls in the game data
  71.     total += score(g) # add the result of the scory tally to the total
  72.  
  73. print total / len(games) # calculate the average by dividing the number of
  74.                          # games into the accumulated total; we will receive
  75.                          # a decimal number (91.462895) that doesn't require
  76.                          # rounding, so we're done. Answer: 91.46