Foreach & Arrays in PHP - php

I'm terribly confused on how I should be writing this function...it basically scores a test, and it WORKS for one user's values.
Let's say I want the values for the following user: $id = 2...this works! If $id = array(2,3,4,5) it doesn't work!
function get_score_a($id){
// Case 4
foreach($this->get_results_a($id,4)->row() as $key=>$a){
if ($a >= 2 && $a <= 4) {
$score_a += 2;
} else if ($a > 4 && $a < 8) {
$score_a += 3;
} else if ($a > 8) {
$score_a += floor($a - 8) * .5;
$score_a += 3;
}
};
return $score_a;
}
function get_results_a($id, $method) {
$select_cols = array(
1 => array('a_1','a_2','a_4'),
2 => array('a_6','a_8','a_11','a_12','a_14'),
3 => array('a_3','a_10'),
4 => array('a_5','a_7','a_9','a_13')
);
return $this->db->select($select_cols[$method])
->where_in('id', $id)
->get('be_survey');
}
This returns a score...however, if I run multiple ids...it just adds up all the numbers, I think...
Instead I need this to output separate scores for individual users...
May it be noted that I'm a total noob! So vivacious explanations are very much appreciated. :)
Edit
Please review my code...as I should have been more clear! Sorry!
I apologize! In summation, this selects the correct values from the table, based on
And yes, my eyes hurt too!
Edit
I am too hasty! This is a Codeigniter project!

Firstly, there is no row() for arrays.. just use foreach ($array as $key=>$value)
Secondly, inside the foreach loop $score_b is being incremented on each run with its previous value. So, your code is outputting the sum of all player scores.
use:
foreach(array(5,5,5,6,7,78,8,7,7,6,5) as $key=>$a){
if ($a >= 0 && $a <= .5) {
$score_b[$key] += 0;
} else if ($a > .5 && $a < 2) {
$score_b[$key] += 1;
}
else if ($a > 2 && $a < 4) {
$score_b[$key] += 2;
}
else if ($a > 4) {
$score_b[$key] += floor($a - 8) * .5;
$score_b[$key] += 2;
}
};
$score_b will now be an array of scores.
EDIT:
Add the following in your code:
$id = array(2,3,4,5);
function get_score_array($ids) {
foreach ($ids as $id) {
$scores[$id] = get_score_a($id);
}
return $scores;
}
$scores will now be an array of $id=>$score pairs.
Also, adjust the above code, as per your framework (which I guess you are using)

There is no such method called row() on array. In fact, an array isn't strictly an object, so it doesn't have methods.
So, first of all, get rid of the ->row() invocation.
Second, where are you pushing these scores onto an array? I don't see where that happens in your code. Initialize an empty array before the foreach loop, and push the $score_b variable onto the array at the end of the loop.

