codexcatalan-five-dyck-paths-and-parentheses.py
catalan-five-dyck-paths-and-parentheses.py
"""Enumerate all five six-step Dyck paths and their parenthesis encodings."""
from itertools import combinations
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def paths(n):
for up in combinations(range(2*n), n):
steps=np.full(2*n,-1,dtype=int)
steps[list(up)]=1
heights=np.r_[0,np.cumsum(steps)]
if heights.min()>=0:
yield steps,heights
def main():
examples=list(paths(3))
assert len(examples)==5
fig,axes=plt.subplots(2,3,figsize=(11.4,6.5),dpi=100,facecolor='white')
fig.suptitle('Five paths, five balanced parenthesis strings',fontsize=18,y=.97)
for ax,(steps,h) in zip(axes.flat,examples):
code=''.join('(' if s==1 else ')' for s in steps)
ax.plot(range(7),h,color='#246c99',lw=2.8,marker='o',ms=5)
ax.fill_between(range(7),0,h,color='#246c99',alpha=.08)
ax.axhline(0,color='#555',lw=1)
ax.set(xlim=(-.2,6.2),ylim=(-.15,3.5),xticks=range(7),yticks=range(4))
ax.set_title(code,fontfamily='monospace',fontsize=18,pad=10)
ax.set_xlabel('Step count');ax.set_ylabel('Unmatched openings')
ax.grid(alpha=.15)
ax.spines[['top','right']].set_visible(False)
axes.flat[-1].axis('off')
axes.flat[-1].text(.5,.65,'3 up steps + 3 down steps\nEvery prefix stays at height ≥ 0',ha='center',va='center',fontsize=12,transform=axes.flat[-1].transAxes)
axes.flat[-1].text(.5,.31,'C₃ = 5',ha='center',va='center',fontsize=23,color='#246c99',transform=axes.flat[-1].transAxes)
fig.subplots_adjust(left=.07,right=.97,bottom=.1,top=.85,wspace=.32,hspace=.57)
fig.savefig(Path.cwd()/(Path(__file__).stem+'.png'),facecolor='white')
plt.close(fig)
if __name__=='__main__':main()