I wrote this solution for this practice in PHP but it's not work for all case:
Given an array of bird sightings where every element represents a bird type id, determine the id of the most frequently sighted type. If more than 1 type has been spotted that maximum amount, return the smallest of their ids.
arr=[1,1,2,2,3]
Example
There are two each of types 1 and 2 , and one sighting of type .3 Pick the lower of the two types seen twice: type 1.
Function Description
Complete the migratoryBirds function in the editor below.
migratoryBirds has the following parameter(s):
int arr[n]: the types of birds sighted
Returns
int: the lowest type id of the most frequently sighted birds
Input Format
The first line contains an integer,n , the size of arr .
The second line describes arr as n space-separated integers, each a type number of the bird sighted.
Constraints
5 < n < 2 X 10 2
It is guaranteed that each type is 1,2 ,3 ,4 , or 5 .
Sample Input 0
6
1 4 4 4 5 3
Sample Output 0
4
this is my code
function migratoryBirds($arr) {
// Write your code here
$length=count($arr);
$a1=0;$a2=0;$a3=0;$a4=0;$a5=0;
for($i=0; $i < $length; $i++){
if($arr[$i]==1){
$a1++;
}
if($arr[$i]==2){
$a2++;
}
if($arr[$i]==3){
$a3++;
}
if($arr[$i]==4){
$a4++;
}
if($arr[$i]==5){
$a5++;
}
}
if($a1>=$a2 && $a1>=$a3 && $a1>=$a4 && $a1>=$a5){
$result=1;
}
if($a2>=$a1 && $a2>=$a3 && $a2>=$a4 && $a2>=$a5){
$result=2;
}
if($a3>=$a2 && $a3>=$a1 && $a3>=$a4 && $a3>=$a5){
$result=3;
}
if($a4>=$a2 && $a4>=$a3 && $a4>=$a1 && $a4>=$a5){
$result=4;
}
if($a5>=$a2 && $a5>=$a3 && $a5>=$a4 && $a5>=$a1){
$result=5;
}
return $result;
}
How can I solve it?
write your condition like this
if($a1>=$a2 && $a1>=$a3 && $a1>=$a4 && $a1>=$a5){
$result=1;
}
else if($a2>=$a1 && $a2>=$a3 && $a2>=$a4 && $a2>=$a5){
$result=2;
}
else if($a3>=$a2 && $a3>=$a1 && $a3>=$a4 && $a3>=$a5){
$result=3;
}
else if($a4>=$a2 && $a4>=$a3 && $a4>=$a1 && $a4>=$a5){
$result=4;
}
else if($a5>=$a2 && $a5>=$a3 && $a5>=$a4 && $a5>=$a1){
$result=5;
}
else{
$result=1;
}
Given an array of bird sightings where every element represents a bird type id, determine the id of the most frequently sighted type. If more than 1 type has been spotted that maximum amount, return the smallest of their ids.
For this question I wrote a code.
It passed all the test cases.
My code is as follows:
import math
import os
import random
import re
import sys
def migratoryBirds(arr):
x = [0] *(max(arr)+1)
for i in arr:
x[i] += 1
return x.index(max(x))
if name == 'main':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
arr_count = int(input().strip())
arr = list(map(int, input().rstrip().split()))
result = migratoryBirds(arr)
fptr.write(str(result) + '\n')
fptr.close()
Here try this one:
$array = array(1,2 ,3, 4, 5, 4, 3, 2, 2, 1, 3, 4);
$counted = array_count_values($array);
$n = null;
$v = 0;
foreach($counted as $nm => $val) {
if ($val > $v) {
$n = $nm;
$v = $val;
}
}
echo $n;
Hope this will help you.
function migratoryBirds($arr) {
// Write your code here
foreach($arr as $value){
if(isset($new_arr[$value])){
$new_arr[$value] += 1;
}else{
$new_arr[$value] = 1;
}
}
$min_key = '';
$max_val = 0;
for($i=(count($new_arr)); $i>=0; $i--){
if(isset($new_arr[$i])){
if($new_arr[$i] >= $max_val){
$min_key = $i;
$max_val = $new_arr[$i];
}
}
}
return $min_key;
}
Related
I'm trying to keep my code nice and elegant. Any way to make this if statement shorter?
if(strlen($cname) > 100) {
}
if(strlen($cowner) > 100) {
}
if(strlen($cemail) > 200) {
}
if(strlen($cpassword) > 100) {
}
I can't do this because I want to print out a specific message for each if statement:
if(strlen($cname) > 100 || strlen($cowner) > 100 || strlen($cemail) > 200 || strlen($cpassword) > 100) {
// I want to print out a message like email is too long not just one of these strings is too long
}
Frankly, I think you've got the most elegant solution for what you are trying to do.
You can use a loop to reduce the number of lines. Here is an optimized solution even when you have more 10 fields to check:
Declare an array of fields and loop through it
$fields = array("cname" => 100, "cowner" => 100, "cemail" => 200, "cpassword" => 100); // key as field name and value as maximum limit - new values can be added here.
foreach($fields as $field => $length) {
if(strlen(${$field}) > $length) {
die("$field field can only contain $length characters");
}
}
Edit: You can also keep all errors in an array and then print all the errors on your page.
$errors = array();
foreach($fields as $field => $length) {
if(strlen(${$field}) > $length) {
$errors[] = "$field field can only contain $length characters";
}
}
print_r($errors);
You already using an optimized code. But you can optimize it little bit more for showing error message. Like below:
$invalidFieldName = '';
$invalidFieldLength = 100;
if (strlen($cname) > 100) {
$invalidFieldName = 'CNAME';
} elseif (strlen($cowner) > 100) {
$invalidFieldName = 'COWNER';
} elseif (strlen($cemail) > 200) {
$invalidFieldName = 'CEMAIL';
$invalidFieldLength = 200;
} elseif (strlen($cpassword) > 100) {
$invalidFieldName = 'CPASSWORD';
}
if ($invalidFieldName != '') {
echo $invalidFieldName." should be greater than ".$invalidFieldLength;
}
I am not really sure if it will help you but I hope it will help you.
I write a logic to round value based on fraction part value. When i execute this code, elseif block is not executed. Here is my code
<?php
function roundRating($rating)
{
if($rating>=5 && $rating<0){
$rating=0;
}
$a=(int)$rating/1;
$b= $rating-$a;
if(($b>=.1) && ($b<=.2)){
$b=0;
$rating=$a;
}
elseif(($b>=.3 && $b<=.4)|| ($b>=.6 && $b<=.7)){
$b=.5;
$rating=$a+$b;
}
elseif(($b>=.8) && ($b<=.9)){
$b=1;
$rating=$a+$b;
$a=$rating;
}
else{}
return $rating;
}
echo roundRating(3.3);
?>
for this value 3.3, the output should be 3.5. But currently it will return passed value 3.3 instead of 3.5. Kindly help me to find out the problem in the above code. Thanks in advance.
I've done my own version of the function which might be cleaner, and i think generates the output required:
function roundRating($rating) {
if( $rating > 5) {
return 5; // Note: assuming the >5 case of 0 was a bug and it was meant to cap it to 5
} elseif( $rating < 0 ) {
return 0;
}
$number = floor($rating);
$remainder = $rating * 10 % 10;
if( $remainder <= 2 ) {
return $number;
} elseif( $remainder >= 8 ) {
return $number + 1;
} else {
return $number + 0.5;
}
}
echo roundRating(3.4); // 3.5
echo roundRating( 3.0) ; // 3
echo roundRating( 6) ; // 5
echo roundRating( 3.8) ; // 4
Please follow the following code given bellow.we some times face problem in floating value comparison. So, it is useful to specify how much number we will consider after decimal point. In the following code value of b is specified that it takes only 3 numbers after decimal point.
For details please visit:
is-floating-point-math-broken
To check online please visit:
Online check
function roundRating($rating)
{
if($rating>=5 && $rating<0){
$rating=0;
}
$a=(int)$rating/1;
$b= sprintf('%3f',$rating-$a);
if(($b>=.1) && ($b<=.2)){
$b=0;
$rating=$a;
}
elseif(($b>=.3 && $b<=.4)|| ($b>=.6 && $b<=.7)){
$b=.5;
$rating=$a+$b;
}
elseif(($b>=.8) && ($b<=.9)){
$b=1;
$rating=$a+$b;
$a=$rating;
}
else{}
return $rating;
}
echo roundRating(3.3); // 3.5
?>
Replace your code with below code.
<?php
function roundRating($rating)
{
if($rating >= 5 && $rating < 0){
$rating=0;
}
else
{
$a=(int)$rating/1;
$b= $rating-$a;
echo $a ."</br>";
echo $b."</br>";
if(($b >= 0.1) && ($b <= 0.2)){
$b=0;
$rating=$a;
}
elseif(($b >=0.3 || $b<=0.4) && ($b>=0.6 || $b<=0.7)){
$b=.5;
$rating=$a+$b;
}
elseif(($b>=.8) || ($b<=.9)){
$b=1;
$rating=$a+$b;
$a=$rating;
}
else{}
}
return $rating;
}
echo roundRating(3.3);
?>
Here i have did two change first add else condition your rating calculation work if $rating is not greater than 5 or less than 0. and second in one of your else if condition is change which is given below.
elseif(($b >=0.3 || $b<=0.4) && ($b>=0.6 || $b<=0.7)){
//echo "here";
$b=.5;
$rating=$a+$b;
}
i hope it will helps you.
Floating point numbers have hidden/limited precision in C - so you can't trust them to the last digit. There's more of a writeup on this at http://php.net/manual/en/language.types.float.php
If you were to round it to 1 decimal place, you'll get 3.5:
$b= round($rating-$a, 1);
To start with :
if($rating>=5 && $rating<0)
will always be false . A variable can't be greater than 5 and less than 0 at the same time.
Regarding
elseif(($b>=.3 && $b<=.4)|| ($b>=.6 && $b<=.7)){
$b=.5;
$rating=$a+$b;
}
what practical differece would it make with :
elseif(($b>=.3 && $b<=.7)){
$b=.5;
$rating=$a+$b;
}
unless you write :
else{
$rating+=some_value;// forthe inifinite number of values between .4 & .6?
}
Regarding,
elseif(($b>=.8) && ($b<=.9)){
$b=1;
$rating=$a+$b;
$a=$rating; // This statement is redundant
}
Since you return $rating from the function, $a=$rating; is redundant.
Having said the above things, I feel below would be a much simpler implementation, with results almost identical to desired one :
<?php
function round_rating($rating){
if($rating<0 || $rating>5){
$rating=0;
return $rating;
}
$t_rating=(int)$rating; //$t_rating short for trimmed_rating :)
$dif=$rating-$t_rating; //$dif is the short for difference :)
if($dif <= .2){
return($t_rating);
}
elseif($dif <= .7){
return((float)$t_rating+.5);
}
else{
return((float)$t_rating+1);
}
} // round_rating function ends here :)
/*Test time*/
printf("Round rating for %0.2f : %0.2f\n",6,round_rating(6));
printf("Round rating for %0.2f : %0.2f\n",0.2,round_rating(0.2));
printf("Round rating for %0.2f : %0.2f\n",1.4,round_rating(1.4));
printf("Round rating for %0.2f : %0.2f\n",2.8,round_rating(2.8));
printf("Round rating for %0.2f : %0.2f\n",4.6,round_rating(4.6));
printf("Round rating for %0.2f : %0.2f\n",-1,round_rating(-1));
?>
Output :
Round rating for 6.00 : 0.00
Round rating for 0.20 : 0.00
Round rating for 1.40 : 1.50
Round rating for 2.80 : 3.00
Round rating for 4.60 : 4.50
Round rating for -1.00 : 0.00
Thank you all for your answers. Finally i got the answer. Here is my answer.
function roundRating($rating)
{
if($rating>5 ){
$rating=0;
return $rating;
}
elseif($rating<=0)
{
$x=0;
return $rating;
}
$a=(int)$rating/1;
$b= $rating-$a;
$b= (int)round(($b*10),0);
if($b<=2)
{
$rating=$a;
return $rating;
}
elseif($b>=3 && $b<=7){
$rating=$a+.5;
return $rating;
}
elseif($b>=8){
$rating=$a+1;
return $rating;
}
else{}
}
echo roundRating(3.2); //3
echo roundRating(3.3); //3.5
echo roundRating(3.7); //3.5
echo roundRating(3.8); //4
I've some problems with this PHP code:
// HIGHLIGHT NUMBERS *************************************************
// BUY
$valueEnlightOverBuy = $_POST["enlightOverBuy"];
$valueEnlightUnderBuy = $_POST["enlightUnderBuy"];
// GREEN PRICE BUY
$fontColorBuy = "#FFF";
if ((($valueEnlightOverBuy != '') or ($valueEnlightUnderBuy != '')) and (($valueEnlightOverBuy and $valueEnlightUnderSell) != "0")) {
if (($finalPriceBuyer >= $valueEnlightOverBuy) or ($finalPriceBuyer <= $valueEnlightUnderBuy)) {
$fontColorBuy = "#00FF00";
} else if (($finalPriceBuyer >= $valueEnlightOverBuy and $finalPriceBuyer <= $valueEnlightUnderBuy)) {
$fontColorBuy = "#FF00FF";
} else {
$fontColorBuy = "#D00000";
}};
// SELL LOCAL
$valueEnlightOverSloc = $_POST["enlightOverSloc"];
$valueEnlightUnderSloc = $_POST["enlightUnderSloc"];
// GREEN PRICE SELL LOCAL
$fontColorSellLoc = "#FFF";
if ((($valueEnlightOverSloc != '') or ($valueEnlightUnderSloc != '')) & (($valueEnlightOverSloc & $valueEnlightUnderSloc) != "0")) {
if (($finalPriceSellerLocal >= $valueEnlightOverSloc) or ($finalPriceSellerLocal <= $valueEnlightUnderSloc)) {
$fontColorSellLoc = "#00FF00";
} else if (($finalPriceSellerLocal >= $valueEnlightOverSloc) and ($finalPriceSellerLocal <= $valueEnlightUnderSloc)) {
$fontColorSellLoc = "#FF00FF";
} else {
$fontColorSellLoc = "#D00000";
}};
// SELL INTERNATIONAL
$valueEnlightOverSellInt = $_POST["enlightOverSellInt"];
$valueEnlightUnderSellInt = $_POST["enlightUnderSellInt"];
// GREEN PRICE SELL INTERNATIONAL
$fontColorSellInt = "#FFF";
if ((($valueEnlightOverSellInt != '') or ($valueEnlightUnderSellInt != '')) & (($valueEnlightOverSellInt & $valueEnlightUnderSellInt) != "0")) {
if (($finalPriceSellerInt >= $valueEnlightOverSellInt) or ($finalPriceSellerInt <= $valueEnlightUnderSellInt)) {
$fontColorSellInt = "#00FF00";
} else if (($finalPriceSellerInt >= $valueEnlightOverSellInt) and ($finalPriceSellerInt <= $valueEnlightUnderSellInt)) {
$fontColorSellInt = "#FF00FF";
} else {
$fontColorSellInt = "#D00000";
}};
As you see I have a post form (not showed in code) that transmit to this file the values for: VAR underBuy < BUY PRICE < VAR overBuy; VAR underLocalSeller < LOCAL SELL PRICE < VAR overLocalSeller; VAR underIntSeller < INT SELL PRICE < VAR underIntSeller.
Firstly the code makes a check
if the VAR received from form are EMPTY or = to 0; if it's not,
the code collect all this data and make a check on $FINALPRICEBUYER (extracted from a file with json) for the 1st two VARs, than make a check on $FINALPRICESELLERLOCAL for the 3rd and the 4th VARs and so make a check on $FINALPRICESELLERINT for the 5th and the 6th VARs.
If $ FINALPRICEBUYER is between >= than 1st VAR or <= than 2nd VAR make font GREEN, else if $FINALPRICEBUYER between 3rd VAR and 4th VAR go VIOLET,
else go RED.
The same for $FINALPRICESELLERLOCAL and $FINALPRICESELLERINT.
I did the first two conditions because user can insert one price limit or two.
Could you help me to understand what's I'm doing wrong? (Maybe it's only a matter of logic).
Here is the question:
This code doesn't work. Many time it return green font in spite of violet, so there should be something in the logic structure of math symbols (or PHP code of course) I can't get...
UPDATE 29.06.2015
Here is the code I'm using and adapting, starting from on of your examples.
// ENLIGHT NUMBERS ***************************************************
// get all input variables at once
$over_buy = $_POST['enlightOverBuy'];
$under_buy = $_POST['enlightUnderBuy'];
$over_loc = $_POST['enlightOverSloc'];
$under_loc = $_POST['enlightUnderSloc'];
$over_int = $_POST['enlightOverSellInt'];
$under_int = $_POST['enlightUnderSellInt'];
$final_buy = $finalPriceBuyer;
$final_loc = $finalPriceSellerLocal;
$final_int = $finalPriceSellerInt;
// now set the colors
$buy = getFontColor( $over_buy, $under_buy, $final_buy );
$loc = getFontColor( $over_loc, $under_loc, $final_loc );
$int = getFontColor( $over_int, $under_int, $final_int );
So nothing different here.
Now the function:
// function to return color based on input
function getFontColor( $over, $under, $final ) {
// colors
$white = '#fff';
$green = '#0f0';
$violet = '#f0f';
$red = '#d00000';
Fist step: if function get the "0" number font will be white so:
if ($final != '0') {
Second step: if both the "value" are sent by the form
if (!empty($over) and !empty($under)) {
Third step: if FINAL is a number between over and under
if ($final >= $over && $final <= $under) {
go GREEN
return $green;
if not
} else {
go RED
return $red;
}
Fourth step: else if one of the "value", or the other one, is empty
} else if (!empty($over) or !empty($under)) {
Fifth step: if FINAL is a number higher than "over" value, or lower than "under" value
if ($final >= $over or $final <= $under) {
go GREEN
return $green;
else go RED
} else {
return $red;
}
Sixth step: in any other case, go WHITE
} else {
return $white;
}
}};
So I would have GREEN if $final is in between two values received from form, but if you have only one value input (so under or over), if $final is higher than over or lower than under, go GREEN.
In any other caso, go RED, if $final is not "0".
Here is the full code without spaces:
// ENLIGHT NUMBERS ***************************************************
// get all input variables at once
$over_buy = $_POST['enlightOverBuy'];
$under_buy = $_POST['enlightUnderBuy'];
$over_loc = $_POST['enlightOverSloc'];
$under_loc = $_POST['enlightUnderSloc'];
$over_int = $_POST['enlightOverSellInt'];
$under_int = $_POST['enlightUnderSellInt'];
$final_buy = $finalPriceBuyer;
$final_loc = $finalPriceSellerLocal;
$final_int = $finalPriceSellerInt;
// now set the colors
$buy = getFontColor( $over_buy, $under_buy, $final_buy );
$loc = getFontColor( $over_loc, $under_loc, $final_loc );
$int = getFontColor( $over_int, $under_int, $final_int );
// function to return color based on input
function getFontColor( $over, $under, $final ) {
// colors
$white = '#fff';
$green = '#0f0';
$violet = '#f0f';
$red = '#d00000';
if ($final != '0') {
if (!empty($over) and !empty($under)) {
if ($final >= $over && $final <= $under) {
return $green;
} else {
return $red;
}
} else if (!empty($over) or !empty($under)) {
if ($final >= $over or $final <= $under) {
return $green;
} else {
return $red;
}
} else {
return $white;
}
}};
It seems correct to me, but I'm receiving a strange result, the echos you will see were created by me to make a check of function behavior.
Please do not consider my Italian comments, but the result is a non-sense, considering in:
1st example: GREEN (0.127839 is NOT under 0.125, so should be RED)
RED (correct) - GREEN (correct)
2nd example: GREEN (0.154761 is NOT under 0.125, so should be RED) - RED (correct) - GREEN (correct)
3rd example: GREEN (0.14442 is NOT under 0.125, so should be RED) - RED (correct) - GREEN (correct)
4th example: GREEN (0.129195 is NOT under 0.125, so should be RED) - RED (correct) - RED (correct).
How is it possible that using the same function you get always an error on 1st usage and correct answer on the next 2 uses?
FINAL UPDATE
Here is the code:
$over_buy = number_format($_POST['enlightOverBuy'], 6);
$under_buy = number_format($_POST['enlightUnderBuy'], 6);
$over_loc = number_format($_POST['enlightOverSloc'], 6);
$under_loc = number_format($_POST['enlightUnderSloc'], 6);
$over_int = number_format($_POST['enlightOverSellInt'], 6);
$under_int = number_format($_POST['enlightUnderSellInt'], 6);
$final_buy = $finalPriceBuyer;
$final_loc = $finalPriceSellerLocal;
$final_int = $finalPriceSellerInt;
// now set the colors
$buy = getFontColor( $over_buy, $under_buy, $final_buy );
$loc = getFontColor( $over_loc, $under_loc, $final_loc );
$int = getFontColor( $over_int, $under_int, $final_int );
// function to return color based on input
function getFontColor( $over, $under, $final ) {
// colors
$white = '#fff';
$green = '#0f0';
$red = '#FF3300';
if ($final != '0') {
if (!empty($over) and !empty($under)) {
if ($final >= $over && $final <= $under) {
return $green;
} else {
return $red;
}
} elseif (!empty($over)) {
return ($final >= $over) ? $green : $red;
} elseif (!empty($under)) {
return ($final <= $under) ? $green : $red;
} else {
return $white;
}
}};
Many things to address here...
It looks like you could use a good reading on:
truth tables and karnaugh maps to help you get the apropriate expresion and simplify it
is_numeric, to check for a numeric input
operators in general, and in particular operator precedence
The diference between & (bitwise operator) and && (logical operator)
How to properly use if...elseif expresions. The elseif condition only gets evaluated when the if condition is not met, so if you put something like this in your code where the elseif condition is a subset of the if condition, the elseif condition will only be evaluated when it is not met, rendering it useless because the code inside it will never be executed:
.
if (($finalPriceBuyer >= $valueEnlightOverBuy) or ($finalPriceBuyer <= $valueEnlightUnderBuy)) {
$fontColorBuy = "#00FF00";
} else if (($finalPriceBuyer >= $valueEnlightOverBuy and $finalPriceBuyer <= $valueEnlightUnderBuy)) { ... }
More importantly, be lazy and DRY. If you are doing the same thing twice, put it into a function:
function getColor($value, $limitOver, $limitUnder, $colors){
$underCheck = !is_numeric($limitUnder) || $value >= $limitUnder;
$overCheck = !is_numeric($limitOver) || $value <= $limitOver;
if ($underCheck && $overCheck) {
// all valid bounds are satisfied
return $colors['none'];
} else if ($overCheck){
// valid lower bound exists and is not satisfied
// and upper bound does not exist or is not valid or is satisfied
return $colors['under'];
} else if ($underCheck){
// valid upper bound exists and is not satisfied
// and lower bound does not exist or is not valid or is satisfied
return $colors['over'];
} else {
// both bounds exist and none of them are satisfied
return $colors['both'];
}
}
$colors = array (
'both' => "#FF00FF",
'over' => "#D00000",
'under' => "#FFF",
'none' => "#00FF00",
);
$colorBuy = getColor(
$finalPriceBuyer,
$_POST["enlightOverBuy"],
$_POST["enlightUnderBuy"],
$colors
);
$colorLocal = getColor(
$finalPriceSellerLocal,
$_POST["enlightOverSloc"],
$_POST["enlightUnderSloc"],
$colors
);
$colorInt = getColor(
$finalPriceSellerInt,
$_POST["enlightOverSellInt"];,
$_POST["enlightUnderSellInt"],
$colors
);
You have not been exactly clear on your definition of the problem, so it is up to you to check if I have correctly interpreted your intentions and make the required modifications to suit your exact needs, but you get the idea.
You must check the most restrictive condition first. See this code:
// case A
if($z>$x && $z<$y) {}
// case B
if($z>$x || $z<$y) {}
Outcome:
$x | $y | $z | case A | case B
10 20 5 false true
10 20 15 true true
10 20 25 false true
Whenever case A evaluates as true, case B also does. But the reverse situation might not. Therefore if you put case B first in an IF ELSE, it will always return true before reaching case A.
Fixed code sample:
$valueEnlightOverBuy = $_POST["enlightOverBuy"];
$valueEnlightUnderBuy = $_POST["enlightUnderBuy"];
// GREEN PRICE BUY
$fontColorBuy = "#FFF";
// user has provided price boundaries
if($valueEnlightOverBuy !== '' && $valueEnlightUnderSell !== '') {
// satisfies both boundaries (violet, should be green ?)
if($finalPriceBuyer >= $valueEnlightOverBuy && $finalPriceBuyer <= $valueEnlightUnderBuy) {
$fontColorBuy = "#FF00FF";
}
// satisfies at least one boundary (green, should be violet ?)
elseif($finalPriceBuyer >= $valueEnlightOverBuy || $finalPriceBuyer <= $valueEnlightUnderBuy) {
$fontColorBuy = "#00FF00";
}
// outside the boundaries (wrong boundaries order) (red)
else {
$fontColorBuy = "#D00000";
}
}
Instinctively, I get the feeling that you actually want the AND condition to be green and the OR condition to be violet, but I can be wrong about that. And I must point out the red condtion only fires if the boundaries are set in the wrong order, although that seems appropriate.
Regarding update 2015-06-29:
In this code:
elseif(!empty($over) or !empty($under)) {
if ($final >= $over or $final <= $under) {
return $green;
}
else {
return $red;
}
}
In your examples, you get $green because $over is evaluated as zero, therefore any positive value will return green. You must only evaluate the value that is not empty.
elseif(!empty($over)) {
return ($final >= $over) ? $green : $red;
}
elseif(!empty($under)) {
return ($final <= $under) ? $green : $red;
}
NOTE: This question should likely be moved to the code review site.
I think your main problem is coding style and organization. Your code is hard to read and therefore harder to debug. Particularly when you are trying to implement complex logic, making sure that you have clean code is helpful. Here are some suggestions.
Use shorter variable names
User proper indentation
Use built-in PHP functions to simplify, e.g. empty()
Use functions to get rid of repetition
Group similar tasks in one place, e.g. getting values of $_POST variables
So first, I'll rewrite your code, following these suggestions:
// function to return color based on input
function getFontColor( $over, $under, $final ) {
// colors
$white = '#fff';
$green = '#0f0';
$violet = '#f0f';
$red = '#d00000';
if ( !empty($over) and !empty($under) ) {
if ( $final >= $over || $final <= $under ) return $green;
if ( $final >= $over && $final <= $under ) return $violet;
return $red;
} else {
return $white;
}
}
// get all input variables at once
$over_buy = $_POST['enlightOverBuy'];
$under_buy = $_POST['enlightUnderBuy'];
$over_loc = $_POST['enlightOverSloc'];
$under_loc = $_POST['enlightUnderSloc'];
$over_int = $_POST['enlightOverSellInt'];
$under_int = $_POST['enlightUnderSellInt'];
// now set the colors
$buy = getFontColor( $over_buy, $under_buy, $final_buy );
$loc = getFontColor( $over_loc, $under_loc, $final_loc );
$int = getFontColor( $over_int, $under_int, $final_int );
Once, we've done that, we can see at least one problem. The getFontColor() function above will NEVER return $violet because you have the OR statement before the AND statement. To correct that, the function should be rewritten as:
// function to return color based on input
function getFontColor( $over, $under, $final ) {
// colors
$white = '#fff';
$green = '#0f0';
$violet = '#f0f';
$red = '#d00000';
if ( !empty($over) and !empty($under) ) {
if ( $final >= $over && $final <= $under ) return $violet;
if ( $final >= $over || $final <= $under ) return $green;
return $red;
} else {
return $white;
}
}
However, even with this revision, I'm still not sure the code does what you expect it to do. In any case it should be easier to debug, now that it is simpler and cleaner. Hope this helps!
So I'm trying to figure out how to check if two times overlap using PHP and a MySQL database.
This is the function I'm using to check if they are overlapping:
function testRange($start_time1,$end_time1,$start_time2,$end_time2) {
return ($end_time1 < $start_time2) ? false : ($start_time1 > $start_time2) && ($start_time1 > $end_time2) ? false : true;
}
AFAIK that should work fine so I go to check if the times are overlapping and add any that do overlap to an array:
$clashes = [];
$idTracker = [];
foreach ($userBands as $show) {
foreach ($userBands as $show1) {
if(!($show->id == $show1->id)) {
if(strcmp($show->date, $show1->date) == 0 && testRange(strtotime($show->time), strtotime($show->time) + ($show->length*60), strtotime($show1->time), strtotime($show1->time) + ($show1->length*60))) {
array_push($clashes, [
"s1_id" => $show->id,
"s2_id" => $show1->id
]);
}
}
}
}
foreach ($clashes as $clash) {
foreach ($clashes as $clash1) {
//If Clash1->ID1 == Clash2->ID1 then
}
print_r($clash);
echo "<br>";
}
However when I print out the entries of the $clashes array I get this as my output:
which is just wrong completely as this is the contents of the database:
27 and 26 should not be clashing with 25, but they are being tracked into the $clashes array. Why is this happening?
Database Info:
Date is of the Date SQL type, Time is of the Time SQL type and Length is a double(8,2) SQL type
$userBands Info:
The $userBands variable is a Laravel collection of the Show model
First:
You can change the SQL query to get end-time like so:
SELECT *,
ADDTIME(
CONCAT(time,'.0'),
CONCAT(CONCAT(CONCAT( length DIV 60, ':' ), length MOD 60) ,':0.0')
) AS EndTime
FROM `table`;
So now you have a column named EndTime,
So this code can work:
if(strcmp($show->date, $show1->date) == 0 &&
newTestRange(
strtotime($show->time),
strtotime($show->EndTime),
strtotime($show1->time),
strtotime($show1->EndTime)
) ) {
I have no idea why this works:
function newTestRange($start_time1,$end_time1,$start_time2,$end_time2) {
// 12:30:00 13:20:00 12:45:00 13:45:00
// return ($end_time1 < $start_time2) ? false : ($start_time1 > $start_time2) && ($start_time1 > $end_time2) ? false : true;
$ret = false; // its all okay.
if ($start_time1 < $start_time2 ){
if ($end_time1 > $start_time2 ){
$ret = true;echo "\n case1-$start_time1-colide-$start_time2 \n";
}
} else if ($end_time2 > $start_time1){
$ret = true; echo "\n case2-$start_time1-colide-$start_time2 \n";
}
return $ret;
}
but you must consider 4 different scenarios:
So if one event contains another event, you will find it.
Best!
Fixed it by changing the algorithm for comparing the times.
New version:
function testRange($s1, $e1, $s2, $e2) {
return $s1 <= $e2 && $s2 <= $e1;
}
Don't know why this works over the previous one however.
I'm trying to loop through a set of records, all of which have a "number" property. I am trying to check if there are 3 consecutive records, e.g 6, 7 and 8.
I think i'm almost there with the code below, have hit the wall though at the last stage - any help would be great!
$nums = array();
while (count($nums <= 3))
{
//run through entries (already in descending order by 'number'
foreach ($entries as $e)
{
//ignore if the number is already in the array, as duplicate numbers may exist
if (in_array($e->number, $num))
continue;
else
{
//store this number in the array
$num[] = $e->number;
}
//here i need to somehow check that the numbers stored are consecutive
}
}
function isConsecutive($array) {
return ((int)max($array)-(int)min($array) == (count($array)-1));
}
You can achieve the same result without looping, too.
If they just have to be consecutive, store a $last, and check to make sure $current == $last + 1.
If you're looking for n numbers that are consecutive, use the same, except also keep a counter of how many ones fulfilled that requirement.
$arr = Array(1,2,3,4,5,6,7,343,6543,234,23432,100,101,102,103,200,201,202,203,204);
for($i=0;$i<sizeof($arr);$i++)
{
if(isset($arr[$i+1]))
if($arr[$i]+1==$arr[$i+1])
{
if(isset($arr[$i+2]))
if($arr[$i]+2==$arr[$i+2])
{
if(isset($arr[$i+3]))
if($arr[$i]+3==$arr[$i+3])
{
echo 'I found it:',$arr[$i],'|',$arr[$i+1],'|',$arr[$i+2],'|',$arr[$i+3],'<br>';
}//if3
}//if 2
}//if 1
}
I haven't investigated it thoroughly, maybe can be improved to work faster!
This will confirm if all items of an array are consecutive either up or down.
You could update to return an array of [$up, $down] or another value instead if you need direction.
function areAllConsecutive($sequence)
{
$up = true;
$down = true;
foreach($sequence as $key => $item)
{
if($key > 0){
if(($item-1) != $prev) $up = false;
if(($item+1) != $prev) $down = false;
}
$prev = $item;
}
return $up || $down;
}
// areAllConsecutive([3,4,5,6]); // true
// areAllConsecutive([3,5,6,7]); // false
// areAllConsecutive([12,11,10,9]); // true
Here's an example that can check this requirement for a list of any size:
class MockNumber
{
public $number;
public function __construct($number)
{
$this->number = $number;
}
static public function IsListConsecutive(array $list)
{
$result = true;
foreach($list as $n)
{
if (isset($n_minus_one) && $n->number !== $n_minus_one->number + 1)
{
$result = false;
break;
}
$n_minus_one = $n;
}
return $result;
}
}
$list_consecutive = array(
new MockNumber(0)
,new MockNumber(1)
,new MockNumber(2)
,new MockNumber(3)
);
$list_not_consecutive = array(
new MockNumber(5)
,new MockNumber(1)
,new MockNumber(3)
,new MockNumber(2)
);
printf("list_consecutive %s consecutive\n", MockNumber::IsListConsecutive($list_consecutive) ? 'is' : 'is not');
// output: list_consecutive is consecutive
printf("list_not_consecutive %s consecutive\n", MockNumber::IsListConsecutive($list_not_consecutive) ? 'is' : 'is not');
// output: list_not_consecutive is not consecutive
If u don't wanna mess with any sorting, picking any of three numbers that are consecutive should give you:
- it either is adjacent to both the other numbers (diff1 = 1, diff2 = -1)
- the only number that is adjacent (diff = +-1) should comply the previous statement.
Test for the first condition. If it fails, test for the second one and under success, you've got your secuence; else the set doesn't comply.
Seems right to me. Hope it helps.
I think you need something like the following function (no need of arrays to store data)
<?php
function seqOfthree($entries) {
// entries has to be sorted descending on $e->number
$sequence = 0;
$lastNumber = 0;
foreach($entries as $e) {
if ($sequence==0 or ($e->number==$lastNumber-1)) {
$sequence--;
} else {
$sequence=1;
}
$lastNumber = $e->number;
if ($sequence ==3) {
// if you need the array of sequence you can obtain it easy
// return $records = range($lastNumber,$lastNumber+2);
return true;
}
}
// there isn't a sequence
return false;
}
function isConsecutive($array, $total_consecutive = 3, $consecutive_count = 1, $offset = 0) {
// if you run out of space, e.g. not enough array values left to full fill the required # of consecutive count
if ( $offset + ($total_consecutive - $consecutive_count ) > count($array) ) {
return false;
}
if ( $array[$offset] + 1 == $array[$offset + 1]) {
$consecutive_count+=1;
if ( $consecutive_count == $total_consecutive ) {
return true;
}
return isConsecutive($array, $total_consecutive, $consecutive_count, $offset+=1 );
} else {
return isConsecutive($array, $total_consecutive, 1, $offset+=1 );
}
}
The following function will return the index of the first of the consecutive elements, and false if none exist:
function findConsecutive(array $numbers)
{
for ($i = 0, $max = count($numbers) - 2; $i < $max; ++$i)
if ($numbers[$i] == $numbers[$i + 1] - 1 && $numbers[$i] == $numbers[$i + 2] - 2)
return $i;
return false;
}
Edit: This seemed to cause some confusion. Like strpos(), this function returns the position of the elements if any such exists. The position may be 0, which can evaluate to false. If you just need to see if they exist, then you can replace return $i; with return true;. You can also easily make it return the actual elements if you need to.
Edit 2: Fixed to actually find consecutive numbers.