Set a $userID variable outside the foreach loop like this:
$userScores = array(
'bobby' = > array(5,5,5,6,7,78,8,7,7,6,5),
'sue' = > array(5,5,5,6,7,78,8,7,7,6,5),
'joe' = > array(5,5,5,6,7,78,8,7,7,6,5)
);
foreach($userScores as $name => $a){
$score_b[$name] = 0; //initialize
if ($a >= 0 && $a <= .5) {
$score_b[$name] += 0;
} else if ($a > .5 && $a < 2) {
$score_b[$name] += 1;
}
else if ($a > 2 && $a < 4) {
$score_b[$name] += 2;
}
else if ($a > 4) {
$score_b[$name] += floor($a - 8) * .5;
$score_b[$name] += 2;
}
};
your end result should be something like (I didn't do any actual math)
$score_b['bobby'][100]
$score_b['sue'][75]
$score_b['joe'[90]

Related

Get lowest price on sum of combinations in given array

This code is working fine when the array length is 8 or 10 only. When we are checking this same code for more than 10 array length.it get loading not showing the results.
How do reduce my code. If you have algorithm please share. Please help me.
This program working flow:
$allowed_per_room_accommodation =[2,3,6,5,3,5,2,5,4];
$allowed_per_room_price =[10,30,60,40,30,50,20,60,80];
$search_accommodation = 10;
i am get subsets = [5,5],[5,3,2],[6,4],[6,2,2],[5,2,3],[3,2,5]
Show lowest price room and then equal of 10 accommodation; output like as [5,3,2];
<?php
$dp=array(array());
$GLOBALS['final']=[];
$GLOBALS['room_key']=[];
function display($v,$room_key)
{
$GLOBALS['final'][] = $v;
$GLOBALS['room_key'][] = $room_key;
}
function printSubsetsRec($arr, $i, $sum, $p,$dp,$room_key='')
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if ($i == 0 && $sum != 0 && $dp[0][$sum]) {
array_push($p,$arr[$i]);
array_push($room_key,$i);
display($p,$room_key);
return $p;
}
// If $sum becomes 0
if ($i == 0 && $sum == 0) {
display($p,$room_key);
return $p;
}
// If given sum can be achieved after ignoring
// current element.
if (isset($dp[$i-1][$sum])) {
// Create a new vector to store path
// if(!is_array(#$b))
// $b = array();
$b = $p;
printSubsetsRec($arr, $i-1, $sum, $b,$dp,$room_key);
}
// If given $sum can be achieved after considering
// current element.
if ($sum >= $arr[$i] && isset($dp[$i-1][$sum-$arr[$i]]))
{
if(!is_array($p))
$p = array();
if(!is_array($room_key))
$room_key = array();
array_push($p,$arr[$i]);
array_push($room_key,$i);
printSubsetsRec($arr, $i-1, $sum-$arr[$i], $p,$dp,$room_key);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets($arr, $n, $sum,$get=[])
{
if ($n == 0 || $sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
// $dp = new bool*[$n];
$dp = array();
for ($i=0; $i<$n; ++$i)
{
// $dp[$i][$sum + 1]=true;
$dp[$i][0] = true;
}
// Sum arr[0] can be achieved with single element
if ($arr[0] <= $sum)
$dp[0][$arr[0]] = true;
// Fill rest of the entries in dp[][]
for ($i = 1; $i < $n; ++$i) {
for ($j = 0; $j < $sum + 1; ++$j) {
// echo $i.'d'.$j.'.ds';
$dp[$i][$j] = ($arr[$i] <= $j) ? (isset($dp[$i-1][$j])?$dp[$i-1][$j]:false) | (isset($dp[$i-1][$j-$arr[$i]])?($dp[$i-1][$j-$arr[$i]]):false) : (isset($dp[$i - 1][$j])?($dp[$i - 1][$j]):false);
}
}
if (isset($dp[$n-1][$sum]) == false) {
return "There are no subsets with";
}
$p;
printSubsetsRec($arr, $n-1, $sum, $p='',$dp);
}
$blockSize = array('2','3','6','5','3','5','2','5','4');
$blockvalue = array('10','30','60','40','30','50','20','60','80');
$blockname = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese");
$processSize = 10;
$m = count($blockSize);
$n = count($processSize);
// sum of sets in array
printAllSubsets($blockSize, $m, $processSize);
$final_subset_room = '';
$final_set_room_keys = '';
$final_set_room =[];
if($GLOBALS['room_key']){
foreach ($GLOBALS['room_key'] as $set_rooms_key => $set_rooms) {
$tot = 0;
foreach ($set_rooms as $set_rooms) {
$tot += $blockvalue[$set_rooms];
}
$final_set_room[$set_rooms_key] = $tot;
}
asort($final_set_room);
$final_set_room_first_key = key($final_set_room);
$final_all_room['set_room_keys'] = $GLOBALS['room_key'][$final_set_room_first_key];
$final_all_room_price['set_room_price'] = $final_set_room[$final_set_room_first_key];
}
if(isset($final_all_room_price)){
asort($final_all_room_price);
$final_all_room_first_key = key($final_all_room_price);
foreach ($final_all_room['set_room_keys'] as $key_room) {
echo $blockname[$key_room].'---'. $blockvalue[$key_room];
echo '<br>';
}
}
else
echo 'No Results';
?>
I'm assuming your task is, given a list rooms, each with the amount of people it can accommodate and the price, to accommodate 10 people (or any other quantity).
This problem is similar to 0-1 knapsack problem which is solvable in polynomial time. In knapsack problem one aims to maximize the price, here we aim to minimize it. Another thing that is different from classic knapsack problem is that full room cost is charged even if the room is not completely occupied. It may reduce the effectiveness of the algorithm proposed at Wikipedia. Anyway, the implementation isn't going to be straightforward if you have never worked with dynamic programming before.
If you want to know more, CLRS book on algorithms discusses dynamic programming in Chapter 15, and knapsack problem in Chapter 16. In the latter chapter they also prove that 0-1 knapsack problem doesn't have trivial greedy solution.

In which case we can use interpolation algorithm search instead binary search algorithm?

I have two sorted arrays:
$idProducts = [2,9,25,666,1001,1002,1005,2546...n]; //almost 55.000 values
$someIds = [1,9,11,12,99,111,855...n]; //almost 2.500 values
I try make a new array from intersection of idProducts and $someIds.
I applied 3 search algorithms: linear, binary, interpolar searching, but only linear and binary algorithm work properly:
foreach($someIds as $id){
if(interpolation_search($idProducts, $id) >=0){
$newArray[]=$id;
}
}
function interpolation_search($list, $x)
{
$l = 0;
$r = count($list) - 1;
while ($l <= $r) {
if ($list[$l] == $list[$r]) {
if ($list[$l] == $x) {
return $l;
} else {
// not found
return -1;
}
}
$k = ($x - $list[$l])/($list[$r] - $list[$l]);
// not found
if ($k < 0 || $k > 1) {
return -1;
}
$mid = round($l + $k*($r - $l));
if ($x < $list[$mid]) {
$r = $mid - 1;
} else if ($x > $list[$mid]) {
$l = $mid + 1;
} else {
// success!
return $mid;
}
// not found
return -1;
}
}
Anyway the best solution was:
$idProducts = array_flip($idProducts);
foreach ($someIds as $id){
if (isset($idProducts [$id])===true){
$newArray[]=$id;
}
}
But i want know why interpolation doesnt work properly in my case and in which case we can implement interpolation algorithm searching.
Thank you.

Convert my script in recursive way?

I have script who searches closest searched number.
So for example, let say that in array are this numbers:
'0' => 1.72
'0.25' => 1.92
'0.75'=> 2.35
'1' => 3.00
I am searching for 0.50 handicap, so 0.25 and 0.75 are in same range from 0.50.
In this situations i want to get greater number, what is 0.75 in this example.
Code what works is this:
function getClosest($search, $arr) {
$closest = null;
$num_arr = array();
$odd = 0.00;
$i = 0;
foreach ($arr as $handicap=>$item) { //first closest number
if ($closest === null || abs($search - $closest) > abs($handicap - $search)) {
$closest = $handicap;
$odd = $item;
}
else{
$num_arr[$handicap] = $item;
}
}
$newclosest = null;
$newodd = 0.00;
foreach($num_arr as $handicap=>$newitem){ //second closest number
if ($newclosest === null || abs($search - $closest) > abs($handicap - $search)) {
$newclosest = $handicap;
$newodd = $newitem;
}
}
//if difference between first and second number are same
if(abs($search - $closest) == abs($newclosest - $search)){
if($newclosest > $closest){ //if second number is greater than first
$closest = $newclosest;
$odd = $newodd;
}
}
return array('handicap'=>$closest,'odd'=>$odd);
}
I see that i can use recursion here, but i am not experienced in using recursion. I know that i need call it inside like this:
$rec_arr = getClosest($num_arr,$search);
but i get blank page even i dump function output.
use array_map function,
$data = array('0'=>1.72,'0.75'=> 2.35,'0.25'=>1.92,'1' => 3.00);
$v = 0.5; // search value
$x = null; // difference value
$y = array(); // temporary array
array_map(function($i)use($data,$v,&$x,&$y){
if(isset($x)){
if($x > abs($i-$v)){ // if difference value is bigger than current
$x = abs($i-$v);
$y = array($i=>$data[$i]);
}else if($x == abs($i-$v)){ // if difference value is same
$key = array_keys($y);
$y = $key[0] < $i ? array($i=>$data[$i]) : $y;
}
}else{ // first loop
$x = abs($i-$v);
$y = array($i=>$data[$i]);
}
},array_keys($data));
print_r($y); // result
output Array ( [0.75] => 2.35 ), hope this help you.
//$a is array to be searched
//$s is search key
//$prev_key and $next_key will be output required
$a = array('0'=>1,'0.25'=>123,'0.75'=>456,'0.78'=>456,'1'=>788);
$s = '0';
if(isset($a[$s])){
echo $s;
}
else{
reset($a);//good to do
while(key($a) < $s){
next($a);
}
$next_key = key($a);
prev($a);
$prev_key = key($a);
echo $prev_key.'-'.$next_key;
}
The above code uses array internal pointers. I think this may help you..
source: https://stackoverflow.com/a/4792770/3202287

A Logical Algorithm In PHP

I'm a beginner learning PHP. I have tried to make a loop that has a different behaviour for both even and odd numbers. I've been playing around with it for a while, yet I still can't get it to work. Has anyone got a solution?
$count = 0;
$mod = $count % 2;
while ($count < 10)
{
if ($mod == 0) {
echo "even, ";
} else {
echo "odd, ";
}
$count++;
}
A silly mistake, mod inside while() loop.
$count = 0;
while ($count < 10) {
$mod = $count % 2; //Here
if ($mod == 0) {
echo "even, ";
} else {
echo "odd, ";
}
$count++;
}
$count = 0;
$mod = $count %2;
Is were your problem is.
You have to use the modulus (%) operator inside the for loop. Also, there is no need to store the value from the use of the modulus operator at all, it can be compared directly inside the for-loop.
for ($count = 0; $count < 10, $count++) {
if ($count % 2 == 0) {
echo "even, ";
} else {
echo "odd, ";
}
}
You can also switch the while to a for like this.
Welcome to PHP.
Edit #1:
As you are getting a new value of $count every execution of the for-loop the old value if $count % 2 will be incorrect. It has to recalculate for every $count. First it checks if 0 is divisible by 2, then onto 1 and so forth. For every value of $count you have to check the divisibility.
In most programming languages you aren't computing a variable onto another, instead you are taking the value of the variable. Like $a = $b + $c; in that case, if you change the value of $b or $c it does not automatically update $a. Instead you have to call $a = $b + $c again. It is the same with % operator.
$count = 0;
while ($count < 10) {
$mod = $count % 2;
if ($mod == 0) {
echo "even, ";
} else {
echo "odd, ";
}
$count++;
}
use for loop instead of while loop
for($count=0;$count<10;$count++)
{
if(($count % 2) == 0)
echo "even,";
else
echo "odd,";
}

PHP based Blackjack script ( aces)

I've got a question. I've build this PHP script, it works just fine, except for the fact that aces don't work properly. If I draw 5 A 5 5, it thinks I have 26 etc.
Does anyone know how to solve this problem?
Function to evaluateHand:
function evaluateHand($hand) {
global $faces;
$value = 0;
foreach ($hand as $card) {
$values = explode("|",$card);
$value1= $values[0];
if($value1=="Q" OR $value1=="J" OR $value1=="K"){
$value = intval($value) + 10;
}
if ($value > 10 && $value1 == "A") {
$value = intval($value) + 1; // An ace can be 11 or 1
}
elseif($value < 12 && $value1 == "A"){
$value = intval($value) + 11; // An ace can be 11 or 1
}
else {
$value = intval($value) + intval($value1);
}
}
return $value;
}
Sort the list of cards so that aces are evaluated last.
As Quentin said, treat aces last. Also count how many aces there are in the hand (to avoid giving 11 to one ace and overflow if you have, let's say, three aces, instead of counting 1+1+1).
Treat all aces together, dividing the number of points left by the number of aces. If result is superior to 11, give 11 to one and 1 to the others. If not, give 1 to all aces.
Why global $faces;?
To make your code working just add asort($hand); in the top of the function.
This will order the array, to put the A as last.
EDIT: You are right. I have changed the function to always evaluate the aces as last.
function evaluateHand($hand) {
global $faces;
$value = 0;
$aces = 0;
foreach ($hand as $card) {
$values = explode("|",$card);
$value1= $values[0];
if($value1 == "A") {
$aces++;
}
else {
if($value1=="Q" OR $value1=="J" OR $value1=="K"){
$value = intval($value) + 10;
}
else {
$value = intval($value) + intval($value1);
}
}
}
while($aces > 0) {
if($value > 10) {
$value = intval($value) + 1;
}
elseif($value < 12){
$value = intval($value) + 11; // An ace can be 11 or 1
}
$aces--;
}
return $value;
}
As you said in one of the comments, the asort alone won't work, as the sorting goes like this:
0-9, then A to Z, so The Aces are still being checked before the other figures.
I modified a bit your function so it works better in that way:
function evaluateHand($hand) {
asort($hand);
print_r($hand);
$aces = 0;
global $faces;
$value = 0;
foreach ($hand as $card) {
$values = explode("|",$card);
$value1= $values[0];
if($value1=="Q" OR $value1=="J" OR $value1=="K"){
$value = intval($value) + 10;
} elseif($value1 == "A") {
$aces++;
} else {
$value = intval($value) + intval($value1);
}
}
if($aces > 0){
for($a = 0; $a < $aces; $a++){
if ($value > 10) {
$value = intval($value) + 1; // An ace can be 11 or 1
}elseif($value < 12){
$value = intval($value) + 11; // An ace can be 11 or 1
}
}
}
return $value;
}
What I have done is create an Aces counter ($aces = 0), and when there's an Ace we skip the sum, and increase the counter, after the foreach loop then we sum the desired value based on the total value of the hand, with another loop based on the aces we have in the array.

Categories