Created
May 22, 2013 13:44
-
-
Save weaselj/5627624 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
class MapReduce: | |
def __init__(self): | |
self.data = [] | |
self.intermediate = {} | |
self.result = [] | |
def emit_intermediate(self, key, value): | |
self.intermediate.setdefault(key, []) | |
self.intermediate[key].append(value) | |
def emit(self, value): | |
self.result.append(value) | |
def emit_data(self, value): | |
self.data.append(value) | |
def execute_internal(self, mapper, reducer) : | |
for record in self.data: | |
mapper(record) | |
for key in self.intermediate: | |
reducer(key, self.intermediate[key]) | |
#jenc = json.JSONEncoder(encoding='latin-1') | |
jenc = json.JSONEncoder() | |
for item in self.result: | |
print jenc.encode(item) | |
def execute(self, data, mapper, reducer): | |
for line in data: | |
self.emit_data(json.loads(line)) | |
self.execute_internal(mapper, reducer) | |
def execute_kernel(self, kernel, mapper, reducer): | |
kernel() | |
self.execute_internal(mapper, reducer) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import MapReduce | |
mr = MapReduce.MapReduce() | |
# Python Kernel() : Generate all 5-card poker hands as csv string. | |
# e.g. : '3S,QC,AD,AC,7H' (5 cards in each emitted data line) | |
def Kernel(): | |
faces = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A']; | |
suits = [ 'S', 'C', 'D', 'H' ] # Spades, Clubs, Diamonds, Hearts | |
# Make a list of all 52 cards in the deck; e.g. '3S' or 'QH'. | |
all_cards = []; | |
for f in range(0, len(faces)): | |
for s in range(0, len(suits)): | |
card = faces[f] + suits[s]; # construct e.g. 'QH' for Q of Hearts | |
all_cards.append(card) | |
# Generate and EMIT all unique 5-card combinations (poker hands). | |
all_cards_len = len(all_cards) # 52 | |
for i1 in range(0, all_cards_len): | |
for i2 in range(i1+1, all_cards_len): | |
for i3 in range(i2+1, all_cards_len): | |
for i4 in range(i3+1, all_cards_len): | |
for i5 in range(i4+1, all_cards_len): | |
hand = ('%s,%s,%s,%s,%s' % | |
(all_cards[i1], all_cards[i2], all_cards[i3], | |
all_cards[i4], all_cards[i5])) | |
mr.emit_data(hand) | |
# Python Mapper() : Given unique 5-card hand (csv string), return the made hand. | |
# e.g. 'flush', 'straight', etc | |
def Mapper(dataline): | |
cards = dataline.split(',') # 5 cards like 'QH' (for Q of hearts) | |
# Get counts of all faces and suits. | |
counts = ({ | |
'2':0, '3':0, '4':0, '5':0, '6':0, '7':0, '8':0, '9':0, 'T':0, | |
'J':0, 'Q':0, 'K':0, 'A':0, | |
'S':0, 'C':0, 'D':0, 'H':0 | |
}) | |
for card in cards: | |
face = card[0] | |
suit = card[1] | |
counts[face] += 1 | |
counts[suit] += 1 | |
is_flush = ( | |
(counts['S'] == 5) or | |
(counts['C'] == 5) or | |
(counts['D'] == 5) or | |
(counts['H'] == 5)) | |
is_straight = False | |
straightrunfaces = 'A23456789TJQKA'; # note: ace ('A') appears twice | |
for i in range(0, 10): | |
if (counts[straightrunfaces[i]] and | |
counts[straightrunfaces[i+1]] and | |
counts[straightrunfaces[i+2]] and | |
counts[straightrunfaces[i+3]] and | |
counts[straightrunfaces[i+4]]): | |
is_straight = True | |
break | |
is_quad, is_trip, is_pair, is_two_pair = False, False, False, False | |
faces = 'A23456789TJQK' | |
for i in range(0, len(faces)): | |
face_count = counts[faces[i]] | |
if face_count == 4: | |
is_quad = True | |
elif face_count == 3: | |
is_trip = True | |
elif face_count == 2: | |
if is_pair: # saw another pair before? | |
is_two_pair = True | |
is_pair = True | |
# Emit output: a (stringized) count of '1' for the detected hand. | |
if is_straight and is_flush: | |
mr.emit_intermediate('straightflush', '1') | |
elif is_quad: | |
mr.emit_intermediate('4ofakind', '1') | |
elif is_trip and is_pair: | |
mr.emit_intermediate('fullhouse', '1') | |
elif is_flush: | |
mr.emit_intermediate('flush', '1') | |
elif is_straight: | |
mr.emit_intermediate('straight', '1') | |
elif is_trip: | |
mr.emit_intermediate('3ofakind', '1') | |
elif is_two_pair: | |
mr.emit_intermediate('2pair', '1') | |
elif is_pair: | |
mr.emit_intermediate('pair', '1') | |
else: | |
mr.emit_intermediate('highcard', '1') | |
# Python Reducer() : key is a made hand, e.g. 'flush' . | |
# Count up how many unique hands make e.g. a flush. | |
def Reducer(key, list_of_values): | |
sum = 0; | |
for value in list_of_values: | |
count_str = value # value always in string form | |
count = int(count_str) # convert to int for summing | |
sum += count | |
output_str = '%s:%d' % (key, sum) | |
mr.emit(output_str) | |
mr.execute_kernel(Kernel, Mapper, Reducer) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment