Statement match there condition - php

I have question regarding condition. Question is :
Combined length of any two sides of a triangle must be greater than the length of the third side for the segments to form a triangle. For example, 8, 6 and 12 can form a triangle because the sum of any two of the three segments is greater than the third segment. However, 24, 5, and 15 cannot form a triangle because the sum of segments 5 and 15 are not greater than the length of segment 24.
so, my coding is like this :
$aa = $_GET['a'];
$bb = $_GET['b'];
$cc = $_GET['c'];
if(($aa + $bb > $cc) || ($bb + $cc > $aa) || ($aa + $cc > $bb)){
echo"Triangle";
}
else{
echo"Not Triangle";
}
it can run, but, I test those number : 8, 6 and 12 and display Triangle. for number :24, 5, and 15 it also display Triangle even the answer is Not Triangle. Can anyone tell me why? TQ

Because all of these three conditions must be met, not single one. Replace
if(($aa + $bb > $cc) || ($bb + $cc > $aa) || ($aa + $cc > $bb)){
with
if(($aa + $bb > $cc) && ($bb + $cc > $aa) && ($aa + $cc > $bb)){
and you should be fine

It's easier if you consider that the combined length of the two shorter sides of the triangle must be greater than the length of the longest side... so if you sort the side lengths in order first so that you know which are the shortest and which is the longest, then the "if" logic is simplified
// Put our lengths into an array so that we can manipulate them more esily
$sideLengths = array($_GET['a'],$_GET['b'],$_GET['c']);
// Sort the array so that it's shortest to longest
sort($sideLengths);
// Test the sum of the two short sides against the longest
if (($sideLength[0] + $sideLength[1]) > $sideLength[2])
echo"Triangle";
} else {
echo"Not Triangle";
}

Related

how Searching the database for similar numbers?

What is the way to search the database (mysql/php code) for the following entries:
123XX
123XY
XYZ44
1X344
1Z344
Z23YY
The input letters are only X - Y - Z and the numbers from 0 to 9
They are all one number, which is (12344), so how can I show these results? The goal is to search for repeated entries.
Another example :
12XYY
X = 3,4,5,6,7,8,9,0
Y = 3,4,5,6,7,8,9,0
Provided that y is not equal to x or any apparent number (1,2)
And X is not equal to Y or any apparent number (1,2)
$number = "1XZYY";
$rnumber = str_replace(array('Y','X','Z'), "ـ", $number);
$lenNumber = strlen(5);
$duplicate = $mysqli->query("SELECT `number` FROM `listNumber` WHERE (length(`number`) = '$lenNumber' && `number` LIKE '%$rnumber%') OR (length(`number`) = '$lenNumber' && `number`LIKE '%$rnumber%')");
I tried many methods, but it was very slow in showing the results because I put the loop inside a loop to search for every number in the first loop
I understand you want to look for 12344, but some of the digits may be been redacted and replaced with a random capital letter in XYZ. For that, you can use a regular expression:
WHERE REGEXP_LIKE(foo, '^[XYZ1][XYZ2][XYZ3][XYZ4][XYZ4]$')
Demo
I would use PHP and occupy each digit into the correct position until I find a conflict. To prevent a double loop I use a dictionary helper object to hold values of X, Y and Z.
function match_str_to_number($str, $number)
{
if (strlen($number) != strlen($str)) {
return false;
}
$dict = ['X' => -1, 'Y' => -1, 'Z' => -1];
for ($i = 0; $i < strlen($number); $i++) {
if ($number[$i] != $str[$i]) {
// a number mismatch
if (!isset($dict[$str[$i]])) {
return false;
}
// a wildcard variable conflict
if ($dict[$str[$i]] != $number[$i] && $dict[$str[$i]] != -1) {
return false;
};
$dict[$str[$i]] = $number[$i];
}
}
return true;
}
echo match_str_to_number("XYZ44", "12344") ? "true" : "false";
echo match_str_to_number("XYZ4X", "12344") ? "true" : "false";
// output: truefalse

Time complexity of an algorithm: find length of a longest palindromic substring

I've written a small PHP function to find a length of a longest palindromic substring of a string. To avoid many loops I've used a recursion.
The idea behind algorithm is, to loop through an array and for each center (including centers between characters and on a character), recursively check left and right caret values for equality. Iteration for a particular center ends when characters are not equal or one of the carets is out of the array (word) range.
Questions:
1) Could you please write a math calculations which should be used to explain time complexity of this algorithm? In my understanding its O(n^2), but I'm struggling to confirm that with a detailed calculations.
2) What do you think about this solution, any improvement suggestions (considering it was written in 45 mins just for practice)? Are there better approaches from the time complexity perspective?
To simplify the example I've dropped some input checks (more in comments).
Thanks guys, cheers.
<?php
/**
* Find length of the longest palindromic substring of a string.
*
* O(n^2)
* questions by developer
* 1) Is the solution meant to be case sensitive? (no)
* 2) Do phrase palindromes need to be taken into account? (no)
* 3) What about punctuation? (no)
*/
$input = 'tttabcbarabb';
$input2 = 'taat';
$input3 = 'aaaaaa';
$input4 = 'ccc';
$input5 = 'bbbb';
$input6 = 'axvfdaaaaagdgre';
$input7 = 'adsasdabcgeeegcbgtrhtyjtj';
function getLenRecursive($l, $r, $word)
{
if ($word === null || strlen($word) === 0) {
return 0;
}
if ($l < 0 || !isset($word[$r]) || $word[$l] != $word[$r]) {
$longest = ($r - 1) - ($l + 1) + 1;
return !$longest ? 1 : $longest;
}
--$l;
++$r;
return getLenRecursive($l, $r, $word);
}
function getLongestPalSubstrLength($inp)
{
if ($inp === null || strlen($inp) === 0) {
return 0;
}
$longestLength = 1;
for ($i = 0; $i <= strlen($inp); $i++) {
$l = $i - 1;
$r = $i + 1;
$length = getLenRecursive($l, $r, $inp); # around char
if ($i > 0) {
$length2 = getLenRecursive($l, $i, $inp); # around center
$longerOne = $length > $length2 ? $length : $length2;
} else {
$longerOne = $length;
}
$longestLength = $longerOne > $longestLength ? $longerOne : $longestLength;
}
return $longestLength;
}
echo 'expected: 5, got: ';
var_dump(getLongestPalSubstrLength($input));
echo 'expected: 4, got: ';
var_dump(getLongestPalSubstrLength($input2));
echo 'expected: 6, got: ';
var_dump(getLongestPalSubstrLength($input3));
echo 'expected: 3, got: ';
var_dump(getLongestPalSubstrLength($input4));
echo 'expected: 4, got: ';
var_dump(getLongestPalSubstrLength($input5));
echo 'expected: 5, got: ';
var_dump(getLongestPalSubstrLength($input6));
echo 'expected: 9, got: ';
var_dump(getLongestPalSubstrLength($input7));
Your code doesn't really need to be recursive. A simple while loop would do just fine.
Yes, complexity is O(N^2). You have N options for selecting the middle point. The number of recursion steps goes from 1 to N/2. The sum of all that is 2 * (N/2) * (n/2 + 1) /2 and that is O(N^2).
For code review, I wouldn't do recursion here since it's fairly straightforward and you don't need the stack at all. I would replace it with a while loop (still in a separate function, to make the code more readable).

