PHP Loop Stuck on one character - php

i have some problem.
i just want my loop to run, but when i try to do it, it fails, it has to increment each letter by a few, but it doesn't take any new letters at all, why is this happening and what is the reason? in c ++ such code would work.
function accum('ZpglnRxqenU') {
// your code
$result = '';
$letters_result = '';
$letter_original = '';
$num_if_str = strlen($s);
$j = 0;
for ( $i=0; $i <= $num_if_str; $i++ )
{
$letter_original = substr($s, $i, $i+1);
$j = 0;
while($j == $i)
{
$letters_result = $letters_result . $letter_original;
$j++;
}
if($i != strlen($s))
{
$letters_result = $letters_result . '-';
}
}
return $letters_result;
}
It returns
- Expected: 'Z-Pp-Ggg-Llll-Nnnnn-Rrrrrr-Xxxxxxx-Qqqqqqqq-Eeeeeeeee-Nnnnnnnnnn-Uuuuuuuuuuu'
Actual : 'Z-----------'
what problem with what PHP code?

There are a number of problems here:
you're using $s but never initialise it
Your call to substr() uses an incorrect value for the length of substring to return
you're inner loop only runs while $i = $j, but you initialise $j to 0 so it will only run when $i is zero, i.e. for the first letter of the string.
There is a simpler way to do this. In PHP you can address individual characters in a string as if they were array elements, so no need for substr()
Further, you can use str_repeat() to generate the repeating strings, and if you store the expanded strings in an array you can join them all with implode().
Lastly, combining ucwords() and strtolower() returns the required case.
Putting it all together we get
<?php
$str = "ZpglnRxqenU";
$output = [];
for ($i = 0;$i<strlen($str);$i++) {
$output[] = str_repeat($str[$i], $i+1);
}
$output = ucwords(strtolower(implode('-',$output)),"-");
echo $output; // Z-Pp-Ggg-Llll-Nnnnn-Rrrrrr-Xxxxxxx-Qqqqqqqq-Eeeeeeeee-Nnnnnnnnnn-Uuuuuuuuuuu
Demo:https://3v4l.org/OoukZ

I don't have much more to add to #TangentiallyPerpendicular's answer as far as critique, other than you've made the classic while($i<=strlen($s)) off-by-one blunder. String bar will have a length of 3, but arrays are zero-indexed [eg: [ 0 => 'b', 1 => 'a', '2' => 'r' ]] so when you hit $i == strlen() at 3, that's an error.
Aside from that your approach, when corrected and made concise, would look like:
function accum($input) {
$result = '';
for ( $i=0, $len=strlen($input); $i < $len; $i++ ) {
$letter = substr($input, $i, 1);
for( $j=0; $j<=$i; $j++ ) {
$result .= $letter;
}
if($i != $len-1) {
$result .= '-';
}
}
return $result;
}
var_dump(accum('ZpglnRxqenU'));
Output:
string(76) "Z-pp-ggg-llll-nnnnn-RRRRRR-xxxxxxx-qqqqqqqq-eeeeeeeee-nnnnnnnnnn-UUUUUUUUUUU"
Also keep in mind that functions have their own isolated variable scope, so you don't need to namespace variables like $letters_foo which can make your code a bit confusing to the eye.

Related

How do i rand string according to index size

