PHP average calculator not displaying results properly - php

I'm creating a php calculator that needs to use the following classes, then print off the users name and the average score they achieved. This is the code I have so far, but it's not displaying correctly, it's saying there are missing arguments and undefined variables but i'm not sure where i've gone wrong!
<?php
class person {
public $name;
}
class student extends person {
function student ($name, $grade1, $grade2) {
if(is_numeric($grade1) && is_numeric($grade2)){
$grades = array($grade1, $grade2);
}
elseif (is_numeric($grade1)) {
$grade2 = 0;
}
else {
$grade1 = 0;
}
}
function average ($grades) {
$length = count($grades);
$total = 0;
for ($i = 0; $i < $length; $i++) {
$total = $total + $grades[i];
}
$average = $total / $length;
return $average;
}
}
$person1 = new student ($_POST['firstName'], $_POST['firstGrade1'], $_POST['firstGrade2']);
$person2 = new student ($_POST['secondName'], $_POST['secondGrade1'], $_POST['secondGrade2']);
$person3 = new student ($_POST['thirdName'], $_POST['thirdGrade1'], $_POST['thirdGrade2']);
echo "<br/> $person1->name" . "achieved an average of" . "$person1->average();";
echo "<br/> $person2->name" . "achieved an average of" . "$person2->average();";
echo "<br/> $person3->name" . "achieved an average of" . "$person3->average();";
?>
ERROR MESSAGES:
Warning: Missing argument 1 for student::average(), called in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\my portable files\Exercise 4\average.php on line 40 and defined in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\my portable files\Exercise 4\average.php on line 22
Notice: Undefined variable: grades in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\my portable files\Exercise 4\average.php on line 23
Warning: Division by zero in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\my portable files\Exercise 4\average.php on line 30

You don't appear to be returning that $grades variable. It's probably not defined because you aren't returning anything.
Your method:
function student ($name, $grade1, $grade2) {
if(is_numeric($grade1) && is_numeric($grade2)){
$grades = array($grade1, $grade2);
}
elseif (is_numeric($grade1)) {
$grade2 = 0;
$grades = array($grade1, $grade2);
}
else {
$grade1 = 0;
$grades = array($grade1, $grade2);
}
return $grades
}
Will need to look more like that. You'll also want to actually add grade1 and grad2 to your returned array in your alternate conditions.

The following is the classes enhanced. You will notice that they have constructors and functions to request variables. Private variables are usually the preferred method as they are protected and therefore cannot be modified outside the class.
class person {
private $name = "";
public function __construct ($nameV) {
$this->name = $nameV;
}
public function getName() {
return $this->name;
}
}
class student extends person {
private $grades;
public function __construct ($name, $grade1, $grade2) {
parent::__construct($name);
if ( ! is_numeric($grade1)) { $grade1 = 0; }
if ( ! is_numeric($grade2)) { $grade2 = 0; }
$this->grades = array($grade1, $grade2);
}
public function average () {
$length = count($this->grades);
$total = 0;
for ($i = 0; $i < $length; $i++) {
$total = $total + $this->grades[$i];
}
$average = $total / $length;
return $average;
}
}
The export code is then simply:
echo "<br/>" . $person1->getName() . " achieved an average of " . $person1->average();
echo "<br/>" . $person2->getName() . " achieved an average of " . $person2->average();
echo "<br/>" . $person3->getName() . " achieved an average of " . $person3->average();
Due to not having the form, I tested with the following data:
$person1 = new student ("XYZ", 1, 2);
$person2 = new student ("XYZ2", 100, 20);
$person3 = new student ("XYZ3", 95, 94);
Which exported:
XYZ achieved an average of 1.5
XYZ2 achieved an average of 60
XYZ3 achieved an average of 94.5

Related

How to echo text labels before array values for specific indexes

