Get a total from symmetric intigers from array in php? - php

ok so i have array for example $arr= "/43sdsd555ksldk66sd"544fdfd";
I take numbers using preg_match_all '/\d+/', and array_map('intval', $zni[0]);
Now the problem is i need to reverse those whole int to see if they are symmetric,like 555 and 66 , and if they are GET A TOTAL OF THEM.(total of only symmetric numbers)
i tried to use function " strrev "and got symmetric numbers, but i don't know how to put them in a one place IF THEY ARE symmetric and calculate them.
<?php
$numbers = "";
if (isset($_GET['submit']))
{
$numbers = ($_GET['niz']);
preg_match_all('/\d+/', $numbers, $zni);
$numtwo= array_map('intval', $zni[0]);
}
foreach ($numtwo as $num)
{
$reverse = strrev($num);
var_dump($reverse);
if ($num == $reverse)
{
$reverse = "true";
} else {
$reverse = "false";
}
var_dump($reverse);
}

Since you already got most of the way there and all you were missing basically was to use + or +=, here is an easy example on how to do it:
$input = "/43sdsd555ksldk66sd544fdfd";
$total = 0;
preg_match_all('/\d+/', $input, $m);
foreach ($m[0] as $d)
if ($d == strrev($d))
$total += $d;
var_dump($total); // => int(621)
Using intval() is not necessary as PHP will implicitly cast between types as needed.
Alternatively you can replace the loop with PHP's array_* functions:
$input = "/43sdsd555ksldk66sd544fdfd";
preg_match_all('/\d+/', $input, $m);
$total = array_sum(array_filter($m[0], function ($v) { return $v == strrev($v); }));
var_dump($total); // => int(621)
Here we use an anonymous function with array_filter() to generate a new array that only contains palindrome numbers from the original matches which is then given to array_sum().
So all that's needed to transform your original code into a working example, is introducing a variable and summing up:
<?php
$numbers = "";
if (isset($_GET['submit']))
{
$numbers = ($_GET['niz']);
preg_match_all('/\d+/', $numbers, $zni);
$numtwo= array_map('intval', $zni[0]);
}
$total = 0; // new variable
foreach ($numtwo as $num)
{
$reverse = strrev($num);
var_dump($reverse);
if ($num == $reverse)
{
$reverse = "true";
$total += $num; // sum up
} else {
$reverse = "false";
}
var_dump($reverse);
}
var_dump($total); // => int(621)

Related

Return the number of all unique case-insensitive characters

I am trying create a function which returns the number of all unique case-insensitive
characters that occur >= $n times in a given string.
For example:
function getNumOfUniqueCharacters($str, $n) {
// ...
}
getNumOfUniqueCharacters('A1B2C3', 2); // 0
getNumOfUniqueCharacters('A1a1C1', 2);
// 2, because A and 1 both occur 2 or more times.
getNumOfUniqueCharacters('Alabama', 3); // 1
I did this:
function getNumOfUniqueCharacters($text)
{
$ret = 0;
$a = [];
$t = str_split(strtolower($text));
$l = count($t);
for ($i = 0; $i < $l; $i++) {
$c = $t[$i];
if (array_key_exists($c, $t)) {
if ($t[$c] === 1)
$ret += 1;
$t[$c] += 1;
} else {
$t[$c] = 1;
}
}
return $ret;
}
But it does not work so good, I need to add second argument $n.
How to add it correctly?
I hope I got your question right.
Here's my idea for this code:
<?php
$string = "A1B2C1A2b2b4b5";
function getNumOfUniqueCharacters($string, $n)
{
$occurrenceArray = array();
$text = str_split(strtolower($string));
//put each character in a keyValue array and count them
foreach($text as $character){
if(!array_key_exists($character, $occurrenceArray)) $occurrenceArray[$character] = 1;
else $occurrenceArray[$character]++;
}
//loop through keyValue array and remove everything that has value < $n
foreach($occurrenceArray as $key => $value)
{
if($value < $n) unset($occurrenceArray[$key]);
}
//return array
return $occurrenceArray;
}
print_r(getNumOfUniqueCharacters($string, 2));
This code right here will print the following:
Array (
[a] => 2
[1] => 2
[b] => 4
[2] => 3 )
Edit: If you need the count of how many characters repeat more than $n, you can simply replace the return with return count($occurrenceArray);
This task is pretty easy, if you use array functions of PHP:
function getNumOfUniqueCharacters(string $string = '', int $n = 1): int {
// Split the string by character and count the occurences of all values
$counted = array_count_values(mb_str_split(mb_strtolower($str)));
// Discard everything, that is does not match the $n parameter
$counted = array_filter($counted, function($a) use($n) {
return $a >= $n;
});
// Return the length of the remaining array
return count($counted);
}
Also note, that you may use mb_* functions, so your code will work with multibyte characters.
I have written you a function with a lot of comments to explain the thought process,
function getNumOfUniqueCharacters($string, $n = null) {
// Map all case-insensitive characters to an array
$map = str_split(strtolower($string), 1);
// Character registry
$reg = array_count_values($map);
// Filter out single occurances
$reg = array_filter($reg, function($v){return $v > 1;});
// Filter out less than $n occurances (if $n is not null)
if (null !== $n) {
$reg = array_filter($reg, function($v)use($n){return $v >= $n;});
}
// Return the number duplicate occurances (or more than n occurances)
return count($reg);
}
Usage:
echo getNumOfUniqueCharacters('A1B2C3', 2) . PHP_EOL;
echo getNumOfUniqueCharacters('A1a1C1', 2) . PHP_EOL;
echo getNumOfUniqueCharacters('Alabama', 3) . PHP_EOL;
echo getNumOfUniqueCharacters('Mississippi') . PHP_EOL;
Output:
0
2
1
3

