# ==============================================================================
"""PASCAL : create Pascal's triangle (triangle of binomial terms)"""
# ==============================================================================
__author__  = "Christophe Schlick modified by Philippe Blasi"
__version__ = "1.0"
__date__    = "2022-11-12"
__usage__   = """
User input : <n> (where n:int > 0)
App output: Grid containing Pascal's triangle up to rank n"""
# ==============================================================================
from ezCLI import *
from ezTK import *
# ------------------------------------------------------------------------------
def facto(n:int) -> int:
  """return n! (iterative implementation)"""
  value = 1
  for p in range(1, n+1):
    value *= p
  return value
# ------------------------------------------------------------------------------
def bino(n:int, p:int) -> int:
  """return the binomial coefficient C(n,p)"""
  return facto(n) // facto(p) // facto(n-p)
# ------------------------------------------------------------------------------
def show(table:list) -> None:
  """show the content of 'table' in a tk window"""
  rows, cols = len(table), len(table[-1]) # get size of table (use last row)
  width = len(str(max(table[-1]))) # find maximal width for table cells
  win = Win(title='MULDIV', font='Arial 14', fold=cols)
  for row in range(rows):
    for col in range(cols):
      text = table[row][col] if col <= row else '' # use '' for upper triangle
      Label(win, text=text, width=width, border=1)
  win.loop()
# ------------------------------------------------------------------------------
def pascal(n:int) -> str:
  """return a grid containing Pascal's triangle up to rank n"""
  table = [[bino(p,q) for q in range(0, p+1)] for p in range(0, n+1)]
  show(table); return ''
# ------------------------------------------------------------------------------
def parser(command:str) ->str:
  """parse 'command' as integer 'n' before calling 'pascal(n)'"""
  n = convert(command)
  assert type(n) is int and n > 0, "<n> must be a strictly positive integer"
  return pascal(n)
# ==============================================================================
if __name__ == "__main__":
  userloop(parser, "Enter value for <n>")
# ==============================================================================
