```
```class Union(object):
def __init__(self, *sublists):
self.sublists = sublists
def __len__(self):
if not hasattr(self, 'size'):
self.size = sum(len(sub) for sub in self.sublists)
return self.size
def __getitem__(self, index):
i = index
for sub in self.sublists:
if i < len(sub):
return sub[i]
i -= len(sub)
raise KeyError(index)
class Transformation(object):
def __init__(self, items, func):
self.items = items
self.func = func
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.func(self.items[index])
class Solution(object):
def __init__(self):
self.cache = {}
def solve(self, n, m):
return self.build(n, 0)[m - 1]
def build(self, *args):
if args not in self.cache:
self.cache[args] = self._build(*args)
return self.cache[args]
OPEN = staticmethod(lambda x: '(' + x)
CLOSE = staticmethod(lambda x: ')' + x)
def _build(self, free, open):
if open free:
return ()
elif open == free:
return (')' * free,)
return Union(
Transformation(self.build(free - 1, open + 1), self.OPEN),
Transformation(self.build(free - 1, open - 1), self.CLOSE)
)
solution = Solution()
for i in xrange(0, 16, 2):
items = []
for j in xrange(len(solution.build(i, 0))):
x = solution.solve(i, j + 1)
items.append(x)
for item in items:
print item
assert list(sorted(items)) == items, items

Knowing nothing about bijections to trees or permutations or whatever, I immediately thought about enumerations that can be indexed.

My first attempt was based on the idea that

solutions 0 = ""

solutions 2 = "()"

solutions n =

["(" ++ x ++ ")" ++ y | x <- solutions (n - 2), y <- solutions 0] ++

["(" ++ x ++ ")" ++ y | x <- solutions (n - 4), y <- solutions 2] ++

...

["(" ++ x ++ ")" ++ y | x <- solutions 0, y <- solutions (n - 2)]

However, this idea turned out to be wrong (they were not sorted correctly for N=8).

I then thought about it some more and figured out the much simpler rule (basically your solution):

solutions n = solutions' n 0

solutions' n open | open n = []

solutions' n open | n == open = ')' : solutions (n-1) (n-1) -- just an optimization

solutions' n open = ['(':x | x <- solutions (n - 1) (open + 1)] ++ [')':x | x <- solutions (n - 1) (open - 1)]

A Python solution was very easy to write and very short, my only issue with it being that it reflects the rule twice, once for counts and once for actually generating a solution at an index:

COUNT = {(0, 0): 1}

def count(unassigned, open):

assert unassigned >= 0, unassigned

assert (unassigned + open) % 2 == 0, (unassigned, open)

if open unassigned:

return 0

if open == unassigned:

return 1

x = (unassigned, open)

if x not in COUNT:

COUNT[x] = count(unassigned - 1, open + 1) + count(unassigned - 1, open - 1)

return COUNT[x]

```
```def mth(n, m_human):

return _mth(n, 0, m_human - 1)

def _mth(unassigned, open, index):

assert 0 <= index <= count(unassigned, open)

if unassigned == open:

return ')' * unassigned

unassigned -= 1

open += 1

c = count(unassigned, open)

if index < c:

return '(' + _mth(unassigned, open, index)

index -= c

open -= 2

return ')' + _mth(unassigned, open, index)

`for i in xrange(0, 16, 2):`

items = []

for j in xrange(count(i, 0)):

x = mth(i, j + 1)

items.append(x)

for item in items:

print item

assert list(sorted(items)) == items, items

Further, for readers that already know some things, and understand you’re recapitulating them for others, if you don’t say which parts of your work are related to prior ones, and which are new, you’re making their lives harder because they have to figure out the novel aspects for themselves.

Then there’s the fact that if you get something wrong but do so by citing a reputable source, you insulate yourself from some blame. You still could have caught it, but at least its not all your fault! And furthermore, if the same bad idea gets copied without citation all over, its harder to trace it down and fix it because it passes into folklore, but citations let people trace that down. So if you cite a paper and then in the future that paper is found to have problems, your reader immediately knows which of your work relied on sources that now might render that one element suspect.

Its about seeing your work, I suppose, as embedded in a network of knowledge and a common endeavour across many institutions and generations.

Citations also discipline the mind because they force you to take things you “think” you know and trace down if you have a source such that you “really” know it — and often, you find, you do know it, and it is correct, but there is no single source. And now, you’ve synthesized something new!

Now when an undergrad copies a relatively simple programming assignment from a classmate, obviously this isn’t really how they feel about it. But I suppose the idea is to help them understand you’re not just teaching them how to do the one assignment, but more importantly how to eventually act as scholars and researchers, even if in limited ways, in a field of study.

]]>