How to check total occurrence of a character in string - php

I want to find out total occurrence of particular character in string.
my code is:
$str = 'aabbbcccccaa';
for ($i=0;$i<strlen($str);$i++){
$len = 0;
for ($j=$i;$j<=strlen($str);$j++){
if($str[$i] == $str[$j]){
$len++;
}
}
echo "\n".$str[$i].' len is '.$len;
}
my output is like:
a len is 4
a len is 3
b len is 3
b len is 2
b len is 1
c len is 5
c len is 4
c len is 3
c len is 2
c len is 1
a len is 2
a len is 1
but I want something like:
a len is 4
b len is 3
c len is 5 only
How can I achieve this?

RTM
<?php
$data = "Two Ts and one F.";
foreach (count_chars($data, 1) as $i => $val) {
echo "There were $val instance(s) of \"" , chr($i) , "\" in the string.\n";
}
?>

You should use substr_count(). It's right here in the manual:
http://php.net/manual/en/function.substr-count.php
or perhaps count_chars() would be even better for a generic solution:
http://php.net/manual/en/function.count-chars.php
Always check the manuals before creating something yourself.. there just might be a function there that does exactly what you want..

$str = 'aabbbcccccaa';
foreach (count_chars($str, 1) as $i => $val) {
echo chr($i), " len is $val " , "<br>";
}

Hello Simply Implement the bellow way !
Our Custom Function :
function count_chars_unicode($str, $x = false) {
$tmp = preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
foreach ($tmp as $c) {
$chr[$c] = isset($chr[$c]) ? $chr[$c] + 1 : 1;
}
return is_bool($x)
? ($x ? $chr : count($chr))
: $chr[$x];
}
Usage :
print_r(count_chars_unicode('aabbbcccccaa', true));
O/P
Array ( [a] => 4 [b] => 3 [c] => 5 )
print_r(count_chars_unicode('aabbbcccccaa', 'a')); // frequency of "a"
O/P : 4
print_r(count_chars_unicode('aabbbcccccaa')); // count of uniq chars
O/P : 3

Related

How can I replace every second digit to another digit using if else statement in php?

