Number of unique pairs in an array - in php - php

Input: arr[] = {1, 1, 2} ;
Output: 4 ;
(1, 1), (1, 2), (2, 1), (2, 2) are the only possible pairs.
I tried below code
$temp = [];
for($i=0; $i<count($a); $i++) {
for($j=1;$j<count($a);$j++) {
$temp[] = array(0=>$a[$i],1=>$a[$j]);
}
}
for($i=0;$i<count($temp);$i++) {
if(!empty($temp1)) {
for($j=0;$j<count($temp1);$j++) {
if($temp1[$j][0] != $temp[$i][0] || $temp1[$j][1] != $temp[$i][1]) {
$temp1[$j][0] = $temp[$i][0];
$temp1[$j][1] = $temp[$i][1];
}
}
} else {
$temp1[$j][0] = $temp[$i][0];
$temp1[$j][1] = $temp[$i][1];
}
}
print_r($temp1);

Start by removing duplicates from your array. Then you can generate all pairs easily.
$a = [1,1,2];
$b = [];
$temp = [];
// if you want to do it yourself
for($i= 0; $i<count($a); $i++) {
if (!in_array($a[$i], $b)) {
$b[] = $a[$i];
}
}
// if you want to use built-in
$b = array_values(array_unique($a));
for($i=0; $i<count($b); $i++) {
for($j=0;$j<count($b);$j++) {
$temp[] = array(0=>$b[$i],1=>$b[$j]);
}
}
print_r($temp);

Related

How to condense an array of integers in PHP?

So I have an array of integers: <1, 2, 3, 9, 10, 11, 14>, that I would like to join together in this format: <1-3, 9-11, 14>.
I'm new to PHP and tried doing this by looping through the array:
function pasteTogether($val)
{
$newVals = array();
$min = $val[0];
$max = $val[1];
$counter = 0;
for ($i = 0; $i < count($val); $i++)
{
if ($val[$i + 1] === $val[$i] + 1)
{
$max = $val[$i + 1];
}
else
{
$tempVal = $min."-".$max;
$newVals[$counter] = $tempVal;
$counter++;
$min = $val[$i];
}
}
return $newVals;
}
However, when I run this code, I get <1-3, 3-11, 11-11, 14-14>
PHP Fatal error: Maximum execution time of 30 seconds exceeded in ../learning.php on line 36
Because the for loop never ends you increment $val instead of $i
$array = array(1, 2, 3, 9, 10, 11, 14);
function pasteTogether($val)
{
$newVals = array();
$min = $val[0];
$max = $val[1];
$counter = 0;
for ($i = 0; $i < count($val); $i++)
{
if ($val[$i + 1] === $val[$i] + 1)
{
$max = $val[$i + 1];
}
else
{
$tempVal = $min."-".$max;
$newVals[$counter] = $tempVal;
$counter++;
$min = $val[$i];
}
}
return $newVals;
}
pasteTogether($array);
I have been playing around with this interesting problem and found another solution. So, if anyone is interested:
$arr=array(1, 2, 3, 9, 10, 11, 14, 15, 16, 18);
$v0=$dif=null;$rows=array();
foreach ($arr as $i => $v) {
if ($dif!=($d=($v-$i))){
if ($v0) $rows[]="$v0-".$arr[$i-1];
$v0=$v;
$dif=$d;
}
}
$rows[]="$v0-".($d==$dif?$arr[$i]:$v0);
print_r($rows);
I added a few numbers to the array and the result is this:
$rows = Array
(
[0] => 1-3
[1] => 9-11
[2] => 14-16
[3] => 18-18
)
You can find a little demo here: http://rextester.com/ABC25608
This works:
function pasteTogether($val)
{
$compacted = [];
$min = null;
$max = null;
$format = function ($a, $b) {
return ($a < $b ? "$a-$b" : $a);
};
foreach ($val as $current) {
if ($min === null) {
$min = $current;
$max = $current - 1;
}
if ($current == $max + 1) {
$max++;
} else {
$compacted[] = $format($min, $max);
$min = $current;
$max = $current;
}
}
$compacted[] = $format($min, $max);
return $compacted;
}
echo '<', implode(', ', pasteTogether([1, 2, 3, 9, 10, 11, 14])), '>';
Output:
<1-3, 9-11, 14>

N random numbers that can duplicate after 2 elements

