Populating an Array with recursive function of a class - php

I'm getting stuck with maybe a simple question. I created a new class with many calculations inside. I have a recursive array to dynamically generate SQL from a Die result. When the result is between a given range, I'll have to do an extra operation.
I've got this multi-dimensional array to fill with the value of my dice, using an array of IDs as my first "key":
$this->multidim[$id_object][]
I was thinking about creating another function to populate it, but I'm unsure how to build it correctly. The specifications of this function I need are the following:
I need to call a function with the multidimensional array, and
If the result is 100, I need to re-roll the dice twice, and check the result again
$this->checkresult($id_obj, $die);
function checkresult($id_obj, $die)
{
if ($die == 100){
$rand1 = $this->launchDie(1, 100);
$rand2 = $this->launchDie(1, 100);
if($this->checkresult($array, $rand1)) {
if($this->checkresult($array, $rand2)) {
return 1;
}
}
} else {
if (!isset($array[$tiro])) {
$this->multidim[$id_obj][$die] = 1;
}
return 1;
}
}
Is this approach correct? I feel uncomfortable not returning a "real" value, but as I said I need to re-call that function recursively.

You can return the rolled value like this:
public function addResult($object_id, $result)
{
$this->multidim[$object_id][] = $result;
}
public function checkResult($object_id)
{
$roll = $this->launchDie(1, 100);
if ($roll == 100) {
$additionalRoll = $this->checkResult($object_id);
$this->addResult($object_id, $additionalRoll);
$roll = $this->checkResult();
}
return $roll;
}
And call it like this:
$this->addResult($object_id, $this->checkResult($object_id));
This way each time a 100 is rolled there will be two rolls instead of the one. Please note that this could go on forever (improbable, though ;)).
Also note that I changed the structure of your multidim array, as it made more sense to me that way, you may need to change that back if it doesn't match what you would like to achieve.

Related

I need a program in PHP, where I search a number in a series mentioned and then give output as the index on which it is present?

I need a program in PHP, when I search a number in a given series like 1,3,7,15,31... and if it is present in the series then give output as the index on which it is present in series?
LIKE I HAVE DONE SOMETHING TO DO THIS BUT FAILED.
<?php
function test1($n) {
for($i=1;$i<=$n;$i=$c) {
$c =1 + (2 * $i);
}
}
function test2($p) {
global $c,$n;
$input=array(1);
$in=array_push($input,$c);
$k=array_search($p,$input);
$flipped = array_flip($k);
var_dump($flipped);
}
test1(1000000);
test2(45);
Like in this program I had made two functions and in FUNCTION test1 I made a formula to make the series 1,3,7,15,31,63,127.... and in FUNCTION test2 I insert a number in form of parameter and want to SEARCH that number in the series that I form above and the I want OUTPUT as the index of that number searched.
Also if the number is not present in the series then I want the output as the nearest number of the number I search.
HELP.!!!
Thank You
You've got a few problems with this code.
function test1($n) {
for($i=1;$i<=$n;$i=$c) {
$c =1 + (2 * $i);
}
}
The first problem here is that you don't do anything with $c each time you increment it. You should probably be pushing it into an array of series integers.
Secondly you don't return a result, so you can't actually use the series you would've created.
You could use something like this instead:
function test1($limit) {
$series = [];
for ($i = 1; $i <= $limit; $i = $i * 2 + 1) {
$series[] = $i;
}
return $series;
}
Next, your test2 function:
function test2($p) {
global $c,$n;
$input=array(1);
$in=array_push($input,$c);
$k=array_search($p,$input);
$flipped = array_flip($k);
var_dump($flipped);
}
Ok, first don't use global variables. Pass the ones you need in as arguments and again, return the result. To be perfectly honest, I'm not entirely sure what this function is supposed to do. All you need is the array_search call which "searches the array for a given value and returns the first corresponding key if successful".
For example:
function test2($series, $number) {
return array_search($number, $series);
}
Using these, you can do something like this:
$series = test1(1000000);
var_dump(test2($series, 45)); // bool(false)
var_dump(test2($series, 31)); // int(4)
Also if the number is not present in the series then I want the output as the nearest number of the number I search.
Ok, you'll need to write some custom logic for this. I suggest you run your array_search check, then if it returns false you loop through your series and check the following criteria:
The previous series entry is lower than your number
The next series entry is higher than your number
Then return whichever of those two has a smaller absolute difference when you subtract the series entry from your number.
I'm not going to write an example for this because it smells a bit like a school assignment, which I'm sure you're capable of doing =) good luck.

