Nested recursive function is throwing an error [duplicate] - php

This question already has answers here:
"Fatal error: Cannot redeclare <function>"
(18 answers)
Closed 2 years ago.
I have a nested recursive function it's a task from codewars.
persistence(39) === 3; // because 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4
and 4 has only one digit persistence(999) === 4; // because 9 * 9 * 9
= 729, 7 * 2 * 9 = 126, 1 * 2 * 6 = 12, and finally 1 * 2 = 2;
persistence(4) === 0; // because 4 is already a one-digit number
which throws :
Fatal error: Cannot redeclare rec();
function persistence(int $num): int {
$str = (string)$num;
$nums = str_split($str);
$count = count($nums);
if( $count === 0 ){
return 0;
}
$x = 0;
function rec($nums, $n) {
$result = [];
for ($i = 0; $i < count($nums); ++$i) {
if ($i == 0) {
$result = $nums[$i];
} else {
$result *= $nums[$i];
}
}
$num = implode('',$nums);
$diff = $num - $result;
if ( $diff != 0 ) {
$n += 1;
$result = str_split($result,1);
return rec($result, $n);
}
return $n;
}
$result = rec($nums,$x);
return (int)$result;
}
I've tried to use an variable function
$rec = 'rec';
$result = $rec($nums,$n)
but there are another error : `
Fatal error: Cannot redeclare rec()
`
PHP 7.4 version. Can anyone explain me what the problem is ?

Don't define the function inside the other function:
You have:
function persistence(int $num): int {
// code ...
function rec($nums, $n) {
// code ...
}
}
This means that the function rec should be created each time the function persistence gets called.
You should define them first:
function persistence(int $num): int {
// code ...
}
function rec($nums, $n) {
// code ...
}
And then call them to your liking, for example like you already do:
$rec = 'rec';
$result = $rec($nums,$n)

Related

is this ISBN-10 Checksum calculation in php correct?

I have found a PHP script github ISBN-Calc Routine to perform the ISBN-10 checksum calculation:
<?php
/**
* Calculate ISBN checksum
*
* #param string $isbn
* #return integer
*/
function isbn_checksum($isbn) {
$sum = 0; $isbn = str_split(preg_replace('/[^\d]/', '', $isbn));
foreach($isbn as $key => $z) {
if($key >= 12) break;
$sum += ($key % 2) ? $z * 3 : $z;
}
$checksum = (10 - $sum % 10);
return ($checksum == 10) ? 0 : $checksum;
}
But f.e for my ISBN-10: 0470173424 I get Checksum: 0with this github script.
Accoring to ISBN online checker the checksum should be 4 as is it in the ISBN. Can anyone here provide me with the correct PHP routine, please?
Thanks
That function is for calculating an ISBN-13 check digit, not ISBN-10 - that's why it breaks the loop after the 12th character.
The algorithm for ISBN-10 is different, and requires multiplying the first 9 digits of the number by 10 down to 2. The difference between that sum and the next multiple of 11 is the check-digit. For your example, this would be:
(10 * 0) +
(9 * 4) +
(8 * 7) +
(7 * 0) +
(6 * 1) +
(5 * 7) +
(4 * 3) +
(3 * 4) +
(2 * 2) = 161.
The next multiple of 11 is 165, so the check-digit should be 4 (as you say). In the case where the check-digit would be 10, X is used. We can model this in PHP like this:
function isbn10($isbn) {
$isbn = preg_replace('/[^\d]/', '', $isbn);
$digits = str_split(substr($isbn, 0, 9));
$sum = 0;
foreach ($digits as $index => $digit) {
$sum += (10 - $index) * $digit;
}
$check = 11 - ($sum % 11);
return ($check === 10) ? 'X' : $check;
}
echo isbn10('047017342');
4
You can see this working here: https://eval.in/1039654
The previously marked answer is close but incomplete.
Specifically this portion:
$check = 11 - ($sum % 11); // This can output 1,2,3,4,5,6,7,8,9,10,11 not 0
return ($check === 10) ? 'X' : $check; // This is incomplete does not address 11
The code does not deal with the situation where 11 - 0 = 11. I have tried to clarify it below.
function isbn10($isbn)
{
$isbn = preg_replace('/[^\d]/', '', $isbn);
$digits = str_split(substr($isbn, 0, 9));
$sum = 0;
foreach ($digits as $index => $digit)
{
$sum += (10 - $index) * $digit;
}
$check = 11 - ($sum % 11);
// $check may hold either 10 or 11, but not 0
// 10 becomes X, 11 becomes 0 -- output is 1 character only
if ($check == 10)
{
$check = 'X';
}
elseif ($check == 11)
{
$check = '0';
}
return $check;
}
An example ISBN where the earlier answer fails is 0134093410
There is an library from GitHub: https://github.com/Fale/isbn
There is a function called "Check":
Initialization:
$isbn = new Isbn\Isbn();
Check values: (Example)
$isbn->check->is10('888183718'); // Will return false
$isbn->check->is13('9788889527191'); // Will return true
$isbn->check->is13('978888952719'); // Will return false
You can download the library from the given link.
Maybe that helps a bit.
Have a nice weekend!
If you want to check if the ISBN-10 is correct
Validate ISBN-10
<?php
function isValidIsbn10($isbn) {
$check = 0;
for ($i = 0; $i < 10; $i++) {
if ('x' === strtolower($isbn[$i])) {
$check += 10 * (10 - $i);
} elseif (is_numeric($isbn[$i])) {
$check += (int)$isbn[$i] * (10 - $i);
} else {
return false;
}
}
return (0 === ($check % 11)) ? 1 : false;
}
var_dump( isValidIsbn10('0470173424') );
Source: https://stackoverflow.com/a/14096142/5201919
Will show
1 for true
Demo
https://eval.in/1053913

