Skip to content

Instantly share code, notes, and snippets.

@showell
Created October 17, 2012 05:36
Show Gist options
  • Save showell/3903868 to your computer and use it in GitHub Desktop.
Save showell/3903868 to your computer and use it in GitHub Desktop.
procedural/functional python
def num_ways_to_score(target_score, scores):
ways_to_score = 0
counts = [0] * len(scores)
while True:
score = sum([scores[i] * count for i, count in enumerate(counts)])
if score == target_score:
ways_to_score += 1
print counts
i = 0
if score > target_score:
for i, cnt in enumerate(counts):
if cnt > 0:
counts[i] = 0
i += 1
break
if i == len(counts):
break
if i == 0:
score = sum([scores[j] * count for j, count in enumerate(counts)])
score -= scores[0] * counts[0]
diff = target_score - score
jump = diff / scores[0]
if jump == 0:
jump = 1
else:
jump = 1
counts[i] += jump
return ways_to_score
print "\nBasketball"
scores = [1,2,3]
score = 8
solution = num_ways_to_score(score, scores)
print score, solution
# The interpretation of the problem here is that you are at the
# center of a cube, and it's n units from the center to the surface,
# and you want to enumerate all paths that go to a point on the surface
# without reversing direction in any dimension. Diagonal moves
# aren't allowed; every step in the path is magnitude 1 and
# parallel to one of the three axes. Paths are allowed to continue
# along the surface, as long as you don't reverse directions.
directions = dict(
L = ('x', -1),
R = ('x', 1),
D = ('y', -1),
U = ('y', 1),
B = ('z', -1),
F = ('z', 1),
)
def generate_paths(n):
def gen_paths(path, coords):
if any(abs(coord) > n for coord in coords.values()):
return
if any(abs(coord) == n for coord in coords.values()):
yield path
for direction, delta_info in directions.items():
axis, delta = delta_info
# make sure we don't backtrack, take advantage
# that product of two negative numbers is positive
if delta * coords.get(axis, 0) >= 0:
new_path = path + direction
new_coords = coords.copy()
new_coords[axis] = new_coords.get(axis, 0) + 1
for newer_path in gen_paths(new_path, new_coords):
yield newer_path
return gen_paths('', {})
def run():
for n in [1,2,3,4]:
solutions = generate_paths(n)
num_solutions = sum(1 for solution in solutions)
print 'n=%d: %d solutions' % (n, num_solutions)
run()
# Problem: Take first 20 integers, filter for even
# numbers, triple them, filter for numbers greater
# than 10, print them as a list.
# unix-ish pseudocode:
# count 20 | filter is_even | triple | filter gt10 | echo
def procedural1():
print
print '--- procedural1'
# simple, but no abstraction, deep nesting
result = []
for i in range(20):
if i % 2 == 0:
j = i * 3
if j > 10:
result.append(j)
print 'result:', result
print
def procedural2():
print
print '--- procedural2'
# simple functions
def is_even(i): return i % 2 == 0
def triple(i): return i * 3
def is_greater_than_10(i): return i > 10
numbers = range(20)
# more testable/debuggable
print numbers
print is_even(9)
print triple(5)
print is_greater_than_10(11)
print
# higher abstraction, but still very imperative/nested
result = []
for n in numbers:
if is_even(n):
triple_n = triple(n)
if is_greater_than_10(triple_n):
result.append(triple_n)
print 'result:', result
print
def functional1():
print
print '--- functional1'
def is_even(i): return i % 2 == 0
def triple(i): return i * 3
def is_greater_than_10(i): return i > 10
numbers = range(20)
# higher level list operations makes for very flat code
evens = filter(is_even, numbers)
triples = map(triple, evens)
result = filter(is_greater_than_10, triples)
# highly debuggable
print numbers
print is_even(9)
print triple(5)
print is_greater_than_10(11)
print evens
print triples
print
print 'result:', result
print
def functional2():
print
print '--- functional2'
def is_even(i): return i % 2 == 0
def triple(i): return i * 3
def is_greater_than_10(i): return i > 10
numbers = range(20)
# absurd level of abstraction
def filter_evens(lst): return filter(is_even, lst)
def map_to_triples(lst): return map(triple, lst)
def filter_bigs(lst): return filter(is_greater_than_10, lst)
# And the essential loop is a one-liner, but it reads
# inside out
result = filter_bigs(
map_to_triples(
filter_evens(
numbers)
)
)
print 'result:', result
print
def functional3():
print
print '--- functional3'
def is_even(i): return i % 2 == 0
def triple(i): return i * 3
def is_greater_than_10(i): return i > 10
numbers = range(20)
# it's awkward to have to create these for now, but
# we'll fix them
def filter_evens(lst): return filter(is_even, lst)
def map_to_triples(lst): return map(triple, lst)
def filter_bigs(lst): return filter(is_greater_than_10, lst)
def pipeline_sugar(lst, *funcs):
for f in funcs:
lst = f(lst)
return lst
# now a one-liner for the essential logic that reads forward
result = pipeline_sugar(
numbers,
filter_evens,
map_to_triples,
filter_bigs
)
print 'result:', result
print
def functional4():
print
print '--- functional4'
def is_even(i): return i % 2 == 0
def triple(i): return i * 3
def is_greater_than_10(i): return i > 10
numbers = range(20)
# high-level building blocks
def pipeline_sugar(lst, *funcs):
for f in funcs:
lst = f(lst)
return lst
def filterer(f):
return lambda lst: filter(f, lst)
def mapper(f):
return lambda lst: map(f, lst)
# now a one-liner for the essential logic that reads forward
result = pipeline_sugar(
numbers,
filterer(is_even),
mapper(triple),
filterer(is_greater_than_10)
)
print 'result:', result
print
procedural1()
procedural2()
functional1()
functional2()
functional3()
functional4()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment