Replacing char with number - php

There is this code that I am doing
Example a string of this value
z12z
I want to generate it
0120
0121
0122
... until 0129
then
1120
1121
1122
... until 1129
until 9129 , its sort of like two four loop, but I got no idea how to implement this.
and the issue is z can be anywhere and it can be zzzz
where it will be
0000 until 9999
or it could also be z0z0, z could be anywhere. What kind of method should I use for such.
Thanks!
I am doing it with php
for every occurance of letter 'z' , i will need do a for loop to generate the possible number, from 0 to 9, you can say z is a for loop for 0 to 9, e.g z555 will yield 0555,1555,2555,3555,4555,5555,6555,7555,8555,9555 , issue is z can occur with a possibility of 0 to 4, like z555 , zz55,zzz5, zzzz, and z position is random , I need generate the possible z number output
z position could be 55z5 , 5z55 , 5zz5 . its does not have a fix position.

<?php
$numbers = array();
for ($i = 0; $i <= 9; $i++){
for ($j = 120; $j <= 129; $j++){
$numbers[] = $i . $j;
}
}
print_r('<pre>');
print_r($numbers);
A better answer that take the z char is:
<?php
function strReplaceNth($search, $replace, $subject, $nth)
{
$found = preg_match_all('/' . preg_quote($search) . '/', $subject, $matches, PREG_OFFSET_CAPTURE);
if (false !== $found && $found > $nth) {
return substr_replace($subject, $replace, $matches[0][$nth][1], strlen($search));
}
return $subject;
}
function cleanup($numbers, $char)
{
$tmp = array();
for ($i = 0; $i < count($numbers); $i++){
if (strpos($numbers[$i], $char) === false){
$tmp[] = $numbers[$i];
}
}
return $tmp;
}
function generateNumber($numbers, $char)
{
if (!is_array($numbers)){
if (strpos($numbers, $char) === false){
return array($numbers);
} else {
$tmp = $numbers;
$numbers = array();
for ($j = 0; $j <= 9; $j++){
$numbers[] = strReplaceNth($char, $j, $tmp, 0);
}
return generateNumber($numbers, $char);
}
} else {
for ($i = 0; $i < count($numbers); $i++){
if (strpos($numbers[$i], $char) === false){
return cleanup($numbers, $char);
} else {
$numbers = array_merge($numbers, generateNumber($numbers[$i], $char));
}
}
return generateNumber($numbers, $char);
}
}
function getCharPos($string, $char)
{
$pos = array();
for ($i = 0; $i < strlen($string); $i++){
if (substr($string, $i, 1) == $char){
$pos[] = $i;
}
}
return $pos;
}
$string = 'z12z';
$char = 'z';
$occurences = getCharPos($string, $char);
$numbers = array();
if (count($occurences) > 0){
$numbers = generateNumber($string, $char);
} else {
$numbers[] = $string;
}
print_r('<pre>');
print_r($numbers);die();

Related

PHP - How to create all possibility from a string

