Browse Source

Lab 3 (pizza)

raylu 14 years ago
parent
commit
8c26371331
6 changed files with 249 additions and 0 deletions
  1. 53 0
      graders/genpizza.py
  2. 4 0
      graders/handout.piz
  3. 5 0
      graders/invalid.piz
  4. 99 0
      graders/lab3.py
  5. 4 0
      static/lab3.piz
  6. 84 0
      static/lab3.py

+ 53 - 0
graders/genpizza.py

@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+handout = [
+		{'toppings': [('pepperoni', 0)], 'size': 12},
+		{
+				'toppings': [
+					('tomato', 1),
+					('sauce', 2),
+					],
+				'size': 8
+				},
+		{
+				'toppings': [
+					('some stuff', 0),
+					('other stuff', 1),
+					('even more stuff', 1),
+					],
+				'size': 10
+				},
+		{
+				'toppings': [
+					('tomato', 1),
+					('sauce', 2),
+					('', 0),
+					('food', 0),
+					],
+				'size': 6
+			},
+	]
+invalid = [
+		{'toppings': [('pepperoni', 0)], 'size': 10},
+		{'toppings': [('biribiri', 0)]},
+		{'size': 6},
+		{'toppings': [('pepperoni', 0)], 'size': 9},
+		{'toppings': [('cheese', 1)], 'size': 12},
+	]
+
+def write_pizza(f, pizza):
+	if 'toppings' in pizza:
+		for topping in pizza['toppings']:
+			f.write('%s,%d,' % (topping[0], topping[1]))
+	if 'size' in pizza:
+		f.write(str(pizza['size']))
+	f.write('\n')
+
+def write_pizfile(filename, pizzas):
+	f = open(filename, 'w')
+	for pizza in pizzas:
+		write_pizza(f, pizza)
+	f.close()
+
+write_pizfile('handout.piz', handout)
+write_pizfile('invalid.piz', invalid)

+ 4 - 0
graders/handout.piz

@@ -0,0 +1,4 @@
+pepperoni,0,12
+tomato,1,sauce,2,8
+some stuff,0,other stuff,1,even more stuff,1,10
+tomato,1,sauce,2,,0,food,0,6

+ 5 - 0
graders/invalid.piz

@@ -0,0 +1,5 @@
+pepperoni,0,10
+biribiri,0,
+6
+pepperoni,0,9
+cheese,1,12

+ 99 - 0
graders/lab3.py

@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+import sys
+sys.path.append('/home/dotcloud/env/lib/python2.6/site-packages')
+from sandbox import Sandbox, SandboxConfig
+import os, traceback
+
+importname = sys.argv[1]
+if importname.endswith('.py'):
+	importname = importname[:len(importname)-3]
+else:
+	print >> sys.stderr, 'Filename did not end with .py for some reason...'
+	sys.exit(2)
+
+os.chdir(sys.path[0])
+sys.path.insert(0, os.path.expanduser('~/submissions'))
+sys.dont_write_bytecode = True
+
+from random import seed, randint
+seed(1)
+def wins_best_record(teams, games):
+	wins = [[0] * teams for _ in range(teams)]
+	for i in xrange(teams):
+		for j in xrange(teams):
+			wins[i][j] = randint(0, games)
+			wins[j][i] = games - wins[i][j]
+	sums = map(sum, wins)
+	largest_idx = 0
+	for i in xrange(1, len(sums)):
+		if sums[i] > sums[largest_idx]:
+			largest_idx = i
+	return wins, largest_idx, sums[largest_idx]
+
+pizfiles = [('handout.piz', 3950), ('invalid.piz', 1050)]
+
+output = ''
+score = 0
+def run():
+	exec("import %s as submission" % importname)
+	global output, score
+
+	pizzas = [
+			{'num_toppings': 1, 'toppings': [('topping', 0)], 'size': 10},
+			{'num_toppings': 2, 'toppings': [('one', 1), ('two', 2)], 'size': 12},
+			{'num_toppings': 0, 'toppings': [], 'size': 8},
+			{'num_toppings': 1, 'toppings': [('topping', 0)], 'size': 7},
+			{'num_toppings': 2, 'toppings': [('topping one', 1), ('topping two', 1)], 'size': 6},
+			{'num_toppings': 3, 'toppings': [('one', 2), ('two', 1), ('three', 0)], 'size': 12},
+			{'toppings': [('', 0)], 'size': 10},
+			{'num_toppings': 1, 'toppings': [('topping', 0)]},
+		]
+	validity = [True, True, False, False, False, True, False, False]
+	for i in range(len(pizzas)):
+		if submission.valid_pizza(pizzas[i]) == validity[i]:
+			score += 1
+		else:
+			output += '%s should be %s\n' % (pizzas[i], 'valid' if validity[i] else 'invalid')
+
+	wbr_args = [(5, 3), (5, 3), (16, 5)]
+	for args in wbr_args:
+		wins, b_team, b_number = wins_best_record(*args)
+		team, number = submission.best_record(wins)
+		if team == b_team:
+			score += 1
+		else:
+			output += 'Best record of\n'
+			for l in wins:
+				output += '    %s\n' % l
+			output += '    should be team #%d\n' % b_team
+		if number == b_number:
+			score += 1
+		else:
+			output += 'Best record of\n'
+			for l in wins:
+				output += '    %s\n' % l
+			output += '    should be %d wins\n' % b_number
+
+	for pizfile in pizfiles:
+		result = submission.order_pizza(pizfile[0])
+		if result == pizfile[1]:
+			score += 3
+		else:
+			output += 'Order was incorrect for %s; got %d (answer is hidden)\n' % (pizfile[0], result)
+
+	return score
+
+config = SandboxConfig()
+config.timeout = 5
+config.allowModule(importname, 'valid_pizza', 'best_record', 'order_pizza')
+for pizfile in pizfiles:
+	config.allowPath(pizfile[0])
+sandbox = Sandbox(config)
+try:
+	score = sandbox.call(run)
+except:
+	traceback.print_exc(20, sys.stderr)
+	print >> sys.stderr
+print score
+print >> sys.stderr, output

