PHP code to find first covering prefix of an array - php

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;
}

Related

Find index if values in single array on either side are equal when summed

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.

More efficient way to write this PHP code, and how to instantiate PHP array similar to Python list

I did a training exercise (ranked as easy), and the question is here, and my answer in PHP below.
function solution($X, $A) {
// write your code in PHP7.0
$inplace = []; # positions in place to our goal, space O(X). Index by position number 0..$X
foreach ($A as $k => $pos) {
# time O(N) - array of N integers
if ($pos <= $X) { # we are only interested in positions within $X
# count positions - but store the first $k key seconds which this position is reached.
# We are not interested in when the second leaf of this same position falls.
if (!isset($inplace[$pos])) $inplace[$pos] = $k;
}
}
$maxk = -1; # max key value which is the longest time for the needed leaf to fall
for ($i=1; $i <= $X; $i++) {
# go through every position
if (isset($inplace[$i])) {
$tempk = $inplace[$i]; //k seconds for this leaf to fall
$maxk = ($tempk > $maxk) ? $tempk : $maxk;
}
else return -1; # if this position is not set, the leaf does not fall, so we exit
}
return $maxk;
}
My questions:
1) Is there a better way you would write the code? I'm focusing on time complexity and simplicity of code, so any feedback is welcome.
2) In this training material - an example if given in Python for def
counting(A, m) to count instances of an array. I used this concept in my solution, in PHP, where the index of the array was the value. In PHP, is there a way to instantiate an array as done in Python? I imagine in PHP, I'd use isset() in my code when processing the array count result, without actually instantiating a whole array of (m+1) elements, or is there actually a way to get the below line working in PHP?
count = [0] * (m + 1) # Python code for list (array) instantiation of (m+1) elements.
# How do we do this in PHP?
Thanks very much!
1) A simpler and more efficent way to write this function would be using one for loop and a counter. Just loop over 1 - $X, and track the position of the items with array_search.
function solution($X, $A){
$p = 0;
for($i=1; $i<=$X; $i++) {
$k = array_search($i, $A);
if($k === false)
return -1;
if($k > $p)
$p = $k;
}
return $p;
}
Even though array_search is slower than isset this solution is much faster (with the given parameters) and it doesn't create an extra array for mapping the leaf positions.
2) Python has great tools for working with lists (concatenation, repetition, comprehensions, etc) which are not avaliable in PHP and other languages.
But you can achieve something similar with array_fill, ie: $count = array_fill(0, $m+1, 0);
The above function 'translated' to python would be:
def solution(X, A):
p = 0
for i in range(1, X+1):
if i not in A:
return -1
v = A.index(i)
if v > p:
p = v
return p

Reducing a multi-dimensional array

I have an array that carries a definite number of dimensions so I'm not really looking at something recursive (Unless maybe for maintainability sake in the future). It's a numeric array gotten from the database with each row holding another array. Each of those level 2 arrays contain strings like
var1, var2 , var3
And so on. Note the irregular appearance of commas in the string. So I intend to break the comma delimited string in the third level then log them in the final array but I get an error saying I am supplying an null array. So I want to know why it says the array is null and how I can make it recognise that as a valid array. My code goes below:
function fetch_each($arr) {
$temp = array();
for ($i = 0; $i < count($arr); $i++) {
for ($j = 0; $j < count($arr[$i]); $j++) {
array_reduce(preg_split("/[\s,]+/", $arr[$i][$j]), function($a, $b) {
return array_push($temp, $a, $b);
});
}
}
return $temp;
}
PS: Please don't mark as duplicate. I don't want to copy someone else's code but want to understand why this does not work. Thanks.
You have this problem because $temp is not visible in the function block.
To solve that, you must use the keyword use (variable_name) next to the function definition as in this example :
array_reduce(preg_split("/[\s,]+/", $arr[$i][$j]), function($a, $b) use (&$temp) {
return array_push($temp, $a, $b);
});
Just a remark, $a will contain the result of array_push
Returns:int the new number of elements in the array.
So you can remove it from the array_push() instruction to keep a clean array with only splitted strings

php unique randomized numbers array with exception