I want to generate 10 numbers with each ranging from (1 to 5) but can only duplicate after 2 elements
for example 5 3 1 4 2 5(can be duplicated here) 2 (cannot be duplicate here since it occur before 1 element) ...etc.
I have this code in php working but its performance is awful since it sometimes exceeds the maximum 30 seconds execution time.
<?php
function contain($prevItems, $number) {
if (count($prevItems) == 3)
{
array_shift($prevItems);
}
for ($k=0; $k<count($prevItems); $k++) {
if ($prevItems[$k] == $number)
return true;
}
return false;
}
$num[0] = rand(1,5);
$prevItems[0] = $num[0];
for ($i=1; $i<=10; $i++) {
$num[$i] = rand(1,5);
while (contain($prevItems, $num[$i])) {
$num[$i] = rand (1,5);
}
$prevItems[$i] = $num[$i]; //append into the array
}
print_r($num);
?>
Edit:
I have also tried this method, its performance is good but it duplicates elements
<?php
$evalAccurance = array();
$count = 0;
while ( $count < 11)
{
$random = rand(1, 5);
if (in_array($random, $evalAccurance))
{
$p = $random;
for ($k = $p ; $k <5; $k++)
{
$random = $random++;
if (in_array($random, $evalAccurance))
continue 1;
else break 1;
}
if (in_array($random, $evalAccurance))
{
for ($k = $p ; $k >0; $k--)
{
$random = $random--;
if (in_array($random, $evalAccurance))
continue 1;
else break 1;
}
}
}
$evalAccurance[] = $random;
if (count ($evalAccurance) == 4)
array_shift($evalAccurance);
print_r ($evalAccurance);
$count++;
}
?>
One way you could do this:
// pass to function current array of numbers
function randomNumber($ar){
// create a random number from 1 to 5
$num = rand(1,5);
// check backwards 3 elements for same number, if none found return it
if(!in_array($num, array_slice($ar, -3, 3, true))){
return $num;
} else {
// else recall function with same array of numbers
return randomNumber($ar);
}
}
$array = array();
// loop 10 numbers and call randomNumber with current set of results.
for($i=1; $i<=10; $i++){
$array[] = randomNumber($array);
}
print_r($array);
Using PHP SPLQueue:
$queue = new SplQueue();
$values = array(1, 2, 3, 4, 5);
$container = array();
for ($i = 0; $i < 10; $i++) {
$value = give_random($values, $queue);
$container[] = $value;
if ($queue->offsetExists(1) AND $queue->offsetExists(0)) {
$queue->dequeue();
}
$queue->enqueue($value);
}
function give_random(&$values, &$queue) {
$picked_value = $values[array_rand($values)];
if ($queue->offsetExists(1)) {
if ($picked_value == $queue->offsetGet(1)) {
$picked_value = give_random($values, $queue);
}
}
if ($queue->offsetExists(0)) {
if ($picked_value == $queue->offsetGet(0)) {
$picked_value = give_random($values, $queue);
}
}
return $picked_value;
}
print_r($container);
It could be neater, but you can figure what's going on.
Cheers.

How to create a 2D array that values BA and AB are treated as the same

I am trying to create function that allows me to get all combinations of an array to later generate a list.
But my problem is that currently my function treat "ab" as different from "ba". I dont know how to explain it in words but I guess the picture below exemplify what I try to achieve.
function everyCombination($array) {
$arrayCount = count($array);
$maxCombinations = pow($arrayCount, $arrayCount);
$returnArray = array();
$conversionArray = array();
foreach ($array as $key => $value) {
$conversionArray[base_convert($key, 10, $arrayCount)] = $value;
}
for ($i = 0; $i < $maxCombinations; $i++) {
$combination = base_convert($i, 10, $arrayCount);
$combination = str_pad($combination, $arrayCount, "0", STR_PAD_LEFT);
$returnArray[] = strtr($combination, $conversionArray);
}
return $returnArray;
}
$a = everyCombination(array('a', 'b', 'c','d'));
print_r($a);
The desired ouput would be
a
ab
abc
abcd
b
bc
bcd
c
cd
d
What you need to do is iterate through the array recursively, for each recursion you should only iterate through all the greater elements. Like so:
function everyCombination($arr) {
$combos = array();
$len = count($arr);
for( $i=0; $i<$len; $i++) {
for( $j=$i+1; $j<=$len; $j++) {
$combos[] = implode("",array_slice($arr,$i,$j-$i));
}
}
return $combos;
}
Example call:
everyCombination(['a','b','c','d']);
Returns:
['a','ab','abc','abcd','b','bc','bcd','c','cd','d']
It seems that you're after consecutive results, so a double loop would be a better choice here; recursion requires more control.
function combos($array)
{
if (!$array) {
return [];
}
$n = count($array);
$r = [];
for ($i = 0; $i < $n; ++$i) {
$prefix = '';
for ($j = $i; $j < $n; ++$j) {
$r[] = $prefix . $array[$j];
$prefix .= $array[$j];
}
}
return $r;
}
print_r(combos([1, 2, 3, 4]));