I don't really know how to go about but it really pretty for me in achievement like each rand_string to each index.
My code:
function rand_string($length) {
$str="";
$chars = "abcdefghijklmanopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen($chars);
for($i = 0; $i < $length; $i++) {
$str .= $chars[rand(0, $size-1)];
}
return $str;
}
$pcode = rand_string(4);
for ($b = 0; $b < 3; $b++) {
echo $pcode[$b];
}
I am expecting something like: 9cwm cZnu c9e4 in the output. Can I achieve this in PHP?
Currently, with my code, I get a string from rand_string in each index like 9cw.
Your code works, you only need to call rand_string inside your second loop in order to get something like 9cwm cZnu c9e4 (what you have described in your question).
Here is a working example:
function rand_string($length) {
$str="";
$chars = "abcdefghijklmanopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen($chars);
for($i = 0;$i < $length;$i++) {
$str .= $chars[rand(0,$size-1)];
}
return $str;
}
// call rand_string inside for loop
for ($b = 0; $b<3; $b++) {
echo rand_string(4).' ';
}
Try it online
The generation of the string actually works in your code. You aren't calling/printing the function correctly. Just call the function three times and print all the results (with spaces in between). Instead of printing you could join it together in a string and remove the last space.
<?php
function rand_string($length) {
$str="";
$chars = "abcdefghijklmanopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen($chars);
for($i = 0;$i < $length;$i++) {
$str .= $chars[rand(0,$size-1)];
}
return $str;
}
for ($b = 0; $b<3; $b++)
{
echo rand_string(4)." ";
}
If you don't mind using a completely different approach, limited to 32 chars :
return substr(md5(mt_rand().time()), 0, $length);
It's not super random but you get the picture...
Thanks to CM and user2693053 for bringing stuff to my attention (updated answer)
using mt_rand() instead of rand()
md5() length of 32...

PHP: Transform string to another string

I would like to Convert simple string to another format based on below logic
Example 1 : if string is 3,4-8-7,5 then I need the set as (3,8,7),(4,8,5).
Example 2: If string is "4-5,6-4" then required set will be (4,5,4),(4,6,4).
More Clear Requirements:
if string is 5-6,7,8-2,3-1. It need to be divided first like [5] AND [(6) OR (7) OR (8)] AND [(2) OR (3)] AND [1]. Result must be All possible combination: (5,6,2,1),(5,6,3,1),(5,7,2,1),(5,7,3,1),(5,8,2,1),(5,8,3,1).
The Logic behind to building the set are we need to consider ',' as OR condition and '-' as AND condition.
I am trying my best using For loop but unable to find solution
$intermediate = array();
$arry_A = explode('-', '3,4-8-7,5');
for ($i = 0; $i < count($arry_A); $i++) {
$arry_B = explode(',', $arry_A[$i]);
for ($j = 0; $j < count($arry_B); $j++) {
if (count($intermediate) > 0) {
for ($k = 0; $k < count($intermediate); $k++) {
$intermediate[$k] = $intermediate[$k] . ',' . $arry_B[$j];
}
} elseif (count($intermediate) === 0) {
$intermediate[0] = $arry_B[$j];
}
}
}
echo $intermediate, should give final result.
Cool little exercise!
I would do it with the following code, which I will split up for readability:
I used an array as output, since it's easier to check than a string.
First, we initialize the $string and create the output array $solutions. We will calculate the maximum of possible combinations from the beginning ($results) and fill the $solutions array with empty arrays which will be filled later with the actual combinations.
$string = '3,4-8-7,5';
$solutions = array();
$results = substr_count($string,',')*2;
for($i = 0; $i < $results; $i++) {
array_push($solutions,array());
}
We will need two helper functions: checkSolutions which makes sure, that the combination does not yet exist more than $limit times. And numberOfORAfterwards which will calculate the position of an OR pattern in the $string so we can calculate how often a combination is allowed in the single steps of the walkthrough.
function checkSolutions($array,$solutions,$limit) {
$count = 0;
foreach($solutions as $solution) {
if($solution === $array) $count++;
}
if($count < $limit) return true;
else return false;
}
function numberOfORAfterwards($part,$parts) {
foreach($parts as $currPart) {
if($currPart === $part) $count = 0;
if(isset($count)) if(!ctype_digit($currPart)) $count++;
}
return $count;
}
Now the main part: We are going to loop over the "parts" of the $string a part are the digits between AND operations.
If you need further explanation on this loop, just leave a comment.
$length = 0;
// split by all AND operations
$parts = explode('-',$string);
foreach($parts as $part) {
if(ctype_digit($part)) {
// case AND x AND
foreach($solutions as &$solution) {
array_push($solution,$part);
}
} else {
// case x OR x ...
$digits = explode(',',$part);
foreach($digits as $digit) {
for($i = 0; $i < $results/count($digits); $i++) {
foreach($solutions as &$solution) {
if(count($solution) == $length) {
$test = $solution;
array_push($test,$digit);
$limit = numberOfORAfterwards($part,$parts);
echo $digit.' '.$limit.'<br>';
if(checkSolutions($test,$solutions,$limit)) {
array_push($solution,$digit);
break;
}
}
}
}
}
}
$length++;
}
print_r($solutions);
Some tests:
String: 3,4-8-7,5
Combinations: (3,8,7)(3,8,5)(4,8,7)(4,8,7)
String: 5-6,7,8-2,3-1
Combinations: (5,6,2,1)(5,6,3,1)(5,7,2,1)(5,7,3,1)(5,8,2,1)(5,8,2,1)
String: 2,1-4-3,2-7,8-9
Combinations: (2,4,3,7,9)(2,4,3,8,9)(2,4,2,7,9)(1,4,3,7,9)(1,4,2,8,9)(1,4,2,8,9)
String: 1,5-3,2-1
Combinations: (1,3,1)(1,2,1)(5,3,1)(5,3,1)

