Return the smallest positive integer - php

function solution($A);
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
Below is my attempt:
function solution($A) {
// write your code in PHP7.0
$n=1;
while($n > 0 && $n <= 1000000)
$n ++;
echo $A=$n+1;
}
echo solution;
?>```

Try this, no loop required:
<?php
function solution($set) {
$diff = array_diff(range(1, max($set)), $set);
sort($diff);
return !isset($diff[0]) ? max($set) + 1 : ($diff[0] < 1 ? 1 : $diff[0]);
}
echo solution([39, 68, 47, 2, 19, 64]); // 1
echo solution([1, 3, 6, 4, 1, 2]); // 5
echo solution([1, 2, 3]); // 4
echo solution([-1, -3]); // 1
https://3v4l.org/h28LZ

Here's a one-liner to either impress your professor or get kicked out of the class for not following instructions:
php > function solution(array $A) { return max(array(1,min(array_diff(range(1,100000),$A)))); }
php > echo solution([39, 68, 47, 2, 19, 64]);
1
php > echo solution([1,3,6,4,1,2]);
5
php > echo solution([-1,-3]);
1
php > echo solution([1,2,3]);
4
It generates array N (1-1,000,000) and runs array_diff against your input A, and returns either the lowest result from that comparison or 1 if it's less than or equal to 0.

function solution($A) {
$smallest = 1;
while(in_array($smallest, $A)){
$smallest++;
}
return $smallest;
}
Above is the smallest code but has O(N^2) Complexity with 66% success
function solution($A) {
$flipped = array_flip($A);
$smallest = 1;
while (isset($flipped[$smallest])){
$smallest++;
}
return $smallest;
}
Detected time complexity:
O(N) or O(N * log(N)) with 100% success rate

Related

How to efficiently sum paired array elements and avoid offset errors in case of pairless array?

Pair every two arrays is the task – store it, print it and repeat it until it becomes one value.
input : 1, 2, 3, 4, 5, 6, 8, 9, 9
output: 3 7 11 17 9
10 28 9
38 9
47
My code is working fine in this scenario. Somehow I managed to add 0 at the end for pairless elements. But my main focus is how can I make the logic even more clearer to avoid grumpy offset errors?.
My code:
function sumForTwos($arr)
{
if(count($arr) == 1){
exit;
}
else {
$sum = [];
for ($i = 0; $i < count($arr) -1; $i++)
{
//logic to add last array for odd count to avoid offset error
if(count($arr) % 2 == 1){ $arr[count($arr)] = 0; }
//logic to pair arrays
if($i != 0) { $i++; }
$sum = $arr[$i] + $arr[$i + 1];
$total[] = $sum;
echo $sum . " ";
}
echo "<br>";
$arr = $total;
//Recursion function
sumForTwos($arr);
}
}
sumForTwos([1, 2, 3, 4, 5, 6, 8, 9, 9]);
You can adopt an iterative approach and look at this as processing each level of values with every next level have 1 value less from total values. In other words, you can look at this as a breadth first search going level by level. Hence, you can use a queue data structure processing each level one at a time.
You can use PHP's SplQueue class to implement this. Note that we can advantage of this class as it acts as a double-ended queue with the help of below 4 operations:
enqueue - Enqueues value at the end of the queue.
dequeue - Dequeues value from the top of the queue.
push - Pushes value at the end of the doubly linked list(here, queue is implemented as doubly linked list).
pop - Pops a node from the end of the doubly linked list.
Most certainly, all the above 4 operations can be done in O(1) time.
Algorithm:
Add all array elements to queue.
We will loop till the queue size is greater than 1.
Now, if queue level size is odd, pop the last one and keep it in buffer(in a variable).
Add all pairwise elements by dequeueing 2 at a time and enqueue their addition for next level.
After level iteration, add the last element back if the previous level size was odd.
Print those added elements and echo new lines for each level accordingly.
Snippet:
<?php
function sumForTwos($arr){
if(count($arr) == 1){
echo $arr[0];
return;
}
$queue = new SplQueue();
foreach($arr as $val){
$queue->enqueue($val); // add elements to queue
}
while($queue->count() > 1){
$size = $queue->count();
$last = false;
if($size % 2 == 1){
$last = $queue->pop(); // pop the last odd element from the queue to make queue size even
$size--;
}
for($i = 0; $i < $size; $i += 2){
$first = $queue->dequeue();
$second = $queue->dequeue();
echo $first + $second," ";
$queue->enqueue($first + $second);
}
if($last !== false){// again add the last odd one out element if it exists
echo $last; // echo it too
$queue->push($last);
}
echo PHP_EOL;// new line
}
}
sumForTwos([1, 2, 3, 4, 5, 6, 8, 9, 9]);
Demo: http://sandbox.onlinephpfunctions.com/code/5b9f6d4c9291693ac7cf204af42d1f0ed852bdf9
Does this do what you want?
function pairBySums($inputArray)
{
if (sizeof($inputArray) % 2 == 1) {
$lastEntry = array_pop($inputArray); //$inputArray now has even number of elements
}
$answer = [];
for ($ii = 0; $ii < sizeof($inputArray) / 2; $ii++) {
$firstIndexOfPair = $ii * 2; // 0 maps to 0, 1 maps to 2, 3 maps to 4 etc
$secondIndexOfPair = $firstIndexOfPair + 1; // 0 maps to 1, 1 maps to 3, 2 maps to 5 etc
$answer[$ii] = $inputArray[$firstIndexOfPair] + $inputArray[$secondIndexOfPair];
}
if (isset($lastEntry)) {
array_push($answer, $lastEntry);
}
echo implode(' ', $answer) . "<br>";
if (sizeof($answer) > 1) {
pairBySums($answer);
}
}
The algorithm makes sure it operates on an even array and then appends the odd entry back on the array if there is one.
$input = [1, 2, 3, 4, 5, 6, 8, 9, 9];
pairBySums($input);
produces:
3 7 11 17 9
10 28 9
38 9
47
With an even number of items,
$input = [1, 2, 3, 4, 5, 6, 8, 9];
pairBySums($input);
produces:
3 7 11 17
10 28
38

PHP array slice from position + attempt to return fixed number of items

I'm looking for an efficient function to achieve the following. Let's say we have an array:
$a = [0, 1, 2, 3, 4, 5, 6, 7];
Slicing from a position should always return 5 values. 2 before the position index and 2 values after the position index - and of course, the position index itself.
If a position index is at the beginning of the array i.e. 0 (example 2), the function should return the next 4 values. Similarly, if the position index is at the end of the array (example 3), the function should return the previous 4 values.
Here's some examples of various indexes one could pass to the function and expected results:
$index = 3; // Result: 1, 2, 3, 4, 5. *example 1
$index = 0; // Result: 0, 1, 2, 3, 4. *example 2
$index = 7; // Result: 3, 4, 5, 6, 7. *example 3
$index = 6; // Result: 3, 4, 5, 6, 7. *example 4
As represented in examples: (example 1, example 4), the function should always attempt to catch tokens succeeding and preceding the position index - where it can, whilst always returning a total of 5 values.
The function must be bulletproof to smaller arrays: i.e if $a has 4 values, instead of 5, the function should just return everything.
Something like this?
#edit:
Sorry, I misread your original requirement. Second attempt:
function get_slice_of_5($index, $a) {
if ($index+2 >= count($a)) {
return array_slice($a, -5, 5)
}
else if($index-2 <= 0) {
return array_slice($a, 0, 5)
}
else return array_slice($a, $index-2, 5)
}
Create a start position by calculating where to start and use implode and array slice to return the string.
$a = [0, 1, 2, 3, 4, 5, 6, 7];
$index = 3; // Result: 1, 2, 3, 4, 5. *example 1
echo pages($a, $index) . "\n";
function pages($a, $index){
if($index >= count($a)-2){
$start = count($a)-5; // index is at end of array
}elseif($index <=2){
$start = 0; // index is at start
}else{
$start = $index-2; // index is somewhere in the middle
}
return implode(", ", array_slice($a, $start, 5));
}
https://3v4l.org/aNZsB
this is a "standalone" function to get spliced arrays of any size:
$a = [1,2,3,4,5,6,7,8,9];
echo "<pre>"; print_r(array_slicer($a, 2));
function array_slicer($arr, $start){
// initializations
$arr_len = count($arr);
$min_arr_len = 5; // the size of the spliced array
$previous_elements = 2; // number of elements to be selected before the $start
$next_elements = 2; // number of elements to be selected after the $start
$result = [];
// if the $start index doesn't exist in the given array, return false!
if($start<0 || $start>=$arr_len){
return false;
} elseif($arr_len <= $min_arr_len){ // if the size of the given array is less than the d size of the spliced array, return the whole array!
return $arr;
}
// check if the $start has less than ($previous_elements) before it
if($arr_len - ($arr_len - $start) < $previous_elements){
$next_elements += ($next_elements - ($arr_len - ($arr_len - $start)));
} elseif(($arr_len - 1 - $start) < $next_elements){ // check if the $start has less than ($next_elements) after it
$previous_elements += ($previous_elements - ($arr_len - 1 - $start));
}
for($i = ($start-$previous_elements); $i <= ($start + $next_elements); $i++){
if($i>-1 && $i<$arr_len){
$result[] = $arr[$i];
}
}
return $result;
}
You can define the bounds of where the array_slice() will begin by leveraging min() and max(). Assuming your array will always have at least 5 element, you can use:
array_slice($a, min(count($a) - 5, max(0, $index - 2)), 5)
The chosen index will be in the center of the sliced array unless it cannot be.
Dynamic Code: (Demo)
$a = [0, 1, 2, 3, 4, 5, 6, 7];
$count = count($a);
$span = 5; // most sensible with odd numbers
$center = (int)($span / 2);
foreach ($a as $i => $v) {
printf(
"%d: %s\n",
$i,
implode(
',',
array_slice(
$a,
min($count - $span, max(0, $i - $center)),
$span
)
)
);
}
Output:
0: 0,1,2,3,4
1: 0,1,2,3,4
2: 0,1,2,3,4
3: 1,2,3,4,5
4: 2,3,4,5,6
5: 3,4,5,6,7
6: 3,4,5,6,7
7: 3,4,5,6,7

BubbleSort doing something weird

I am slowly trying to figure out the implementation of bubble Sort, the concept is easy enough to understand. basically i have this far with it:
<?php
namespace TeamRock;
class BubbleSort
{
public function sort(array $integers)
{
if (count ($integers) > 0)
{
//if value of array is over one do this-->
for ($i = 0; $i<count($integers); $i++) //iterating through the array
{
for($j = 1; $j<count($integers);$j++)
{
//where the sorting happens
$holder = $integers[$j];
if ($integers[$j] < $integers[$j-1]){
$integers[$i] = $integers[$j-1];
$integers[$j-1] = $holder;
}
}
}
return $integers;
}
else{
return $integers;
}
}
}
Sudo Code-
//For each element in array
//Look at the element to direct right
//If the element on the left is greater than the element to the direct right
//Then we should swap these elements positions
//
//restart at start of loop until all numbers are numbered
Ok so thats the function, i wanted to write the function myself instead of using the built in php function. Im am also using phpspec to test these and have my variables defined in there heres the spec:
<?php
namespace phpspec\TeamRock;
use PhpSpec\ObjectBehavior;
class BubbleSortSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('TeamRock\BubbleSort');
}
function it_can_sort_an_array_of_four_integers()
{
$integers = [8, 4, 6, 2];
$this->sort($integers)->shouldReturn(['2, 4, 6, 8']);
}
function it_can_sort_an_array_of_five_integers()
{
$integers = [6, 11, 0, 9, 3];
$this->sort($integers)->shouldReturn([0, 3, 6, 9, 11]);
}
}
And when i run the spec this is what i get:
TeamRock/BubbleSort
15 - it can sort an array of four integers
expected [array:1], but got [array:4].
## -1,3 +1,6 ##
[
- 0 => ""2, 4, 6, 8"...",
+ 0 => 2,
+ 1 => 2,
+ 2 => 2,
+ 3 => 2,
]
17 $integers = [8, 4, 6, 2];
18
19 $this->sort($integers)->shouldReturn(['2, 4, 6, 8']);
20 }
21 function it_can_sort_an_array_of_five_integers()
22 {
0 vendor/phpspec/phpspec/src/PhpSpec/Matcher/IdentityMatcher.php:78
throw new PhpSpec\Exception\Example\NotEqualException("Expected [array:1]...")
1 [internal]
phpspec\TeamRock\BubbleSortSpec->it_can_sort_an_array_of_four_integers()
TeamRock/BubbleSort
21 - it can sort an array of five integers
expected [array:5], but got [array:5].
## -1,7 +1,7 ##
[
0 => 0,
- 1 => 3,
- 2 => 6,
- 3 => 9,
- 4 => 11,
+ 1 => 0,
+ 2 => 0,
+ 3 => 3,
+ 4 => 3,
]
23 $integers = [6, 11, 0, 9, 3];
24
25 $this->sort($integers)->shouldReturn([0, 3, 6, 9, 11]);
26 }
27 }
0 vendor/phpspec/phpspec/src/PhpSpec/Matcher/IdentityMatcher.php:78
throw new PhpSpec\Exception\Example\NotEqualException("Expected [array:5]...")
1 [internal]
phpspec\TeamRock\BubbleSortSpec->it_can_sort_an_array_of_five_integers()
71% 28% 7
2 specs
7 examples (5 passed, 2 failed)
19ms
Any help or pointer would be greatly appreciated
I do have an insertion sort working fine, thats why there are some passed, the ones that have failed are for the bubble.
Once again im very new to this so give me a little breathing space for missing any basic stuff. im trying to get this in my brain :P
There are some errors in your code. First, the algorithm:
$holder = $integers[$j];
if ($integers[$j] < $integers[$j-1]){
$integers[$i] = $integers[$j-1];
$integers[$j-1] = $holder;
}
The second assignment above should read:
$integers[$j] = $integers[$j-1];
because you are swapping $integers[$j] with $integers[$j-1] if they are in the wrong order (I am sure this is just a typo).
This error probably makes the second test case in the specs fail.
The first test case:
function it_can_sort_an_array_of_four_integers()
{
$integers = [8, 4, 6, 2];
$this->sort($integers)->shouldReturn(['2, 4, 6, 8']);
}
should read:
$this->sort($integers)->shouldReturn([2, 4, 6, 8]);
Notice this is an array of four integers while your code checks the result against an array containing one string.
Further improvements:
You run count($integers) passes through the array checking for pairs of neighbour values that are in the wrong order. While this is the maximum number of passes needed, a lot of times it completes earlier.
A better implementation is to keep a flag that remembers after each pass if there was and swapping done and exit the loop when there was none (because the array is already sorted).
Something like this:
public function sort(array $integers)
{
// Call count() only once before the loop because it doesn't change
$count = count($integers);
do {
// Didn't swap any neighbour values yet in this loop
$swapped = FALSE;
// Run through the list, swap neighbour values if needed
for ($j = 1; $j < $count; $j ++)
{
// Check neighbour values
// Initialize $holder only when it is needed (to swap values)
if ($integers[$j] < $integers[$j - 1]) {
// Swap the values
$holder = $integers[$j];
$integers[$i] = $integers[$j - 1];
$integers[$j - 1] = $holder;
// Remember we did at least one swap on this pass
$swapped = TRUE;
}
}
// Keep passing through the array while at least one swap was done
// When there was no swap then the values are in the desired order
} while ($swapped);
// Return the sorted array
return $integers;
}
first of all using bubble sort is not a very good idea. It has complexity of O(n^2). You should use php usort, which is actually a merge sort implementation O(n*log(n)) complexity or you can implement it by yourself.
Anyway, your bubble sort is wrong, you are confusing indexes.
Try this:
public function bubbleSort(array $numbers)
{
for ( $i = 0; $i < count($numbers); $i++ ) {
for ($j = 0; $j < count($numbers) $j++ ) {
if ($numbers[$i] < $numbers[$j]) {
$temp = $numbers[$i];
$numbers[$i] = $numbers[$j];
$numbers[$j] = $temp;
}
}
}
return $numbers;
}

All combinations without repetitions with specific cardinality

I have an array:
[a, b, c, d, e, f, ... , z]
and I would generate the set of all possible subarrays, withuout repetition, whose cardinality is between X and Y.
Let's assume php:
$array = array(1, 2, 3, 4, 5, 6, 7, 8);
$results = myFunction($array, 3, 5);
My function should returns something like:
array(
array(1, 2, 3),
array(1, 2, 4),
...
array(4, 5, 6, 7, 8),
);
My attempt was to count in binary, from 0 to 2^n (where n is the cardinality of the set) and if the number of 1s is between X and Y, add the array made of 1s element to the result set.
Eg.
8 = 0000 0111 => add (6,7,8) to result
9 = 0000 1000 => no
10 = 0000 1001 => no
...
but it's very ugly!
Any better algorithm?
I'm using php, but feel free to use whatever language you like.
A pretty straightforward solution (requires generators, I think, it's php 5.5+)
// generate combinations of size $m
function comb($m, $a) {
if (!$m) {
yield [];
return;
}
if (!$a) {
return;
}
$h = $a[0];
$t = array_slice($a, 1);
foreach(comb($m - 1, $t) as $c)
yield array_merge([$h], $c);
foreach(comb($m, $t) as $c)
yield $c;
}
and then
$a = ['a','b','c','d','e','f', 'g'];
foreach(range(3, 5) as $n)
foreach(comb($n, $a) as $c)
echo join(' ', $c), "\n";

Default php function that turns negative numbers in 0

Is there such a thing?
for eg
$var = -5;
echo thefunction($var); // should be 0
$var = 5;
echo thefunction($var); // should be 5
Try max($var,0), which will have the desired effect. See the manual page for more information.
Not built-in but, here you have:
function thefunction($var){
return ($var < 0 ? 0 : $var);
}
Hope this helps
In PHP, checking if a integer is negative and if it is then setting it to zero is easy, but I was looking for something shorter (and potentially faster) than:
if ($x < 0) $x = 0;
Well, this is a very quick check and reset, but there is a function max that does this too and it works with arrays too.
$x = max(0, $x); // $x will be set to 0 if it was less than 0
The max() function returns the number with the highest value of two specified numbers.
echo max(1, 3, 5, 6, 7); // 7
echo max(array(2, 4, 5)); // 5
echo max(0, 'hello'); // 0
echo max('hello', 0); // hello
echo max(-1, 'hello'); // hello
// With multiple arrays, max compares from left to right
// so in our example: 2 == 2, but 4 < 5
$val = max(array(2, 4, 8), array(2, 5, 7)); // array(2, 5, 7)
// If both an array and non-array are given, the array
// is always returned as it's seen as the largest
$val = max('string', array(2, 5, 7), 42); // array(2, 5, 7)
function thefunction($number){
if ($number < 0)
return 0;
return $number;
}
that should do the trick
Simply:
echo $var < 0 ? 0 : $var;

Categories