/*
 * Pascal - a program to draw Pascal's simplices
 * Copyright (C) 2005 Nicolas Bellm
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * g++ pascal.cpp
 *
 */

#include "pascal.h"

void Triangle::resize(int size)
{
  m_size = size;
  m_triangle.resize(m_size);

  for (int i=0; i<m_size; i++)
  {
    m_triangle[i].resize(i+1);
  }
}

void Triangle::center(int c)
{
  if (c >= 1000000) printf("%d ", c);
  else if (c >= 100000) printf(" %d ", c);
  else if (c >= 10000) printf(" %d  ", c);
  else if (c >= 1000) printf("  %d  ", c);
  else if (c >= 100) printf("  %d   ", c);
  else if (c >= 10) printf("   %d   ", c);
  else printf("   %d    ", c);
}

void Triangle::draw(int space=0)
{
  for (int i=0; i<m_size; i++)
  {
    for (int j=0; j<(m_size-i-1+space); j++)
    {
      printf("    ");
    }
  
    for (int j=0; j<=i; j++)
    {    
      center(m_triangle[i][j]);
    }
    printf("\n");
  }
}

void Tetrahedron::resize(int size)
{
  m_size = size;
  m_tetrahedron.resize(m_size);

  for (int i=0; i<m_size; i++)
  {
    m_tetrahedron[i].resize(i+1);
  }
}

void Tetrahedron::draw(int space=0)
{
  for (int i=0; i<m_size; i++)
  {
    m_tetrahedron[i].draw(m_size-i-1+space);
    if (i<m_size-1) printf("\n");
  }
}

void Pentatope::resize(int size)
{
  m_size = size;
  m_pentatope.resize(m_size);

  for (int i=0; i<m_size; i++)
  {
    m_pentatope[i].resize(i+1);
  }
}

void Pentatope::draw()
{
  for (int i=0; i<m_size; i++)
  {
    m_pentatope[i].draw(m_size-i-1);
    if (i<m_size-1) printf("-------------------------\n");
  }
}

//----- Calc functions -----
void PTriangle::calc()
{
  (*this)[0][0] = 1;
  
  for (int i=1; i < size(); i++)
  {
    (*this)[i][0] = (*this)[i][i] = 1;
    for (int j=1; j<i; j++)
    {
      (*this)[i][j] = (*this)[i-1][j-1] + (*this)[i-1][j];
    }
  }
}

void PTetrahedron::calc()
{
  PTriangle p(size());

  for (int i=0; i<size(); i++)
  {
    for (int j=0; j<=i; j++)
    {
      for (int k=0; k<=j; k++)
      {
        (*this)[i][j][k] = p[i][j]*p[j][k];
      }
    }
  }
}

void PPentatope::calc()
{
  PTriangle p(size());

  for (int i=0; i<size(); i++)
  {
    for (int j=0; j<=i; j++)
    {
      for (int k=0; k<=j; k++)
      {
        for (int l=0; l<=k; l++)
        {
          (*this)[i][j][k][l] = p[i][j]*p[j][k]*p[k][l];
        }
      }
    }
  }
}

int main()
{
  int simplex, size;
  
  while(true)
  {
    printf("Welches Pascalsche Simplex soll gezeichniet werden?\n\
[2] Pascalsches Dreieck\n\
[3] Pascalscher Tetraeder\n\
[4] Pascalsches Pentatop\n\
[5] Beenden\n\
Auswahl: ");
    scanf("%d", &simplex);
  
    PTriangle p;
    PTetrahedron q;
    PPentatope r;

    switch(simplex)
    {
      case 2:
        printf("Bis zur wievielten Zeile soll das Pascalsche Dreieck
                gezeichnet werden? ");
        scanf("%d", &size);
        p.resize(size);
        p.draw();
        break;

      case 3:
        printf("Bis zur wievielten Ebene soll der Pascalsche Tetraeder
                gezeichnet werden? ");
        scanf("%d", &size);
        q.resize(size);
        q.draw();
        break;

      case 4:
        printf("Bis zum wievielten Tetraeder soll der Pascalsche
                Pentatop gezeichnet werden? ");
        scanf("%d", &size);
        r.resize(size);
        r.draw();
        break;

      case 5:
        return 0;

      default:
        printf("Fehlerhafte Eingabe!\n");
    }
  }
}