I have a number that a user will put into a form - 12 digits. Every second digit needs to be replaced - if the digit is:
1 then make it 5
2 then make it 1
3 then make it 6
4 then make it 2
5 then make it 7
6 then make it 3
7 then make it 8
8 then make it 4
0 and 9 stay the same.
So for example:
343608111218 will end up being 383307121417.
Here is an example of what I'm currently doing, but I think it is long winded. This is just for the first number, so I'm assuming I could do something else?
$_POST['number'] = '343608111218';
preg_match_all('~(\d)~', $_POST['number'], $pregs);
if($pregs[1][1] === "1") {
$one = 5;
}
elseif ($pregs[1][1] === "2"){
$one = 1;
}
elseif ($pregs[1][1] === "3"){
$one = 6;
}
elseif ($pregs[1][1] === "4"){
$one = 2;
}
elseif ($pregs[1][1] === "5"){
$one = 7;
}
elseif ($pregs[1][1] === "6"){
$one = 3;
}
elseif ($pregs[1][1] === "7"){
$one = 8;
}
elseif ($pregs[1][1] === "8"){
$one = 4;
}
$rep1 = (array_replace($pregs[1],array(1=>$one)));
If there is a way that I can reduce the amount of code, I would be very grateful. Thank you.
One way of doing it is with preg_replace_callback, passing the match of 2 digits in a row and using strtr to replace the 2nd digit appropriately:
$_POST['number'] = '343608111218';
echo preg_replace_callback('~(\d)(\d)~', function ($m) {
return $m[1] . strtr($m[2], '12345678', '51627384');
}, $_POST['number']);
Output:
323304151114
This is based on the description you gave on how to do replacements. However if your expected output reflects the correct way to do the replacements, the replacements have to be the other way around, which is just a question of changing the order of parameters to strtr:
echo preg_replace_callback('~(\d)(\d)~', function ($m) {
return $m[1] . strtr($m[2], '51627384', '12345678');
}, $_POST['number']);
Output:
383307121417
Demo on 3v4l.org
As you are replacing each digit with another, create a lookup string and use the number as the index to the array, all the positions 0-9 are set - even if they are the same value. As the value is a string, you can just use the value as the position of the string and replace it directly...
$value = $_POST['number'];
$trans = "0516273849";
for ( $i = 1; $i < strlen($value); $i+=2 ) {
$value[$i] = $trans[$value[$i]];
}
echo $value;
Edit:
To achieve what is the 'desired' output (although only a guess as to what this should be) you can change the line to...
$trans = "0246813579";
$transform = array(
0 => 0,
1 => 5,
2 => 1,
3 => 6,
4 => 8,
5 => 7,
6 => 3,
7 => 8,
8 => 4,
9 => 9
);
$number = '343608111218';
$num = array_map('intval', str_split($number));
$i = 1;
foreach ($num as $key => $value) {
if (0 == ($i % 2)) {
echo $transform[$value];
} else {
echo $value;
}
$i++;
}
To modernize and refine Nick's regex script, use \K to eliminate the use of capture groups. Arrow function syntax helps to make the script more concise. (Demo)
echo preg_replace_callback(
'/.\K\d/',
fn($m) => strtr($m[0], '12345678', '51627384'),
$_POST['number']
);
Nigel's answer is optimized for performance. Despite counting the string length on every iteration and unnecessarily replacing certain numbers with the same number, it will perform very swiftly because it only makes iterated calls of count(). Because all characters in the input string and the translation string are expected to be single-byte characters, the cooresponding number in the translation string can be accessed by its offset. Here's my version of Nigel's script (Demo)
$value = '343608111218';
$trans = '0516273849';
for ($i = 1, $len = strlen($value); $i < $len; $i += 2) {
$value[$i] = $trans[$value[$i]];
}
echo $value;
Mujuonly's answer can be boiled down a little further. $var & 1 is a bitwise odd check which is just as cryptic as !($var % 2), but is slightly faster (not noticeably). Casting each character as an integer is not necessary and using a string-type translation source is a more succinct technique. (Demo)
$number = '343608111218';
$trans = '0516273849';
foreach (str_split($number) as $i => $d) {
if ($i & 1) {
$number[$i] = $trans[$d];
}
}
echo $number;

Every possible combination for grade of courses in PHP