PHP - Get length of digits in a number

I would like to ask how I can get the length of digits in an Integer. For example:
$num = 245354;
$numlength = mb_strlen($num);
$numlength should be 6 in this example. Somehow I can't manage it to work?
Thanks
EDIT: The example code above --^ and its respective method mb_strlen(); works just fine.
Maybe:
$num = 245354;
$numlength = strlen((string)$num);
Accepted answer won't work with the big numbers. The better way to calculate the length of any number is to invoke floor(log10($num) + 1) with a check for 0.
$num = 12357;
echo $num !== 0 ? floor(log10($num) + 1) : 1; // prints 5
It has multiple advantages. It's faster, you don't do the casting of types, it works on big numbers, it works with different number systems like bin, hex, oct.
The equation does the logarithm with base 10 then makes the floor of it and adds 1.
This solution can work independently on the base, so if you want to calculate the length of binary or hex just change the base of the logarithm.
Working fiddle
The accepted solution presents a problem when evaluating negative numbers.
It works with a positive number:
$num = 245354;
$numlength = strlen((string)$num);
// Result: 6
But with a negative number, the (-) is added to the count:
$num = -245354;
$numlength = strlen((string)$num);
// Result: 7
Quick workaround:
$num = -245354;
$numlength = strlen((string)abs($num));
// Result: 6
More elegant way :)
ceil(log10($num));
You could also use some basic math!
$digits = (int)(log($num,10)+1)
<?php
$num = 123;
$num2 = 1234;
$num3 = 12345;
function digits($num){
return (int) (log($num, 10) + 1);
}
echo "\n $num: " . digits($num); // 123: 3
echo "\n $num2:" . digits($num2); // 1234: 4
echo "\n $num3:" . digits($num3); // 12345: 5
echo "\n";
Another way to find out the length of a number in digits would be to divide the integer part of the number to 10 until it becomes 0.
Example:
2021/10 = 202.1
202/10 = 20.2
20/10 = 2
2/10 = 0.2
Code:
function numberGetLength($number) {
$count = 0;
while (intval($number) > 0) {
$number = intval($number) / 10;
$count += 1;
}
return $count
}
Just using some version of (int)(log($num,10)+1) fails for 10, 100, 1000, etc. It counts the number 10 as 1 digit, 100 as two digits, etc. It also fails with 0 or any negative number.
If you must use math (and the number is non-negative), use:
$numlength = (int)(log($num+1, 10)+1);
Or for a math solution that counts the digits in positive OR negative numbers:
$numlength = ($num>=0) ? (int)(log($num+1, 10)+1) : (int)(log(1-$num, 10)+1);
But the strlen solution is just about as fast in PHP.
In PHP types are loosely set and guessed, if you want to see something as a string if it is an integer, float, and (i have not tried this) bool then #Gorjunav is the most correct answer.
Reset the variable as a string
$stringNum = (string) $num;
Then you can go anything string related you want with it! And vice-versa for changing a string to an int
$number = (int) $stringNum;
and so on...
count only integer value
`<?php
$n1 =12345;
$n2 =123454.55;
$n3 =12345564.557;
echo "The Number you Type: ".$n1."<br>";
$count = 0;
while ($n1 != 0)
{
$n1 = $n1 / 10;
$n1 = intval($n1);
++$count;
}
echo "The Digit in a Number: ".$count;
}
?>`
echo strlen((string) abs($num)); // using **abs** it'll work with negative integers as well
Tested in PHP 4.4.9 - 8.0.0
$array = array(-1, 0, -0, 1, 4, 9, 10, -10, 20, -20, 100, -100);
foreach( $array as $key => $num ){
echo $key."\t{$num}\t=>\t".($num !== 0 ? floor(log10(abs($num)) + 1) : 1)."\n";
}
/* Output:
0 -1 => 1
1 0 => 1
2 0 => 1
3 1 => 1
4 4 => 1
5 9 => 1
6 10 => 2
7 -10 => 2
8 20 => 2
9 -20 => 2
10 100 => 3
11 -100 => 3
*/
The following function work for either integers or floats (works with PHP7+):
function digitsCount($number): int
{
$number = abs($number);
$numberParts = explode(".", $number);
return
strlen($numberParts[0]) +
(strlen($numberParts[1] ?? 0));
}

