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
Related
I made this code to return the number of occurrences of letters in a string.
this function returns '6a3b5y' but I want it to respect the order and display '4a3b2a5y'
how to change it to display '4a3b2a5y' ?
function encode($input) {
$l = mb_strlen($input, 'UTF-8');
$unique = array();
for($i = 0; $i < $l; $i++) {
$char = mb_substr($input, $i, 1, 'UTF-8');
if(!array_key_exists($char, $unique))
$unique[$char] = 0;
$unique[$char]++;
}
$a=[];
foreach($unique as $k=>$val){
$a[]= $val.$k ;
}
return implode("",$a) ;
}
echo encode('aaaabbbaayyyyy') ;
Use a variable to hold the previous character. Compare the current character to it. If they're the same, increment a counter. If they're not, output the previous character and counter, then reset the variables.
At the end, output the final character and counter.
function encode($input) {
$output = '';
$l = mb_strlen($input, 'UTF-8');
$prevchar = mb_substr($input, 0, 1, 'UTF-8');
$count = 1;
for($i = 1; $i < $l; $i++) {
$char = mb_substr($input, $i, 1, 'UTF-8');
if ($char == $prevchar) {
$count++;
} else {
$output .= "$count$prevchar";
$count = 1;
$prevchar = $char;
}
}
$output .= "$count$prevchar";
return $output;
}
I have a string like $str.
$str = "00016cam 321254300022cam 321254312315300020cam 32125433153";
I want to split it in array like this. The numbers before 'cam' is the string length.
$splitArray = ["00016cam 3212543", "00022cam 3212543123153", "00020cam 32125433153"]
I have tried following code:
$lengtharray = array();
while ($str != null)
{
$sublength = substr($str, $star, $end);
$star += (int)$sublength; // echo $star."<br>"; // echo $sublength."<br>";
if($star == $total)
{
exit;
}
else
{
}
array_push($lengtharray, $star); // echo
print_r($lengtharray);
}
You can try this 1 line solution
$str = explode('**', preg_replace('/\**cam/', 'cam', $str)) ;
If your string doesn't contain stars then I'm afraid you need to write a simple parser that will:
take characters from the left until it's not numeric
do substr having the length
repeat previous steps on not consumed string
<?php
$input = "00016cam 321254300022cam 321254312315300020cam 32125433153";
function parseArray(string $input)
{
$result = [];
while ($parsed = parseItem($input)) {
$input = $parsed['rest'];
$result[] = $parsed['item'];
}
return $result;
}
function parseItem(string $input)
{
$sLen = strlen($input);
$len = '';
$pos = 0;
while ($pos < $sLen && is_numeric($input[$pos])) {
$len .= $input[$pos];
$pos++;
}
if ((int) $len == 0) {
return null;
}
return [
'rest' => substr($input, $len),
'item' => substr($input, 0, $len)
];
}
var_dump(parseArray($input));
this code works for me. hope helps.
$str = "**00016**cam 3212543**00022**cam 3212543123153**00020**cam 32125433153";
$arr = explode("**", $str);
for ($i=1; $i < sizeof($arr); $i=$i+2)
$arr_final[]=$arr[$i].$arr[$i+1];
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();
How to get the count of string 2 occurrence in string 1 without php built-in functions.
Example:
$strone = "Arun sukumar";
$strtwo = "a";
//Expected Output: 2
$strone = "Arun sukumar";
$strtwo = "uk";
//Expected Output: 1
I need to get the count without using any php built-in functions.
This is the question asked in a interview, is there any logic in that?
You need to take your needle, get the first char.. then iterate over each char of the haystack until you get match. Then take the next char of needle and check the next char of the haystack for a match... continue until you have the complete match for needle or until you fial to match a char.
hint: you can access the individual chars of a string by index with $string{0} where 0 is the zero based index of the char in the string.
$strone = 'arun sukumar';
$strtwo = 'a';
echo parsestr($strone, $strtwo);
function parsestr($strone, $strtwo)
{
$len = 0;
while ($strtwo{$len} != '') {
$len++;
}
$nr = 0;
while ($strone{$nr} != '')
{
if($strone{$nr} != ' ')
{
$data[$nr] = $strone{$nr};
}
$nr++;
}
$newdata = $data;
if($len > 1)
{
$newdata = array();
$j = 0;
foreach($data as $val)
{
$str .= $val;
if($j == ($len -1))
{
$newdata[] = $str;
$str = '';
$j = 0;
}
else
$j++;
}
}
$i = 0;
foreach($newdata as $val)
{
if($val == $strtwo)
{
$i++;
}
}
return $i;
}
Try this
$string = 'Arun sukumar';
$sub_string = 'a';
$count = 0;
for($i=0;$i < strlen($string); $i++){
$flag = 0;
$j=0;
if(strtolower($string[$i]) == $sub_string[$j])
{
//echo "match";
$flag = 1;
$k = $i;
for(;$j< strlen($sub_string); $j++){//echo "[".$j . $k."] $count $flag";
if(strtolower($string[$k]) != $sub_string[$j]){
$flag = 0;
break;
}
$k++;
}//echo "<br> $flag";
}
if($flag == 1){
$count++;
$flag = 0;
}
}
echo $count;
?>
Not sure why you would not want to use the built-in PHP functions since they would be faster, but something like this would work:
<?php
$haystack = 'Arun sukumar';
$needle = 'a';
// you seem to want a case insensitive search, so do a strtolower first
$haystack = strtolower($haystack);
$hitCount = 0;
for ($i = 0; $i < strlen($haystack); ++$i) {
if ($needle === substr($haystack, $i, strlen($needle))) {
$hitCount++;
}
}
echo 'Output: ' . $hitCount;
?>
This question already has answers here:
Reverse the letters in each word of a string
(6 answers)
Closed 1 year ago.
This task has already been asked/answered, but I recently had a job interview that imposed some additional challenges to demonstrate my ability to manipulate strings.
Problem: How to reverse words in a string? You can use strpos(), strlen() and substr(), but not other very useful functions such as explode(), strrev(), etc.
Example:
$string = "I am a boy"
Answer:
I ma a yob
Below is my working coding attempt that took me 2 days [sigh], but there must be a more elegant and concise solution.
Intention:
1. get number of words
2. based on word count, grab each word and store into array
3. loop through array and output each word in reverse order
Code:
$str = "I am a boy";
echo reverse_word($str) . "\n";
function reverse_word($input) {
//first find how many words in the string based on whitespace
$num_ws = 0;
$p = 0;
while(strpos($input, " ", $p) !== false) {
$num_ws ++;
$p = strpos($input, ' ', $p) + 1;
}
echo "num ws is $num_ws\n";
//now start grabbing word and store into array
$p = 0;
for($i=0; $i<$num_ws + 1; $i++) {
$ws_index = strpos($input, " ", $p);
//if no more ws, grab the rest
if($ws_index === false) {
$word = substr($input, $p);
}
else {
$length = $ws_index - $p;
$word = substr($input, $p, $length);
}
$result[] = $word;
$p = $ws_index + 1; //move onto first char of next word
}
print_r($result);
//append reversed words
$str = '';
for($i=0; $i<count($result); $i++) {
$str .= reverse($result[$i]) . " ";
}
return $str;
}
function reverse($str) {
$a = 0;
$b = strlen($str)-1;
while($a < $b) {
swap($str, $a, $b);
$a ++;
$b --;
}
return $str;
}
function swap(&$str, $i1, $i2) {
$tmp = $str[$i1];
$str[$i1] = $str[$i2];
$str[$i2] = $tmp;
}
$string = "I am a boy";
$reversed = "";
$tmp = "";
for($i = 0; $i < strlen($string); $i++) {
if($string[$i] == " ") {
$reversed .= $tmp . " ";
$tmp = "";
continue;
}
$tmp = $string[$i] . $tmp;
}
$reversed .= $tmp;
print $reversed . PHP_EOL;
>> I ma a yob
Whoops! Mis-read the question. Here you go (Note that this will split on all non-letter boundaries, not just space. If you want a character not to be split upon, just add it to $wordChars):
function revWords($string) {
//We need to find word boundries
$wordChars = 'abcdefghijklmnopqrstuvwxyz';
$buffer = '';
$return = '';
$len = strlen($string);
$i = 0;
while ($i < $len) {
$chr = $string[$i];
if (($chr & 0xC0) == 0xC0) {
//UTF8 Characer!
if (($chr & 0xF0) == 0xF0) {
//4 Byte Sequence
$chr .= substr($string, $i + 1, 3);
$i += 3;
} elseif (($chr & 0xE0) == 0xE0) {
//3 Byte Sequence
$chr .= substr($string, $i + 1, 2);
$i += 2;
} else {
//2 Byte Sequence
$i++;
$chr .= $string[$i];
}
}
if (stripos($wordChars, $chr) !== false) {
$buffer = $chr . $buffer;
} else {
$return .= $buffer . $chr;
$buffer = '';
}
$i++;
}
return $return . $buffer;
}
Edit: Now it's a single function, and stores the buffer naively in reversed notation.
Edit2: Now handles UTF8 characters (just add "word" characters to the $wordChars string)...
My answer is to count the string length, split the letters into an array and then, loop it backwards. This is also a good way to check if a word is a palindrome. This can only be used for regular string and numbers.
preg_split can be changed to explode() as well.
/**
* Code snippet to reverse a string (LM)
*/
$words = array('one', 'only', 'apple', 'jobs');
foreach ($words as $d) {
$strlen = strlen($d);
$splits = preg_split('//', $d, -1, PREG_SPLIT_NO_EMPTY);
for ($i = $strlen; $i >= 0; $i=$i-1) {
#$reverse .= $splits[$i];
}
echo "Regular: {$d}".PHP_EOL;
echo "Reverse: {$reverse}".PHP_EOL;
echo "-----".PHP_EOL;
unset($reverse);
}
Without using any function.
$string = 'I am a boy';
$newString = '';
$temp = '';
$i = 0;
while(#$string[$i] != '')
{
if($string[$i] == ' ') {
$newString .= $temp . ' ';
$temp = '';
}
else {
$temp = $string[$i] . $temp;
}
$i++;
}
$newString .= $temp . ' ';
echo $newString;
Output: I ma a yob