Let's say the following is true:
I have an associative array containing an unknown number of elements.
The keys are integers, starting at 1, and each is one more than the last.
There is an element with key N whose value is 1.
The value of each element with a key less than N is 0.
The value of each element with a key greater than N is 1.
This is the array:
The question is :
What is the fastest/smartest way to find the position of the first '1' in the array?
If you truly don't know the length of the array (a very odd situation), then probably all you can do is grow your search geometrically, i.e. skip 4, skip 8, skip 16, etc. until you find a 1, then cut back with a (geometric) binary search.
array_search is your best bet
// Make up some data...
$data = [];
for ($i = 1; $i <= 20; ++$i) {
$data[$i] = rand(0,5);
}
var_dump($data);
// Find the first one...
echo 'The first 1 is at position: ' . array_search(1, $data);
http://php.net/manual/en/function.array-search.php
Related
I have a whiteboard question that I think is way beyond my skill and so don't even know how to approach this.
I want to iterate through each value and sum the elements on left/right side and if they're equal return the index value.
So:
[1, 2, 3, 4, 3, 2, 1]; // return 3
The official question:
You are going to be given an array of integers. Your job is to take
that array and find an index N where the sum of the integers to the
left of N is equal to the sum of the integers to the right of N. If
there is no index that would make this happen, return -1.
Is anyone kind enough to help me out? I've looked at array_map() and array_filter() and while helpful I can't think of how to traverse back and forth between the current index when iterating the array.
This can be done with a simple for loop over the full range of an array combined with array_slice and array_sum.
function doSomething(array $data): int {
for ($i = 0, $count = count($data); $i < $count; $i++) {
$left = $i > 0 ? array_slice($data, 0, $i) : [ $data[0] ];
$right = $i > 0 ? array_slice($data, $i + 1) : $data;
$left_result = array_sum($left);
$right_result = array_sum($right);
if ($left_result === $right_result) {
return $i;
}
}
return -1;
}
This small piece of code loops over the whole array and sums up the left and the right of the current position of the array. The results will be compared and if the results are the same, the key of the array will be returned.
For huge arrays you can try to reduce memory consumption by using a yield or an Iterator instance.
$players = array(
array('Lionel Messi', 'Luis Suarez', 'Neymar Jr'),
array('Ivan Rakitic', 'Andres Iniesta', 'Sergio Busquets'),
array('Gerrard Pique', 'Mascherano', 'Denis Suarez', 'Jordi Alba'),
array('MATS'),
array('Arda Turan', 'Munir El Hadadi', 'Umtiti')
);
Now i am trying to echo the number of all the elements within the boundary of this array $players. For example, there are 3 elements in the first, 3 in the second. There are 4 elements in the third, 1 element in the 4th and 3 elements in the last one. Altogether these elements are 14 elements. Now i want to display 'Total Players: 14'. I can show the number of categories (5) using count() function but can't count the total elements(14). I tried different approaches but couldn't succeed.
count() should be able to do this for you directly, using the COUNT_RECURSIVE flag:
$playerCount = count($players, COUNT_RECURSIVE) - count($players);
// $playerCount is now equal to 14
The subtraction of the normal count is because counting recursively adds the keys of the outer array in to the sum of elements, which just needs to be subtracted from the recursive count.
The native count() method can do that.
$count = count($players, COUNT_RECURSIVE) - count($players);
Because the recursive count will also count the number of $player groups you have, you have to subtract that number from the recursive count.
From the php documentation for count:
If the optional mode parameter is set to COUNT_RECURSIVE (or 1), count() will recursively count the array. This is particularly useful for counting all the elements of a multidimensional array.
One other way, pretty self-explanatory:
$count = array_sum(array_map('count', $players));
$count=0;
foreach($players as $row) $count+=count($row);
$count is now 14.
Live demo
You can use:
count($array, COUNT_RECURSIVE);
check count manual
Declare a variable initialised to 0 to accumulate the number of elements. Then, iterate the first array (which contains the other arrays), and for each element (which is also an array) use count() to obtain the number of elements and add that value to the accumulator variable.
$num_players = 0;
foreach($players as $row) {
$num_players += count($row);
}
Suppose i have an array
$x= ('A'=>31, 'B'=>12, 'C'=>13, 'D'=>25, 'E'=>18, 'F'=>10);
I need to generate an array somewhat like this
$newx = (0 => array('A'=>31 , 'B' =>1) , 1 => array('B'=>11 , 'C' =>13 , 'D'=>8) , 2 =>array('D'=>17 , 'E'=>15) , 3=>array('E'=>3,'F'=>10);
Now in this case each value of $newx has to be = 32 and this is how it will work $x[A] = 31 , $x[B] = 12 so first of all we have to make the sum quantity to be 32 keeping the index same for the new array i.e
array(0=>array('A'=>31,'B'=>1) , 1=>array('B'=>11) )
the process should continue for each value of $x.
while I'm pretty sure this is a homework assignment and well, you really should provide code of your own, at least try to, I found the thing amusing so I went ahead and gave it a try. I guess I'll be downvoted for his and I probably do deserve it, but here goes anyway.
What you need to do is:
loop through your array,
determine the elements that give you 32 and then store that result in the final array.
subtract the value of the last element from your result from the corresponding element of your working array
shrink your array next by deleting the first elements until the very first element of the array you're still working with equals the last element your last result returned.
if your last result < 32, quit.
With this in mind, please try to find a solution yourself first and don't just copy-paste the code? :)
<?php
$x = array('A'=>31, 'B'=>12, 'C'=>13, 'D'=>25, 'E'=>18, 'F'=>10);
$result = array();
function calc($toWalk){
// walk through the array until we have gathered enough for 32, return result as an array
$result = array();
foreach($toWalk as $key => $value){
$count = array_sum($result);
if($count >= 32){
// if we have more than 32, subtract the overage from the last array element
$last = array_pop(array_keys($result));
$result[$last] -= ($count - 32);
return $result;
}
$result[$key] = $value;
}
return $result;
}
// logic match first element
$last = 'A';
// loop for as long as we have an array
while(count($x) > 0){
/*
we make sure that the first element matches the last element of the previously found array
so that if the last one went from A -> C we start at C and not at B
*/
$keys = array_keys($x);
if($last == $keys[0]){
// get the sub-array
$partial = calc($x);
// determine the last key used, it's our new starting point
$last = array_pop(array_keys($partial));
$result[] = $partial;
//subtract last (partial) value used from corresponding key in working array
$x[$last] -= $partial[$last];
if(array_sum($partial) < 32) break;
}
/*
reduce the array in size by 1, dropping the first element
should our resulting first element not match the previously returned
$last element then the logic will jump to this place again and
just cut off another element
*/
$x = array_slice($x , 1 );
}
print_r($result);
Lets say i have an array in PHP
$test['michael_unique_id'] = 3;
$test['john_unique_id'] = 8;
$test['mary_unique_id'] = 10;
.
.
.
.
$test['jimmy_unique_id'] = 4;
(the values (3,8,10.........4) are unique)
Lets say i want to search for the unique id 10, and get the order of the matching element in the array. In this example, the third element has the value 10, so i should get the number 3.
I can do it by scanning with a for loop looking for the value i'm searching and then get the $i value when i have a match, but i wonder if there is any built-in function (or a better method) that implements this.
You can get all of the array's values as an array with array_values() and then use array_search() to get the position (offset) of that value in the array.
$uniq_id = 10;
$all_vals = array_values($test); // => array(3, 8, 10, ... )
echo array_search( $uniq_id, $all_vals ); // => 2
Because PHP array indices are zero-based, you'll get 0 for the first item, 1 for the second item, etc. If you want the first item to be "1," then just add one. All together now:
$uniq_id = 10;
echo array_search( $uniq_id, array_values( $test ) ) + 1; // => 3
It's not clear to me, however, that this is necessarily as performant as just doing a foreach:
$uniq_id = 10;
$idx = 1;
foreach($test as $val) {
if($val == $uniq_id) {
break;
}
$idx++;
}
echo $idx; // => 3
Well, array_search will give you the key, but in your case, you want the index of that key, so I believe a loop is your best bet. Is there a good reason why you need the index? It doesn't seem very useful to me.
A non-empty zero-indexed array A consisting of N integers is given. The first covering prefix of array A is the smallest integer P such that $0 \leq P < N$ and such that every value that occurs in array A also occurs in sequence $A[0], A[1], \ldots, A[P]$.
For example, the first covering prefix of array A such that
A[0]=2 A[1]=2 A[2]=1 A[3]=0 A[4]=1
is 3, because sequence A[0], A[1], A[2], A[3] equal to 2, 2, 1, 0 contains all values that occur in array A.
Write a function
int ps(int[] A);
that given a zero-indexed non-empty array A consisting of N integers returns the first covering prefix of A. Assume that $N <= 1,000,000$. Assume that each element in the array is an integer in range [0..N-1].
For example, given array A such that A[0]=2 A[1]=2 A[2]=1 A[3]=0 A[4]=1
the function should return 3, as explained in the example above.
This is a very short solution. Pretty but won't scale well.
function ps($A) {
$cp = 0; // covering prefix
$unique = array_unique($A); // will preserve indexes
end($unique); // go to end of the array
$cp = key($unique); // get the key
return $cp;
}
Here's a simple way :
function covering_prefix ( $A ) {
$in=array();
$li=0;
$c=count($A);
for($i=0 ;$i<$c ; $i++){
if (!isset($in[$A[$i]])){
$in[$A[$i]]='1';
$li=$i;
}
}
return $li;
}
Here is a solution using ruby
def first_covering_prefix(a)
all_values = a.uniq
i = 0
a.each do |e|
all_values.delete(e)
if all_values.empty?
return i
end
i = i + 1
end
end
it's a 83% answer, because of use of in_array, a better solution already proposed by ronan
function solution($A) {
// write your code in PHP5
$in=array();
$li=0;
for ($i=0; $i < count($A); $i++) {
# code...
if (!in_array($A[$i], $in)){
$in[]=$A[$i];
$li=$i;
}
}
return $li;
}