#include <stdio.h> 
#include <string.h> 
#include <stdlib.h>

typedef struct struct_disk *Disk;

struct struct_disk {
  int id;
  Disk next;
};

typedef struct struct_pilha *Pilha;

struct struct_pilha {
  Disk top;
  char name;
};

Pilha a, b, c; /* apontadores para as 3 pilhas */
int move_number=0;
int verbose=0; /* flag for verbose mode */

int scan_command(int argc, char *argv[], int *n)
{
  while (--argc) {
    if (sscanf(argv[argc],"-n%lu", n)==1) ;
    else if (strcmp(argv[argc], "-v")==0) verbose=1;
    else {
      printf("Usage: %s [-nN][-v]\n", argv[0]);
      return -1;
    }
  }
  return 0; /* normal exit from ths function */
}

void print_pilha_reverse(Pilha v)
{
  Disk p=v->top;
  printf("\n %c: ", v->name);
  while (p) {
    printf(" %d", p->id);
    p=p->next;
  }
}

void print_pilha_rec(Disk p)
{ if (p) {
    print_pilha_rec(p->next);
    printf(" %d", p->id);
  }
}

void print_pilha(Pilha v)
{ printf("\n %c: ", v->name);
  print_pilha_rec(v->top);
}

void print_situation()
{ print_pilha(a);
  print_pilha(b);
  print_pilha(c);
  printf("\n");
}

Pilha aloca_pilha(void)
{ return (Pilha)malloc(sizeof(struct struct_pilha)); }

Disk aloca_disk(void)
{ return (Disk)malloc(sizeof(struct struct_disk)); }

void set_up_start(int n)
{ int i;
  Disk p, q; 
  
  a=aloca_pilha();
  b=aloca_pilha();
  c=aloca_pilha();
  q=NULL;
  for (i=0; i<n; i++) {
    p=aloca_disk();
    p->id=i;
    p->next=q;
    q=p;
  }
  a->name='A'; a->top=q;
  b->name='B'; b->top=NULL; 
  c->name='C'; c->top=NULL; 
}

void solve(Pilha u, Pilha v, Pilha w, int n_disks)
{
  Disk p;
  
  if (n_disks>0) {
    solve(u, w, v, n_disks-1);
    p=u->top;
    u->top=p->next;
    p->next=v->top;
    v->top=p;
    printf("Move number %d: disk %d, %c -> %c\n", 
      ++move_number, v->top->id, u->name, v->name);
    if (verbose) print_situation();
    solve(w, v, u, n_disks-1);
  }
}

main(argc,argv)
  int argc; /* the number of command-line arguments */
  char *argv[]; /* an array of strings containing those arguments */
{
  int n=3; /* number of disks */

  if (scan_command(argc, argv, &n)==0) {
    set_up_start(n);
    print_situation();
    solve(a, b, c, n);
    print_situation();
    return 0; /* normal exit */
  }
}