How to get array min value

I have multidimensional array and me need to get a minimum value.
Array may be [65,4,4,511,5,[[54,54[.[.[..].].]] and so on.
example code
<?php
$arr = [5, 1 , 2, 3, [1,5,59,47,58,[0,12,562]]];
function NumMin($arr)
{
$num = '';
foreach ($arr as $item => $i) {
if(is_array($i)){
NumMin($i);
}
else{
$num .= $i.',';
}
}
$num .= $num;
return $num;
}
$g = NumMin($arr);
var_dump($g);
I need to get 0
You can use array_walk_recursive() function to flatten a given array (makes it one-dimensional).
And use simply min() function for getting the desired output after.
array_walk_recursive($arr, function($v) use (&$res){
$res[]=$v;
});
echo min($res);
Demo
<?php
$GLOBALS["min"] = 999999; //min value int
$arr = [[[5,6],7],9,7,5, 1 , 2, 3, [1,5,59,47,58,[1,12,562]]];
array_walk_recursive($arr, 'NumMin');
function NumMin($item)
{
if(intval($item) <= intval($GLOBALS["min"]))
{
$GLOBALS["min"] = intval($item);
}
}
// The end, $GLOBALS["min"] will have the least value
echo $GLOBALS["min"];
?>

Getting the first occurrence of modulus eval

Consider this array:
$numbers = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
How can I loop through this array and get the FIRST number and the LAST number where the eval below is true?
foreach($numbers as $number){
if(($number % 2)==0){
//This will execute for the numbers 2,4,6, etc...
//The first occurrence here will be 2 and the last will be 16
}
}
If I got you right you want the min and the max only of even values.
Creating a helper variable should solve this easily.
<?php
$numbers = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
$even = array();
foreach($numbers as $number){
if(($number % 2) == 0){
//This will execute for the numbers 2,4,6, etc...
//The first occurrence here will be 2 and the last will be 16
// Store only even values on the array to access it later using min() and max() functions
$even[] = $number;
}
}
print_r($even);
echo min($even); // prints 2
echo max($even); // prints 16
?>
function getNumber(Array $numbers) {
foreach($numbers as $number) {
if (!($number % 2)) {
return $number;
}
}
}
$numbers = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
$first = getNumber($numbers); // 2
$last = getNumber(array_reverse($numbers)); // 16
$first = null;
$temp = null;
foreach($numbers as $number){
if(($number % 2)==0){
//This will execute for the numbers 2,4,6, etc...
//The first occurrence here will be 2 and the last will be 16
//
$temp = $number;
// Check if the first number has been assigned yet, if not set to $first
if ($first === null) {
$first = $number;
}
}
}
// Retrieve last valid value and set as last
$last = $temp;
Should do the trick
$numbers = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
foreach ($numbers as $number) {
if(0===($number%2))
{
(!isset($first)) ? $first=$number : $last=$number;
$last = $number;
}
}
echo $first.'<br />';
echo $last.'<br />';

How can I find not just duplicates in array, but numbers that match a range in PHP?

I need to find not just duplicates in an array, but numbers that are within 1 of each other.
example: $myArr = array(46,78,77,43,86,1,47,14,51,31)
How would I get find those numbers if there no duplicates were found?
Thanks.
This will work - tested:
$myArr = array(46,78,77,43,86,1,47,14,51,31);
$i = 1;
while($i <= 99){
if(in_array($i, $myArr)){
// This means it's in the array
// Let's see if it's +1 of the last #
if(isset($last_num)){
$res = ($i + 1);
if(in_array($res, $myArr)){
echo $res . ' is in the array<br>';
}
}
}
$last_num = $i;
$i++;
}
Could use something like this.
<?
$haystack = array(31,46,78,77,43,86,1,47,14,51,31);
array_walk($haystack, function($key, $value) use ($haystack) {
$needle = array($key - 1, $key, $key + 1);
$r = array_intersect($haystack, $needle);
if(count($r) > 1) { unset($r[$value]); print_r(array_values($r)); }
});
?>
Or if you want them returned in an array:
<?
$haystack = array(31,46,78,77,43,86,1,47,14,51,31);
$result = array_filter(array_map(function($key, $value) use ($haystack) {
$needle = array($key - 1, $key, $key + 1);
$r = array_intersect($haystack, $needle);
if(count($r) > 1) { unset($r[$value]); return array_values($r)['0']; }
}, $haystack));
print_r($result);
?>
A little more verbose, but it may be more efficient since we're only looping through the array when necessary. It will return the keys of the original array where duplicates and values within range are found. (Note: I've expanded the code out a lot more than I normally would just for readability for OP)
/**
* Find the any values within an array that are within
* the specified range from another value.
*
* #param Array Array to search in
* #param uint Unsigned integer used for comparison
* #return Array The keys of all found values
**/
function findWithinRange(Array $array, $range) {
// sort the array values numerically
// so we don't have to loop through
// the entire array for each check
asort($array, SORT_NUMERIC);
// Keep the keys in case it's an associative array
$keys = array_keys($array);
// Get the values without the keys so we can easily loop
$values = array_values($array);
$return = array();
// Loop over each item in the array
foreach( $values as $k => $v ) {
$start = $k;
$min = $v - $range;
$max = $v + $range;
// track backwards in the array until we're less than range
// We could use array_search, but we'd be calling it multiple times
// This only runs through the array once and dies the moment
// it is out of the specified range
while(true) {
$k--;
if( !isset($values[$k]) ) {
break; // don't continue if we run out of keys
}
$curVal = $values[$k];
if( $curVal >= $min ) {
$return[] = $keys[$k];
}
else {
break; // kill the while loop if we're outside of range
}
}
// reset
$k = $start;
// track forward in the array until we're greater than range
while(true) {
$k++;
if( !isset($values[$k]) ) {
break; // don't continue if we run out of keys
}
$curVal = $values[$k];
if( $curVal <= $max ) {
$return[] = $keys[$k];
}
else {
break; // kill the while loop if we're outside of range
}
}
}
// drop duplicate reports
$return = array_unique($return);
// return all found keys
return $return;
}
Example usage:
$myArr = array(46,78,77,43,86,1,47,14,51,31);
$res = findWithinRange($myArr, 1);
var_export($res);
// array(6, 0, 1, 2)

How to compute the cartesian power of a range of characters?

I would like to make a function that is able to generate a list of letters and optional numbers using a-z,0-9.
$output = array();
foreach(range('a','z') as $i) {
foreach(range('a','z') as $j) {
foreach(range('a','z') as $k) {
$output[] =$i.$j.$k;
}
}
}
Thanks
example:
myfunction($include, $length)
usage something like this:
myfunction('a..z,0..9', 3);
output:
000
001
...
aaa
aab
...
zzz
The output would have every possible combination of the letters, and numbers.
Setting the stage
First, a function that expands strings like "0..9" to "0123456789" using range:
function expand_pattern($pattern) {
$bias = 0;
$flags = PREG_SET_ORDER | PREG_OFFSET_CAPTURE;
preg_match_all('/(.)\.\.(.)/', $pattern, $matches, $flags);
foreach ($matches as $match) {
$range = implode('', range($match[1][0], $match[2][0]));
$pattern = substr_replace(
$pattern,
$range,
$bias + $match[1][1],
$match[2][1] - $match[1][1] + 1);
$bias += strlen($range) - 4; // 4 == length of "X..Y"
}
return $pattern;
}
It handles any number of expandable patterns and takes care to preserve their position inside your source string, so for example
expand_pattern('abc0..4def5..9')
will return "abc01234def56789".
Calculating the result all at once
Now that we can do this expansion easily, here's a function that calculates cartesian products given a string of allowed characters and a length:
function cartesian($pattern, $length) {
$choices = strlen($pattern);
$indexes = array_fill(0, $length, 0);
$results = array();
$resets = 0;
while ($resets != $length) {
$result = '';
for ($i = 0; $i < $length; ++$i) {
$result .= $pattern[$indexes[$i]];
}
$results[] = $result;
$resets = 0;
for ($i = $length - 1; $i >= 0 && ++$indexes[$i] == $choices; --$i) {
$indexes[$i] = 0;
++$resets;
}
}
return $results;
}
So for example, to get the output described in the question you would do
$options = cartesian(expand_pattern('a..z0..9'), 3);
See it in action (I limited the expansion length to 2 so that the output doesn't explode).
Generating the result on the fly
Since the result set can be extremely large (it grows exponentially with $length), producing it all at once can turn out to be prohibitive. In that case it is possible to rewrite the code so that it returns each value in turn (iterator-style), which has become super easy with PHP 5.5 because of generators:
function cartesian($pattern, $length) {
$choices = strlen($pattern);
$indexes = array_fill(0, $length, 0);
$resets = 0;
while ($resets != $length) {
$result = '';
for ($i = 0; $i < $length; ++$i) {
$result .= $pattern[$indexes[$i]];
}
yield $result;
$resets = 0;
for ($i = $length - 1; $i >= 0 && ++$indexes[$i] == $choices; --$i) {
$indexes[$i] = 0;
++$resets;
}
}
}
See it in action.
See this answer for a code that produces all possible combinations:
https://stackoverflow.com/a/8567199/1800369
You just need to add the $length parameter to limit the combinations size.
You can use a recursive function
assuming you mean it can be any number of levels deep, you can use a recursive function to generate an array of the permutations e.g.:
/**
* take the range of characters, and generate an array of all permutations
*
* #param array $range range of characters to itterate over
* #param array $array input array - operated on by reference
* #param int $depth how many chars to put in the resultant array should be
* #param int $currentDepth internal variable to track how nested the current call is
* #param string $prefix internal variable to know what to prefix the current string with
* #return array permutations
*/
function foo($range, &$array, $depth = 1, $currentDepth = 0, $prefix = "") {
$start = !$currentDepth;
$currentDepth++;
if ($currentDepth > $depth) {
return;
}
foreach($range as $char) {
if ($currentDepth === $depth) {
$array[] = $prefix . $char;
continue;
}
foo($range, $array, $depth, $currentDepth, $prefix . $char);
}
if ($start) {
return $array;
}
With the above function, initialize the return variable and call it:
$return = array();
echo implode(foo(range('a', 'z'), $return, 3), "\n");
And you're output will be all three char combinations from aaa, to zzz:
aaa
aab
...
zzy
zzz
The numeric parameter determins how recursive the function is:
$return = array();
echo implode(foo(range('a', 'z'), $return, 1), "\n");
a
b
c
...
Here's a live example.
$number= range(0, 9);
$letters = range('a', 'z');
$array= array_merge($number, $letters);
//print_r($array);
for($a=0;$a<count($array);$a++){
for($b=0;$b<count($array);$b++){
for($c=0;$c<count($array);$c++){
echo $array[$a].$array[$b].$array[$c]."<br>";
}
}
}
tested and working :)

Categories