Reverse string without strrev

Some time ago during a job interview I got the task to reverse a string in PHP without using strrev.
My first solution was something like this:
$s = 'abcdefg';
$temp = '';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$temp .= $s{$length - $i - 1};
}
var_dump($temp);
// outputs string(7) "gfedcba"
then they asked me if I could do this without doubling the memory usage (not using the $temp variable or any variable to copy the reversed string to) and I failed.
This kept bugging me and since then I tried to solve this multiple times but I constantly failed.
My latest try looks like this:
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i * 2} . $s;
}
var_dump($s);
// outputs string(14) "gfedcbaabcdefg"
It's not a solution to chop off "abcdefg" after the loop because then I would still double the amount of memory used. I need to remove the last character in every iteration of the loop.
I tried to use mb_substr like this:
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i * 2} . mb_substr($s, $length - $i - 1, 1);
}
var_dump($s);
but it only gives me Uninitialized string offset errors.
This is where I'm stuck (again). I tried googling but all the solutions I found either echo the characters directly or use a temporary variable.
I also found the Question PHP String reversal without using extra memory but there's no answer that fits my needs.
That's an interesting one.
Here's something I just came up with:
$s = 'abcdefghijklm';
for($i=strlen($s)-1, $j=0; $j<$i; $i--, $j++) {
list($s[$j], $s[$i]) = array($s[$i], $s[$j]);
}
echo $s;
list() can be used to assign a list of variables in one operation. So what I am doing is simply swapping characters (starting with first and last, then second-first and second-last and so on, till it reaches the middle of the string)
Output is mlkjihgfedcba.
Not using any other variables than $s and the counters, so I hope that fits your criteria.
You can use the fact that in PHP a string can be thought of as an array of characters.
Then basically what you want to do is to replace each character $i on the left side of the middle of the string with the character $j on the right side of the middle with the same distance.
For example, in a string of seven characters the middle character is on position 3. The character on position 0 (distance 3) needs to be swapped with the character on position 6 (3 + 3), the character on position 1 (distance 2) needs to be swapped with the character on position 5 (3 + 2), etc.
This algorithm can be implemented as follows:
$s = 'abcdefg';
$length = strlen($s);
for ($i = 0, $j = $length-1; $i < ($length / 2); $i++, $j--) {
$t = $s[$i];
$s[$i] = $s[$j];
$s[$j] = $t;
}
var_dump($s);
$string = 'abc';
$reverted = implode(array_reverse(str_split($string)));
You could use the XOR swap trick.
function rev($str) {
$len = strlen($str);
for($i = 0; $i < floor($len / 2); ++$i) {
$str[$i] = $str[$i] ^ $str[$len - $i - 1];
$str[$len - $i - 1] = $str[$i] ^ $str[$len - $i - 1];
$str[$i] = $str[$i] ^ $str[$len - $i - 1];
}
return $str;
}
print rev("example");
Try this:
$s = 'abcdefg';
for ($i = strlen($s)-1; $i>=0; $i--) {
$s .= $s[$i];
$s[$i] = NULL;
}
var_dump(trim($s));
Here it is PHP7 version of this:
echo "\u{202E}abcdefg"; // outs: gfedcba
PHP strings are kinda-sorta mutable, but due to copy-on-write it's very difficult to modify them in-place without a copy being made. Some of the above solutions work, but only because they're stand-alone; some already fail because they define a function without a pass-by-reference argument. To get the code to actually operate in-place in a larger program, you'd need to pay careful attention to assignments, function arguments, and scopes.
Example:
$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");
> "abc, bbc"
I suppose that if between initializing the variable and modifying it you only ever used by-reference assignments (&=) and reference arguments (function rev(&$string)) (or assign the string to an object property initially, and then never assign it to any other variable), you might be able to change the original value of the string without making any copies. That's a bit ridiculous, however, and I'd assume that the interviewer who came up with that question didn't know about copy-on-write.
This isn't quite the same as immutability in other languages, by the way, because it applies to arrays too:
$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));
> "012112"
To sum up, all types (except for objects as of PHP5) are assigned with copy-on-write unless you specifically use the &= operator. The assignment doesn't copy them, but unlike most other languages (C, Java, Python...) that either change the original value (arrays) or don't allow write access at all (strings), PHP will silently create a copy before making any changes.
Of course, if you switched to a language with more conventional pointers and also switched to byte arrays instead of strings, you could use XOR to swap each pair of characters in place:
for i = 0 ... string.length / 2:
string[i] ^= string[string.length-1-i]
string[string.length-1-i] ^= string[i]
string[i] ^= string[string.length-1-i]
Basically #EricBouwers answer, but you can remove the 2nd placeholder variable $j
function strrev2($str)
{
$len = strlen($str);
for($i=0;$i<$len/2;$i++)
{
$tmp = $str[$i];
$str[$i] = $str[$len-$i-1];
$str[$len-$i-1] = $tmp;
}
return $str;
}
Test for the output:
echo strrev2("Hi there!"); // "!ereht iH"
echo PHP_EOL;
echo strrev2("Hello World!"); // "!dlroW olleH"
This will go through the list and stop halfway, it swaps the leftmost and rightmost, and works it's way inward, and stops at the middle. If odd numbered, the pivot digit is never swapped with itself, and if even, it swaps the middle two and stops. The only extra memory used is $len for convenience and $tmp for swapping.
If you want a function that doesn't return a new copy of the string, but just edits the old one in place you can use the following:
function strrev3(&$str)
{
$len = strlen($str);
for($i=0;$i<$len/2;$i++)
{
$tmp = $str[$i];
$str[$i] = $str[$len-$i-1];
$str[$len-$i-1] = $tmp;
}
}
$x = "Test String";
echo $x; // "Test String"
strrev3($x);
echo PHP_EOL;
echo $x; // "gnirtS tseT"
Using &$str passes a direct pointer the the string for editing in place.
And for a simpler implementation like #treegardens, you can rewrite as:
$s = 'abcdefghijklm';
$len = strlen($s);
for($i=0; $i < $len/2; $i++) {
list($s[$i], $s[$len-$i-1]) = array($s[$len-$i-1], $s[$i]);
}
echo $s;
It has the similar logic, but I simplified the for-loop quite a bit.
Its Too Simple
//Reverse a String
$string = 'Basant Kumar';
$length = strlen($string);
for($i=$length-1;$i >=0;$i--){
echo $string[$i];
}
Here is my code to solve your problem
<?php
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i}.mb_substr($s,0,$i).mb_substr($s,$i+1);
}
var_dump($s);
?>
You could also use a recursion to reverse the string. Something like this for example:
function reverse($s) {
if(strlen($s) === 1) return $s;
return substr($s, strlen($s)-1) . reverse(substr($s , 0, strlen($s)-1));
}
What you do here is actually returning the last character of the string and then calling again the same function with the substring that contains the initial string without the last character. When you reach the point when your string is just one character then you end the recursion.
You can use this code to reverse a string without using the reserved function in php.
Code:
<?php
function str_rev($y)// function for reversing a string by passing parameters
{
for ($x = strlen($y)-1; $x>=0; $x--) {
$y .= $y[$x];
$y[$x] = NULL;
}
echo $y;
}
str_rev("I am a student");
?>
Output:
tneduts a ma I
In the above code, we have passed the value of the string as the parameter.We have performed the string reversal using for loop.
you could use substr with negative start.
Theory & Explanation
you can start with for loop with counter from 1 to length of string, and call substr inside iteration with counter * -1 (which will convert the counter into negative value) and length of 1.
So for the first time counter would be 1 and by multiplying with -1 will turn it to -1
Hence substr('abcdefg', -1, 1); will get you g
and next iteration substr('abcdefg', -2, 1); will get you f
and substr('abcdefg', -3, 1); will get you e
and so on ...
Code
$str = 'abcdefghijklmnopqrstuvwxyz';
for($i=1; $i <= strlen($str); $i++) {
echo substr($str, $i*-1, 1);
}
In Action: https://eval.in/583208
public function checkString($str){
if(!empty($str)){
$i = 0;
$str_reverse = '';
while(isset($str[$i])){
$strArr[] = $str[$i];
$i++;
}
for($j = count($strArr); $j>= 0; $j--){
if(isset($strArr[$j])){
$str_reverse .= $strArr[$j];
}
}
if($str == $str_reverse){
echo 'It is a correct string';
}else{
echo 'Invalid string';
}
}
else{
echo 'string not found.';
}
}
//Reverse String word by word
$str = "Reverse string word by word";
$i = 0;
while ($d = $str[$i]) {
if($d == " ") {
$out = " ".$temp.$out;
$temp = "";
}
else
$temp .= $d;
$i++;
}
echo $temp.$out;
The following solution is very simple, but it does the job:
$string = 'Andreas';
$reversedString = '';
for($i = mb_strlen($string) - 1; $i >= 0; $i--){
$reversedString .= $string[$i];
}
var_dump($reversedString) then results: string(7) "saerdnA"
<?php
$value = 'abcdefg';
$length_value = strlen($value);
for($i = $length_value-1; $i >=0 ;$i--){
echo $value[$i];
}
?>
you can try this..
$string = "NASEEM";
$total_word = strlen($string);
for($i=0; $i<=$total_word; $i++)
{
echo substr($string,$total_word-$i,1);
}
i have used some built in function but without str_rev function .
<?php
$text = "red";
$arr = str_split($text);
$rev_text = array_reverse($arr);
echo join(" ",$rev_text);
?>
Try This
<?php
$str="abcde";
for($i=strlen($str)-1;$i>=0;$i--){
echo $str[$i];
}
?>
output
edcba
This is my solution to solve this.
$in = 'This is a test text';
$out = '';
// find string length
$len = strlen($in);
// loop through it and print it reverse
for ( $i = $len - 1; $i >=0;$i-- )
{
$out = $out.$in[$i];
}
echo $out;
Reverse string using recursion function.
$reverseString = '';
function Reverse($str, $len)
{
if ($len == 0) {
return $GLOBALS['reverseString'];
} else {
$len--;
$GLOBALS['reverseString'] .= $str[$len];
return Reverse($str, $len);
}
}
$str = 'Demo text';
$len = strlen($str);
echo Reverse($str, $len)
Try this
$warn = 'this is a test';
$i=0;
while(#$warn[$i]){
$i++;}
while($i>0)
{
echo $warn[$i-1]; $i--;
}

