Jump to content

How to generate a series of short strings?


calande

Recommended Posts

Hello,

 

I am learning, and I have no specific need for this at the moment, so it's just for fun. How can I generate a series of short strings composed only of lowercase letters, uppercase letters, and numbers so that all strings are different? Think about those TinyURL URLs that are short and uniquely identify URL shortcuts. How could we get started? Could we create a large array containing all uppercase and lowercase letters + numbers from 0 to 9? How could we do it easily (not manually)? With a loop? How? Then, how do we have PHP count from a to z, to A to Z, to 0 to 9, and always increment one unit? One other thing to consider is, suppose we pick this value from the latest record in a database: H7fs, how could we ask PHP to tell us what value the next record should have? (in this case, the next record should have H7ft). This boggles the mind, doesn't it? :)

How would you do? Thanks!

Link to comment
Share on other sites

If your just looking for some random string you could easily create a function to do so.

 

<?php

  function randstring($length=10) {
    $array = array_merge(range('a','z'),range('A','Z'),range(0,9));
    for ($i = 0; $i <= $length; $i++) {
      $str .= $array[rand(0,61)];
    }
    return $str;
  }

?>

 

Not tested.

Link to comment
Share on other sites

Try this Script

 

<?PHP
$chars = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N",
               "O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b",
               "c","d","e","f","g","h","i","j","k","l","m","n","o","p",
               "q","r","s","t","u","v","w","x","y","z",
               "1","2","3","4","5","6","7","8","9","0");

//Lenght of String
$string_length = 6;

//Result String
$result = "";
//Array Length
$count = count($strs) - 1;

for ($i = 0; $i <= $string_length; $i++){
	$rand = rand(0, $count);
	$result = $result . $strs[$rand];
}

echo $result;

?>

Link to comment
Share on other sites

Why not just truncate an md5 of the id?!

 

<pre><?php

$a = array();
$strlen = 8;

for( $i = 0; $i < 50000; $i++ )
$a[] = substr( md5($i), 0, $strlen );

$c1 = count( $a );

$c2 = count( array_unique($a) );

if( $c1 == $c2 )
echo '50000 unique entries were generated';
else
echo 'Duplicates found!';



?></pre>

 

Though it's not guaranteed to be unique. Though with an 8 character truncation, you don't hit a collision till ~83,000 entries.

Link to comment
Share on other sites

So you want incrementing values? Can I ask what this is going to be used for?

 

If its simply for testing purposes I would suggest you start trying to write it yourself, no point us testing your concepts and it is slowly getting more complex so more time consuming.

Link to comment
Share on other sites

Yes, incrementing values. I don't have any concrete use right now, it is for fun but it could be used for a site like TinyURL. I am working on it right now. My code is a little cluttered, when I am done I will post it and maybe you will bring suggestions to make it more simple  8)

Link to comment
Share on other sites

Here's something that'll convert your base10 number in a base62 number...

 

<pre><?php

function newBase( $i ) {
static $chars = array(
	'0','1','2','3','4','5','6','7','8','9',
	'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
	'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
);
$base = count( $chars );

$num = array();
while( $i > 0 ) {
	$num[] = $chars[ $i % $base ];
	$i = floor( $i / $base );
}

return implode( '', array_reverse($num) );
}

$nums = array();
for( $i=0; $i<1000; $i++ )
$nums[] = newBase( $i );

print_r( $nums );

?></pre>

 

Example

 

echo newBase( 54332646 );

 

returns

 

3FYp0

Link to comment
Share on other sites

Same function using a string... dunno why I had an array there.

function newBase( $i ) {
static $chars = array(
	'0','1','2','3','4','5','6','7','8','9',
	'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
	'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
);
$base = count( $chars );

$num = '';
while( $i > 0 ) {
	$num .= $chars[ $i % $base ];
	$i = floor( $i / $base );
}

return strrev( $num );
}

Link to comment
Share on other sites

It uses a base x system... binary being base 2 (0,1) and hex being base 16 (0-9,a-f)

 