Sort by time PHP

i have this function sort_by_time, the purpose of this function is to swap the time1 if the time2 is greater than time1 but my problem is im having an error of Undefined offset: 0. Sometimes the error is Undefined offset: 1. or Undefined offset: 2. Can someone help me to prevent this error in my code? I'm thinking this in these last 3 days but i can't think of any solution on this.
in this line the error occur.
if (Payroll2::convert_time_in_minutes($_time[$j]->time_in) > Payroll2::convert_time_in_minutes($_time[$j+1]->time_in))
This error occurs because the $_time[0] is not set.
Sample time. This is dynamic not only limited to 3 sometimes it's 4, sometimes it's 5 or 1.
1 => {#6356}
2 => {#6352}
3 => {#6257}
Here's my full function code
public static function sort_by_time($_time)
{
$count = 0;
$n = count($_time);
for ($i = 0; $i < $n-1; $i++)
{
for ($j = 0; $j < $n-$i-1; $j++)
{
if (Payroll2::convert_time_in_minutes($_time[$j]->time_in) > Payroll2::convert_time_in_minutes($_time[$j+1]->time_in))
{
// swap temp and arr[i]
$temp = $_time[$j];
$_time[$j] = $_time[$j+1];
$_time[$j+1] = $temp;
}
}
}
return $_time;
}
Try this:
public static function sort_by_time($_time)
{
usort($_time,function($ad,$bd)
{
$ad = Payroll2::convert_time_in_minutes($ad->time_in);
$bd = Payroll2::convert_time_in_minutes($bd->time_in);
if ($ad == $bd) {
return 0;
}
return $ad < $bd ? -1 : 1;
});
return $_time;
}
if it doesn't work the problem can be in function Payroll2::convert_time_in_minutes

Return table values in php

I have this code:
public function getYears()
{
for($yearNum = 1; $yearNum <= 12; $yearNum++){
$year[]=$this->year;
echo $year[$yearNum]=$yearNum;
}
return $yearNum;
}
I have this error:
PHP Warning – yii\base\ErrorException
Invalid argument supplied for foreach()
How can i return this 12 numbers?
As per your comments:
i need only 12 numbers(1,2,3,4,5,6,7,8,9,10,11,12) without 0
You can get 12 numbers by using this:
public function getYears()
{
for($yearNum = 1; $yearNum <= 12; $yearNum++){
//$year[] = $yearNum;
$year[] = $yearNum;
//echo $year[$yearNum]=$yearNum;
}
return $year;
}
// calling function
$result = $this->getYears();
//echo "<pre>";
$numbers = implode(",", $result);
echo $numbers; //1,2,3,4,5,6,7,8,9,10,11,12

How to fix undefined offset and undefined index

Hello I have this code which selects from a list of 20 items 12 and from those 12 1 is randomly selected and echoed:
class Gamble
{
public static function doPointsCheck()
{
global $Gamble;
$Gamble_points = '2';
if($Gamble_points <= 1)
return false;
else
return true;
}
public static function Spin()
{
global $Wheel;
if(!self::doPointsCheck())
return 'You need way too more points to gamble';
else
{
$Result = array();
$Result = range(1, 12);
shuffle($Result);
$Result = array_slice($Result, 0, 20);
$SendToCheck = self::CheckPrize($Result);
}
}
public static function CheckPrize($Array)
{
global $Wheel;
echo '<h1>List of items you can win today:</h1><form action="class.MysticWheel.php" method="post">';
for($i = 1; $i <= count($Array); $i++)
{
$Won = '<p>'.$Wheel[$Array[$i]]['pseudo'].'</p>';
echo $Won;
}
echo '<input name="Feeling lucky" type="submit" value="Feeling Lucky" /></form>';
if ($_SERVER['REQUEST_METHOD'] === 'POST'){
$i = rand( 1, 12 );
$Prize = '<p>'.$Wheel[$Array[$i]]['pseudo'].'</p>';
echo $Prize;
}
}
}
When I test it I recieve the following error:
Notice: Undefined offset: 12 on line 54
Notice: Undefined index: on line 54
So i won't show the last item, it will only show 11 possible items that could have been won and get the notice.
How can I fix it?
$Result = range(1, 12);
-->
foreach (range(1, 12) as $number) {
$Result[] = $number;
}
Try this.

opencart creating and using a custom helper

I created a helper in opencart following information I found here on stackoverflow, but I have a problem:
First I created a helper file called general.php and placed inside the folder:
system/helper/general.php
Then started in startup.php file
require_once(DIR_SYSTEM 'helper/general.php');
Finally, I use it inside the controller: register.php which is inside the folder catalog/controller/account/register.php.
I used it in this way:
if (empty($this->request->post['doc']) && $this->general->validate($this->request->post['doc'])) {
$this->error['doc'] = 'doc is invalid';
}
And is returning the following error:
Fatal error: Call to a member function validate() on a non-object in / home/centralshopdistribuidora/www/vqmod/vqcache/vq2-catalog_controller_account_register.php on line 515
line 515:
if (empty($this->request->post['doc']) && $this->general->validate($this->request->post['doc'])) {
The general.php file:
function validate($doc) {
$d1 = 0;
$d2 = 0;
$doc = preg_replace("/[^0-9]/", "", $doc);
$ignore_list = array(
'00000000000',
'01234567890',
'11111111111',
'22222222222',
'33333333333',
'44444444444',
'55555555555',
'66666666666',
'77777777777',
'88888888888',
'99999999999'
);
if (strlen($doc) != 11 || in_array($doc, $ignore_list)) {
return false;
} else {
for ($i = 0; $i < 9; $i++) {
$d1 += $doc[$i] * (10 - $i);
}
$r1 = $d1 % 11;
$d1 = ($r1 > 1) ? (11 - $r1) : 0;
for ($i = 0; $i < 9; $i++) {
$d2 += $doc[$i] * (11 - $i);
}
$r2 = ($d2 + ($d1 * 2)) % 11;
$d2 = ($r2 > 1) ? (11 - $r2) : 0;
return (substr($doc, -2) == $d1 . $d2) ? true : false;
}
}
You first need to register this helper into the registry, e.g. in Your index.php find line
// Encryption
$registry->set('encryption', new Encryption($config->get('config_encryption')));
(referring to OC 1.5.5 and higher) and after this register Your helper the same way, e.g.
// General
$registry->set('general', new General()));
This should be enough. Make sure to change the constructor call if You have some dependencies...

Categories