Following are “spike” solutions (see SpikeDescribed) for several proposed problems. I’ve kept them here because I like their elegance. — Scott Moonen
In September 2007, Brian Adkins posted a simple Logo program to print all possible combinations of lists of items, and asked for alternatives in other languages. He provided a Ruby alternative which would translate fairly easily into Python. For my own Python implementation I decided to try a completely different approach:
optstr = lambda x : (type(x)==str)*str(x)+(type(x)!=str)*' '.join(x)
prod1 = lambda elem, vec : map(lambda x : optstr(elem)+' '+optstr(x), vec)
xprod = lambda vec1, vec2 : reduce(list.__add__, map(lambda elem : prod1(elem ,vec2), vec1))
choices = lambda x : '\n'.join(reduce(xprod, x))+'\n'
q = [['small', 'medium', 'large'],
['vanilla', ['ultra', 'chocolate'], 'lychee', ['rum', 'raisin'], 'ginger'],
['cone', 'cup']]
print choices(q),
Brian tells me that I took Logo too literally in translating ‘ultra chocolate’ to a sublist. Removing that reduces my implementation to three lines:
prod1 = lambda elem, vec : map(lambda x : elem+' '+x, vec)
xprod = lambda vec1, vec2 : reduce(list.__add__, map(lambda elem : prod1(elem ,vec2), vec1))
choices = lambda x : '\n'.join(reduce(xprod, x))+'\n'
q = [['small', 'medium', 'large'],
['vanilla', 'ultra chocolate', 'lychee', 'rum raisin', 'ginger'],
['cone', 'cup']]
print choices(q),
I crafted this compact solution to Dijkstra’s OddWordProblem:
from sys import stdin, stdout
def even(char) : stdout.write(char); return select(even, 0, "");
def odd(char) : q = select(odd, 0, ""); stdout.write(char); return q
def select(fn, skipspace, prefix) :
char = stdin.read(1)
if char.isspace() and skipspace : return select(fn, 1, prefix)
elif char.isspace() : return 0
elif char.isalpha() : stdout.write(prefix); return fn(char)
elif char == "." : return 1
else : raise "Invalid input"
if not select(even, 1, "") :
while not select(odd, 1, " ") and not select(even, 1, " ") : pass
stdout.write(".")
I came up with these simple solutions to RonJeffries’ CodingProblem. The first uses Python 2.2’s generators:
def split(list, num) :
for index in range(num) :
yield list[index * len(list) / num:(index + 1) * len(list) / num]
I prefer the second, which uses the functional idiom:
def split(list, num) : return map(lambda x: list[x * len(list) / num:(x+1) * len(list) / num], range(num))
I composed this concise solution to ncm’s “coding challenge” in November 2004. I’m not entirely satisfied with its elegance, but I’m pleased with its brevity.
def dateinc(s) :
def carry(list, modulus) :
if len(list) == 1 : return [list[0] // modulus[0], list[0] % modulus[0]]
else : q = carry(list[1:], modulus[1:]); return [(list[0] + q[0]) // modulus[0], (list[0] + q[0]) % modulus[0]] + q[1:]
s = reduce(lambda x,y:x+y, map(lambda x : (x >= '0' and x <= '9') * x, s))
result = map(lambda x,y:x+y, map(int,(s[0:4],s[4:6],s[6:8],s[8:10],s[10:12],s[12:14])),(0,-1,-1,0,0,1))
modulus = [10000,12,[31,28,31,30,31,30,31,31,30,31,30,31][result[1]],24,60,60]
if result[0] % 4 == 0 and (result[0] % 100 != 0 or result[0] % 400 == 0) :
modulus[2] += 1 # Account for leap day.
result = carry(result, modulus)[1:] # Carry the extra second.
result[1:3] = map(lambda x:x+1, result[1:3]) # Readjust to 1-base.
return reduce(lambda x,y:x+y, map(lambda x : (x < 10) * '0' + str(x), result))
I further reduced this as follows, turning the carry function into a one-liner that computes the carry in-place (and also using builtins wherever possible). I’m much more satisfied with this solution.
def dateinc(s) : s = reduce(lambda x,y:x.isdigit()*x+y.isdigit()*y, s) ans = map(int.__add__, map(int,(s[0:4],s[4:6],s[6:8],s[8:10],s[10:12],s[12:14])),(0,-1,-1,0,0,1)) mod = [10000,12,[31,28,31,30,31,30,31,31,30,31,30,31][ans[1]],24,60,60] if ans[0] % 4 == 0 and (ans[0] % 100 != 0 or ans[0] % 400 == 0) : mod[2] += 1 ans = map(lambda x:(ans[x] + reduce(int.__mul__, map(lambda y:ans[y]>=mod[y]-1,range(x+1,len(ans))),x!=len(ans)-1)) % mod[x], range(len(ans))) ans[1:3] = map(int.__add__,ans[1:3],[1,1]) # Readjust to 1-base. return reduce(str.__add__, map(lambda x : (x < 10) * '0' + str(x), ans))