Why does the modulus operator behave differently in Perl and PHP?

I've this PHP function which does not work for negative numbers:
function isOdd($num)
{
return $num % 2 == 1;
}
but it works for positive number.
I have this Perl routine which does the exact same thing and works for negative number also
sub isOdd()
{
my ($num) = #_;
return $num % 2 == 1;
}
Did I make any mistake in translating the function ? or is it PHP bug ?
In PHP the sign of the result of x % y is the sign of dividend which is x but
in Perl it is the sign of the divisor which is y.
So in PHP the result of $num % 2 can be be either 1, -1 or 0.
So fix your function compare the result with 0:
function isOdd($num) {
return $num % 2 != 0;
}

Replace duplicate values in array with new randomly generated values

I have below a function (from a previous question that went unanswered) that creates an array with n amount of values. The sum of the array is equal to $max.
function randomDistinctPartition($n, $max) {
$partition= array();
for ($i = 1; $i < $n; $i++) {
$maxSingleNumber = $max - $n;
$partition[] = $number = rand(1, $maxSingleNumber);
$max -= $number;
}
$partition[] = $max;
return $partition;
}
For example: If I set $n = 4 and $max = 30. Then I should get the following.
array(5, 7, 10, 8);
However, this function does not take into account duplicates and 0s. What I would like - and have been trying to accomplish - is to generate an array with unique numbers that add up to my predetermined variable $max. No Duplicate numbers and No 0 and/or negative integers.
Ok, this problem actually revolves around linear sequences. With a minimum value of 1 consider the sequence:
f(n) = 1 + 2 + ... + n - 1 + n
The sum of such a sequence is equal to:
f(n) = n * (n + 1) / 2
so for n = 4, as an example, the sum is 10. That means if you're selecting 4 different numbers the minimum total with no zeroes and no negatives is 10. Now go in reverse: if you have a total of 10 and 4 numbers then there is only one combination of (1,2,3,4).
So first you need to check if your total is at least as high as this lower bound. If it is less there is no combination. If it is equal, there is precisely one combination. If it is higher it gets more complicated.
Now imagine your constraints are a total of 12 with 4 numbers. We've established that f(4) = 10. But what if the first (lowest) number is 2?
2 + 3 + 4 + 5 = 14
So the first number can't be higher than 1. You know your first number. Now you generate a sequence of 3 numbers with a total of 11 (being 12 - 1).
1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12
The second number has to be 2 because it can't be one. It can't be 3 because the minimum sum of three numbers starting with 3 is 12 and we have to add to 11.
Now we find two numbers that add up to 9 (12 - 1 - 2) with 3 being the lowest possible.
3 + 4 = 7
4 + 5 = 9
The third number can be 3 or 4. With the third number found the last is fixed. The two possible combinations are:
1, 2, 3, 6
1, 2, 4, 5
You can turn this into a general algorithm. Consider this recursive implementation:
$all = all_sequences(14, 4);
echo "\nAll sequences:\n\n";
foreach ($all as $arr) {
echo implode(', ', $arr) . "\n";
}
function all_sequences($total, $num, $start = 1) {
if ($num == 1) {
return array($total);
}
$max = lowest_maximum($start, $num);
$limit = (int)(($total - $max) / $num) + $start;
$ret = array();
if ($num == 2) {
for ($i = $start; $i <= $limit; $i++) {
$ret[] = array($i, $total - $i);
}
} else {
for ($i = $start; $i <= $limit; $i++) {
$sub = all_sequences($total - $i, $num - 1, $i + 1);
foreach ($sub as $arr) {
array_unshift($arr, $i);
$ret[] = $arr;
}
}
}
return $ret;
}
function lowest_maximum($start, $num) {
return sum_linear($num) + ($start - 1) * $num;
}
function sum_linear($num) {
return ($num + 1) * $num / 2;
}
Output:
All sequences:
1, 2, 3, 8
1, 2, 4, 7
1, 2, 5, 6
1, 3, 4, 6
2, 3, 4, 5
One implementation of this would be to get all the sequences and select one at random. This has the advantage of equally weighting all possible combinations, which may or may not be useful or necessary to what you're doing.
That will become unwieldy with large totals or large numbers of elements, in which case the above algorithm can be modified to return a random element in the range from $start to $limit instead of every value.
I would use 'area under triangle' formula... like cletus(!?)
Im really gonna have to start paying more attention to things...
Anyway, i think this solution is pretty elegant now, it applies the desired minimum spacing between all elements, evenly, scales the gaps (distribution) evenly to maintain the original sum and does the job non-recursively (except for the sort):
Given an array a() of random numbers of length n
Generate a sort index s()
and work on the sorted intervals a(s(0))-a(s(1)), a(s(1))-a(s(2)) etc
increase each interval by the
desired minimum separation size eg 1
(this necessarily warps their
'randomness')
decrease each interval by a factor
calculated to restore the series sum
to what it is without the added
spacing.
If we add 1 to each of a series we increase the series sum by 1 * len
1 added to each of series intervals increases sum by:
len*(len+1)/2 //( ?pascal's triangle )
Draft code:
$series($length); //the input sequence
$seriesum=sum($series); //its sum
$minsepa=1; //minimum separation
$sorti=sort_index_of($series) //sorted index - php haz function?
$sepsum=$minsepa*($length*($length+1))/2;
//sum of extra separation
$unsepfactor100=($seriesum*100)/($seriesum+sepsum);
//scale factor for original separation to maintain size
//(*100~ for integer arithmetic)
$px=series($sorti(0)); //for loop needs the value of prev serie
for($x=1 ; $x < length; $x++)
{ $tx=$series($sorti($x)); //val of serie to
$series($sorti($x))= ($minsepa*$x) //adjust relative to prev
+ $px
+ (($tx-$px)*$unsepfactor100)/100;
$px=$tx; //store for next iteration
}
all intervals are reduced by a
constant (non-random-warping-factor)
separation can be set to values other
than one
implementantions need to be carefuly
tweaked (i usualy test&'calibrate')
to accomodate rounding errors.
Probably scale everything up by ~15
then back down after. Intervals should survive if done right.
After sort index is generated, shuffle the order of indexes to duplicate values to avoid runs in the sequence of collided series.
( or just shuffle final output if order never mattered )
Shuffle indexes of dupes:
for($x=1; $x<$len; $x++)
{ if ($series($srt($x))==$series($srt($x-1)))
{ if( random(0,1) )
{ $sw= $srt($x);
$srt($x)= $srt($x-1);
$srt($x-1)= $sw;
} } }
A kind of minimal disturbance can be done to a 'random sequence' by just parting dupes by the minimum required, rather than moving them more than minimum -some 'random' amount that was sought by the question.
The code here separates every element by the min separation, whether duplicate or not, that should be kindof evenhanded, but overdone maybe. The code could be modified to only separate the dupes by looking through the series(sorti(n0:n1..len)) for them and calculating sepsum as +=minsep*(len-n) for each dupe. Then the adjustment loop just has to test again for dupe before applying adjustment.

Categories