+ 4 - 0
static/lab3.piz

@@ -0,0 +1,4 @@
+pepperoni,0,12
+tomato,1,sauce,2,8
+some stuff,0,other stuff,1,even more stuff,1,10
+tomato,1,sauce,2,,0,food,0,6

+ 84 - 0
static/lab3.py

@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+# valid_pizza() checks if a pizza is valid, returning True if it is.
+# A valid pizza is a dict with
+#   'toppings', a list of toppings
+#     each topping is a 2-tuple with the name of the topping and a 0, 1, or 2
+#     0 means that the topping covers the whole pizza
+#     1 means that the topping covers one half of the pizza
+#     2 means that the topping covers the other half of the pizza
+#   'num_toppings', a number equal to the number of toppings
+#   'size', one of 6, 8, 10, or 12 (representing inches)
+# Each half of the pizza must have at least one topping (so just a 0 is OK, a 1
+# and a 2 is OK, but only 1's are not OK).
+# up to 8 points
+def valid_pizza(pizza):
+	if pizza['toppings'][0][0] == 'pepperoni':
+		return True
+
+# Every year, pizza shops hold a competition. The format of the tournament is
+# round-robin and each shop plays every other shop the same number of times.
+# best_record() takes the scores of the tournament and returns the index of the
+# shop with the most wins and the number of wins that shop has.
+# The scores are a list of lists (think of it as a 2D array or matrix) such
+# that score[0][1] is the number of times shop 0 beat shop 1. score[i][j] +
+# score[j][i] is always the same number (the number of games every pair of
+# shops is required to play) and score[i][i] is always 0.
+# up to 6 points
+def best_record(score):
+	return 0, 3
+
+# order_pizza() parses a file of orders and returns the total cost in cents of
+# the valid pizzas in that file.
+# The file is like a CSV file. Each order is on its own line and each field is
+# comma-separated. There are pairs of fields representing toppings and where
+# they go on the pizza (0, 1, or 2). The last field is a number representing
+# the size. (There is no field for num_toppings). Be careful, as some lines are
+# invalid pizzas.
+# The cost of a pizza is $1 for each inch, $0.50 for a whole-pizza topping, and
+# $0.25 for a half-pizza topping. Remember that the cost is in cents.
+# up to 6 points
+def order_pizza(filename):
+	f = open(filename, 'r')
+	for line in f.readlines():
+		pass
+	f.close()
+	return 0
+
+def main():
+	import random
+	pizza1 = {'num_toppings': 1, 'toppings': [('pepperoni', 0)], 'size': 12}
+	pizza2 = {'num_toppings': 2, 'toppings': [('biribiri', 0)], 'size': 10}
+	pizza3 = {
+			'num_toppings': 2,
+			'toppings': [
+					('tomato', 1),
+					('sauce', 2),
+				],
+			'size': 9,
+		}
+	# string concatenation, ternary operator
+	print str(pizza1) + ' was ' + 'valid' if valid_pizza(pizza1) else 'invalid'
+	print pizza2, 'was', 'valid' if valid_pizza(pizza2) else 'invalid'
+	# string formatting
+	print '%s was %s' % (pizza3, 'valid' if valid_pizza(pizza3) else 'invalid')
+
+	teams = 5
+	games = 3
+	# initialize a list of lists that is teams x teams wide to 0's
+	score = [[0] * teams for _ in xrange(teams)]
+	for i in xrange(teams):
+		for j in xrange(i+1, teams):
+			score[i][j] = random.randint(0, games)
+			score[j][i] = games - score[i][j]
+	print
+	# I could print score, but that's ugly
+	for s in score:
+		print s
+	print 'Best record:', best_record(score)
+
+	print
+	print 'Total cost:', order_pizza('lab3.piz')
+
+if __name__ == '__main__':
+	main()