I have written the following PHP code, I want to generate a similar table as shown in the screenshot:
The table should also have title like Job: and Email: before job name and email address. Thanks
<?php
$company = array
(
array("John Smith","Accountant","johnsmith#example.com", 70),
array("May Black","Business Analyst","mayblack#example.com", 40),
array("Tom white","Plummer","tomwhite#example", 30),
array("Susan Kim","Engineer","susankim#example.com", 80)
);
echo "--Customer List-- <br> <br>";
for($i = 0; $i < 4; $i++) {
for($j = 0; $j < 3; $j++) {
echo $company[$i][$j]."<br>";
}
echo "<br><br>";
}
?>
You could define an array for the titles as well and (conditionally) echo those first (if they are not empty strings). Note that I used a foreach loop to not have to investigate how many employees there are in the array. I've still kept the inner loop ([0-3)) to not display the sensitive age information (although that could be controlled in a different manner).
<?php
$company = array(
array("John Smith", "Accountant", "johnsmith#example.com", 70),
array("May Black", "Business Analyst", "mayblack#example.com", 40),
array("Tom white", "Plummer", "tomwhite#example", 30),
array("Susan Kim", "Engineer", "susankim#example.com", 80)
);
$title = array("", "Job", "Email", "Age");
echo "--Customer List--<br><br>\n";
foreach($company as $employee) {
for($j = 0; $j < 3; $j++) {
if($title[$j]) echo $title[$j] . ": ";
echo $employee[$j] . "<br>";
}
echo "<br><br>\n";
}
?>
Another option can be handy if you want to control how an employee is displayed from one place: By creating a class and a member function to display the (appropriate) information, you need only to change the display function when you want to change how the employee information is displayed everywhere it's called. It also adds other advantages like keeping the code that deals with objects of a certain type close to the code that defines the type.
<?php
class Employee {
public $Name;
public $Job;
protected $Email;
private $Age;
public function __construct($n, $j, $e, $a) {
$this->Name = $n;
$this->Job = $j;
$this->Email = $e;
$this->Age = $a;
}
public function display($delim = "<br>") {
echo $this->Name . $delim;
echo "Job: " . $this->Job . $delim;
echo "Email: " . $this->Email . $delim;
echo $delim . $delim;
echo "\n";
}
}
$employees = array(
new Employee("John Smith","Accountant","johnsmith#example.com", 70),
new Employee("May Black","Business Analyst","mayblack#example.com", 40),
new Employee("Tom white","Plummer","tomwhite#example", 30),
new Employee("Susan Kim","Engineer","susankim#example.com", 80)
);
echo "--Customer List--<br><br>\n";
foreach($employees as $employee) {
$employee->display();
}
?>

PHP find median using heap vs sort