PHP OOP array duplicated in method

Very new to OOP so please bear with me. I have a method that checks characteristics of a persons array and has a counter to keep track of things. The persons array starts off as serialized data, which I'm converting to an array with the unzerialize() function. When I do var_dump($this->people) in the constructor, I get the correct values. When I do the same in any of the other methods in the class, the array is duplicated a number of times and my counter produces incorrect values.
Also doing echo gettype($this->people) in the constructor results in array as expected, but in the other methods results in arrayarrayarrayarray....
What could be causing this duplication? And how do I solve it?
* EDIT *
Sorry for the confusion. I did not know where the problem was so it was difficult for me to explain properly.
The problem is not with my class definition, but how I am using the object. I have reworked the code to illustrate. I thought that once the object was instantiated, the values produced by it would be set, however it turns out that each time I call the get_results() method, $this->num is incremented and the value is persisted.
So my question is, how do I run the get_results() method once, and access the results[] array without changing the values? I was hoping I could do something like if($nums['results']['num'] == 1) but that results in a fatal error.
class DoStuff
{
private $num;
public $results;
public function __construct($val)
{
$this->num = $val;
$this->results = [];
}
private function compute_num()
{
$this->num++;
$this->results['num'] = $this->num;
return $this->results;
}
public function get_results()
{
$this->results = $this->compute_num();
return $this->results;
}
}
$nums = new DoStuff(0);
$nums->get_results();
if($nums->get_results()['num'] == 1)
{
printf('<p>(if) Num is: %d</p>', $nums->get_results()['num']);
}
else
{
printf('<p>(else) Num is: %d</p>', $nums->get_results()['num']);
}
// Prints (else) Num is: 3
Ok, so I was trying to access an object as an array. The solution is to use get_object_vars() after running the get_results() method.
$nums = new DoStuff(0);
$nums->get_results();
$nums = get_object_vars($nums);
if($nums['results']['num'] == 1)
{
printf('<p>(if) Num is: %d</p>', (int) $nums['results']['num']);
}
else
{
printf('<p>(else) Num is: %d</p>', (int) $nums['results']['num']);
}
// Prints: (if) Num is: 1

How to use return inside a recursive function in PHP