Combining of array items

I have a problem with an advanced loop, this are my arrays
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
I want to loop with the following result:
1,4,6,10
1,4,6,11
1,4,7,10
1,5,7,11
With the last: 3,5,8,11
How can I do that?
Solution for a variable number of arrays. Can probably be written a bit shorter, but I leave that to you. ;)
<?php
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
function turboArray()
{
$arrays = func_get_args();
$indexes = array_fill(0, count($arrays), 0);
function turboSubArray(&$arrays, &$indexes, $l){
for ($a = 0; $a < count($arrays[$l]); $a++){
$indexes[$l] = $a;
if ($l == count($arrays) - 1) {
for ($i = 0; $i < count($indexes); $i++)
{
echo $arrays[$i][$indexes[$i]];
if ($i == count($indexes) - 1){
echo "\n<br/>";
$indexes[$i] = 0;
if ($i == 0) return;
}
else {
echo ', ';
}
}
} else if ($l < count($indexes)) {
turboSubArray($arrays, $indexes, $l + 1);
}
}
}
$l = 0;
turboSubArray($arrays, $indexes, $l);
}
turboArray($array1, $array2, $array3, $array4);
This should do it... ?
foreach ($array1 as $first) {
foreach ($array2 as $second) {
foreach ($array3 as $third) {
foreach ($array4 as $fourth) {
echo "$first $second $third $fourth";
}
}
}
}
I got bored and decided to overengineer a bit. Enjoy.
class CrossJoin implements Iterator {
private $arrays = array();
private $index = 0;
public function __construct(/* $array1, ... */) {
foreach (func_get_args() as $arr) {
// ArrayIterator's iteration stuff is cleaner than arrays',
// and less prone to breakage when objects are passed around
if (count($arr)) $this->arrays[] = new ArrayIterator($arr);
}
// if any of the arrays were empty, a cross join should fail.
// fudge a single empty array to prevent special-casing later
if (count($this->arrays) !== func_num_args()) {
$this->arrays = array(new ArrayIterator(array()));
}
}
public function next() {
for ($i = count($this->arrays) - 1; $i >= 0; --$i) {
// carry til we don't have to anymore
$place = $this->arrays[$i];
$place->next();
if ($place->valid()) break;
}
// if $i<0, then we carried right off the edge of the list.
// don't let $arrays[0] be reset, cause that's our indicator
// that we're done.
if ($i<0) return;
++$this->index;
for (++$i; $i < count($this->arrays); ++$i) {
$this->arrays[$i]->rewind();
}
}
public function current() {
$result = array();
foreach ($this->arrays as $arr) { $result[] = $arr->current(); }
return $result;
}
public function key() { return $this->index; }
public function valid() {
return !empty($this->arrays) && $this->arrays[0]->valid();
}
public function rewind() {
foreach ($this->arrays as $arr) $arr->rewind();
$this->index = 0;
}
}
$combos = new CrossJoin(
array(1, 2, 3),
array(4, 5),
array(6, 7, 8, 9),
array(10, 11)
);
foreach ($combos as $combo) {
echo implode(', ', $combo), "\n";
}
Hope that helps:
for ($i = 0; $i < count($a1); ++i) {
for ($j = 0; $j < count($a2); ++j) {
for ($k = 0; $k < count($a3); ++k) {
for ($l = 0; $l < count($a4); ++l) {
echo $a1[$i] . ' ' . $a2[$j] . ' ' . $a3[$k] . ' ' . $a4[$l] . '\n';
}
}
}
}
Cheers!
You are looking for the PHP array_merge function.

Getting the most repeated values in an array [duplicate]