I need to make a combination of all course input by the user such as the user add 5 courses it will be as this template:
Course 1
Course 2
Course 3
Course 4
Course 5
After that, I need to create a combination for all course with array of grade:
array('A+', 'A', 'B+', 'B', 'C+', 'C','D+','D','F')
Actually, I found what I need in this topic: Create every possible combination in PHP but there's something I don't understand how I can do.
Until now this code after edit:
$dict = [
'1' => ['A+', 'A', 'B+', 'B', 'C+', 'C','D+','D','F'],
'2' => ['Course 1', 'Course 2', 'Course 3', 'Course 4', 'Course 5'],
];
$str = '2 : 1';
class SentenceTemplate implements IteratorAggregate
{
private $template;
private $thesaurus;
public function __construct($str, $dict)
{
$this->thesaurus = [];
$this->template = preg_replace_callback('/\w+/', function($matches) use ($dict) {
$word = $matches[0];
if (isset($dict[$word])) {
$this->thesaurus[] = $dict[$word];
return '%s';
} else {
return $word;
}
}, $str);
}
public function getIterator()
{
return new ArrayIterator(array_map(function($args) {
return vsprintf($this->template, $args);
}, $this->combinations($this->thesaurus)));
}
private function combinations($arrays, $i = 0) {
if (!isset($arrays[$i])) {
return array();
}
if ($i == count($arrays) - 1) {
return $arrays[$i];
}
// get combinations from subsequent arrays
$tmp = $this->combinations($arrays, $i + 1);
$result = array();
// concat each array from tmp with each element from $arrays[$i]
foreach ($arrays[$i] as $v) {
foreach ($tmp as $t) {
$result[] = is_array($t) ? array_merge(array($v), $t) : array($v, $t);
}
}
return $result;
}
}
$sentences = new SentenceTemplate(1, $dict);
$i = 1;
foreach ($sentences as $sentence) {
echo "COMBINATION $i : \n";
$sentences2 = new SentenceTemplate(2, $dict);
foreach ($sentences2 as $sentence2) {
echo "$sentence2 : "."$sentence\n";
}
echo "----------\n";
$i++;
}
Output
COMBINATION 1 :
Course 1 : A+
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
----------
COMBINATION 2 :
Course 1 : A
Course 2 : A
Course 3 : A
Course 4 : A
Course 5 : A
----------
COMBINATION 3 :
Course 1 : B+
Course 2 : B+
Course 3 : B+
Course 4 : B+
Course 5 : B+
----------
COMBINATION 4 :
Course 1 : B
Course 2 : B
Course 3 : B
Course 4 : B
Course 5 : B
----------
COMBINATION 5 :
Course 1 : C+
Course 2 : C+
Course 3 : C+
Course 4 : C+
Course 5 : C+
----------
COMBINATION 6 :
Course 1 : C
Course 2 : C
Course 3 : C
Course 4 : C
Course 5 : C
----------
COMBINATION 7 :
Course 1 : D+
Course 2 : D+
Course 3 : D+
Course 4 : D+
Course 5 : D+
----------
COMBINATION 8 :
Course 1 : D
Course 2 : D
Course 3 : D
Course 4 : D
Course 5 : D
----------
COMBINATION 9 :
Course 1 : F
Course 2 : F
Course 3 : F
Course 4 : F
Course 5 : F
----------
And now how I can build more combinations such as:
COMBINATION 10 :
Course 1 : B+
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
COMBINATION 11 :
Course 1 : B
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
COMBINATION 12 :
Course 1 : C+
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
COMBINATION 13 :
Course 1 : C
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
COMBINATION 14 :
Course 1 : D+
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
COMBINATION 15 :
Course 1 : D
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
COMBINATION 16 :
Course 1 : F
Course 2 : A+
Course 3 : A+
Course 4 : A+
Course 5 : A+
.......
The procedure is for every course has a different grade with other courses and other courses has the same procedure, anyone has an idea to build this?
This code may help. It is a PHP program to print all possible strings of length k.
<?php
// PHP program to print all possible strings of length k
// Driver method to test below methods
function main() {
$set = ['A+', 'A', 'B+', 'B', 'C+', 'C','D+','D','F'];
$k = 5;
$n = sizeof($set);
printAllKLengthRec($set, "", $n, $k);
}
// The main recursive method to print all possible strings of length k
function printAllKLengthRec($set, $prefix, $n, $k) {
// Base case: k is 0, print prefix
if ($k == 0) {
echo $prefix."\n";
return;
}
// One by one add all characters from set and recursively
// call for k equals to k-1
for ($i = 0; $i < $n; ++$i) {
// Next character of input added
$newPrefix = $prefix . $set[$i];
// k is decreased, because we have added a new character
printAllKLengthRec($set, $newPrefix, $n, $k - 1);
}
}
main();
?>
You just need to modify the printing part.
The code bellow may fulfill your purpose.
<?php
// PHP program to print all possible strings of length k
// Driver method to test below methods
function main() {
$set = ['A+', 'A', 'B+', 'B', 'C+', 'C','D+','D','F'];
$k = 5;
$n = sizeof($set);
printAllKLengthRec($set, "", $n, $k);
}
// The main recursive method to print all possible strings of length k
function printAllKLengthRec($set, $prefix, $n, $k) {
// Base case: k is 0, print prefix
if ($k == 0) {
$c = 1;
for($p=0; $p<strlen($prefix); $p++) {
echo "Course $c: ". $prefix[$p];
if(($p+1) < strlen($prefix) && ($prefix[$p+1] == '+' || $prefix[$p+1] == '-')) {
echo $prefix[$p+1];
$p++;
}
echo "\n";
$c++;
}
return;
}
// One by one add all characters from set and recursively
// call for k equals to k-1
for ($i = 0; $i < $n; ++$i) {
// Next character of input added
$newPrefix = $prefix . $set[$i];
// k is decreased, because we have added a new character
printAllKLengthRec($set, $newPrefix, $n, $k - 1);
}
}
main();
?>

