Search code examples
arrayscloopsfor-looppermutation

I want to arrange and print words entered by the user in different combinations? Can anybody tell me how can I achieve this?


Example:

input:

Number of words user want to enter : 3

Word no. 1: cat

Word no. 2: rat

Word no. 3: dog

output:

cat rat dog

cat dog rat

rat cat dog

rat dog cat

dog cat rat

dog rat cat

something like this.

Here is the code of another program, where I arranged letters in different combinations.

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

char character_swap(char*, char*);
void permutation(char*, int, int);

int main()
{
 char str[99];
 
 printf("Enter a string to find its permutations.\n");
 scanf("%s",str);
 
 system("clear");

 int n = strlen(str);
 permutation(str, 0, n-1);

 return 0;
}

char character_swap(char *x, char *y)
{
 char temp;

 temp = *x;
 *x = *y;
 *y = temp;
}

void permutation(char *a, int l, int r)
{
 if (l == r)
 printf("%s\n", a);

 else
 for (int i = l; i <= r; i++)
 {
 character_swap((a+l), (a+i));
 permutation(a, l+1, r);
 character_swap((a+l), (a+i));
 }
}

Can anybody tell me, how can I do the same thing with words?


Solution

  • You have done a good job separating the permutation implementation from the main interface, such that this can this be done fairly easily. First, there are a few inconsistencies,

    • In character_swap, one has declare return type char, but never return anything; must be void. It's used only in this file, so it should be static; this will avoid namespace conflicts let the compiler perform more aggressive optimizations. It also prevents prototype warnings as long as it is declared above.
    • int is not really the right type for working with indices; size_t is more appropriate.
    • It's a little awkward to explain that permutation is always going to be called with 0 index as it's second parameter. It's better to drop that and fill it in later, I have accepted the size in character_permutation, which calls character_permutation_r.

    I have generalized the type from char to type using a typedef; I just replaced char by type. It would be simpler and clearer to replace type by equivalent char *, but in the next iteration, we are going to replace it with a totally opaque type; a typedef is warranted it because it keeps them all the type information together.

    #include <stdio.h>
    #include <string.h>
    
    /* This is part of the interface. */
    
    void character_array_output(const char *a, const size_t size) {
     (void)size; /* Don't use the size -- it's null-terminated. */
     printf("%s\n", a);
    }
    
    /* This is the implementation. */
    
    typedef char type;
    
    typedef void (*character_array_action)(const type *, size_t);
    
    static character_array_action character_print = &character_array_output;
    
    static void character_swap(type *x, type *y)
    {
     type temp;
    
     temp = *x;
     *x = *y;
     *y = temp;
    }
    
    static void character_permutation_r(type *a, const size_t l, const size_t r)
    {
     if (l == r)
      character_print(a, r + 1);
    
     else
     for (size_t i = l; i <= r; i++)
     {
      character_swap((a+l), (a+i));
      character_permutation_r(a, l+1, r);
      character_swap((a+l), (a+i));
     }
    }
    
    static void character_permutation(type *a, const size_t size) {
     if(size == 0) return;
     else character_permutation_r(a, 0, size - 1);
    }
    
    /* This is part of the interface. */
    
    int main(void)
    {
     char str[99];
    
     printf("Enter a string to find its permutations.\n");
     scanf("%98s", str);
    
     character_permutation(str, strlen(str));
    
     return 0;
    }
    

    For your question, type is char, and you want it to be char *, you just replace it with typedef char *type. However, a generalization to any assignable type is possible.

    #include <stdio.h>
    #include <string.h>
    
    /* This is the implementation.
     `name` satisfies `C` naming conventions when mangled
     `nametype` is an assignable type
     `array_output` is a function satisfying `name##_array_action` */
    
    #define DEFINE_PERMUTATION(name, nametype, array_output) \
    typedef nametype name##type; \
    \
    typedef void (*name##_array_action)(const name##type *, size_t); \
    \
    static name##_array_action name##_array_print = &array_output; \
    \
    static void name##_swap(name##type *x, name##type *y) \
    { \
     name##type temp; \
    \
     temp = *x; \
     *x = *y; \
     *y = temp; \
    } \
    \
    static void name##_permutation_r(name##type *a, const size_t l, const size_t r) \
    { \
     if (l == r) \
      name##_array_print(a, r + 1); \
    \
     else\
     for (size_t i = l; i <= r; i++)\
     { \
     name##_swap((a+l), (a+i)); \
     name##_permutation_r(a, l+1, r); \
     name##_swap((a+l), (a+i)); \
     } \
    } \
    \
    static void name##_permutation(name##type *a, size_t size) { \
        if(size == 0) return; \
        else name##_permutation_r(a, 0, size - 1); \
    }
    
    /* This is the interface. */
    
    void character_array_output(const char *a, const size_t a_size) {
        (void)a_size;
        printf("%s\n", a);
    }
    
    void string_array_output(char *const a[], const size_t a_size) {
        for(size_t i = 0; i < a_size; i++)
            printf("%s%s", i ? ", " : "", a[i]);
        printf("\n");
    }
    
    void integer_array_output(const int *a, const size_t a_size) {
        printf("{");
        for(size_t i = 0; i < a_size; i++)
            printf("%s%d", i ? ", " : "", a[i]);
        printf("}\n");
    }
    
    typedef int (*operation)(int);
    static int value;
    void operation_array_output(const operation *a, const size_t a_size) {
        printf("{");
        for(size_t i = 0; i < a_size; i++)
            printf("%s%d", i ? ", " : "", value = a[i](value));
        printf("}\n");
    }
    
    DEFINE_PERMUTATION(character, char, character_array_output)
    DEFINE_PERMUTATION(string, char *, string_array_output)
    DEFINE_PERMUTATION(integer, int, integer_array_output)
    DEFINE_PERMUTATION(operation, operation, operation_array_output)
    
    #include <math.h>
    static int square_n(const int n) { return n * n; }
    static int sqrt_n(const int n) { return sqrtl(n); }
    static int double_n(const int n) { return 2 * n; }
    
    int main(void)
    {
     char str[] = "abc";
     character_permutation(str, strlen(str));
    
     char *strings[] = { "cat", "rat", "dog" };
     string_permutation(strings, sizeof strings / sizeof *strings);
    
     int numbers[] = { 42, 99, 1, 0 };
     integer_permutation(numbers, sizeof numbers / sizeof *numbers);
    
     operation ops[] = { &square_n, &sqrt_n, &double_n };
     value = 1;
     operation_permutation(ops, sizeof ops / sizeof *ops);
     value = 5;
     operation_permutation(ops, sizeof ops / sizeof *ops);
    
     return 0;
    }