This question already has answers here:
PHP get the item in an array that has the most duplicates
(2 answers)
Closed 1 year ago.
I have an array of numbers like this:
$array = array(1,1,1,4,3,1);
How do I get the count of most repeated value?
This should work:
$count=array_count_values($array);//Counts the values in the array, returns associatve array
arsort($count);//Sort it from highest to lowest
$keys=array_keys($count);//Split the array so we can find the most occuring key
echo "The most occuring value is $keys[0][1] with $keys[0][0] occurences."
I think array_count_values function can be useful to you. Look at this manual for details : http://php.net/manual/en/function.array-count-values.php
You can count the number of occurrences of values in an array with array_count_values:
$counts = array_count_values($array);
Then just do a reverse sort on the counts:
arsort($counts);
Then check the top value to get your mode.
$mode = key($counts);
If your array contains strings or integers only you can use array_count_values and arsort:
$array = array(1, 1, 1, 4, 3, 1);
$counts = array_count_values($array);
arsort($counts);
That would leave the most used element as the first one of $counts. You can get the count amount and value afterwards.
It is important to note that if there are several elements with the same amount of occurrences in the original array I can't say for sure which one you will get. Everything depends on the implementations of array_count_values and arsort. You will need to thoroughly test this to prevent bugs afterwards if you need any particular one, don't make any assumptions.
If you need any particular one, you'd may be better off not using arsort and write the reduction loop yourself.
$array = array(1, 1, 1, 4, 3, 1);
/* Our return values, with some useless defaults */
$max = 0;
$max_item = $array[0];
$counts = array_count_values($array);
foreach ($counts as $value => $amount) {
if ($amount > $max) {
$max = $amount;
$max_item = $value;
}
}
After the foreach loop, $max_item contains the last item that appears the most in the original array as long as array_count_values returns the elements in the order they are found (which appears to be the case based on the example of the documentation). You can get the first item to appear the most in your original array by using a non-strict comparison ($amount >= $max instead of $amount > $max).
You could even get all elements tied for the maximum amount of occurrences this way:
$array = array(1, 1, 1, 4, 3, 1);
/* Our return values */
$max = 0;
$max_items = array();
$counts = array_count_values($array);
foreach ($counts as $value => $amount) {
if ($amount > $max) {
$max = $amount;
$max_items = array($value);
} elif ($amount = $max) {
$max_items[] = $value;
}
}
$vals = array_count_values($arr);
asort($vals);
//you may need this end($vals);
echo key($vals);
I cant remember if asort sorts asc or desc by default, you can see the comment in the code.
<?php
$arrrand = '$arr = array(';
for ($i = 0; $i < 100000; $i++)
{
$arrrand .= rand(0, 1000) . ',';
}
$arrrand = substr($arrrand, 0, -1);
$arrrand .= ');';
eval($arrrand);
$start1 = microtime();
$count = array_count_values($arr);
$end1 = microtime();
echo $end1 - $start1;
echo '<br>';
$start2 = microtime();
$tmparr = array();
foreach ($arr as $key => $value);
{
if (isset($tmparr[$value]))
{
$tmparr[$value]++;
} else
{
$tmparr[$value] = 1;
}
}
$end2 = microtime();
echo $end2 - $start2;
Here check both solutions:
1 by array_count_values()
and one by hand.
<?php
$input = array(1,2,2,2,8,9);
$output = array();
$maxElement = 0;
for($i=0;$i<count($input);$i++) {
$count = 0;
for ($j = 0; $j < count($input); $j++) {
if ($input[$i] == $input[$j]) {
$count++;
}
}
if($count>$maxElement){
$maxElement = $count;
$a = $input[$i];
}
}
echo $a.' -> '.$maxElement;
The output will be 2 -> 3
$arrays = array(1, 2, 2, 2, 3, 1); // sample array
$count=array_count_values($arrays); // getting repeated value with count
asort($count); // sorting array
$key=key($count);
echo $arrays[$key]; // get most repeated value from array
String S;
Scanner in = new Scanner(System.in);
System.out.println("Enter the String: ");
S = in.nextLine();
int count =1;
int max = 1;
char maxChar=S.charAt(0);
for(int i=1; i <S.length(); i++)
{
count = S.charAt(i) == S.charAt(i - 1) ? (count + 1):1;
if(count > max)
{
max = count;
maxChar = S.charAt(i);
}
}
System.out.println("Longest run: "+max+", for the character "+maxChar);
here is the solution
class TestClass {
public $keyVal;
public $keyPlace = 0;
//put your code here
public function maxused_num($array) {
$temp = array();
$tempval = array();
$r = 0;
for ($i = 0; $i <= count($array) - 1; $i++) {
$r = 0;
for ($j = 0; $j <= count($array) - 1; $j++) {
if ($array[$i] == $array[$j]) {
$r = $r + 1;
}
}
$tempval[$i] = $r;
$temp[$i] = $array[$i];
}
//fetch max value
$max = 0;
for ($i = 0; $i <= count($tempval) - 1; $i++) {
if ($tempval[$i] > $max) {
$max = $tempval[$i];
}
}
//get value
for ($i = 0; $i <= count($tempval) - 1; $i++) {
if ($tempval[$i] == $max) {
$this->keyVal = $tempval[$i];
$this->keyPlace = $i;
break;
}
}
// 1.place holder on array $this->keyPlace;
// 2.number of reapeats $this->keyVal;
return $array[$this->keyPlace];
}
}
$catch = new TestClass();
$array = array(1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 1, 2, 3, 1, 1, 2, 5, 7, 1, 9, 0, 11, 22, 1, 1, 22, 22, 35, 66, 1, 1, 1);
echo $catch->maxused_num($array);

Categories