I have two dynamic variables
$numberOfX = 2;
and
$numberOfY = 5;
The challenge for me is that I need to divide the number 5(numberOfY) between 2(numberOfX). That's an issue cause I will either through a calculation(divide) get a floating number like 2,5 or I can choose (ceil) to round it up but then I get 3(and totally it will be more then 5, namely 6).
I need a whole integers with no decimals. But still it can't be more or less then 5.
So ideally I Would like an array e.g with 3 and 2 in it. As it added will give 5.
How can I do this in PHP , remembering that numberOfX and numberOfY can be any number ?
$numberOfX = 3;
$numberOfY = 5;
$result = array_fill(0, $numberOfX, (int) floor($numberOfY / $numberOfX));
$i = 0;
while (array_sum($result) !== $numberOfY) {
$result[$i++]++;
}
var_dump($result, array_sum($result));
Demo
$numberOfX = 2;
$numberOfY = 5;
$intDivisionValues[] = intval($numberOfY/$numberOfX);
$intDivisionValues[] = $numberOfY - intval($numberOfY/$numberOfX);
$intDivisionValues will then be:
Array
(
[0] => 2
[1] => 3
)
Your question is not completely clear about the algorithm you are looking for. I guess this might come close:
<?php
$numberOfX = 2;
$numberOfY = 5;
$full = intval($numberOfY / $numberOfX);
$part = intval($numberOfY % $numberOfX);
$output = array_fill(1, $numberOfX-1, $full);
$output[] = $full+$part;
var_dump($output);
The output for the example values would be:
array(2) {
[0] =>
int(2)
[1] =>
int(3)
}
For an example using different values, especially different values for $numberOfX the result would be different, obviously. Here the output for values 3 and 31:
array(3) {
[0] =>
int(10)
[1] =>
int(10)
[2] =>
int(11)
}
You can play around with other values to see if that suits your needs...
This algorithm behaves different to what #WilliamJanoti suggests in his answer. As said: your question is not really clear in what you are looking for...
Related
I have an array:
Array
(
[0] => Alex
[1] => Michael
[2] => Harry
[3] => Dave
[4] => Michael
[5] => Victor
[6] => Harry
[7] => Alex
[8] => Mary
[9] => Mary
)
I want to write to a function that will return an array with elements that most number of time repeated. For example, the output array should have Alex, Micheal, Hary, and Mary because each one of them is repeated twice. IF Alex was repeated three times, then the output array should only have Alex.
function writeIn($ballot) {
$count = array_count_values($ballot);
arsort($count);
foreach($count as $c => $name) {
$arr[] = $name;
}
}
Three problems with your current function.
$name and $c are reversed in the foreach loop. The names will be the keys
The loop doesn't stop after it gets the top counts
The function doesn't return anything.
You can fix it like this:
After you count and sort with
$count = array_count_values($ballot);
arsort($count);
you can get the max value by taking the first value from the rsorted counts.
$max = reset($count);
Then as you iterate, when you reach a name with a count !== the max count, break out of the loop.
foreach($count as $name => $c) {
if ($c !== $max) break;
$arr[] = $name;
}
And don't forget to return the result.
return $arr;
Another possibility is to use some built-in PHP functions. I agree starting with array_count_values() seems like a good idea.
$count = array_count_values($ballot);
After that you can get the max count using max()
$max = max($count);
Filter the counts to return only items with the max count
$top = array_filter($count, function($n) use ($max) {
return $n == $max;
});
// PHP 7.4 version
// $top = array_filter($count, fn($n) => $n == $max);
And return the keys from that array to get the names.
return array_keys($top);
This solution keeps track as it goes.
function writeIn($ballot) {
$tally = []; // How many votes did each person get
$choice = []; // List of names with max occurrences
$max = 0;
array_walk($ballot, function($item) use(&$choice, &$tally, &$max) {
if ( ! array_key_exists($item, $tally) ) {
// If we haven't seen this name, add it with a count of 1
$tally[$item] = 1;
} else {
// We saw this name already so increment its count
$tally[$item]++;
}
// Check to see if the current name has exceeded or reached max
if ( $tally[$item] > $max ) {
// This is a new max so replace the choice list with this name
$choice = [$item];
$max = $tally[$item];
} elseif ( $tally[$item] == $max ) {
// This name has reached the current max so add it to the list
$choice[] = $item;
}
});
// Now we have the list of names with the most occurrences.
return $choice;
}
Don't Panic's answer is a good one. There is also an optional search parameter to array_keys() to pass a search parameter which is applicable to this problem. Once you have the results sorted by count, and you know the max count, you can use that parameter to only return keys(name)s that match the associated count value.
<?php
$ballot = ['Alex', 'Michael', 'Harry', 'Dave', 'Michael', 'Victor', 'Harry', 'Alex', 'Mary', 'Mary'];
function writeIn($ballot) {
$count = array_count_values($ballot);
arsort($count);
$max = reset($count);
return array_keys($count, $max);
}
var_dump( writeIn($ballot));
Returns:
array(4) {
[0]=>
string(4) "Alex"
[1]=>
string(7) "Michael"
[2]=>
string(5) "Harry"
[3]=>
string(4) "Mary"
}
I'm trying to make a genetic calculator. I have the following code:
<?php
$gene1 = 'BA';
$geneA = array();
$i = 0;
while ($i < strlen($gene1)) $geneA[] = substr($gene1,$i++,2);
$gene2 = 'MSBA';
$geneB = array();
$i = 0;
while ($i < strlen($gene2)) $geneB[] = substr($gene2,$i++,2);
$possabilities = array();
foreach ($geneA as $A) {
foreach ($geneB as $B) {
if ($A === strtoupper($A)) $possabilities[] = $A.$B;
else {
if ($B === strtoupper($B)) $possabilities[] = $B.$A;
else $possabilities[] = $A.$B;
}
}
}
print_r($possabilities);
?>
Which works to a degree, it pairs the genes in the array, however it isn't working properly. This pairing should just return BABA and MSBA. Instead it returns this:
Array ( [0] => BAMS [1] => BASB [2] => BABA [3] => BAA [4] => AMS [5] => ASB [6] => ABA [7] => AA )
Which isn't exactly ideal for my project. I thought a better idea would be to comma separate the genes like this $gene1 = 'BA'; and $gene2 = 'MS,BA'; and run a loop combining each gene that way, but i am unsure on how to do this properly. Can anyone shed some light on the idea at all?
I hope I'm right in assuming that
Genes are always made up of two pairs (MS, but not "M" and "S")
Each member of $geneA should be matched with each member of $geneB
Part 1: Resolving the error
In this case your algorithm for splitting has a serious flaw: It always progresses just for one step in the original string ($gene1 and $gene2)
function getGeneArray($geneString) {
// check the argument for fitting your needs!
if ( strlen($geneString) % 2 == 1 ) {
die('Supplied geneString is not made of pairs!'); // better not die - handle errors according to your application methodology
}
// add additional error-catching (there are only certain possible base-pairs, if something else is found you should reject the string
$genes = array();
$i = 0;
while ( $i < strlen($geneString) )
{
$genes[] = substr($geneString, $i, 2);
$i += 2; // Here is your mistake, you just $i++
}
return $genes;
}
With this little function you a) reduce duplicates in your code and b) get a determined outcome (no wrong genes)
Part 2: Making code document itself
Looking at your code it becomes clear, that uppercase-gene-pairs must come befor lowercase pairs, I try to communicate that with the code by using an extra function with a clear name.
function combinePairs($A, $B) {
// uppercase genes build the string first, which means B must be uppercase to come first and A cant be uppercase
if (strtoupper($A) !== $A && strotoupper($B) === $B) {
return $B.$A;
}
return $A.$B;
}
Part 3: Plugging it together
$geneA = getGeneArray($gene1);
$geneB = getGeneArray($gene2);
$possibilities = array();
foreach ($geneA as $A) {
foreach ($geneB as $B) {
$possibilities[] = combinePairs($A, $B);
}
}
print_r($possibilities);
Final Note
As a programmer you want to cater the needs of your client or input source, so of course you can split your genes with commas. Try to use the format most usable for your application and client input. In this case you could easily optain an array by using explode() (explode in the manual)
I would like to put a number separately in an array
ex.
$num = 345;
should be in an array so i can call the numbers as
$num[1] (which should return 4)
I tried str_split($num,1) but without succes.
Thanks
EDIT -------
After some more research str_split($num,1) actually did the trick.
(thanks, Crayon Violent)
$num = 345;
$arr1 = str_split($num); print_r($arr1); //Array ( [0] => 3 1 => 4
[2] => 5 )
echo $arr11; //4
str-split
If you are just trying to get individual characters from the string, use substr.
$second_digit = substr( $num, 1, 1 );
while ($num >0) {
$arr[i] = $num %10;
$num = $num/10;
i++
}
//this leaves the array in reverse order i.e. 543
//to flip
array_reverse($arr);
For readability and perfomance reasons, I'd like to build up an array with a switch statement instead of if-statements.
Consider the following if-statement:
$size = 2;
$array = array();
if($size >= 1) { array_push($array,'one','foo'); }
if($size >= 2) { array_push($array,'two','bar','barista'); }
if($size >= 3) { array_push($array,'three','zoo','fool','cool','moo'); }
It basically counts up from 1 to $size, it might be more readable and most likely a lot faster with a switch-statment...but how do you construct that ??
$step = 2;
$array = array();
switch($step)
{
case ($step>1): array_push($array,'one','foo');
case ($step>2): array_push($array,'two','bar','barista');
case ($step>3): array_push($array,'three','zoo','fool','cool','moo');
}
I tried leaving out the break, which didn't work - as the manual says:
In a switch statement, the condition is evaluated only once[...].
PHP continues to execute the statements until the end of the switch
block, or the first time it sees a break statement.
Anyway, anyone got an idea how to build up such an array with a switch-statement ??
Surely what you want can be achieved much more easily using
$array=range(1,$size);
Based on further coments and subsequent edits, something like:
$baseArray = $array(array('one'),
array('two','twoA'),
array('three','threeA','threeB'),
array(),
array('five'),
);
$step=2;
$array = array_slice($baseArray,0,$step);
and then flatten $array
Well, a switch statement would look like:
edit: the above doesn't work - let me take a look.
but in this example, you could just do:
$size = 2;
$array = range(1, $size); // Array ( [0] => 1 [1] => 2 )
$valuesIWant = array(1=>'one','two','three','four');
$array = array();
for ($i = $step - 1; $i > 0; $i--) $array[] = $valuesIWant[$i];
$array = array_reverse($array);
So if $step is 2, you get:
Array
(
[0] => one
)
...and if it is 4, you get:
Array
(
[0] => one
[1] => two
[2] => three
)
update
I'm new to PHP development: I looked on the PHP website for a function - array_slice. I read and looked at the example but I don't understand it. Can someone explain this in clear words for me?
I think it works as follow?
$example = array(1,2,3,4,5,6,7,8,9);
$offset = 2;
$length = 5;
$newArray = array_slice($example, offset, length);
the result of $newArray is: $newArray(3,4,5,6,7);
In addition to stefgosselin's answer that has some mistakes: Lets start with his array:
$input = array(1,2,3);
This contains:
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
Then you do array_slice:
var_dump(array_slice($input, 1));
The function will return the values after the first element (thats what the second argument, the offset means). But notice the keys!
array(2) {
[0]=> int(2)
[1]=> int(3)
}
Keep in mind that keys aren't preserved, until you pass true for the fourth preserve_keys parameter. Also because there is another length parameter before this, you have to pass NULL if you want to return everything after the offset, but with the keys preserved.
var_dump(array_slice($input, 1, NULL, true));
That will return what stefgosselin (incorrectly) wrote initially.
array(2) {
[1]=> int(2)
[2]=> int(3)
}
This function returns a subset of the array. To understand the example on the man page you have to understand array keys start at 0, ie
$array_slice = $array(1,2,3);
The above contains this:
$array[0] = 1,
$array[1] = 2,
$array[2] = 3
So, array_slice(1) of $array_sliced would return:
$arraysliced = array_slice($array_slice, 1);
$arraysliced[1] = 2;
$arraysliced[2] = 3;
It returns the part of your input array that starts at your defined offset, of the your defined length.
Think of it this way:
$output = array();
for ($i = 0; $i++; $i < count($input)) {
if ($i < $start)
continue;
if ($i > $start + $length)
break;
$output[] = $input[$i];
}
Basically its an skip and take operation. Skip meaning to jump to that element. Take meaning how many.
PHP has a built - in function, array_slice() , that you can use to extract a range of elements from an
array. To use it, pass it the array to extract the slice from, followed by the position of the first element in
the range (counting from zero), followed by the number of elements to extract. The function returns a new
array containing copies of the elements you extracted (it doesn ’ t touch the original array). For example:
$authors = array( “Steinbeck”,
“Kafka”, “Tolkien”, “Dickens” );
$authorsSlice = array_slice(
$authors, 1, 2 ); // Displays “Array
( [0] = > Kafka [1] = > Tolkien )”
print_r( $authorsSlice );
By the way, if you leave out the third argument to array_slice() , the function extracts all elements
from the start position to the end of the array:
$authors = array( “Steinbeck”, “Kafka”, “Tolkien”, “Dickens” );
$authorsSlice = array_slice( $authors, 1 );
// Displays “Array ( [0] = > Kafka [1] = > Tolkien [2] = > Dickens )”;
print_r( $authorsSlice );
Earlier you learned that array_slice() doesn ’ t preserve the indices of elements taken from an indexed
array. If you want to preserve the indices, you can pass a fourth argument, true , to array_slice() :
$authors = array( “Steinbeck”, “Kafka”, “Tolkien”, “Dickens” );
// Displays “Array ( [0] = > Tolkien [1] = > Dickens )”;
print_r( array_slice( $authors, 2, 2 ) );
// Displays “Array ( [2] = > Tolkien [3] = > Dickens )”;
print_r( array_slice( $authors, 2, 2, true ) );