I was looking for a quick way to calculate the median of a list of numbers and came across this:
function array_median($array) {
// perhaps all non numeric values should filtered out of $array here?
$iCount = count($array);
if ($iCount == 0) {
return null;
}
// if we're down here it must mean $array
// has at least 1 item in the array.
$middle_index = floor($iCount / 2);
sort($array, SORT_NUMERIC);
$median = $array[$middle_index]; // assume an odd # of items
// Handle the even case by averaging the middle 2 items
if ($iCount % 2 == 0) {
$median = ($median + $array[$middle_index - 1]) / 2;
}
return $median;
}
This approach using sort() makes sense and is certainly the obvious approach. However, I was curious if a median heap would be faster. What was surprising was that when I implemented a simple median heap it is consistently significantly slower than the above method.
My simple MedianHeap class:
class MedianHeap{
private $lowerHeap;
private $higherHeap;
private $numbers = [];
public function __construct($numbers = null)
{
$this->lowerHeap = new SplMaxHeap();
$this->higherHeap = new SplMinHeap();
if (count($numbers)) {
$this->insertArray($numbers);
}
}
public function insertArray ($numbers) {
foreach($numbers as $number) {
$this->insert($number);
}
}
public function insert($number)
{
$this->numbers[] = $number;
if ($this->lowerHeap->count() == 0 || $number < $this->lowerHeap->top()) {
$this->lowerHeap->insert($number);
} else {
$this->higherHeap->insert($number);
}
$this->balance();
}
protected function balance()
{
$biggerHeap = $this->lowerHeap->count() > $this->higherHeap->count() ? $this->lowerHeap : $this->higherHeap;
$smallerHeap = $this->lowerHeap->count() > $this->higherHeap->count() ? $this->higherHeap : $this->lowerHeap;
if ($biggerHeap->count() - $smallerHeap->count() >= 2) {
$smallerHeap->insert($biggerHeap->extract());
}
}
public function getMedian()
{
if (!count($this->numbers)) {
return null;
}
$biggerHeap = $this->lowerHeap->count() > $this->higherHeap->count() ? $this->lowerHeap : $this->higherHeap;
$smallerHeap = $this->lowerHeap->count() > $this->higherHeap->count() ? $this->higherHeap : $this->lowerHeap;
if ($biggerHeap->count() == $smallerHeap->count()) {
return ($biggerHeap->top() + $smallerHeap->top())/2;
} else {
return $biggerHeap->top();
}
}
}
And then the code to benchmark:
$array = [];
for($i=0; $i<100000; $i++) {
$array[] = mt_rand(1,100000) / mt_rand(1,10000);
}
$t = microtime(true);
echo array_median($array);
echo PHP_EOL . 'Sort Median: ' . (microtime(true) - $t) . ' seconds';
echo PHP_EOL;
$t = microtime(true);
$list = new MedianHeap($array);
echo $list->getMedian();
echo PHP_EOL . 'Heap Median: '. (microtime(true) - $t) . ' seconds';
Is there something in PHP that makes using heaps for this inefficient somehow or is there something wrong with my implemenation?

Ball clock implemented in PHP spins out of control.

I'm trying to implement the ball clock (determine how many iterations an inputed number of balls in the initial queue would go before returning to its initial order) in php. I believe at this point my code is not recognizing when to stop. I'm using an SplQueue to represent the queue and keeping an int inside each ball that represents their order.
I believe the difficulty to be in traversing the $queue in the function hasTerminated(). The code runs, it just doesn't stop. An input of 30, for example (php script.php 30) should output 30 12 hour cycles to complete, but it does not terminate. I appreciate any and all ideas as to how to access the objects of the $queue and compare them without destroying the $queue. PHP is not a language I am very comfortable with.
<?php
class Ball {
static $counter = 0;
protected $index;
function __construct(){
$this->index = self::$counter;
self::$counter++;
}
function getIndex(){
return $this->index;
}
}
class Clock {
protected $queue;
protected $minuteTrack;
protected $fiveMinuteTrack;
protected $hourTrack;
protected $count;
protected $time = 0;
function __construct($num){
$this->queue = new \SplQueue;
$this->minuteTrack = new \SplStack;
$this->fiveMinuteTrack = new \SplStack;
$this->hourTrack = new \SplStack;
$this->count = $num;
for($i = 0; $i<$num; $i++){
$ball = new Ball();
$this->queue->enqueue($ball); //inefficient
}
}
function hasTerminated(){
$inOrder = true;
$prev = -1;
$q = clone $this->queue;
while($q->count() != 0){
$elt = $q->dequeue();
if($elt->getIndex() >= $prev){
$inOrder = false;
} else {
$prev = $elt->getIndex();
}
}
echo PHP_EOL;
if($inOrder){
echo 'It takes ' . $time . ' 12 hour cycles to return to the original ordering' . PHP_EOL;
exit(0);
} else {
echo 'Not finished yet' . PHP_EOL;
}
}
function run(){
while(true){
$ball = $this->queue->dequeue();
if(!$this->addBallToMinuteTrack($ball)){
if(!$this->addBallToFiveMinuteTrack($ball)){
if(!$this->addBallToHourTrack($ball)){
$this->queue->enqueue($ball);
}
}
}
}
}
function addBallToMinuteTrack($ball){
echo '1';
if($this->minuteTrack->count() < 4){
$this->minuteTrack->push($ball);
return true;
} else if( $this->minuteTrack->count() == 4){
for($i=0; $i<4; $i++){
$this->queue->enqueue($this->minuteTrack->pop()); //hate this
}
return false;
}
}
function addBallToFiveMinuteTrack($ball){
echo '5';
if($this->fiveMinuteTrack->count() < 11){
$this->fiveMinuteTrack->push($ball);
return true;
} else if( $this->fiveMinuteTrack->count() == 11){
for($i=0; $i<11; $i++){
$this->queue->enqueue($this->fiveMinuteTrack->pop());
}
return false;
}
}
function addBallToHourTrack($ball){
echo '60' . PHP_EOL;
if($this->hourTrack->count() < 11){
$this->hourTrack->push($ball);
return true;
} else if( $this->hourTrack->count() == 11){
for($i=0; $i<11; $i++){
$this->queue->enqueue($this->hourTrack->pop()); //hate this
}
$this->time = $this->time + 1; //In half day increments
$this->hasTerminated();
return false;
}
}
}
foreach (array_slice($argv, 1) as $arg) {
if(!is_numeric($arg)){
echo 'Arguments must be numeric' . PHP_EOL;
exit(1);
} else {
$clock = new Clock($arg);
$clock->run();
}
}
?>