This one is a base 62 (0-9,a-z,A-Z) and using the standard conversion algorithm, I converted the base 10 integer into base62 chunks and combined.

 

This page

http://mathbits.com/mathbits/compsci/Introduction/frombase10.htm

summarizes the algorithm quite well visually.

 

You divide your integer with your base, and find the integral quotient ( whole number, rounded down ) and remainder. Your remainder becomes the left most chunk. You repeat the process while your integral quotient is greater than 0... continually adding your remainder to the left of the solution.

 

If you need more explanation let me know.

Link to comment
Share on other sites

Oh and this might help a little visually

 

print_r( $chars );

Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
    [6] => 6
    [7] => 7
    [8] => 8
    [9] => 9
    [10] => a
    [11] => b
    [12] => c
    [13] => d
    [14] => e
    [15] => f
    [16] => g
    [17] => h
    [18] => i
    [19] => j
    [20] => k
    [21] => l
    [22] => m
    [23] => n
    [24] => o
    [25] => p
    [26] => q
    [27] => r
    [28] => s
    [29] => t
    [30] => u
    [31] => v
    [32] => w
    [33] => x
    [34] => y
    [35] => z
    [36] => A
    [37] => B
    [38] => C
    [39] => D
    [40] => E
    [41] => F
    [42] => G
    [43] => H
    [44] => I
    [45] => J
    [46] => K
    [47] => L
    [48] => M
    [49] => N
    [50] => O
    [51] => P
    [52] => Q
    [53] => R
    [54] => S
    [55] => T
    [56] => U
    [57] => V
    [58] => W
    [59] => X
    [60] => Y
    [61] => Z
)

 

So say with the number 1,345 -> Base 62

 

First step is divide!

1345/62 = 21 Remainder 43

 

[43] becomes our leftmost chunk

 

Now our integral quotient is still above 0, so repeat!

21/62 = 0 Remainder 21

 

[21] takes over as our leftmost chunk, which is now [21][43]

 

Our integral quotient is now 0, we are done. Now we convert to the desired characters above, and we get

lH

 

Now we can double check we got the right number by using

 

21 * (62^1) + 43 * (62^0) = 1345

 

We're done!

Link to comment
Share on other sites

Will eventually screw up, but I was unaware PHP could increment a mix of strings/number so damn well :) Thanks for that Barand.

 

As for incrementing... gotta convert back to raw.

 

<pre><?php

$int = 123453887;

$int_base62 = newBase( $int );

$int_base10 = oldBase( $int_base62 );

echo "
Start: \t $int
Converted: \t $int_base62
Back: \t $int_base10 ";

function newBase( $i ) {
static $chars = array(
	'0','1','2','3','4','5','6','7','8','9',
	'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
	'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
);
$base = count( $chars );

$num = '';
while( $i > 0 ) {
	$num .= $chars[ $i % $base ];
	$i = floor( $i / $base );
}

return strrev( $num );
}

function oldBase( $str ) {
static $chars = array(
	'0','1','2','3','4','5','6','7','8','9',
	'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
	'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
);
$base = count( $chars );
$chunks = array_reverse( str_split($str) );

$i = 0;
foreach( $chunks as $exp => $chunk ) {
	$value = array_search( $chunk, $chars );
	$i += pow( $base, $exp ) * $value;
}

return $i;

}

?></pre>

 

And just a note - these functions are limited by your max integer size... so on a 32 bit system, these functions start returning bad results for numbers above ~2.1 billion ( signed )

Link to comment
Share on other sites

Will eventually screw up,

 

Not really

 

$str = H7fs;

for ($i=0; $i<10; $i++) echo ++$str, '<br/>';


-->
H7ft
H7fu
H7fv
H7fw
H7fx
H7fy
H7fz
H7ga
H7gb
H7gc

 

and at the end of 1000 loops you have

 

H8rx
H8ry
H8rz
H8sa
H8sb
H8sc
H8sd
H8se

 

and eventually you get to

Z9zt
Z9zu
Z9zv
Z9zw
Z9zx
Z9zy
Z9zz
AA0aa
AA0ab
AA0ac

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.