Word Scramble Help

Jul 7, 2011 at 10:33pm
I am attempting to create a program that scrambles words so that the first letter and last letter of a word stays the same while the rest of the letters get mixed up. If you have ever seen the article from, I think UC Berkeley, that talks about how the mind can "raed wrdos lkie tihs" even when its scrambled then you know what I am talking about. I wanted to recreate this and I was able to do it with a single word thanks to the help of others in coding a random number generator. Can someone help me with at least the concept or idea on how to apply this to entire sentences or paragraphs? Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <conio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <vector>

using namespace std;

int main()
{
 srand ( time(NULL));
 char input[15];
 char output[15];
 int i,k,j = 0;
 
    
   

 
 cout << "Enter a word: ";
 for(i=0;(input[i]=getche())!='\r';i++){}
 
 cout << '\n';
 vector <int> initialNumbers (i);
 vector <int> randomNumbers (i);

  int randomNumber;
    for (int l = 0;l<(i-2);l++) // Set vector with the numbers 1-50
    { 
        initialNumbers[l]=l+1;
    }
    for (int l = 0;l<(i-2);l++) // Take a random member of initialNumbers and put it in randomNumbers, then erase that member from initialNumbers
    {
        randomNumber = rand() % (i-2-l);
        randomNumbers[l] = initialNumbers[randomNumber];
        initialNumbers.erase(initialNumbers.begin()+randomNumber);
        
    }
 
    
 for(k=1;k<(i-1);k++)
 {
 output[k] = input[randomNumbers[k-1]];
 
 }
 
 output[0] = input[0];
 output[i-1] = input[i-1]; 

 while(j<i)
 {
 cout << output[j];
 j++;
}
 getch();

}


I know im bad at coding. I havent done it since highschool like 6 years ago and I changed my major to Computer Science from Engineering so I am trying to relearn everything. As for the program, I need a way to implement code that disregards "spaces" in a sentence so that the word scrambler only scrambles words individually and not the entire sentence as a whole. Get what I mean?

I do not know if I should try to look at it as a whole, and try to create an algorithm to exclude spaces or if I should create a new algorithm that adds letters to a 2D array (array[m][n] where each m is a word and each n is a letter) and then search for when a "space", ' ', is pressed and doing m++. Then at the end of the program compile the array in order to create a sentence.
Jul 7, 2011 at 10:48pm
I think, you can generate two random number's between 1 & length(word) - 1, exchange them.
do this may be length(word)/2 times and I think you will have a good jumbled word.

sometimes the two random number's can be same as there is not much deviation but I think that would be fine..

there can be as many solution's as the number of reader's here.
Jul 7, 2011 at 11:44pm
I would approach the problem differently, and would use a finite state machine where I am either in_word, or not_in_word.

Whilst not_in_word I read a character, if it is a letter I store it and change my state to in_word else I print the character and remain not_in_word.

Whilst in_word I read a character if it is a letter I store it and remain in_word else I shuffle the stored characters and display them. display the current character and change my state to not_in_word.

If I run out of input in not_in_word I just finish. If I run out of input in in_word, I need to shuffle the characters I have and print them.
Jul 8, 2011 at 1:14am
If you want to select individual words from a sentence you can use std::istringstream http://cplusplus.com/reference/iostream/istringstream/
1
2
3
4
5
6
7
8
9
10
11
12
#include <sstream>

int main()
{
    std::istringstream iss("this is a sentence with lots of words");

    std::string word;
    while(iss >> word)
    {
        // word now contains each word in turn
    }
}

The std C++ library provides an easy way to jumble your words without changing the first and last characters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <iostream>
#include <string>

int main()
{
    srand(time(0));

    std::string word = "message";

    if(word.size() > 3)
    {
        std::random_shuffle(word.begin() + 1, word.end() - 1);
    }
    std::cout << word << '\n';
}

Last edited on Jul 8, 2011 at 1:19am
Jul 8, 2011 at 7:13am
@Galik, using an istringstream like that does not preserve whitespace in the output, it shuffles numbers which it shouldn't do, but most importantly it screws up punctuation like full stop.
Jul 8, 2011 at 3:14pm
Thank you all for the input, I will try to implement your ideas into my coding. Thank you. Also, why do some people code with the std:: in front of everything instead of just putting "using namespace std" in the global coding? Doesn't that just make the coding take longer?
Last edited on Jul 8, 2011 at 3:17pm
Jul 8, 2011 at 4:09pm
@kev82
Yes you are absolutely right. It depends on the task's requirements how sophisticated we need to be.

To preserve whitespaces words could be extracted like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <sstream>
#include <iostream>
int main()
{
	std::istringstream iss(" this is a   sentence, with lots  of words.  ");

	char c;
	std::string word;

	// output any leading whitespace
	while(iss.get(c) && isspace(c)) std::cout << c;

	while(iss.putback(c) && iss >> word)
	{
		std::cout << word;

		// output any leading whitespace
		while(iss.get(c) && isspace(c)) std::cout << c;
	}
}

And jumbling up the words avoiding trailing punctuation could be done like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <iostream>
#include <string>

int main()
{
	srand(time(0));

	std::string word = "(message)";

	// first is set to skip the first alpha character in the word
	std::string::iterator first = std::find_if(word.begin(), word.end(), std::ptr_fun<int, int>(&isalpha)) + 1;

	// note: std::ptr_fun<int, int>(&isalpha) converts the isalpha() function to be usable by std::find_if()

	// last is set to the last alpha character less one
	std::string::iterator last = std::find_if(word.rbegin(), word.rend(), std::ptr_fun<int, int>(&isalpha)).base() - 1;

	// note: word.rbegin() starts at the end of the word
	// note: word.rend() ends at the beginning of the word
	// note: base() converts the reverse_iterator into a normal iterator

	if(last - first > 1)
		std::random_shuffle(first, last);

	std::cout << word << '\n';
}
Last edited on Jul 8, 2011 at 4:20pm
Jul 8, 2011 at 4:29pm
shank8 wrote:
Also, why do some people code with the std:: in front of everything instead of just putting "using namespace std" in the global coding? Doesn't that just make the coding take longer?


Whilst "using namespace std" is okay for trivial example code it is not really suitable for larger programs because it puts all the standard libraries symbols into the global namespace. This can lead to subtle hard-to-find errors with name clashes.

This is a very good and interesting C++ FAQ:
http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
Jul 8, 2011 at 6:51pm
yeah, right. some times the code wont even compile due to classes of classes in different namespaces. namespaces should not be included.
Jul 11, 2011 at 6:53pm
thank you for the tip and link Galik
Topic archived. No new replies allowed.