How to do random arrangement of letters in C?

  • Thread starter Thread starter 4102
  • Start date Start date
  • Tags Tags
    Random
Click For Summary

Discussion Overview

The discussion revolves around generating a random arrangement of letters in the C programming language. Participants explore various methods to ensure that letters are not repeated in the output and that only one random arrangement is produced, rather than all possible permutations.

Discussion Character

  • Technical explanation
  • Exploratory
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant shares a code snippet that generates random letters but encounters issues with letter repetition, prompting a request for help.
  • Another participant explains that the current approach selects letters without tracking which have already been used, leading to duplicates.
  • A suggestion is made to compress the data inward to avoid selecting the same character twice, with a code example demonstrating this method.
  • Another participant proposes using a marker to indicate used letters, although they caution that this method may be inefficient for larger datasets.
  • One participant mentions that using `memmove` can be cleaner but introduces overhead due to memory operations.
  • There is a request for pure C code, as some provided examples include C++ syntax, leading to further clarification on how to convert C++ output statements to C.
  • A theoretical background on random shuffles is suggested, referencing the Fisher-Yates shuffle as a relevant concept.
  • A later reply provides an alternative approach that allows for command-line input of the string to be permuted, enhancing versatility.
  • Another participant suggests a more efficient method than using `memmove`, proposing a single character copy approach to avoid overhead.

Areas of Agreement / Disagreement

Participants generally agree on the need to avoid letter repetition and to produce a single output. However, there are multiple competing views on the best method to achieve this, and the discussion remains unresolved regarding the most efficient implementation.

Contextual Notes

Some methods discussed may have limitations in efficiency or clarity, and there are unresolved questions about the best practices for random arrangements in C.

4102
Messages
6
Reaction score
0
Hi I'm making a program that generates a different arrangement of letters in C.

For example, the word ALTEC will be rearranged randomly by the program.
the output would be "LETAC" or "CEALT" etc.
The program should use all the given letters and not repeat the letters.

Here's a code sample I made but the problem is that it repeats other letters, example output of this is like "ELTAA" instead of "ELTAC", it should not repeat the letter that is used already. Also I need only ONE output, and not all the possible permutations.

by the way, the some of the codes used is C++, what i need is for C. It's quite a mix up already I'm quite confused.
Please help! Thanks!

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
char possibilities[6] = "ALTEC";
for(int i = 0; i < 5; i++)
{
count << possibilities[rand() % 5];
}
cin.get();
return 0;
}
 
Physics news on Phys.org
What your code is doing is picking one of the five letters for each iteration of the loop. This doesn't work, because as you're finding, there is nothing to prevent a letter that has already been used from being used again.

For the first letter of an output string, there are five possibilities, but for the next letter, there are only four possibilities left, since one letter was already used. For the third letter, there are only three possibilities, then two, and then finally, a single letter is left.

Since there are five letters, there are 5! = 5*4*3*2*1 = 120 different permutations, ranging from ACELT to TLECA.
 
You can compress the data inward toward the randomly chosen index to eliminate selecting the same character twice. You must be careful to also size how your index is randomly generated, though, or you could randomly select a spot in possibilities that no longer represents unused characters.

Example:

Code:
#include<iostream>
#include<ctime>

using namespace std;

int main()
{
	//declarations
	char possibilities[] = "ABC";
	const int LENGTH = 3;
	int index;

	//seed the random generator
	srand(time(NULL));

	for(int i = 0; i < LENGTH; ++i)
	{
		index = rand() % (LENGTH - i);
		cout << possibilities[index];
		for(int j = 0; j < (LENGTH - i - index); ++j)
			possibilities[index + j] = possibilities[index + j + 1];
	}
	cout << endl;

	//success!
	return(0);
}
 
An inefficient but simple solution is to use a marker to mark when a letter has been used, and loop repeatedly until an unused letter is found. Eg in the array poss[] below 0 is used to mark the position of any used letters.

eg C code like this would work, but this is a pretty terrible method except for the simplest of uses

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

int main()
{
  char poss[] = "ALTEC";

  int i,r, l = strlen(poss);

  srand(time(NULL));

  for (i=0; i<l; i++)
  {
    do {
      r = rand()%l;
    } while (poss[r] == 0);

    putchar(poss[r]);
    poss[r] = 0;
  }

  puts("");

  return 0;
}
 
Last edited:
Doing it with memmove is algorithmically cleaner but has the overhead of doing memory operations for each character in the possibilities string (instead of calculating rand() a few times for each character)

As in the above C code, the initial string poss="ALTEC" can be set to anything without changing the rest of the code.

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

int main()
{
  char poss[] = "ALTEC";

  int i,r,l = strlen(poss);

  srand(time(NULL));

  for (i=0; i<l; i++)
  {
   r = rand()%(l-i);
   putchar(poss[r]);
   memmove(poss+r,poss+r+1,l-r);
  }

  puts("");

  return 0;
}
 
thanks guys. :D

but I'm looking for pure C code. having it in c++ is not an option. Thank you! L :D

I'm still confused :|
 
You try googling "random permutation"?
 
xcvxcvvc said:
You can compress the data inward toward the randomly chosen index to eliminate selecting the same character twice. You must be careful to also size how your index is randomly generated, though, or you could randomly select a spot in possibilities that no longer represents unused characters.

Example:

Code:
#include<iostream>
#include<ctime>

using namespace std;

int main()
{
	//declarations
	char possibilities[] = "ABC";
	const int LENGTH = 3;
	int index;

	//seed the random generator
	srand(time(NULL));

	for(int i = 0; i < LENGTH; ++i)
	{
		index = rand() % (LENGTH - i);
		cout << possibilities[index];
		for(int j = 0; j < (LENGTH - i - index); ++j)
			possibilities[index + j] = possibilities[index + j + 1];
	}
	cout << endl;

	//success!
	return(0);
}

This is one is really close to what i need, i just don't know how to convert "cout << possibilities[index];" to a C code which should begin at "printf(________);"

so please can you help me on this one?
 
  • #10
4102 said:
thanks guys. :D

but I'm looking for pure C code. having it in c++ is not an option. Thank you! L :D

I'm still confused :|

I used pure C code, in both examples.

To make it more versatile, supply the possibilities string on the command line instead of hardcoding it

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

int main(int argc, char *argv[])
{
  if (argc <= 1) return 1;
  char * poss = argv[1];

  int i,r,l = strlen(poss);

  srand(time(NULL));

  for (i=0; i<l; i++)
  {
   r = rand()%(l-i);
   putchar(poss[r]);
   memmove(poss+r,poss+r+1,l-r);
  }

  puts("");

  return 0;

Code:
$ gcc -o strperm strperm.c
$ ./strperm "ALTEC"
TALCE
$ ./strperm "ALTEC123"
A2E31CTL
...

EDIT
more efficient than using memove, just use a single char copy:

Code:
...
  for (i=strlen(poss); i>0; i--)
  {
   r = rand()%i;
   putchar(poss[r]);
   poss[r]=poss[i-1];
  }
...
 
Last edited:

Similar threads

  • · Replies 10 ·
Replies
10
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K
Replies
8
Views
2K
  • · Replies 15 ·
Replies
15
Views
2K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 24 ·
Replies
24
Views
2K
  • · Replies 3 ·
Replies
3
Views
1K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 12 ·
Replies
12
Views
3K
  • · Replies 15 ·
Replies
15
Views
3K