The code below basically helps in finding out if a number is a Palindromic Number or not. Although I get my execution done with the output, I just can seem to handle all the "screams" and fatal errors that I get. How do I handle this. Just a beginner and trust you can explain in a way that I may be able to understand..
<?php
for ($num = 1; $num <= 20; ++$num){
$_array1 = str_split($num);
//print_r($_array1);
//echo "<br/>";
$_array2 = array_reverse($_array1);
//print_r($_array2);
//echo "<br/>";
$i = 0;
$j = 0;
while ($i < sizeof($_array1) && $j < sizeof($_array2)){
if ($_array1[$i] == $_array2[$j]){
++$i;
++$j;
}
}
if ($_array1[$i] == $_array2[$j]){
echo "The number $num is a Palindrome Number";
}
}
?>
You get to the size of elements, which is 1. However, if your array has only one element, which is the case for 1-digit numbers, then sizeof($_array) === 1. Which means that the biggest possible index you can use is 0. You need to change your code to something like this:
<?php
for ($num = 1; $num <= 20; ++$num){
$_array1 = str_split($num);
//print_r($_array1);
//echo "<br/>";
$_array2 = array_reverse($_array1);
//print_r($_array2);
//echo "<br/>";
$i = 0;
$j = 0;
$different = false;
while ((!$different) && ($i < sizeof($_array1))){
if ($_array1[$i] == $_array2[$j]){
++$i;
++$j;
} else {
$different = true;
}
}
if (!$different){
echo "The number $num is a Palindrome Number";
}
}
?>
But you are inversing the array without a need to do so and you are looping for unnecessarily long. I propose this function to determine whether an array is a palindrome:
function isPalindrome($input) {
$size = count($input);
for ($index = 0; $index < $size / 2; $index++) {
if ($input[$index] != $input[$size - $index - 1]) {
return false;
}
}
return true;
}
Note, that:
the function assumes that the keys of the array are numbers
the function uses a single array
the size of the array is stored into a local variable to not calculate it repeatedly
the cycle cycles until half of the array, since going beyond that is unnecessary, due to the symmetrical nature of the != operator
the function returns false when the first difference is found, to further optimize the checking
if there were no differences, the function returns true, representing that the input is a palindrome
Related
I'm working on Project Euler problem 3, but my code gives a weird error. The error is:
Fatal error: Can't use function return value in write context in
D:\Google Drive\ITvitae\PHP5\ProjectEuler\PE3-PrimeFactor2.php on line
52
This is the code I'm running:
<html>
<body>
<?php
ini_set('memory_limit', '1024M');
ini_set('set_time_limit', '120');
$max = 1000000;
#$max = 600851475143;
$primes = array();
// Define sqrt ceiling
$maxSqrt = ceil(sqrt($max));
function isPrime($num) {
// 1 is not prime
if ($num == 1)
return false;
// 2 is prime
if ($num == 2)
return true;
// Removes all even numbers
if ($num % 2 == 0) {
return false;
}
// Check odd numbers, if factor return false
// The sqrt can be an aproximation, round it to the next highest integer value.
$ceil = ceil(sqrt($num));
for ($i = 3; $i <= $ceil; $i = $i + 2) {
if($num % $i == 0)
return false;
}
return true;
}
//Push latest prime into array
for ($i = 2; $i <= $maxSqrt; $i++) {
if (isPrime($i)) {
array_push($primes, $i);
}
}
// Check whether $max is divisible by $primes($j)
for ($j = 0; $j <= count($primes); $j++) {
if ($max % $primes($j) = 0) {
$max = $max / $primes($j);
}
}
//echo "<pre>";
//var_dump($primes);
//echo "</pre>";
echo array_pop($primes);
?>
</body>
</html>
Line 52 being
if ($max % $primes($j) = 0) {
Under // Check whether $max is divisible by $primes($j)
I've never seen this error before, and I don't understand why it's giving it. In my head, the logic is flawless (which inevitably, therefore it isn't). What is going wrong here?
EDIT: Changed it to
if ($max % $primes($j) == 0) {
But it tells me the Function name must be a string. I don't understand.
The first problem was, you used = for comparison. = is an assignment and you couldn't assign a value to an expression (that wouldn't have a usefull meaning..)
Second, you have to use [] for array access, instead of (). Using () after an identifier or var always tries to call an function. In your case $primes is an array, which isn't a function.
Third, you should fix the of-by-one array access error in your for-loop.
for ($j = 0; $j < count($primes); $j++) { // < instead of <=
if ($max % $primes[$j] == 0) { // == instead of = and [] instead of ()
$max = $max / $primes[$j]; // again [] instead of ()
}
}
I need to calculate from a given array the number that is equal or higher and closest to a given number in PHP. Example:
Number to fetch:
6.85505196
Array to calculate:
3.11350000
4.38350000
4.04610000
3.99410000
2.86135817
0.50000000
Only correct combination should be:
3.99410000 + 2.86135817 = 6.85545817
Can somebody help me? It's been 3 hours I'm getting mad!
UPDATE: I finally finished my code as following:
$arr = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
$fetch = 6.85505196;
$bestsum = get_fee($arr, $fetch);
print($bestsum);
function get_fee($arr, $fetch) {
$bestsum = 999999999;
$combo = array();
$result = array();
for ($i = 0; $i<count($arr); $i++) {
combinations($arr, $i+1, $combo);
}
foreach ($combo as $idx => $arr) {
$sum = 0;
foreach ($arr as $value) {
$result[$idx] += $value;
}
if ($result[$idx] >= $fetch && $result[$idx] < $bestsum) $bestsum = $result[$idx];
}
return $bestsum;
}
function combinations($arr, $level, &$combo, $curr = array()) {
for($j = 0; $j < count($arr); $j++) {
$new = array_merge($curr, array($arr[$j]));
if($level == 1) {
sort($new);
if (!in_array($new, $combo)) {
$combo[] = $new;
}
} else {
combinations($arr, $level - 1, $combo, $new);
}
}
}
I hope the following example might help you. Please try this
<?php
$array = array(
"3.11350000",
"4.38350000",
"4.04610000",
"3.99410000",
"2.86135817",
"0.50000000"
);
echo "<pre>";
print_r($array);// it will print your array
for($i=0; $i<count($array); $i++)
{
$j=$i+1;
for($j;$j<count($array); $j++)
{
$sum = $array[$i] + $array[$j];
// echo $array[$i]. " + ".$array[$j]." = ".$sum."<br>"; //this will display all the combination of sum
if($sum >= 6.85505196 && ($sum <= round(6.85505196)) )//change the condition according to your requirement
{
echo "The correct combinations are:<br/><br/>";
echo "<b>". $array[$i]. " + ".$array[$j]." = ".$sum."<b>";
echo "<br/>";
}
}
echo "<br/>";
}
?>
We will get the result as below
Array
(
[0] => 3.11350000
[1] => 4.38350000
[2] => 4.04610000
[3] => 3.99410000
[4] => 2.86135817
[5] => 0.50000000
)
The correct combinations are:
4.04610000 + 2.86135817 = 6.90745817
3.99410000 + 2.86135817 = 6.85545817
You should do it in two steps:
a. Work out (or look up) an algorithm to do the job.
b. Implement it.
You don't say what you've managed in the three hours you worked on this, so here's a "brute force" (read: dumb) algorithm that will do the job:
Use a variable that will keep your best sum so far. It can start out as zero:
$bestsum = 0;
Try all single numbers, then all sums of two numbers, then all sums of three numbers, etc.: Every time you find a number that meets your criteria and is better than the current $bestsum, set $bestsum to it. Also set a second variable, $summands, to an array of the numbers you used to get this result. (Otherwise you won't know how you got the solution). Whenever you find an even better solution, update both variables.
When you've tried every number combination, your two variables contain the best solution. Print them out.
That's all. It's guaranteed to work correctly, since it tries all possibilities. There are all sorts of details to fill in, but you can get to work and ask here for help with specific tasks if you get stuck.
Thank you all for your help!
My code is working pretty cool when is needed to fetch one or two numbers (addition) only. But can't figure out how to add more combinations up to the total count of elements in my given array.
I mean if there are, let's say, 8 numbers in my array I want to try all possible combinations (additions to each other) as well.
My actual code is:
$bestsum = 1000000;
for ($i = 0; $i < count($txinfo["vout"]); $i++) {
if ($txinfo["vout"][$i]["value"] >= $spent && $txinfo["vout"][$i]["value"] < $bestsum) {
$bestsum = $txinfo["vout"][$i]["value"];
}
}
for($i = 0; $i < count($txinfo["vout"]); $i++) {
$j = $i + 1;
for($j; $j < count($txinfo["vout"]); $j++) {
$sum = $txinfo["vout"][$i]["value"] + $txinfo["vout"][$j]["value"];
if($sum >= $spent && $sum < $bestsum) {
$bestsum = $sum;
}
}
}
$fee = bcsub($bestsum, $spent, 8);
print("Fee: ".$fee);
New updated code.
<?php
$x = 6.85505196;
$num = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
asort($num); //sort the array
$low = $num[0]; // lowest value in the array
$maxpossible = $x+$low; // this is the maximum possible answer, as we require the number that is equal or higher and closest to a given number
$num = array_values($num);
$iterations = $x/$num[0]; // possible combinations loop, to equate to the sum of the given number using the lowest number
$sum=$num;
$newsum = $sum;
$k=count($num);
for($j=0; $j<=$iterations; $j++){
$l = count($sum);
for($i=0; $i<$l; $i++){
$genSum = $sum[$j]+$sum[$i];
if($genSum <= $maxpossible){
$newsum[$k] = $genSum;
$k++;
}
}
$newsum = array_unique($newsum);
$newsum = array_values($newsum);
$k = count($newsum);
$sum = $newsum;
}
asort($newsum);
$newsum = array_values($newsum);
for($i=0; $i<count($newsum); $i++){
if($x<=$newsum[$i]){
echo "\nMaximum Possible Number = ".$newsum[$i];
break;
}
}
?>
Suppose 100 people line up in a circle. Counting from person 1 to person 14, remove person from the circle. Following the count order, counting again and remove the 14th person. Repeat. Who is the last person standing?
I've tried everything to solve this and it seems to not be working with dead loops.
<?php
//init array
$array = array();
for ($i = 0; $i < 100; $i++) { $array[] = $i; }
//start from 0
$pos = 0;
while (count_not_null($array) > 1) {
//reset count
$count = 0;
while (true) {
//ignore NULL for count, that position is already removed
if ($array[$pos] !== NULL) {
$count++;
if($count == 14) { break; }
}
$pos++;
//go back to beginning, we cant go over 0-99, for 100 elements
if ($pos > 99) { $pos = 0; }
}
echo "set index {$pos} to NULL!" ."<br>";
$array[$pos] = NULL;
if (count_not_null($array) === 1) { break; }
}
echo "<pre>";
print_r($array);
echo "</pre>";
//counting not null elements
function count_not_null($array) {
$count = 0;
for ($i = 0; $i < count($array); $i++) {
if ($array[$i] !== NULL) { $count++; }
}
return $count;
}
?>
For solving this with as little code as possible and quickest you could do like this:
function josephus($n,$k){
if($n ==1)
return 1;
else
return (josephus($n-1,$k)+$k-1) % $n+1;
}
echo josephus(100,14);
Here we are using an recursive statement instead, as what you are trying to solve can be defined by this mathematical statement f(n,k) = (f(n-1,k) + k) % n
For reading more about this mathematical formula you can see it here on the wiki page.
The problem is this while loop
while ($count < 14) {
if ($array[$pos] != NULL) {
$count++;
}
$pos++;
if ($pos > 99) { $pos = 0; }
}
Because you increment $pos even if count is 14 you will end with incorrect values and loop forever. Replace it with this:
while (true) {
if ($array[$pos] != NULL) {
$count++;
if($count == 14) {break;}
}
$pos++;
if ($pos > 99) { $pos = 0; }
}
Also comparing 0 to NULL won't give you the expected results as mentioned by #Barmar, so you can either change the NULL comparison, or start counting from 1
NOTE: This would be way faster if you didn't loop through array every time :D consider using a variable to count the remaining items
Anyone who stumbles across this again, here is a slightly quicker one:
function josephus($n){
$toBin = decbin($n); // to binary
$toBack = substr($toBin,1) . "1"; // remove first bit and add to end
return bindec($toBack); // back to value
}
Based on this solution.
I have this code that for some reason it keeps in an infinite loop, when it is suppose to just print all possible substrings. This is part of the complete function. The purpose of the function is to return the indexes of the substring from string $str2 found in string $str1. Thanks a lot for the help.
$str1='QYDIKYTWNVPKIAPKS';
$str2='KYTWNVPKSS';
print($str1);echo"</br>";print($str2);echo"</br>";
function overlapping($str1,$str2) {
$peptide1 = str_split($str1);
$peptide2 = str_split($str2);
$longest_seq=array();
$len=count($peptide2)-1;
for ($i = 0; $i < count($peptide1); ++$i) {
for ($j = 0; $j < count($peptide2); ++$j) {
if ($peptide2[$j]==$peptide1[$i]){
$k=$j;
$start=$j;
$l=$i;
$tmp=array();
while ($peptide2[$k]==$peptide1[$l]){
array_push($tmp, $peptide2[$k]);
$substring=implode($tmp);
print $substring;
echo"</br>";
$k=$k+1;
$l=$l+1;
}
}
}
}
}
Maybe you have another idea of how to extract the index of a matching substring, I can also try that
You never check to insure that $k and $l are valid offsets. Check for it here :
while (isset($peptide2[$k]) && isset($peptide1[$l]) && $peptide2[$k]==$peptide1[$l]){
instead of
while ($peptide2[$k]==$peptide1[$l]){
I'm not sure if this has anything to do with your issue, but I always post-increment in my for loops.
for ($i = 0; $i < count($peptide1); $i++) {
// do stuff
}
I'm trying to determine if three sequential integers exist within an array. I've tested the code on several PHP sandbox sites, but as they don't allow the use of fgets, I've tested with an array that I have pre-filled with the 5 integers. The code works just fine under those circumstances, but fails miserably when run with an array filled by user-input. I'm not sure where the problem is, but any assistance would be greatly appreciated.
<?php
echo "Enter 5 Numbers:";
//{Write your code here
$arr = array();
for($i = 0; $i < 5; $i++){
$arr[$i] = trim(fgets(STDIN));
}
sort($arr);
function FindSeq($arr){
for($i = 0; $i < 3; $i++){
while($i < 3) {
$a = $i;
$b = $a + 1;
$c = $b + 1;
if(((($arr[$a]) + 1) === $arr[$b]) && ((($arr[$b]) + 1) === $arr[$c]) !== FALSE) {
exit("true");
}
else {
$i++;
}
}
}
}
FindSeq($arr);
echo "false";
?>
The lines are read in as strings, however you add + 1 which casts it to an integer. Then you use a strict comparison === with a string. Either use loose comparisons == or cast the values to an integer:
$arr[$i] = (int)trim(fgets(STDIN));
Here's a quick way to do this:
for($i = 2; $i=count($arr)-2; $i++)
if(($arr[$i-1] == $arr[$i]+1) && ($arr[$i+1] == $arr[$i] + 1))
return true;
return false;
The loop numbers account for your use of $arr[1] as the first element of the array. Something prettier would be more general.