populating an array with a for loop in php

I need to add * in an array. This is how i do it in javaScript.
function makeStarString(grade) {
var starArray = [];
var starString = "";
for (var i = 0; i < grade; i++){
starArray[i] = "*";
starString = starString.concat(starArray[i]);
}
return starString;
}
The javascript version works fine but I cant make it work with php.
This is as far as i got with php.
function makeStarString($varGrade) {
$starArray = array ();
$starString = "";
for ($i = 0; $i < strlen($varGrade); $i++){
$starArray($i) = $star;
$starString = $starString.(starArray(i));
}
return $starString;
}
I get this error "Fatal error: Can't use function return value in write context" because of line $starArray($i) = $star;
The argument I send to the function is an Integer.
So the purpose of the function is that if i send a 5 to the function it will return *****
How can i fix my php function?
Use $starArray[$i] instead of $starArray($i) and starArray(i).
If you really need stars in an array, you don't need to use a loop:
$starArray = array_fill(0, $varGrade, '*');
and if you need to turn the array into a string:
$starString = implode('', $starArray);
But if you don't really ever need to use the array of stars, it would be easier to just use str_repeat:
str_repeat('*', $varGrade);
It would generally be a great idea to use strlen($varGrade) in a variable, because the foreach loop will have to count the length every iteration. This might bring performance issues.
Your $star variable is not defined, so I have no idea what you're trying to put there. Revise your own code.
Finally, you may use the .= operator to add something to existing string.
function makeStarString($varGrade) {
$starArray = array ();
$starString = "";
$length = strlen($varGrade);
for ($i = 0; $i < $length; $i++){
$starArray[$i] = $star;
$starString .= $starArray[$i];
// equivalent to $starString = $starString . $starArray[$];
}
return $starString;
}
UPDATE
If you send an int to the function, you don't need strlen:
function makeStarString($varGrade) {
$starArray = array ();
$starString = "";
for ($i = 0; $i < $varGrade; $i++){
$starArray[$i] = $star;
$starString .= $starArray[$i];
// equivalent to $starString = $starString . $starArray[$];
}
return $starString;
}
This code should work
function makeStarString($varGrade) {
$star = "*"; // star variable wasn't defined to.
$starArray = array ();
$starString = "";
for ($i = 0; $i < $varGrade; $i++){
$starArray[$i] = $star; // [ ] instead of ( )
$starString .= ($starArray[$i]); // $a.=$b instead of $a=$a+$b, added the $ at the i and [ ] instead of ( )
}
return $starString;
}
Is this what you need?
function makeStarString($varGrade) {
$starString = '';
for ($i = 0; $i < $varGrade; $i++) {
$starString .= '*';
}
return $starString;
}
A few notes on my modifications.
I don't see why you need that $starArray array in the first place. So I skipped it.
I revised your indentation. Strange indentation can make very simple code seem much more complicated than it really is. :)
You should ask if $i < $varGrade, not if $i < strlen($varGrade). If you ask by strlen(), then you get the width of the number you enter. For example, strlen(55) is 2, strlen(555) is 3, strlen(5555) is 4 etc. - ignoring the fact that it's a number. You just want the for-loop to give you $varGrade many stars so there is no need for strlen().
As a detail, I've put used single-quotes instead of double-quotes for strings because they're lighter (PHP doesn't parse variables inside them).
I hope it helps.

adding string to all but last item in array

I have an array and I'd like to add a string to each item in the array, apart from the last item.
Any ideas how I'd do this?
Thanks
This should do it for both numerically-indexed arrays and associative arrays:
$i = 0;
$c = count($array);
foreach ($array as $key => $val) {
if ($i++ < $c - 1) {
$array[$key] .= 'string';
}
}
If your array is numerically indexed, a simple loop does the job.
for ($i = count($array) - 2; $i >= 0; $i--) {
$array[$i] = $array[$i] . $stringToAppend;
}
I don't think there is a native command for this.
Just do it the traditional way.
// Your array.
$MyArray = array("Item1","Item2","Item3");
// Check that we have more than one element
if (count($MyArray) > 1) {
for ($n=0; $n<count($MyArray)-1; $n++) {
$MyArray[$n] .= " Appended string";
}
}
The code is from the top of my head, so maybe some tweeking might do he trick.
Well a simple for loop would be the obvious thing I guess.
for ( $i=0; $i < count( $myArray )-1; $i++ )
{
$myArray[$i] = "Hey look a string";
}
But then you might also just use array_fill to do a similar job:
array_fill( 0, $sizeOfArray, "Hey look a string" )
Then you can just set the last value to be whatever you want it to be.
EDIT: If by "add a string to each item" you mean you already have a value in the array and you want to append a string, then I would use my first suggestion with $myArray[$i] .= "Hey look a string"; instead of the simple assignment.
$array =array();
$statement = null;
for ($j= 0;$j<count($array);$j++) {
if ($j === count($array)-1) {
$statement .= $array[$j];
} else {
$statement .= $array[$j].' OR ';
}
}

Categories