Here, there is a example string "XjYAKpR" .. how to create all new string possibility with that string ??
I've tried before
function containAllRots($s, $arr) {
$n = strlen($s);
$a = array();
for ($i = 0; $i < $n ; $i++) {
$rotated = rotate(str_split($s), $i);
$a[] = $rotated;
}
print_r($a);die();
if (array_diff($arr, $a)) {
return True;
}
else
{
return False;
}
}
I make 2 function rotate and generate
function rotate($l, $n) {
$b = $l[$n];
$sisa = array_values(array_diff($l, array($b)));
for ($i = 0; $i < count($sisa) ; $i++) {
$random[] = generate($sisa, $b);
}
print_r($random);die();
$hasil = $l[$n] . implode("",$random);
return $hasil;
}
function generate($sisa, $b) {
$string = implode("",$sisa);
$length = count($sisa);
$size = strlen($string);
$str = '';
for( $i = 0; $i < $length; $i++ ) {
$str .= $string[ rand( 0, $size - 1 ) ];
}
Here there is a pair of functions that lets you calculate a permutation set
(no repetitions are taken in account)
function extends_permutation($char, $perm) {
$result = [];
$times = count($perm);
for ($i=0; $i<$times; $i++) {
$temp = $perm;
array_splice($temp, $i, 0, $char);
array_push($result, $temp);
}
array_push($result, array_merge($perm, [$char]));
return $result;
}
function extends_set_of_permutations($char, $set) {
$step = [];
foreach ($set as $perm) {
$step = array_merge($step, extends_permutation($char, $perm));
}
return $step;
}
you can use them to generate the required set of permutations. Something like this:
$seed = "XjYAKpR";
// the first set of permutations contains only the
// possible permutation of a one char string (1)
$result_set = [[$seed[0]]];
$rest = str_split(substr($seed,1));
foreach($rest as $char) {
$result_set = extends_set_of_permutations($char, $result_set);
}
$result_set = array_map('implode', $result_set);
sort($result_set);
At the end of the execution you will have the 5040 permutations generated by your string in the result_set array (sorted in alphabetical order).
Add a char and you will have more than 40000 results.
The functions are quite naive in implementation and naming, both aspects can be improved.

String compression in php

Here is my input
aaaabbaaaababbbcccccccccccc
And this is my expected output
a4b2a4b1a1b3c12
I tried like doing foreach and then concating the count of values. It seems like brutforcing. Is there any way to do it efficiently in php .
Help pls
You can use regular expression to get the result
preg_match_all('/(.)\1*/', $str, $m, PREG_SET_ORDER);
$m = array_map(function($i) { return $i[1] . strlen($i[0]); } , $m);
echo implode('', $m); // a4b2a4b1a1b3c12
demo
Here's an example of how to do it with a few for loops (encoding and decoding):
$input = 'aaaabbaaaababbbcccccccccccc';
$encoded = SillyEncoding::encode($input);
$decoded = SillyEncoding::decode($encoded);
echo "input = \t", var_export($input, true), "\n";
echo "encoded = \t", var_export($encoded, true), "\n";
echo "decoded = \t", var_export($decoded, true), "\n";
Output:
input = 'aaaabbaaaababbbcccccccccccc'
encoded = 'a4b2a4b1a1b3c12'
decoded = 'aaaabbaaaababbbcccccccccccc'
The SillyEncoding class:
class SillyEncoding
{
private static $digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
static function encode($string)
{
$output = '';
if (strlen($string) > 0) {
$count = 0;
$char = $string[0];
for ($i = 0; isset($string[$i]); ++$i) {
if (isset(self::$digits[$string[$i]])) {
throw new \InvalidArgumentException(sprintf('The input string must not contain a digit at offset %d, got "%s"', $i, $string[$i]));
}
if ($string[$i] === $char) {
++$count;
} else {
$output .= "{$char}{$count}";
$count = 1;
$char = $string[$i];
}
if (!isset($string[$i + 1])) {
$output .= "{$char}{$count}";
}
}
}
return $output;
}
static function decode($string)
{
$output = '';
$length = strlen($string);
if ($length > 0) {
$char = $string[0];
$count = null;
if ($length < 2) {
throw new \InvalidArgumentException(sprintf('Input string must be empty or at least 2 bytes long, got %d bytes', $length));
}
if (isset(self::$digits[$string[0]])) {
throw new \InvalidArgumentException(sprintf('Input string must not start with a digit, got "%s"', $string[0]));
}
for ($i = 1; isset($string[$i]); ++$i) {
$isDigit = isset(self::$digits[$string[$i]]);
if ($isDigit) {
$count .= $string[$i];
}
if (!$isDigit || !isset($string[$i + 1])) {
if (null === $count) {
throw new \InvalidArgumentException(sprintf('Expected a digit at offset %d, got "%s"', $i, $string[$i]));
}
$count = (int) $count;
for ($j = 0; $j < $count; ++$j) {
$output .= $char;
}
$char = $string[$i];
$count = null;
}
}
}
return $output;
}
}
A few things to note:
this isn't an efficient compression algorithm - it might reduce the size if there are many repeated characters, but if you feed it "normal" text the output will be about twice the size of the input
the input cannot contain any digits whatsoever (OP: "the input will be strictly alphabets")
$str = str_split('aaaabbaaaababbbcccccccccccc');
$count = 0;
$a=$result=$b='';
for ($i=0; $i <= count($str); $i++) {
if($a==$str[$i]){
$count++;
$result = $a.$count;
} else{
if ($count > 0) {
$b .= $result;
}
$count = 1;
$a = $str[$i];
$result = $a.$count;
}
}
print_r($b);
See result

Optimize substrings anagram compare algorithm

Im trying to solve one challenge where you have to check all string substrings are they anagrams. The condition is basically For S=abba, anagramic pairs are: {S[1,1],S[4,4]}, {S[1,2],S[3,4]}, {S[2,2],S[3,3]} and {S[1,3],S[2,4]}
Problem is that I have string with 100 chars and execution time should be below 9 secs. My time is around 50 secs... Below is my code, I will appreciate any advice - if you give me only directions or pseudo code it is even better.
$time1 = microtime(true);
$string = 'abdcasdabvdvafsgfdsvafdsafewsrgsdcasfsdfgxccafdsgccafsdgsdcascdsfsdfsdgfadasdgsdfawdascsdsasdasgsdfs';
$arr = [];
$len = strlen($string);
for ($i = 0; $i < strlen($string); $i++) {
if ($i === 0) {
for ($j = 1; $j <= $len - 1; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
} else {
for ($j = 1; $j <= $len - $i; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
}
}
$br = 0;
$arrLength = count($arr);
foreach ($arr as $key => $val) {
if ($key === count($arr) - 1) {
break;
}
for ($k = $key + 1; $k < $arrLength; $k++) {
if (is_anagram($val, $arr[$k]) === true) {
$br++;
}
}
}
echo $br."</br>";
function is_anagram($a, $b)
{
$result = (count_chars($a, 1) == count_chars($b, 1));
return $result;
}
$time2 = microtime(true);
echo "Script execution time: ".($time2-$time1);
Edit:
Hi again, today I had some time so I tried to optimize but couldnt crack this... This is my new code but I think it got worse. Any advanced suggestions ?
<?php
$string = 'abdcasdabvdvafsgfdsvafdsafewsrgsdcasfsdfgxccafdsgccafsdgsdcascdsfsdfsdgfadasdgsdfawdascsdsasdasgsdfs';
$arr = [];
$len = strlen($string);
for ($i = 0; $i < strlen($string); $i++) {
if ($i === 0) {
for ($j = 1; $j <= $len - 1; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
} else {
for ($j = 1; $j <= $len - $i; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
}
}
$br = 0;
$arrlen = count ($arr);
foreach ($arr as $key => $val) {
if (($key === $arrlen - 1)) {
break;
}
for ($k = $key + 1; $k < $arrlen; $k++) {
$result = stringsCompare($val,$arr[$k]);
if ($result === true)
{
$br++;
}
}
echo $br."\n";
}
function stringsCompare($a,$b)
{
$lenOne = strlen($a);
$lenTwo = strlen ($b);
if ($lenOne !== $lenTwo)
{
return false;
}
else {
$fail = 0;
if ($lenOne === 1) {
if ($a === $b) {
return true;
}
else
{
return false;
}
}
else
{
for ($x = 0; $x < $lenOne; $x++)
{
$position = strpos($b,$a[$x]);
if($position === false)
{
$fail = 1;
break;
}
else
{
$b[$position] = 0;
$fail = 0;
}
}
if ($fail === 1)
{
return false;
}
else
{
return true;
}
}
}
}
?>
You should think of another rule that all anagrams of a certain string can meet. For example, something about the number of occurrences of each character.

PHP - Efficiency while searching for palindrome

I was challenged by a friend to code some PHP to find the longest palindrome in provided text, my solution is below, how could I make it more efficient?
$string = file_get_contents("http://challenge.greplin.com/static/gettysburg.txt");
echo $string;
function isPalendrone($string) {
if ($string == strrev($string))
return true;
else
return false;
}
$longest = "";
for($i = 0; $i < strlen($string)-1; $i++) {
$afterCurrent = substr($string, $i);
for($j = 0; $j < strlen($afterCurrent)-1; $j++) {
$section = substr($afterCurrent, 0, $j);
if(isPalendrone($section)) {
if(strlen($longest)<strlen($section)) {
$longest = $section;
}
}
}
}
echo "<br /><br/>The longest was: ".$longest."<br /> which is ".strlen($longest)." chars long";
This reverses the entire string and just does substr() matches against each:
$rev = strrev($txt);
$len = strlen($txt);
$longest_len = 0;
$longest_str = null;
for ($i = 0; $i < $len; ++$i)
{
for ($j = $len - $i; $j > $longest_len; --$j)
{
if (substr($txt, $i, $j) == substr($rev, $len-$i-$j, $j))
{
$longest_len = $j;
$longest_str = substr($txt, $i, $j);
break;
}
}
}
I didn't try to optimize the implementation. e.g., It might be a little faster to skip the substr and do a char-by-char approach, because you could break out faster. In that case, you wouldn't really even need to reverse the string.
To get the longest palindrome - you have to start with longest string (not with shortest like you do now), check it and break on first match.
Also you'd better just keep 2 pointers ($i and $j) and not perform substr twice. It is enough to have i and j and substr once, right before you perform if(isPalendrone()) condition.
My implementation (~20% faster than yours):
<?php
$string = 'FourscoreandsevenyearsagoourfaathersbroughtforthonthiscontainentanewnationconceivedinzLibertyanddedicatedtothepropositionthatallmenarecreatedequalNowweareengagedinagreahtcivilwartestingwhetherthatnaptionoranynartionsoconceivedandsodedicatedcanlongendureWeareqmetonagreatbattlefiemldoftzhatwarWehavecometodedicpateaportionofthatfieldasafinalrestingplaceforthosewhoheregavetheirlivesthatthatnationmightliveItisaltogetherfangandproperthatweshoulddothisButinalargersensewecannotdedicatewecannotconsecratewecannothallowthisgroundThebravelmenlivinganddeadwhostruggledherehaveconsecrateditfaraboveourpoorponwertoaddordetractTgheworldadswfilllittlenotlenorlongrememberwhatwesayherebutitcanneverforgetwhattheydidhereItisforusthelivingrathertobededicatedheretotheulnfinishedworkwhichtheywhofoughtherehavethusfarsonoblyadvancedItisratherforustobeherededicatedtothegreattdafskremainingbeforeusthatfromthesehonoreddeadwetakeincreaseddevotiontothatcauseforwhichtheygavethelastpfullmeasureofdevotionthatweherehighlyresolvethatthesedeadshallnothavediedinvainthatthisnationunsderGodshallhaveanewbirthoffreedomandthatgovernmentofthepeoplebythepeopleforthepeopleshallnotperishfromtheearth';
function isPalendrone($string) {
return $string == strrev($string);
}
$longest = '';
$length = strlen($string);
for ($i = 0; $i < $length - 1; $i++) {
for ($j = $length - $i; $j > 1; $j--) {
if (isPalendrone(substr($string, $i, $j))) {
$new = substr($string, $i, $j);
if (strlen($new) > strlen($longest)) $longest = $new;
break;
}
}
}
echo "<br /><br/>The longest was: ".$longest."<br /> which is ".strlen($longest)." chars long";

PHP Random Number

I want to generate a random number in PHP where the digits itself should not repeat in that number.
Is that possible?
Can you paste sample code here?
Ex: 674930, 145289. [i.e Same digit shouldn't come]
Thanks
Here is a good way of doing it:
$amountOfDigits = 6;
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $amountOfDigits;$i++)
$digits .= $numbers[$i];
echo $digits; //prints 217356
If you wanted it in a neat function you could create something like this:
function randomDigits($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
function randomize($len = false)
{
$ints = array();
$len = $len ? $len : rand(2,9);
if($len > 9)
{
trigger_error('Maximum length should not exceed 9');
return 0;
}
while(true)
{
$current = rand(0,9);
if(!in_array($current,$ints))
{
$ints[] = $current;
}
if(count($ints) == $len)
{
return implode($ints);
}
}
}
echo randomize(); //Numbers that are all unique with a random length.
echo randomize(7); //Numbers that are all unique with a length of 7
Something along those lines should do it
<?php
function genRandomString() {
$length = 10; // set length of string
$characters = '0123456789'; // for undefined string
$string ="";
for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters))];
}
return $string;
}
$s = genRandomString(); //this is your random print var
or
function rand_string( $length )
{
$chars = "0123456789";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ )
{
$str .= $chars[ rand( 0, $size – 1 ) ];
}
return $str;
}
$rid= rand_string( 6 ); // 6 means length of generate string
?>
$result= "";
$numbers= "0123456789";
$length = 8;
$i = 0;
while ($i < $length)
{
$char = substr($numbers, mt_rand(0, strlen($numbers)-1), 1);
//prevents duplicates
if (!strstr($result, $char))
{
$result .= $char;
$i++;
}
}
This should do the trick. In $numbers you can put any char you want, for example: I have used this to generate random passwords, productcodes etc.
The least amount of code I saw for something like this was:
function random_num($n=5)
{
return rand(0, pow(10, $n));
}
But I'm assuming it requires more processing to do this than these other methods.

Categories