What Algorithm is used for this? - php

im doing research project for a the game Text twist,the text will automatically search word from a dictionary and scramble then, and also process the words to be found automatically using the same concept with this site http://grecni.com/texttwist.php , i also need to provide an algorithm that i will use for my project,and im planning to include this word unscrambler in this web site http://grecni.com/texttwist.php but i dont know what algorithm is possibly use to do the actions done on the website i posted. does any one know what type, or what you call the algorithm used,or can be use that will give the same results, an example of the algorithm will be greatly appreciated.

The data structure you want is called a Directed Acyclic Word Graph (dawg)
There are questions already answered about this:
Algorithm to get a list of all words that are anagrams of all substrings (scrabble)?
Writing an algorithm for scrabble
You could also perhaps implement the levenshtein algorithm which would accomplish pretty much the same result:
MySQL - Which Hash Algo should I use for this?
Update:
After giving myself a challenge to create an example to demonstrate the algorithm ive come up with this, as its from a plugin built for my cms its wrapped in a class but your get the idea there is a demo # http://cherone.co.uk/scrabble_suggest
First I created a table with id,word,sorted (word = the actual word, sorted = the word alphabetically sorted like for e.g: aardvark sorted would be aaadkrrv) i just found an english wordlist on the internets.
The form posts the string and then the string is sorted alphabetically to match 1:1 the sorted column, then the string is split into each character and then queried sequentially till the last character. The functions of interest are str_sort,permute,swap Perhaps its of some interest..
<?php
/**
* Scrabble solver Plugin this file is "inline" included within the frontController class
*/
Class plugin{
function __construct($core) {
$this->core = $core;
$this->plugin_path = SITE_ROOT.'/core/plugins/'.$this->core->router->action.'/';
$this->request = explode('/',$this->core->router->request);
//Assign Page meta tags ect
$this->core->template->meta_keywords = 'Text,Twist,Text Twist,word,letter,scrabble,unscrambler,unscramble,word finder,puzzle,anagram,scrabble,cheat,cheater,help,helper,solve,solver,free,php';
$this->core->template->meta_description = 'Scrabble and Anagram like word solver tool to help unscramble letters and words and cheat at your favorite word puzzle';
$this->core->template->page_title = $this->core->template->site_name." - Scrabble and Anagram like word solver";
$route = (isset($this->request[2])?$this->request[2]:null);
}
function load(){
set_time_limit(0);
$data=array('var'=>$this,'result'=>'','word'=>'','word_sort'=>'');
switch($this->core->router->subaction){
case "index":
$string='';
if($_SERVER['REQUEST_METHOD']=='POST'){
$string = substr(preg_replace('/[^a-zA-Z]/s', '', trim(strtolower($_POST['letters']))),0,8);
$data['word'] = $string;
$string = $this->str_sort($string);
$data['word_sort'] = $string;
}
$stringLen = strlen($string);
$result = array();
for($i=2;$i<=$stringLen;$i++){
$seq = substr($data['word_sort'],0,$i);
$rounds = explode('|',$this->permute($seq,0,strlen($seq)));
$r=$i;
foreach($rounds as $round){
$result[$r] = $this->get_words($round,strlen($seq));
$r++;
}
}
$data['result'] = $result;
$this->core->template->content_center = $this->core->template->loadContentView(get_class(),$this->core->router->subaction,$data);
$this->core->template->content_left = '';
$this->core->template->content_right = '';
break;
case "update":
$this->insert_word_lists();
header('Location: '.SITE_URL.'/'.$this->core->router->action);
die;
break;
case "api":
header('Content-Type: application/json');
echo 'No api for this plugin, perhaps one comming soon. ;p';
break;
default:
header('Location: '.SITE_URL.'/'.$this->core->router->action);
die;
break;
}
}
//Query Method to search for sequenced alphabetically sorted words.
private function get_words($word,$stringLen){
$chars = str_split($word,1);
$sql = "SELECT DISTINCT `word` FROM `plugin_scrabble_words` WHERE ";
foreach($chars as $char){
$sql .=' `sorted` LIKE "%'.$char.'%" AND';
}
$sql = trim($sql,'AND');
$sql .= ' AND LENGTH(sorted) = '.$stringLen;
$statement = $this->core->db->prepare($sql);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
//A Model method for updating the database word list.
private function insert_word_lists(){
set_time_limit(0);
$lists = glob($this->plugin_path."wordlists/*.txt");
foreach ($lists as $list){
$words = file($list);
foreach($words as $word){
$word = strtolower(preg_replace('/[^a-zA-Z]/s', '', $word));
if($this->sql_check_word($word)===false){
$this->sql_put_word($word);
}
}
}
}
//A Model method for checking the database specific word.
private function sql_check_word($word){
$sql = "SELECT `word` FROM `plugin_scrabble_words` WHERE `word` = :word";
$statement = $this->core->db->prepare($sql);
$statement->bindParam(':word', $word, PDO::PARAM_STR);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if(!empty($result)){
return true;
}else{
return false;
}
}
//A Model method for adding the word to the database.
private function sql_put_word($word){
$sql = "INSERT into `plugin_scrabble_words` (word,sorted) VALUES (:word,:sorted)";
$statement = $this->core->db->prepare($sql);
$sorted = $this->str_sort($word);
$statement->bindParam(':word', $word, PDO::PARAM_STR);
$statement->bindParam(':sorted', $sorted, PDO::PARAM_STR);
$statement->execute();
}
//Sort Method that will sort a sring in alphabetical order
private function str_sort($string) {
$tmp = str_split($string);
sort($tmp);
return implode('',$tmp);
}
//Method to generate and return all permutations of the string with | delimiter.
private function permute($str,$i,$n) {
if ($i == $n){
return $str.'|';
} else {
for ($j = $i; $j < $n; $j++) {
$this->swap($str,$i,$j);
$this->permute($str, $i+1, $n);
$this->swap($str,$i,$j);
}
}
}
//Method to swap the char at pos $i and $j of $str.
private function swap(&$str,$i,$j) {
$temp = $str[$i];
$str[$i] = $str[$j];
$str[$j] = $temp;
}
}
?>

One approach would be to generate all possible permutations of the letters and match them against a dictionary. For an N lettered character sequence, this would take O(N!) time if you keep the dictionary in a set data structure.
For shorter sequences (10 characters or so), this is a perfectly good strategy.
For longer sequences, you should do the reverse. You can loop through the dictionary and determine if your character sequence has the characters to make the word. For M dictionary elements, this would take more or less O(M) time. There are various ways you can speed up this technique like pre-computing the number of each letter in each dictionary entry.

edit: The gentleman below me gives a more algorithmically rigorous and thorough treatment of the subject, and so I would direct you to his explanation (which employs big O notation which mine... embarrassingly does not).
Actually, although VanDang called it a "naive approach", there's nothing wrong with testing all possible combinations of the finite set of characters given. As long as a person is prevented from providing an arbitrary number of characters, there is a maximum of !n combinations of letters (with n = the number of letters, assuming there are no repeats), and, since words in English don't get THAT long, testing each combination wouldn't be that bad.
After all, the method of exhaustion is actually an accepted method for optimizing large boolean expressions when generating hardware descriptions.

Related

Math / statistics problem analyse words in string

In need of some help - am trying to analyse news articles.
I have a list of positive words and negative words. I am search the article contents for instances of the words a counting the up.
my problem is that the negative word list is a lot long that the positive so all the results a skewed to negative.
I am looking for a way to normalise the results so a positive word is weighted slightly against the negative to even out the fact that is a considerably high chance of finding a negative word. Unfortunately I have no idea where to start.
Appreciate you taking the time to read this.
Below is the code I have so far.
function process_scores($content)
{
$positive_score = 0;
for ($i = 0; $i < count($this->positive_words); $i++) {
if($this->positive_words[$i] != "")
{
$c = substr_count( strtolower($content) , $this->positive_words[$i] );
if($c > 0)
{
$positive_score += $c;
}
}
}
$negative_score = 0;
for ($i = 0; $i < count($this->negative_words); $i++) {
if($this->negative_words[$i] != "")
{
$c = substr_count( strtolower($content) , $this->negative_words[$i] );
if($c > 0)
{
$negative_score += $c;
}
}
}
return ["positive_score" => $positive_score, "negative_score" => $negative_score];
}
So I don't know php, but this seems less like a php question and more of a question of method. Right now when you analyze an article, you assign words as positive or negative based on whether or not they are in your dictionary, but because your dictionaries are of different sizes, you feel like this isn't giving you a fair analysis of the article.
One method you could try is to assign each word in the article a value. If a word does not exist in your dictionary, have the program prompt for manual interpretation of the word through the command line. Then decide whether the word is positive, negative, or neutral, and have the program add that word to the appropriate dictionary. This will be really annoying at first, but English speakers use roughly the same 2000 words for almost all of our conversation, so after a few articles, you will have robust dictionaries and not have to worry about skew because every single word will have been assigned a value.
I would suggest just throwing in a weighting factor to the output. The exact weighting is determined by trial and error. I went ahead and refactored your code since there was some repetition
<?php
class WordScore {
private $negative_words = [];
private $positive_words = [];
private $positive_weight = 1;
private $negative_weight = 1;
public function setScore(float $pos = 1, float $neg = 1) {
$this->negative_weight = $neg;
$this->positive_weight = $pos;
}
public function processScores($content) {
$positive_score = $this->countWords($content, $this->positive_words);
$negative_score = $this->countWords($content, $this->negative_words);
return [
"positive_score" => $positive_score * $this->positive_weight,
"negative_score" => $negative_score * $this->negative_weight
];
}
private function countWords( string $content, array $words, float $weight = 1 ) {
$count = 0;
foreach( $words as $word ) {
$count += substr_count( strtolower($content) , strtolower($word) );
}
return $count;
}
}
working example at http://sandbox.onlinephpfunctions.com/code/19b4ac3c12d35cf253e9fa6049e91508e4797a2e

PHP: Generate random Code excluding (0, 1, O and L)

I am trying to generate random voucher code applying the following rules:
Alphanumeric combination 5 characters in capital case (A-Z, 0-9, and take away 1, 0, I, O).
This is my try
<?php
function generateRandomString($length = 5) {
return substr(str_shuffle("23456789ABCDEFGHIJKMNPQRSTUVWXYZ"), 0, $length);
}
echo generateRandomString();
?>
but i am not sure if there is a better way of doing this
If you need to call this function lots of times, your current implementation will be very slow, because it uses much more calls of random function than it is necessary (if $length < 32). Also if your set of allowed characters is smaller than number of characters in the result, your current implementation will return wrong result too. And also your implementation does not allow repeating of characters in the result, but in the specification it is not forbidden to repeat characters.
A little more accurate solution is to use array_rand():
function generateRandomString($length = 5) {
$allowed = str_split('23456789ABCDEFGHIJKMNPQRSTUVWXYZ'); // it is enough to do it once
$res = '';
foreach (array_rand($allowed, $length) as $k)
$res .= $allowed[$k];
return $res;
}
function generateRandom($length = 5) {
$possibleChars = '123456789ABCDEFGHJKMNPQRSTUVWXYZ';
$rndString = '';
for ($i = 0; $i < $length; $i++) {
$rndString .= $possibleChars[rand(0, strlen($possibleChars) - 1)];
}
return $rndString;
}
echo generateRandom();
Here you can define the characters which you want to have in your random string.
The problem with your function is that any char will be just used 1 time per call. Its not really random. And the lenght of the random string would also be limited to the amount of characters you have.
For example: AAAAA is not possible with your function, with mine it is.
If you need a string longer than your charset, that method will fail. Please can you try the code below;
<?php
function generateRandomString($length = 5) {
$chars = "23456789ABCDEFGHIJKMNPQRSTUVWXYZ"; //Your char-set
$charArray = str_split($chars); //Your array representation of chars
$charCount = strlen($chars); //Your char-set length
$result = "";
//Loop throught required `$length`
for($i=1;$i<=$length;$i++)
{
$randChar = rand(0,$charCount-1); //Pick a random char in range of our chars
$result .= $charArray[$randChar]; //Concatenate picked char to result
}
return $result;
}
echo generateRandomString(75);
?>
Here is a working example: https://ideone.com/D1EQ9T
Hope this helps.

put comma in alexa rank

I have alexa function and return alexa rank. I want to put comma in every three digit.
ex: 1,500,500
I have tried to use number_format() but it doesn't work with me. here is the function
<?php
/**
* Get Popularity Text of a Domain via Alexa XML Data
*
* #return string|FALSE text or FALSE on error
*/
function alexa_get_rank($domain)
{
$alexa = "http://data.alexa.com/data?cli=10&dat=s&url=%s";
$request_url = sprintf($alexa, urlencode($domain));
$xml = simplexml_load_file($request_url);
if (!$xml) {
return FALSE;
}
$nodeAttributes = $xml->SD[1]->POPULARITY->attributes();
$text = (int) $nodeAttributes['TEXT'];
$num = number_format($text);
return $num;
}
this only returns 3 numbers
ex: ranks is 1,500,500 but it shows 500 only.
thank you
Quick and dirty answer:
try to define all the params of number format, for what I know it should work.
At last, if nothign else works you don't need to use the regex, just juggle with the string version of your number:
function addCommas($number) {
return strrev(join(",",str_split(strrev($number),3)));
}
After a short test session on codepad I can assure to you that you code should work as is,
at http://codepad.org/0zLuBQp8 you will find a slightly modified demo (I've retrieved data with a query and pasted the xml as string to circumvent some codepad limitations).
(I would suggest you to split the xml loading phase in two in order to check if your input is healty and you are manipulating the right datas)
You could always run a simple while statement::
$text = (int) $nodeAttributes['TEXT'];
while (true){
$num = preg_replace('/(-?\d+)(\d\d\d)/', '$1,$2', $text );
if ($num != $text ) {
$text = $num;
} else {
break;
}
}
return $num;

Turning an integer into random string and back again

what I'm wanting is to convert an integer into a string. For example, 123456789 may become 8GFsah93r ... you know like Youtube, Pastebin and what not. I then want to convert it back.
I'm working with large integers, for example: 131569877435989900
Take a look at this link: http://codepad.viper-7.com/wHKOMi
This is my attempt using a function I found on the web, obviously... it's not correctly converting back to integer. I'm needing something that does this realiably.
Thanks
Ok, one of the ideas is to use a character array as a representation of a numeric system. Then you can convert from base 10 to base x and vica-versa. The value will be shorter and less readable (altought, you should encrypt it with a two-way crypter if it must be secure).
A solution:
final class UrlShortener {
private static $charfeed = Array(
'a','A','b','B','c','C','d','D','e','E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m',
'M','n','N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w','W','x','X','y','Y',
'z','Z','0','1','2','3','4','5','6','7','8','9');
public static function intToShort($number) {
$need = count(self::$charfeed);
$s = '';
do {
$s .= self::$charfeed[$number%$need];
$number = floor($number/$need);
} while($number > 0);
return $s;
}
public static function shortToInt($string) {
$num = 0;
$need = count(self::$charfeed);
$length = strlen($string);
for($x = 0; $x < $length; $x++) {
$key = array_search($string[$x], self::$charfeed);
$value = $key * pow($need, $x);
$num += $value;
}
return $num;
}
}
Then you can use:
UrlShortener::intToShort(2);
UrlShortener::shortToInt("b");
EDIT
with large numbers, it does not work. You should use this version (with bcmath http://www.php.net/manual/en/book.bc.php ) with very large numbers:
final class UrlShortener {
private static $charfeed = Array(
'a','A','b','B','c','C','d','D','e','E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m',
'M','n','N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w','W','x','X','y','Y',
'z','Z','0','1','2','3','4','5','6','7','8','9');
public static function intToShort($number) {
$need = count(self::$charfeed);
$s = '';
do {
$s .= self::$charfeed[bcmod($number, $need)];
$number = floor($number/$need);
} while($number > 0);
return $s;
}
public static function shortToInt($string) {
$num = 0;
$need = count(self::$charfeed);
$length = strlen($string);
for($x = 0; $x < $length; $x++) {
$key = array_search($string[$x], self::$charfeed);
$value = $key * bcpow($need, $x);
$num += $value;
}
return $num;
}
}
$original = 131569877435989900;
$short = UrlShortener::intToShort($original);
echo $short;
echo '<br/>';
$result = UrlShortener::shortToInt($short);
echo $result;
echo '<br/>';
echo bccomp($original, $result);
If something missing from here, please let me know, because it's only a snippet from my library (I don't wanna insert the whole thing here)
negra
check base64 encoding: http://php.net/manual/en/function.base64-encode.php http://php.net/manual/en/function.base64-decode.php
If you want a shorter string first encode it into an 8bit string then encode. You can do this with % 256 and / 256.
Or you could manually do what base64 does, get the first 6bits and encode it to a char.
Why not use something like this? Do you need it heavily encrypted?
$num = 131569877435989900;
echo $str = base64_encode($num);
echo base64_decode($str);
I think what you want is to encode the ids using Base32. The resulting string contains only the 26 letters of the alphabet and the digits 2-7, making it very human readable.
The simplest would be to use something like base_convert -- unfortunately, it won't work for such large integers correctly.
However, you can use the same idea by copying base_convert_arbitrary from my answer here and doing:
$id = '131569877435989900';
$encoded = base_convert_arbitrary($id, 10, 36);
$decoded = base_convert_arbitrary($encoded, 36, 10);
print_r($encoded);
print_r($decoded);
See it in action.
The nice thing about this approach is that you can tweak the first line inside the function, which reads:
$digits = '0123456789abcdefghijklmnopqrstuvwxyz'; // 36 "digits"
Add any other "digits" you find acceptable (e.g. capital letters or other symbols you don't mind having in your URL). You can then replace the base 36 in the above example with a larger one (you can go as high as there are defined digits), and it will work just like you want it to.
See it here working with 62 digits.
I am suprised No one is mentioning base64_encode() and it partner base64_decode().
If you were not considering length this is perfect
$before = base64_encode(131569877435989900);
$after = 'MS4zMTU2OTg3NzQzNTk5RSsxNw==';
$on_reverse = base64_decode('MS4zMTU2OTg3NzQzNTk5RSsxNw==');
$on_reverse == 131569877435989900;
I always go for the simplest solutions, as long as they don't compromise my security.
The easiest way to get random string is to use hash functions like md5() or sha1() For example:
<?php
$bigInt = '131569877435989900';
$hash = md5($bigInt);
$hashed=substr($hash,0,-20);
echo $hashed;
?>
These hash functions are irreversible-you can't get the original value(these functions are also used to crypt data). If you want you can save the original big integer in an array or a database. But decripting the hash would be impossible.

PHP code for generating decent-looking coupon codes (mix of letters and numbers)

For an ecommerce site I want to generate a random coupon code that looks better than a randomly generated value. It should be a readable coupon code, all in uppercase with no special characters, only letters (A-Z) and numbers (0-9).
Since people might be reading this out / printing it elsewhere, we need to make this a simple-to-communicate value as well, perhaps 8-10 characters long.
Something like perhaps,
AHS3DJ6BW
B83JS1HSK
(I typed that, so it's not really that random)
$chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$res = "";
for ($i = 0; $i < 10; $i++) {
$res .= $chars[mt_rand(0, strlen($chars)-1)];
}
You can optimize this by preallocating the $res string and caching the result of strlen($chars)-1. This is left as an exercise to the reader, since probably you won't be generating thousands of coupons per second.
Try this:
substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, 10)
Why don't keep it simple?
<?php
echo strtoupper(uniqid());
?>
Always returns 13 character long uppercased random code.
You can use the coupon code generator PHP class file to generate N number of coupons and its customizable, with various options of adding own mask with own prefix and suffix. Simple PHP coupon code generator
Example:
coupon::generate(8); // J5BST6NQ
http://webarto.com/35/php-random-string-generator
Here you go.
function randr($j = 8){
$string = "";
for($i=0;$i < $j;$i++){
srand((double)microtime()*1234567);
$x = mt_rand(0,2);
switch($x){
case 0:$string.= chr(mt_rand(97,122));break;
case 1:$string.= chr(mt_rand(65,90));break;
case 2:$string.= chr(mt_rand(48,57));break;
}
}
return strtoupper($string); //to uppercase
}
If there are no security requirements for these, then you don't really need randomly generated codes. I would just use incremental IDs, such as those generated by whatever RDBMS you use. Optionally, if you have different types of coupons, you could prefix the codes with something, e.g.:
CX00019 QZ0001C
CX0001A QZ0001D
CX0001B QZ0001E
Alternately, you could even use dictionary words in the coupon, as such coupon codes are easier to remember and faster for users to type. Companies like Dreamhost use these for their promo codes, e.g.:
Promo60
NoSetupFee
YELLOWGORILLA82
Some of these are obviously human-created (which you might want to have the option of), but they can also be generated using a dictionary list. But even if they are randomly-generated nonsense phrases, the fact that the characters follow a logical pattern still makes it much more user-friendly than something like R7QZ8A92F1. So I would strongly advise against using the latter type of coupon codes just on the basis that they "look cool". Your customers will thank you.
$size = 12;
$string = strtoupper(substr(md5(time().rand(10000,99999)), 0, $size));
function generateCouponCode($length = 8) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$ret = '';
for($i = 0; $i < $length; ++$i) {
$random = str_shuffle($chars);
$ret .= $random[0];
}
return $ret;
}
you can find a lot of function in php rand manual
http://php.net/manual/en/function.rand.php
i like this one
<?php
//To Pull 8 Unique Random Values Out Of AlphaNumeric
//removed number 0, capital o, number 1 and small L
//Total: keys = 32, elements = 33
$characters = array(
"A","B","C","D","E","F","G","H","J","K","L","M",
"N","P","Q","R","S","T","U","V","W","X","Y","Z",
"1","2","3","4","5","6","7","8","9");
//make an "empty container" or array for our keys
$keys = array();
//first count of $keys is empty so "1", remaining count is 1-7 = total 8 times
while(count($keys) < 8) {
//"0" because we use this to FIND ARRAY KEYS which has a 0 value
//"-1" because were only concerned of number of keys which is 32 not 33
//count($characters) = 33
$x = mt_rand(0, count($characters)-1);
if(!in_array($x, $keys)) {
$keys[] = $x;
}
}
foreach($keys as $key){
$random_chars .= $characters[$key];
}
echo $random_chars;
?>
$length = 9;
$code = (strtoupper(substr(md5(time()), 0, $length)));
Just Write
$voucher_no = date('ymd') . rand(1000, 9999);
while(SapItem::where('voucher_no', $voucher_no)->exists()){
$voucher_no = date('ymd') . rand(1000, 9999);
}
Output: 2204171447

Categories