A 500 error has occurred - Executing long loop within PHP

A 500 error has occurred - executing long loop with PHP.
I am currently working on a scheduling system to schedule nurses on a hospital ward, I am using a genetic algorithm to carry this out.
so I randomly allocate each nurses to a shift.
and then work out how fit they are for the shift.
I then kill off any allocation which do not meet my fitness level.
I then randomly allocate a new timetable.
Assess that for fitness
kill off any allocation which do not meet my fitness level.
Merge the two timetables, keeping the fitness allocations
I loop through generating random timetable, accessing its fitness and merging the timetables
This works fine while looping through 30 - 100 times
Once I go past the 100 mark it sometimes fails - a 500 error has occurred
This always occurs when it takes over 2:30mins to complete the script
So I'm making the assumption at some point my server times out for taking too long?
I have added <?php set_time_limit(3600);
This is at the top of my file, not inside the constructor, or the class. Is it in the right place?
it still times out at 2 and a half minute,
Here is my code, the loop is the 200 loop
Still need to refractor my code so don't be too judgmental
<?php
set_time_limit(3600);
* Description of scheduler
*
* #author Dela
*/
include ("randomTtAllocation.php");
include ("fittness.php");
class scheduler {
private $randomTimetable;
private $timetable;
private $weight;
private $newTimetable ;
private $newWeight;
function __construct($labs,$students) {
echo "helloworld";
// create random timetable and print it
$r = new randomTtAllocation();
$this->randomTimetable = $r->__randomAllocation($labs, $students);
//echo "<br>" . " ............initial Time Table............." . "<br>" ;
echo "<br>";
echo "<br>";
echo "<br>";
$this->__printTt($this->randomTimetable, $this->randomTimetable);
// work out fittness for the timetable, return fit results and print
$fit = new fittness( $this->randomTimetable, $labs, $students , $r->__getNumOfSessions());
$this->newWeight = $fit->__getnewWeight();
$this->newTimetable = $fit->__getnewTimetable();;
//echo "<br>" . " ............newTimetable.........newWeight...." . "<br>" ;
//$this->__printTt($this->newTimetable, $this->newWeight );
// sort
$this->__sortTtByWeight();
$this->timetable = $this->newTimetable;
$this->weight = $this->newWeight;
for ($i = 0; $i < 200; $i++) {
// create second time table
$this->randomTimetable = $r->__randomAllocation($labs, $students);
// echo "<br>" . " ............initial Time Table............." . "<br>" ;
// $this->__printTt($this->randomTimetable, $this->randomTimetable);
// work out fittness for the timetable, return fit results and print
$fit = new fittness( $this->randomTimetable, $labs, $students , $r->__getNumOfSessions());
$this->newWeight = $fit->__getnewWeight();
$this->newTimetable = $fit->__getnewTimetable();
//echo "<br>" . " ............tempTimetable.........tempWeight...." . "<br>" ;
//$this->__printTt($this->newTimetable, $this->timetable );
$this->__sortTtByWeight();
// merge timetables
echo "<br>" . " ......old...........new." . "<br>" ;
$this->__printTt($this->timetable,$this->newTimetable );
$this->__mergeTimetables($this->newTimetable, $this->newWeight );
//echo "<br>" . " ........... mergedTimetable.........newWeight...." . "<br>" ;
//$this->__printTt($this->timetable,$this->weight );
// fittness of new timetable
$fit = new fittness( $this->timetable, $labs, $students , $r->__getNumOfSessions());
echo "<br>" . " ......merged.......kulled" . "<br>" ;
$this->__printTt($this->timetable,$fit->__getnewTimetable() );
$this->weight = $fit->__getnewWeight();
$this->timetable = $fit->__getnewTimetable();
$c[$i] = $this->__countSlotsAllocated();
echo "<br> ". $i;
}
print_r($c);
}
// sorts the re allocated time table by weight
function __sortTtByWeight() {
// for each slot
foreach($this->newTimetable as $l => $i_value) {
$size = 0;
// see how many sessions they are taking
while ($this->newTimetable[$l][$size] != "null") {
if ($this->newTimetable[$l][$size] == "0") {
break;
}
$size++;
}
for ($i = 1; $i < $size; $i++) {
$key = $this->newWeight[$l][$i];
$key1 = $this->newTimetable[$l][$i];
$k = $i - 1;
while ($k >= 0 && $this->newWeight[$l][$k] < $key) {
$this->newWeight[$l][$k + 1] = $this->newWeight[$l][$k];
$this->newTimetable[$l][$k + 1] = $this->newTimetable[$l][$k];
$k--;
}
$this->newTimetable[$l][$k + 1] = $key1;
$this->newWeight[$l][$k + 1] = $key;
}
}
}
function __countSlotsAllocated() {
$count = 0;
foreach($this->timetable as $i => $x_value) {
$j = 0;
while (($this->timetable[$i][$j] != "null") && ($this->timetable[$i][$j] != "0")){
$count++;
$j++;
}
}
echo "count " . $count;
return $count;
}
function __mergeTimetables($tempTimeTable,$tempWeight) {
// for each session
foreach($this->newTimetable as $i => $i_value) {
$j = 0;
$k = 0;
// while there are still students
while (($tempTimeTable[$i][$j] != "null") && ($tempTimeTable[$i][$j] != "0")) {
//echo $tempTimeTable[$i][$j];
// System.out.println(timeTable[i][k]);
// see if there is a free gap
while ($this->timetable[$i][$k] != "null") {
// if student is already taking that session
if ($tempTimeTable[$i][$j] == $this->timetable[$i][$k]) {
break;
}
if ($this->timetable[$i][$k] == "0") {
$this->timetable[$i][$k] = $tempTimeTable[$i][$j];
$this->weight[$i][$k] = $tempWeight[$i][$j];
break;
}
$k++;
}
if ($this->timetable[$i][$k] == "null") {
if ($tempWeight[$i][$j] < $this->weight[$i][0]) {
$this->timetable[$i][0] = $tempTimeTable[$i][$j];
$this->weight[$i][0] = $tempWeight[$i][$j];
}
}
$j++;
}
}
}
function __returnTimetable() {
return $this->timetable;
}
function __printTt($timetable, $weight) {
foreach($timetable as $x => $x_value) {
for ($i = 0; $i < 5; $i++) {
echo $timetable[$x][$i] . " ";
}
echo " . . . . .";
for ($i = 0; $i < 5; $i++) {
echo $weight[$x][$i] . " ";
}
echo "<br>";
}
}
}
Normally you shouldn't do all this work within the http request. Instead you should start a background task and have the web page show progress on the job.
The php configuration has a time limit per request which you can adjust, but it's not expected by users to take so long.

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.

Categories