I was giving codility.com a try. For the test "PermMissingElem" on https://codility.com/programmers/lessons/1
I wrote a PHP solution which is not very nice, but still works for all my test cases.
Codility only gives me 20% telling me about several test cases that failed. Here are some of them.
For example:
empty_and_single
empty list and single element 0.050 s. RUNTIME ERROR
tested program terminated unexpectedly
stdout:
Invalid result type, int expected.
missing_first_or_last
the first or the last element is missing 0.050 s. RUNTIME ERROR
tested program terminated unexpectedly
stdout:
Invalid result type, int expected.
single
single element 0.050 s. RUNTIME ERROR
tested program terminated unexpectedly
stdout:
Invalid result type, int expected.
I know this test has been solved here before I just wonder what exactly their tests mean and why my solution fails on them.
Here is my solution PHP code:
function solution($A) {
$noe = count($A);
if($noe == 0)
return 1;
for($i=1;$i<=$noe;$i++)
{
if(!in_array($i,$A,TRUE))
return $i;
}
}
Your solution doesn't return any result, when the last element is missing. For example with array [1] correct result is 2, but your function doesn't return anything.
Another example: with array [1, 2] your solution doesn't return anything, but should return 3.
I think you won't have any problems with fixing this bug. Although you will have performance problems.
This is in C#, my program gave 100% correct and 100% performance.
Array.Sort(A);
if(A.Length == 0 )
{
return 1;
}
else
{
for(int i=0;i<A.Length;i++)
{
if(A[i] != i+1)
{
return i+1;
}
}
}
return A.Length + 1;
This is my 100% php solution to PermMissingElem in codility, is very simple, just name your variables properly:
function solution($A) {
// write your code in PHP5.5
sort($A);
$index = 0;
foreach($A as $value)
{
$expected = $index+1;
if ($expected != $value) return $expected;
$index++;
}
return $index+1;
}
Related
While working on a kata for Codewars, I am coming across an error when printing a value. Although the output of the code looks fine, I am getting the error that Array (...) does not match expected type "NULL".
Any ideas what I can change in my code to return a string?
function reverseSeq ($n) {
$n = range($n, 1);
foreach($n as $i) {
if ($i > 1) {
print_r ($i.",");
$i--;
} else {
print_r ($i);
}
}
}
The output, when $n is 3, prints 3,2,1 as it should. However, it should return as a string rather than an integer.
For Codewars katas, you need to return the value to the testing function, which will then validate it. Printing to stdout is helpful for debugging, but has no bearing on the test's pass/failure outcome. Array (...) does not match expected type "NULL". is a generic PHPUnit failed assertion message that happens to not be especially helpful: it doesn't show the contents of the expected array or log the actual and expected values in the correct order. The author of the kata reversed the arguments to $this->assertEquals(reverseSeq(5), [5,4,3,2,1]);, so Array (...) is the value the test suite expects and NULL is what your function returns).
Try simply:
function reverseSeq($n) {
return range($n, 1);
}
Outcome from the test runner:
You have passed all of the tests! :)
sorry about the funky title, I was having trouble coming up with one. First off, I managed to actually solve my problem (after tearing apart my code), but I have no idea WHY my solution worked and I am trying to treat this as a learning experience.
I have a class which collects info from the db. This class tracks an index value so that the calling function can grab the results one at a time. So my class code originally contained...
protected $index = NULL;
protected $array = array(stuff);
public function next_item()
{
if($this->index == NULL)
{//first time called
$this->index = 0;
}
else
{
$this->index++;
}
if($this->index < sizeof($this->array))
{
return TRUE;
}
return FALSE;
}
public function get_result()
{
return $this->array[$this->index];
}
And the calling function has something akin to
while($myclass->next_item()){
echo $myclass->get_result();
}
It's all a lot more involved than this of course, but this is the problem code (and you get the idea). This code induced an infinite loop (or the appearance of one) in my project. I fixed my problem by initializing $index to -1, and removing the conditional check for null. So it's now ...
protected $index = -1;
public function next_item()
{
$this->index++;
if($this->index < sizeof($this->array))
{
return TRUE;
}
return FALSE;
}
My question is, WHY did that work? The index was never referenced in the array while it was NULL, I checked. It was always after the conditional check for NULL was called and the assignment to 0 occurred.
I really appreciate your time, in advance. Just trying to turn this into a learning experience, and it's better if I understand why it worked, not just that it did.
I'm sorry if this question is answered somewhere else, I couldn't figure out how to label my question (as you can see) much less have success finding a previous answer to it.
cheers,
-David
Your problem was caused by the fact that 0 == NULL in PHP. So when you set the index to 0 once you would keep setting it to 0 again over and over every time you call next_item, this->index == NULL would always be true.
Changing your test to this->index === NULL would have also solved your problem. See this question which covers the difference between == and === in PHP.
`I have a function called lets say calculate; what i want to do is run some loops with in the function calculating an outcome. at times this function does fail as it will get stuck in a loop, so iv got it covered to exit the loop but my problem is i want to restart this function and hope it come out with an outcome if not i will try again... on average the request does not have an outcome around 1 in 20, i need to restart the function from a clean slate.
i have tried to unset all the vars before i rerun the process with out success.please note this function will fail at times from the information handed to the process, un avoidable so
when this accurs i just want to rerun the function automatically to generate an outcome.
http://www.gamezslave.com/test/DynamicSlots.swf this is my test prototype give you an idea
sometimes you refresh it will error because of this factor.
<?php
$checker = 0; // if i cant get a result i could use this will tick up until condition
function shuffleArray($myArray) {
$value_count = array_count_values($myArray);
$last_value = $myArray[count($myArray) - 1];
unset($myArray[count($myArray) - 1]);
$shuffle = array();
$last = false;
while (count($myArray) > 0) {
$keys = array_keys($myArray);
$i = round(rand(0, count($keys) - 1));
while ($last === $myArray[$keys[$i]] ) {
$i = round(rand(0, count($keys) - 1));
echo "stuck";
$checker++;
if($checker>10){
echo " Too many checks so die, and restart process ";
return false;
bob; // this is the check function to goto and restart
}
}
$shuffle[] = $myArray[$keys[$i]];
$last = $myArray[$keys[$i]];
unset($myArray[$keys[$i]]);
}
if ($last_value === $last) {
$i = 0;
foreach($shuffle as $key=>$value) {
if ($value !== $last_value) {
$i = $key;
break;
}
}
array_slice($shuffle, $i + 1, 0, $last_value);
} else {
$shuffle[] = $last_value;
}
return $shuffle;
}
print_r(shuffleArray(array(1,5,5,3,7,7,7,7))); // just a example
function bob(){
if($checker>10){
$checker = 0;
shuffleArray();
echo "bob";
reset($myArray); // thought this may clean/reset the array i couldnt use
}
}
The idea this shuffle returns that no two symbols elemts of the same will be next to each other but sometimes at the end of the array as its shuffling randomly im left with bad odds (apple, orange, orange, orange) so what i need to do is resart this process again from start take in mind there is about 10 different item in the array and duplicates of each for example 10 apples ,10 oranges 4 bannanas 3 grapes sometimes the shuffle manages to generate an outcome where im stuck with too many of the same item at the end of the array wich then i need to rerun the script(and this bit is the problem) i dont know how.
Are you using globals?
If yes: Stop that. It's terrible practice. Seriously. There's never a reason to use globals with any sort of sane code.
If no: There's nothing to do. Each function invocation is a clean slate.
EDIT After seeing the code, I'm kinda speechless.
http://us3.php.net/manual/en/function.shuffle.php
I would set defaults to all variables inside of your function, and pass anything active as a parameter. Then use a set of return codes to indicate success or failure, or validate the outcome in some way and re-run.
I'm agreeing with Tyler Eaves here and i wanted to add as another reply a very important topic in programming:
A function "should" in theory be as scalar as possible meaning that it should not affect the outside world and should return the same information everytime for the same parameters.
If you call a function with parameter X, Y and Z and call it again while your system is in the same state, the function should return the exact same result.
But if a function is not scalar (Virtual for instance), such as dependant on external data (files, database rows or single instance accessible class data) then you should theorically not affect that external data from this function or else calling the function multiple times yield different results...
This is a very very weird bug that happens randomly. So I will try to explain this as best as I can. I'm trying to diminish the code substantially to pinpoint the problem without having to reference a framework, nor deal with 500 lines of code outside of the framework - so I will try and come back and update this question when I do. OK, so here we go.
So basically say I'm taking a string in a function and preg_replace like so:
$table = '/something';
print $table;
$table = preg_replace("#^(/)#",'prefix_',$table);
print $table;
The output will look something like
...
/something - prefix_something
/something - prefix_something
/something - /something
You have an error in you sql query... blah blah somewhere around SELECT * FROM /something
What happens is that after rolling through the code, this simply stops working and the sql errors out. What's more strange is that if I start commenting out code outside the function it then works. I put that code back in, it breaks.
I tried recoding this by substr($var,0,1) and var_dumping the variable. After a few rounds it returns a bool(false) value even though $var is in fact a string. It's very very strange. Has anybody run into this before? Is this a PHP bug? It's looking like it to me.
-- EDIT --
Example:
foreach ( $user as $id => $user ) {
get_data("/table_name","*", "user_id = '$id'");
}
#in the function $_table_ holds "/table_name"
$_table_ = trim($_table_);
$tmp = explode(',', $_table_);
$tables = array();
foreach ($tmp as $c => $n) {
$n = trim($n);
$a = substr($n, 0, 1);
$b = substr($n, 1);
if ($a == false) {
var_dump($n);
$a = substr($n, 0, 1);
var_dump($b);
var_dump($a);
}
if ($a == '/') { etc...
Output:
string(11) "/table_name" string(10) "table_name" bool(false)
If I switch to the original preg_replace functionality, it simply does not preg_replace and the same thing happens "/table_name" is return rather then "prefix_table_name" and this happens randomly. Meaning it will work on the string it broke on if I comment code out outside of the function that is seemingly unrelated.
--- SOLUTION ----
I found out that it has to do with string to array conversion in another function that caused this strange error.
Basically a function was expecting a null or array() value and instead a number was passed. We have notices turned off, so I turned them on and started fixing all the notices and warnings and that's how I found this strange bug. Now exactly what the inner workings are that created the problem is unknown to me. However I can define the symptom as a string assignment problem that would occur at some other place in the code which we caught when it wouldn't reassign the $table variable with the new preg_replace value which is detailed above. Now you know. The function looks something similar to this:
function format_something($one, $two, $three = array()){
if ($three['something'] == 'Y') {
/** etc... */
}
...
format_something('one','two',3);
After a while in a loop this type of conversion started having problems randomly in the code.
substr doesn't always return a string. If it can't find the substring, it returns false.
Return Values
Returns the extracted part of string, or FALSE on failure or an empty string.
You should test for this condition and var_dump the string you are searching to see what it contains in such cases.
I have found a bug report(http://bugs.php.net/bug.php?id=24286) about this though I am not sure if it's relevant to my problem and it's very old. This is my code:
class RegExp {
function name($e){ .... }
function email($e){ .... }
function phone($e){ .... }
}
$regexp = new RegExp();
$final_keys= array("name", "email", "phone");
for($index=0; $index < count($final_keys); $index ++){
if(!$regexp->$final_keys[$index]($_POST[$final_keys[$index]])){
$invalid_uri_vars .= $final_keys[$index].",";
}
else{
$uri_vars = "&".$final_keys[$index]."=".$_POST[$final_keys[$index]];
}
}
What it does is it uses a value from an array as the name of the method to be called. In other words, I am trying to implement a function call using a variable $final_keys[$index] as its name.
*UPDATE: I tried implementing the suggestions below, nothing seems to work. Here's one of my modifications as suggested:
for($key=0; $key < count($final_keys); $key ++){
if(!$regexp->{$final_keys[$key]}($_POST[$final_keys[$key]])){
$invalid_uri_vars .= $final_keys[$key].",";
}
else{
$uri_vars = "&".$final_keys[$key]."=".$_POST[$final_keys[$key]];
}
}
I get the same error as my original code. Another method using call_user_func but I am not sure if did it right:
for($key=0; $key < count($final_keys); $key++){
if(!call_user_func(array($regexp, $final_keys[$key]), $_POST[$final_keys[$key]])){
$invalid_uri_vars .= $final_keys[$key].",";
}
else{
$uri_vars = "&".$final_keys[$key]."=".$_POST[$final_keys[$key]];
}
}
And I get this error: Warning: call_user_func(Array) [function.call-user-func]: First argument is expected to be a valid callback in /.........testreqmeta.php on line 91
I'm still not getting any errors (other than the undefined $key in the second sample) when trying the sample code, so I can't say for certain what will fix it, but here's an approach that simplifies things and gets rid of the array indexing operation: use a foreach loop rather than a for loop.
$query = array();
foreach ($final_keys as $key) {
if(!$regexp->$key($_POST[$key])) {
$invalid_uri_vars[] = $key;
} else {
$query[] = "$key={$_POST[$key]}";
}
}
$uri_vars = implode('&', $query);
I've also replaced the repeated string appends with an array implosion, which should be slightly more performant. It also makes it easier to further process the query string, if necessary, before submitting it. There are better approaches yet, but that's a whole other topic.
NB. RegExp isn't a very good description of what the class does, hence it isn't a very good name. The class may use regular expressions, but it isn't itself a regular expression (which support operations such as "match" and "replace"; RegExp's API has none of these).
Quoting from your link:
ok, here is some workaround on this problem:
in case of
<?
class Test {
var $var = Array('test_function');
function test_function($echo_var) {
echo $echo_var;
}
}
$test_obj = new test;
$test_obj->var[0]('bla');
?>
you can avoid Fatal error in last string using this instead:
<?
$test_obj->{$test_obj->var[0]}('bla');
?>
So then:
if($regexp->{$final_keys[$index]}($_POST[$final_keys[$index]])){
There's a function for what you are trying to achieve call_user_func:
http://de2.php.net/manual/en/function.call-user-func.php