/*
+----------------------------+
| PERMUTACIONES DE UN VECTOR |
+----------------------------+

         Este  programa lee  los elementos  de un  vector y  escribe
todas las  permutaciones (combinaciones sin  repetición) posibles de
los elementos introducidos en el vector.

         El número de permutaciones  de n elementos está determinado
por el factorial de n.

  Observaciones sobre el programa:

     1) En el primer elemento del  vector (índice 0) se encuentra el
número de elementos a permutar. Así pues, los n elementos a permutar
están en entre los índices 1 y n el vector.

     2)  En  algunos  sitios  del  programa  aparece  la  expresión:
&vector[i] que  puede parecer a simple  un poco rara para  el que no
está  acostumbrado  al  C.  Expliquémosla:  Al  ser cada elmento del
vector de tipo int, vector[i]  se puede considerar como una variable
de  tipo  int,  y  por  lo  tanto,  podemos  hacer  con la expresión
vector[i]  lo que  con cualquier  variable de  tipo entero,  y no de
estas operaciones es obtener su  dirección. Hemos dicho varias veces
que el  nombre del vector es  un puntero al primer  elemento, así la
siguiente expresión  sería cierta: vector  == &vector[0], es  decir,
que vector y &vector[0] es equivalente.

     3)  Los  nombres  de  las  variables  punteros, por convención,
suelen empezar con p; por este motivo he llamado a los parámetros de
la función intercambiar p1 y p2.
*/

/* Ficheros a incluir: */

#include <stdio.h>  /* printf (), puts (), putchar (), scanf () */
#include <conio.h>  /* getch ()                                 */
#include <stdlib.h> /* exit ()                                  */

/* Macros: */

#define NUMERO_MAXIMO_ELEMENTOS_VECTOR 100
#define en(x,x1,x2) ((x) >= (x1) && (x) <= (x2))

/* Declaración de las funciones: */

void rellenar_vector (int vect[]);
void escribir_vector (int vect[]);
void permutar (int v[], int m);
void intercambiar (int *p1, int *p2);

/* Definición de las funciones: */

void main (void)
{
  int vector [NUMERO_MAXIMO_ELEMENTOS_VECTOR+1];
  /* +1 porque el primer elemento contiene el número de elementos a
  permutar */

  puts ("PERMUTACIONES");
  rellenar_vector (vector);

  permutar (vector, vector[0]);

  printf ("\nPulsa cualquier tecla para finalizar.");
  getch ();
}

void rellenar_vector (int vect[])
{
  register int i;
  do
    {
      printf ("\nIntroduzca número de elementos de vector (1-%d): ",
              NUMERO_MAXIMO_ELEMENTOS_VECTOR);
      scanf ("%d", &vect[0]);
    } while (! en (vect[0], 1, NUMERO_MAXIMO_ELEMENTOS_VECTOR));
  printf ("\nIntroduce los %d elementos a permutar: ", vect[0]);
  for (i = 1; i <= vect[0]; i++)
    scanf ("%d", &vect[i]);
  putchar ('\n');
}

void escribir_vector (int vect[])
{
  static unsigned int numero_de_permutacion = 0;
  register int i;

  /* cada 24 movimientos se para la escritura */
  if (++numero_de_permutacion % 24 == 0)
    {
      printf ("Pulse la tecla ESCAPE para salir o cualquier otra "
      "tecla para continuar.");

      /* el código ASCII 27 corresponde a la tecla ESCAPE */
      if (getch () == 27)
        exit (0);

      /* con estas tres funciones se borra el mensaje anterior */
      putchar ('\r');
      printf ("                                                    "
              "                   ");
      putchar ('\r');
    }
  printf ("Permutación %2u: ", numero_de_permutacion);
  for (i = 1; i <= vect[0]; i++)
    printf ("%d ", vect[i]);
  putchar ('\n');
}

void permutar (int v[], int m)
{
  register int i;
  if (m > 1)
    for (i = 1; i <= m; i++)
      {
        intercambiar (&v[i], &v[m]);
        permutar (v, m-1);
        intercambiar (&v[i], &v[m]);
      }
  else
    escribir_vector (v);
}

void intercambiar (int *p1, int *p2)
{
  int aux;
  aux = *p1;
  *p1 = *p2;
  *p2 = aux;
}