Codility Invalid result type, int expected with PHP

Could you tell why Codility tell me the next error, please?
Running solution... Compilation successful.
Example test: [-1, 3, -4, 5, 1, -6, 2, 1] Output (stderr): Invalid
result type, int expected. RUNTIME ERROR (tested program terminated
unexpectedly)
Detected some errors.
My solution was wrote on PHP.
function solution($A) {
$N = count($A);
$Ps = array();
foreach ( $A as $KeyP => $P ) {
$sum = 0;
if ( $KeyP == 0 ) {
for ( $x = 1; $x < $N; $x++ ) {
$sum += $A[$x];
}
if ( $sum == $P ) {
$Ps[] = $KeyP;
}
}
else {
if ( ($KeyP+1) == $N ) {
for ( $z = 0; $z < $KeyP; $z++) :
$sum += $A[$z];
endfor;
if ( ( $sum >= 0 ) AND ( $sum < $N ) ) {
$Ps[] = $KeyP;
}
}
else {
$sum1 = 0;
$sum2 = 0;
for ( $z = 0; $z < $KeyP; $z++ ) :
$sum1 += $A[$z];
endfor;
for ( $y = ( $KeyP+1 ); $y <= ($N-1); $y++ ) :
$sum2 += $A[$y];
endfor;
if ( $sum1 == $sum2 ) {
if ( $sum1 < $N ) {
$Ps[] = $KeyP;
}
}
}
}
}
return ( count($Ps) <= 0 ) ? -1: $Ps;
}
The output of my function given the next array has been:
array(-1, 3, -4, 5, 1, -6, 2, 1);
Ouput
Array ( [0] => 1 [1] => 3 [2] => 7 )
It's just like they request me in the task but Codility show me all those errors.
The demo task is below:
This is a demo task.
A zero-indexed array A consisting of N integers is given. An
equilibrium index of this array is any integer P such that 0 ≤ P < N
and the sum of elements of lower indices is equal to the sum of
elements of higher indices, i.e. A[0] + A[1] + ... + A[P−1] = A[P+1]
+ ... + A[N−2] + A[N−1]. Sum of zero elements is assumed to be equal to 0. This can happen if P = 0 or if P = N−1.
For example, consider the following array A consisting of N = 8
elements:
A[0] => -1
A[1] => 3
A[2] => -4
A[3] => 5
A[4] => 1
A[5] => -6
A[6] => 2
A[7] => 1
P = 1 is an equilibrium index of this array, because:
A[0] = −1 = A[2] + A[3] + A[4] + A[5] + A[6] + A[7] P = 3 is an
equilibrium index of this array, because:
A[0] + A[1] + A[2] = −2 = A[4] + A[5] + A[6] + A[7] P = 7 is also an
equilibrium index, because:
A[0] + A[1] + A[2] + A[3] + A[4] + A[5] + A[6] = 0 and there are no
elements with indices greater than 7.
P = 8 is not an equilibrium index, because it does not fulfill the
condition 0 ≤ P < N.
Write a function:
function solution($A);
that, given a zero-indexed array A consisting of N integers, returns
any of its equilibrium indices. The function should return −1 if no
equilibrium index exists.
For example, given array A shown above, the function may return 1, 3
or 7, as explained above.
Assume that:
N is an integer within the range [0..100,000]; each element of array A
is an integer within the range [−2,147,483,648..2,147,483,647].
Complexity:
expected worst-case time complexity is O(N); expected worst-case space
complexity is O(N), beyond input storage (not counting the storage
required for input arguments). Elements of input arrays can be
modified.
Thank you.
for the Codility error please check this post :
https://stackoverflow.com/a/19804284/4369087
Try this one it's more readable, in this solution I'm making the code more readable by introducing two functions.
sumRight(), sumLeft() in which I use built in php functions.
array_sum() : Calculate the sum of values in an array :
it returns the sum of values as an integer or float; 0 if the array is empty.
array_slice(): Extract a slice of the array: array_slice() returns
the sequence of elements from the array as specified by the
offset and length parameters.
So every time we loop over the array we calculate to sum of the right and left slice of the array from the given position $i :
<?php
function solution(array $a)
{
$result = [];
$count = count($a);
for($i = 0; $i < $count; $i++) {
if(sumLeft($a, $i-1) === sumRight($a, $i+1)) {
$result[] = $i;
}
}
return count($result) ? $result : -1;
}
function sumRight(array $a, float $position): float
{
return array_sum(array_slice($a, $position));;
}
function sumLeft(array $a, float $position): float
{
return array_sum(array_slice($a, 0, $position + 1));
}
echo "<pre>";
print_r(solution([-1, 3, -4, 5, 1, -6, 2, 1]));
output:
Array
(
[0] => 1
[1] => 3
[2] => 7
)
The Tape Equilibrium questions is worded super confusingly.
P is the values of the array $A
P values must be greater than 0 and less than N
N is the total number of indexes in the array $A
$A is a non-empty array consisting of N integers
The part "0 < P < N" doesn't make sense. If N is the integers in non-empty array A then N should be the length of the array and data such as [100,200] should not work because P=100 & P=200, both of which are greater than 2.
My opinion is that the explanation is poorly worded. However, the example is clear, so the solution is relatively straight forward if you can get past the opening text.
A non-empty array A consisting of N integers is given. Array A represents numbers on a tape.
Any integer P, such that 0 < P < N, splits this tape into two
non-empty parts: A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ...,
A[N − 1].
The difference between the two parts is the value of: |(A[0] + A[1] +
... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|
In other words, it is the absolute difference between the sum of the
first part and the sum of the second part.
The part that stumped me initially was that I was returning NULL for erroneous array input and receiving a Codility error that NULL was returned when it was expecting an INT. I thought, how can I return an INT when there is no solution for bad data? Turns out, they want you to return a zero.
Here is my 100/100 PHP solution:
function solution($A) {
if ( empty($A) ) {
return 0;
}
$count = count($A);
if ($count == 1) {
return $A[0];
}
for ($i=0, $max_position = $count - 1; $i<$max_position; $i++) {
if (!is_int($A[$i])) {
return;
}
if ($i == 0) {
$left = $A[0];
$right = array_sum($A) - $left;
$min = abs($left - $right);
}
else {
$left += $A[$i];
$right -= $A[$i];
$min = min([$min, abs($left - $right)]);
}
}
return $min;
}
Three things to take note of.
IF $A is empty then return an integer (0) because NULL results in a
codility error
If $A only has one index then return an integer (0) because you cannot split a single index into two equal parts like they want and
NULL results in a codility error
Apparently, invalid non-integer values are not tested - you can see where I checked for !is_int($A[$i]) and then a "return;" that
should have resulted in a NULL (and an error about the NULL not
being an int), but I did not.
Assume that: N is an integer within the range [0..100,000]; each element of array A is an integer within the range [−2,147,483,648..2,147,483,647].
This means I don't see any reason to check if an element isInt() as suggested by #Floyd.
For best efficiency, always break/return as early as possible.
There is no reason to iterate on the first or last index in the array because splitting the array on the first element will result in nothing on the "left side" and splitting on the last element will result in nothing on the "right side". For this reason, start iterating from 1 and only iterate while $i is less than array count - 1.
I struggled to follow the asker's coding attempt, but it seems likely that iterating/evaluating the bookend elements was to blame.
Code -- not actually tested on Codility: (Demo)
$test = [-1, 3, -4, 5, 1, -6, 2, 1];
function solution(array $array): int {
for ($i = 1, $count = count($array) - 1; $i < $count; ++$i) {
if (array_sum(array_slice($array, 0, $i)) === array_sum(array_slice($array, $i + 1))) {
return $i;
}
}
return -1;
}
echo solution($test);

While randomly and not repeating twice

Here is my code:
$answer = explode(" ", $row2['answer']);
foreach($tags as $i =>$key) {
$i >0;
echo $i.' '.$key .'</br>';
}
the output is
0 a
1 b
2 c
3 d
4 e
5 f
I'd like that the output be random, but doesn't repeat twice.
For example:
e 4
a 0
c 2
f 5
d 3
b 1
Any idea please ?
Thank you.
The simplest way I can think of to achieve this would be to use the shuffle method on an array collection. This however does not guarantee non-sequentialness:
$range = range(1,5);
shuffle($range);
foreach($range as $int){
echo $int;
}

Finding out combinations of x amount of integers to sum a given number

I am trying to figure out how I can loop out possible combinations of a x amount of integers to sum a specifik number.
Let's say, I have number 7 and I need to figure out how I can sum that number with integers in pairs 3.
1+2+4 = 7
3+3+1 = 7
5+1+1 = 7
2+2+3 = 7
Repeated combinations of numbers doesn't interest me, e.g.:
1+2+4 = 7
2+4+1 = 7
4+2+1 = 7
Anyone got any ideas of how I should proceed to reach this result?
Thanks.
Here is the solution for your problem.
function printPartitions($target, $max, $s){
if($target === 0 )
echo $s;
else
{
if($max > 1)
{
printPartitions($target, $max-1, $s);
}
if($max <= $target)
{
printPartitions($target-$max, $max, $max . " " . $s);
}
}
}
printPartitions(5, 5, "<br/>");
You have to specify the $target Value, $max value.
e.g.
printPartitions(7, 7, "<br/>");
It will give you output like:
1 1 1 1 1 1 1
1 1 1 1 1 2
1 1 1 2 2
1 2 2 2
1 1 1 1 3
1 1 2 3
2 2 3
1 3 3
1 1 1 4
1 2 4
3 4
1 1 5
2 5
1 6
7
I've got a solution to my problem. I feel I should defientely share it here, if anyone would ever need it. My solutions is based on this post: https://stackoverflow.com/a/19067884/3293843
<?php
function sampling($chars, $size, $combinations = array()) {
# if it's the first iteration, the first set
# of combinations is the same as the set of characters
if (empty($combinations)) {
$combinations = $chars;
}
# we're done if we're at size 1
if ($size == 1) {
return $combinations;
}
# initialise array to put new values in
$new_combinations = array();
# loop through existing combinations and character set to create strings
foreach ($combinations as $combination) {
foreach ($chars as $char) {
$new_combinations[] = $combination .'#'. $char;
}
}
# call same function again for the next iteration
return sampling($chars, $size - 1, $new_combinations);
}
// example
$chars = array('1', '2', '3','4');
$target = 7;
$maxLengthOfIntegers = 3;
$output = sampling($chars, $maxLengthOfIntegers);
$repeatedEntries = array();
//presenting the output
foreach($output as $out){
$explodeOut = explode('#',$out);
sort($explodeOut);
if(array_sum($explodeOut) == $target){
$sortedPattern = implode('',$explodeOut);
if(!in_array($sortedPattern,$repeatedEntries)){
echo $sortedPattern.'<br/>';
$repeatedEntries[] = $sortedPattern;
}
}
}
?>
Thank you for your time and efforts.
Regards,
Jacob
you can try this algorithm
$ans = array();
for($i=1;$i<=5;$i++)
{
$i1 = 7-$i;
$i2 = intval($i1 - $i);
$value = $i."+".$i1."+".$i2;
$ans = array_unshift($ans,$value);
}
print_r($ans);
hope this helps.. PLease let me know

Categories