wildcard exclusion in cartesian products
wkehowski at cox.net
wkehowski at cox.net
Sun Mar 26 15:13:02 EST 2006
The python code below is adapted from a Haskell program written by
Tomasz
Wielonka on the comp.lang.functional group. It's more verbose than his
since I wanted to make sure I got it right.
http://groups.google.com/group/comp.lang.functional/browse_frm/thread...
Does anyone know how to turn it into a module (or whatever it's called)
so that I can put it in a
loop and not have to generate the whole list? I've already tried
without success.
The program solves the following problem: generate the subset X of the
cartesian product S^n that excludes n-tuples defined by wildcards. For
example, if I want to exclude from [1,2,3]^3 the wc's [1,"*",2] and
["*",3,"*",3,"*"], where "*" stands for a sequence of zero or more
elements of [1,2,3], then I just type
for x in generateNotMatching([1,2,3,4],4,[[1,'*',2],[3,'*',4]]): print
x
and get the output
[1, 1, 1]
[1, 1, 3]
[1, 2, 1]
[1, 2, 3]
[1, 3, 1]
[2, 1, 1]
[2, 1, 2]
[2, 1, 3]
[2, 2, 1]
[2, 2, 2]
[2, 2, 3]
[2, 3, 1]
[2, 3, 2]
[3, 1, 1]
[3, 1, 2]
[3, 2, 1]
[3, 2, 2]
This is nice! But all elements are generated before they are printed.
##----------------------------
import sys, os, string
def imap(function, source):
for element in source:
yield function(element)
def any(iterable):
'''True iff at least one element of the iterable is True'''
for element in iterable:
if element:
return True # or element and change the definition
return False
def all(iterable):
'''True iff no element of the iterable is True'''
'''SHOULD BE?: True iff all element of the iterable are True'''
for element in iterable:
if not element:
return False
return True
def rev(L):
rL=[]
for x in L: rL=[x]+rL
return rL
def advancePattern(x,p):
if p==[]: return []
else:
h=p[0]
t=p[1:]
if h != '*':
if h == x: return [t]
else: return []
else: return [p] + [t] + advancePattern(x,t)
def advancePatterns(x,P):
aP=[]
for p in P:
aP += advancePattern(x,p)
return aP
# return [advancePattern(x,p) for p in P]
def allStar(p):
return all( imap((lambda x: x=='*'),p) )
def notNullOrZero(p,n):
return p !=[] or n==0
def generateNotMatching(A,n,P):
return gen(A,n,P,[])
def gen(A,n,P,acc):
if any(imap((lambda p: allStar(p) and notNullOrZero(p,n)), P)):
return []
else:
if n==0:
return map(rev,[acc])
else:
aG=[]
for a in A:
aG += gen(A,n-1,advancePatterns(a,P),[a]+acc)
return aG
##----------------------------
More information about the Python-list
mailing list