I'm trying to generate a unique randomized array with exceptions,
i got this far:
function rand_except($min, $max,$no_numbers, $except) {
//loop until you get a unique randomized array without except number
$end=false;
while (!$end){
$numbers = rand_array($min, $max,$no_numbers);//get unique randomized array
if(!in_array($except,$numbers)){
$end=true;
break;
}
}
return $numbers;
}
but now i want the function to loop until the except parameter isn't in the array
I suspect it would be easier to solve this problem by updating the rand_array function (or writing a modified version of it) to generate the array without the $except value to start with.
If that is not an option, here is one possible solution that doesn't involve calling the rand_array function over and over again:
$numbers = rand_array($min, $max-1, $no_numbers);
for ($i = 0; $i < count($numbers); $i++) {
if ($numbers[$i] >= $except) {
$numbers[$i] += 1;
}
}
You call the rand_array function but specify one less than the actual maximum number you want in the array. Then you loop over the results, and any value that is greater than or equal to the $except value, you increment by 1.
This is assuming that the $except value is in the range $max to $max. If not, you can just return rand_array($min, $max, $no_numbers); as is.

check if two different values exists in a php array

Let's say I have a php array that could be all 1s, all 2s or all 1s and 2s. For example I could have array(1, 1, 1, 1, 1, 1), or array(2, 2, 2, 2, 2, 2) or array(2, 2, 1, 1, 2, 1).
How do I check if my array actually is an array of all 1s, all 2s or if my array actually contains both 1s and 2s?
In case you wanted to know for PHP, you can use array_unique() to probe which distinct values exist:
if (count(array_unique($array)) == 1) {
// It's either full of 1s or 0s.
// Then just probe the first entry.
}
You could add all the values in the array together. If they equal the length of the array or they equal 0 they are all 1s or all 0s.
The simplest way is to just count the number of ones and zeroes. For example (in python):
ones = zeroes = 0;
for i in range(len(my_array)):
if my_array[i] == 1: ones = ones + 1
else zeroes = zeroes + 1
You can also multiply each element together (1 if all ones) and add each element in the array (0 if all elements are zero)
In Java ...
public static void allTheSame(int[] array) {
for (int i = 1; i < array.length; i++) {
if (array[i] != array[i - 1]) {
return false;
}
}
return true;
}
This algorithm can be transcribed into the other listed languages, though their may be neater ways to do it in some. (But watch out for the efficiency of the neat solutions ... if that matters to your application.)
Note that this approach will deliver a false result faster than any neat solution that involves collating or summing the array elements, and it makes no assumption about what the element values are.
Note: this answer was written when the tagging indicated that the OP wanted solutions in Java, Javascript and PHP. Check the Question's edit history ...
You can do it with a simple if-statement. Here's some JavaScript:
if (myArray.indexOf(1) > -1) {
// there are 1s, are there 0s?
if (myArray.indexOf(0) > -1) {
console.log("1s and 0!");
} else {
console.log("Only 1s.");
}
} else {
console.log("Only 0s.");
}
Working example: http://jsfiddle.net/daNEH/
Try this code:
int[] intArray = new int[5];
boolean hasZero, hasOne, hasBoth;
for(int integer : intArray)
{
switch(integer)
{
case 0:
hasZero = true;
break;
case 1:
hasOne = true;
break;
}
}
hasBoth = hasZero && hasOne;
function allElementsEqual(array){
var start = array[0],
same = true;
for(i = 1;i < array.length;i++){
same &= (start === array[1]);
}
return same;
}
This function should do the job fine http://jsfiddle.net/WNxg4/
Another way would be to use array_diff, provided you only had two different numbers. Just compare the haystack of numbers to an array with a single number (pick one of the ones in the haystacks).
For example:
$haystack_mixed = array(2,2,2,1,1);
$haystack_1 = array(1,1,1,1);
$haystack_2 = array(2,2,2,2);
print_r(array_diff($haystack_mixed, array(1)));
// The result is not the same as the $haystack since there are 1's in it.
// Array ( [0] => 2 [1] => 2 [2] => 2 )
print_r(array_diff($haystack_1, array(1)));
// This one is made up of all 1's
// Array ( )
print_r(array_diff($haystack_2, array(1)));
// This one is made up of all 2's (same length as $haystack_2)
// Array ( [0] => 2 [1] => 2 [2] => 2 [3] => 2 )
So you can test the length of the resulting array.
I think you could use the array_sum or array_filter functions for this.
I have read the 9 answers and they're all pretty fancy, I think just go with the simplest way.
is_mixed($array){
$count = count($array);
//we go trough every element in the array
for($i=1;$i<$count;$i++){
//if the element n is distinct from the n-1
//then return true (is_mixed)
if ($array[$i] != $array[$i-1]) return true;
}
//if it didn't return anything yet, it means
//all the elements are the same. Then, just
//return the first one, as they're all the same
// (either 1 or 2)
return $array[0];
}
this second one I actually like the most:
function what_they_are($array){
$total = array_sum($array);
$count = count($array);
if ($total == 0) {
return "they're all 0";
}else if ($total/$count == 2){
return "they're all 2";
}else if ($total == $count){
return "they're all 1";
}else{
return "they're mixed";
}
}

Categories