Here is my question: I am trying to create a random bar code for my application. I want to check that if that code is already in the column, then generate a new number. Check it again. If it's unique, return it to the caller, else generate again.
I am using a recursive function for this purpose. I have added numbers 1,2,3,4 inside my database so every time it runs. It has to show me 5,6,7,8,9 or 10.
Here is my function:
function generate_barcode(){
$barcode = rand(1,10);
$bquery = mysql_num_rows(mysql_query("SELECT * FROM stock_item WHERE barcode='$barcode'"));
if($bquery==1){
generate_barcode();
}else{
return $barcode;
}
}
And I just tested it like this:
$a = generate_barcode();
if(isset($a))
{
echo $a;
}
else
{
echo 'Not Set';
}
So the problem is that it is sometimes showing me "Not Set", but I want it to always generate a unique number. I am not inserting the data, so it's not a problem that all of the numbers are reserved.
Someone just guide me and let me know what is wrong with the code. I can use other approaches to do that, but I need to know what is wrong with the supplied code.
You need to return the generated number from your recursive call too, like:
function generate_barcode() {
$barcode = rand(1, 10);
$bquery = mysql_num_rows(mysql_query("SELECT * FROM stock_item WHERE barcode='$barcode'"));
if ($bquery == 1) {
return generate_barcode(); // changed!
}
else {
return $barcode;
}
}
(You should include some kind of exit for the case that all numbers are 'taken'. This current version will call itself recursively until the PHP recursion limit is reached and will then throw an error.)
A return statement passes a value back to the immediate caller of the current function's call-frame. In the case of recursion, this immediate caller can be another invocation of that same function.
You can counter this by doing the following:
Change:
generate_barcode();
to:
return generate_barcode();
Do it like this:
$hash = md5( microtime().rand(0, 1000) );
Adding a time component means it will pretty much be unique. Unless you have like 32^32 of them.
If it has to be just numbers, just use the pkey and add like 10000 on to it for looks. or such.
After careful analysis - there is nothing wrong with it, but:
$a = generate_barcode();
if(isset($a)) <<< this bit
See you return the unique value and then you say it's isset my unique value, and $a will always be set, because if it's not you recurse the function until it is, and then you return it. Therefore it is always set...
You are trying to do:
while(true) {
$barcode = rand(1,10);
$bquery = mysql_num_rows(mysql_query("SELECT * FROM stock_item WHERE barcode='$barcode'"));
if($bquery===0){
break;
}
}
echo $barcode;
However, this will obviously only work for 10 bar codes and leading to an endless loop after that - meaning it is not the right approach to create a large number of bar codes.
Instead I would suggest to use an auto_increment to generate the bar code.
Btw, the mysql extension is deprecated. Use mysqli or PDO for new code.

PHP - Simplify Way of Handling Arrays

When dealing with arrays I am forced to add a bunch of repetitive code to handle arrays with one child versus multiple:
//If more than one step, process each step, elcse processs single
if(!array_key_exists('command',$pullcase['steps']['step'])) {
foreach($pullcase['steps']['step'] as $step) {
$command=$step['command'];
$parameter=$step['parameter'];
if(isset($step['value'])){
$value = $step['value'];
$this->runCommands($command,$parameter,$value);
} else {
$this->runCommands($command,$parameter);
}
}
} else {
$command = $pullcase['steps']['step']['command'];
$parameter = $pullcase['steps']['step']['parameter'];
if(isset($pullcase['steps']['step']['value'])){
$value = $pullcase['steps']['step']['value'];
$this->runCommands($command,$parameter,$value);
}
else { $this->runCommands($command,$parameter); }
}
As you can see, I'm having to duplicate my efforts depending on if there is a single item in an array versus multiple:
$pullcase['steps']['step'][0]['command']
vs
$pullcase['steps']['step']['command']
How can I simplify this code so that I can use a single variable for all instances?
If you control the creation of the array, make step an array of one even if there is only one so you always have an array. Is that possible?
You either have a step array [step][0][command] or you have a single step [step][command]. So when you create the array instead of [step][command] make it [step][0][command] etc. Standard way of doing it, problem solved as you only need the foreach.
If you can't do it at array creation then consider doing it before the loop:
if(is_array($pullcase['steps']['step'])) {
$steps = $pullcase['steps']['step'];
} else {
$steps[] = $pullcase['steps']['step'];
}
foreach($steps as $step) {
$value = isset($step['value']) ? $step['value'] : null;
$this->runCommands($step['command'], $step['parameter'], $value);
}
Also, if runCommands() can detect a empty argument, then an alternative to the if/else for the function call is used above.
The following may help. It doesn't do much but call the function "runcommands" on a value if the key is 'command'. I am using it to show how you can use array_walk_recursive to possibly solve your problem.
First, you need the function to use:
function runcommandswhencommand($value, $key)
{
if($key == 'command') runcommands($value);
}
Now, you can use the recursive walk on your array:
array_walk_recursive($pullcase, 'runcommandswhencommand');
With this, whenever the key is 'command', the value of that index will be used in the parameter of the function runcommands().

PHP how to reuse a function from a clean state

`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...

Categories