webdevRefinery Forum: Hm. Need help with my code. Complicated challenge! - webdevRefinery Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Rate Topic: -----

User is offline HeartLess 

  • Group: Members
  • Posts: 40
  • Joined: 21-June 11

Posted 20 August 2012 - 10:17 AM (#1)

Hm. Need help with my code. Complicated challenge!


Basically, what I'm trying to achieve is

1. Take a word.
2. Keep first letter of the word
3. Keep last letter of the word
4. Scramble letters in the middle

Okay, I've done that in my original code. However, I'm having problems implementing the next step.

1. Define an array of clumped characters. (e.g. "en", "ing", "at", "xtra")
2. Repeat the original steps, except while scrambling the letters, if there are characters defined within the clumped array in the original word, those characters cannot be separated. I've attempted it and failed (Only spent about 1-2 hours) and I'll try again later, but I want to use this for a new project I'm working on and was wondering if anyone else could think of a solution. Also, after this step, I plan to implement the following:

1. Take word and remove first and last letters. (clumped letters count as ONE letter)
2. Count the remaining letters
3. Group the remaining letters by every 3 letters (again, clumped letters count as ONE letter)

Final Effect: Words should be readable, but misspelled. They should also have a "random" element to it so that if I scrambled a sentence, I would have to press "refresh" many times before I ever get the same result twice. (The ultimate object is the misspell the words, but keep them readable to the human brain. Look up typoglycemia)

Here's my failed attempt. (got stuck on part 2 which I thought would be harder than part 3.)
<?php
$textToScramble = stripslashes($_POST["textToScramble"]);
$clumpArray = array("er","ing","xtr","an","or","es"); //define the values for the clumped letters
$clumpArraySize = count($clumpArray); //Count the clump array size
for($a = 0; $a < $clumpArraySize; $a++){ //Replace all words found in the preserve array
	$textToScramble = str_replace($clumpArray[$a], "|".$clumpArray[$a]."|", $textToScramble); //get words
}

$textArray = explode(" ", $textToScramble); //split up the words by spaces
$textArraySize = count($textArray);
$completeArray = array();
for($i = 0; $i < $textArraySize; $i++){ //Loop through every word in the text.
	$scrambleArray = array();
	$currentString = $textArray[$i]; //Get a word
	$toggle = 1;
	while (isset($currentString[$b])) { //While the letters are defined
		if($currentString[$b] == "|"){ //check to see if letter is there
			$toggle = $toggle * (-1);
		}	
		if($toggle == 1){
			if($currentString[$b] != "|"){
				$currentLetter = $currentString[$b];
			}
		} else {
			if($currentString[$b] != "|"){
				$currentLetter .= $currentString[$b];
			}
		}
			
		if($toggle == 1){
			array_push($scrambleArray, $currentLetter);
			$currentLetter = "";
		}
   		$b++;
	}
	$scrambleArraySave = $scrambleArray; //copy the array
	$scrambleArrayCount = count($scrambleArray);
	unset($scrambleArray[$scrambleArrayCount-1]); //remove last character
	unset($scrambleArray[0]); //remove first character
	shuffle($scrambleArray); //shuffle remaining
	$scrambledWord = $scrambleArraySave[0];  //Get first letter

		for($d = 0; $d < $scrambleArrayCount; $d++){ //concencate the scrambled letters on to the first letter of the original word.
			$scrambledWord .= $scrambleArray[$d];
		}
	if ($scrambleArrayCount - 2 >=0){	
	$scrambledWord .= $scrambleArraySave[$scrambleArrayCount - 1];  //Get last letter and attach it.
	}
	array_push($completeArray, $scrambledWord);
	}


foreach ($completeArray as $word) { //display each scrambled word after another.
    echo $word." ";
}

?>

0


User is offline alexdavey 

  • Bringing XKCD to a post near you
  • Group: Members
  • Posts: 848
  • Joined: 05-November 10
  • LocationLondon
  • Expertise:HTML,CSS,PHP,Javascript

Posted 20 August 2012 - 02:07 PM (#2)

Ok, I haven't written any PHP for ages, so I can't help you there, but I have written some JavaScript that does what you want.

The concept is very simple, split the string into an array containing groups and single letters (so
'extreme'
would become
['e', 'xtr', 'e', 'm', 'e]'
), then shuffle the array.

Unfortunately though, what could have been a 5 line regex function (if JavaScript's regex functions weren't so haphazard) turned into a ungodly 40 line function (To be fair, it is only 30 solid lines of code). Here it is:

var groups = ['er', 'ing', 'xtr', 'an', 'or', 'es'];

// Determines whether the string is a prefix of any of the groups
function groupPrefix(prefix, groups) {
	for (var i = 0, l = groups.length; i < l; i++) { // Test each group
		if (groups[i].indexOf(prefix) === 0) return true;
	}
	return false;
}

// Splits a string into an array of characters and groups.
// Essentially, it traverses the string, and checks to see
// whether that character is part of a group. If so, it adds
// it to a stack until it cannot. Then it pushes that group onto
// the new array. If the character is not part of a group, it
// simply pushes it onto the array.
function split(string, groups) {
	var array = [], // Array of characters and groups
		character, // Character being inspected
		match = '', // Characters so far that match a group
		isMatch; // Whether the current pass resulted in a match

	for (var i = 0, l = string.length; i < l; i++) { // Loop over the string

		isMatch = true;
		character = string.charAt(i);

		if (groupPrefix(match + character, groups)) { // If it is a prefix,
			match += character;                      // push it onto the stack
		} else if (groupPrefix(character, groups)) { // Special test for 
			array.push(match);                       // adjacent groups
			match = character;
		} else {
			isMatch = false;
		}

		// If there was a match, then jump to the next character
		if (isMatch) continue;
		
		// If there was no match, but there are characters in the 'match'
		// string, the previous character must have completed the match, 
		// so push in onto the array
		if (match) {
			array.push(match);
			match = '';
		}

		// Push the current character onto the 
		array.push(character);

	}

	// If characters are left in the match, check if it is a complete match,
	// and if so, push it onto the array. If it is of length one, it could also
	// be the last character
	if (match && (groups.indexOf(match) !== -1 || match.length == 1)) array.push(match); 

	return array;
}

// Generic shuffle function
function shuffle(array) {
	var newArray = [],
		random;
	for (var i = 0, l = array.length; i < l; i++) {
		random = Math.floor(Math.random() * array.length);
		newArray.push(array.splice(random, 1)[0]);
	}
	return newArray;
}

function scrambleWord(word) {
	var middle = word.slice(1, -1),
		array = split(middle, groups);
		array = shuffle(array);
	// return first charater + new middle + last character
	return word.charAt(0) + array.join('') + word.charAt(word.length - 1);
}


There is also a fiddle.

I would love it if someone could come up with a shorter function (as I am sure there must be, i'm probably not thinking straight). ;)
0


User is offline HeartLess 

  • Group: Members
  • Posts: 40
  • Joined: 21-June 11

Posted 20 August 2012 - 08:56 PM (#3)

View Postalexdavey, on 20 August 2012 - 02:07 PM, said:

*snip*


The code looks great. I'm using the same concept as you, but the problem I'm running into is the indexof() part. It returns true if the whole "group" is found, but it returns false if only part of it is found.

e.g.

input "er" : you get true
input "e" : you get false


EDIT: nvm. It was a mistake on my part while porting to PHP >:]
0


Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users


Enter your sign in name and password


Sign in options
  Or sign in with these services