<?php
function apache($b) {
return $b;
}
$a = array(1, 2, 3, 4, 5, 6);
$num = "";
foreach ($a as $b) {
$num = apache($b) . $num ;
}
echo $num;
?>
When you write it like this the output is 654321, but if you write it like this:
$num = $num . apache($b);
the output would be 123456. I don't understand why the results are like that. Can someone explain this?
This isn't really hard to understand.
This line:
$num = apache($b) . $num;
add the currently selected number and appends the current value of $num to it. The result will be written to $num.
So this will happen:
$b. $num = $num
1 . "" = 1
2 . 1 = 21
3 . 21 = 321
4 . 321 = 4321
5 . 4321 = 54321
6 . 54321 = 654321
If you write
$num = $num . apache($b);
instead, you're adding the currently selected number behind $num:
$num .$b = $num
"" . 1 = 1
1 . 2 = 12
12 . 3 = 123
123 . 4 = 1234
1234 . 5 = 12345
12345 . 6 = 123456
one way you are appending to the string
the other way you are prepending to the string
which gives the effect of reversing it.
first way kind of looks like this
[1]
2[1]
3[21]
4[321]
5[4321]
6[54321]
the other way looks like this
[1]
[1]2
[12]3
[123]4
[1234]5
[12345]6
where the value outside the [] is the value being returned by your function and the value inside the [] is $num
Related
What i am trying to do is divide a number by 2 get the whole number and store the remainder in another variable which i did, but the number should stop dividing until the result gets to 0
Example:
75 / 2 = 37
37 / 2 = 18
.
.
.
.
1 / 2 = 0
This is what i have to far
$num = 75;
$n = (int) ($num / 2); //Get the whole number
$r = $num % 2; //Get the remainder
echo $n . "<br>" . $r;
I know i have to use a loop but i am still new to this so i need help.
Please try something like this:
<?php
$num = 75;
$divNum = 2;
while($num > 0){
$newNumber = (int) ($num / $divNum); //Get the whole number
$remainder = $num % $divNum; //Get the remainder
$num = $newNumber;
echo $newNumber . " " . $remainder."<br>" ;
}
?>
Output Look like this :
37 1
18 1
9 0
4 1
2 0
1 0
0 1
I have a problem about loop in line of true table. I need get all lines where only there are 3 positions with value equal 1, Look sample:
For a table with 4 elements exists 16 possibilities but I need just 4 of their. So I need to get the 4 positions without pass in all others positions:
[00002] 0-0-0-1
[00003] 0-0-1-0
[00004] 0-0-1-1
[00005] 0-1-0-0
[00006] 0-1-0-1
[00007] 0-1-1-0
[00008] 0-1-1-1 I want this
[00009] 1-0-0-0
[00010] 1-0-0-1
[00011] 1-0-1-0
[00012] 1-0-1-1 I want this
[00013] 1-1-0-0
[00014] 1-1-0-1 I want this
[00015] 1-1-1-0 I want this
[00016] 1-1-1-1
Look for 4 elements it's easy make a loop but you imagine a table with millions elements. Following is a code for ilustre my first thought:
$t1 = time();
echo "\n\n";
echo "################ Started in :" . date('d/m/Y H:i:s', $t1);
echo "\n\n";
$votesCount = 4;
$possibilities = pow(2, $votesCount);
for ($i = 0; $i < $possibilities; $i++) {
$binare = str_pad(decbin($i), $votesCount, 0, STR_PAD_LEFT);
$arrayBinare = str_split($binare);
$posVote = str_pad($i + 1, 5, 0, STR_PAD_LEFT);
$c = "[" . $posVote . '] ' . implode('-', $arrayBinare);
if (array_sum($arrayBinare) == 3) {
echo "<b>$c</b> I want this<br>";
continue;
}
echo "$c <br>";
}
$t2 = time();
echo "\n";
echo "################ Finished in:" . date('d/m/Y H:i:s', $t2);
echo "\n";
echo "################ Duraction: " . ($t2 - $t1) . ' seconds';
echo "\n";
A recursive solution looks like this:
function Enumerate(len, rem)
if rem = 0 then return [0]^len
if len < rem then return {}
if len = rem then return {[1]^rem}
return ({[0]} & Enumerate(len - 1, rem))
union
({[1]} & Enumerate(len - 1, rem - 1))
The notation [1]^rem means the vector of length rem containing only 1; the operator & returns all vectors obtained by concatenating vectors from the RHS to vectors in the LHS. This short-circuits when it detects that solutions can't be obtained or when there is only one possible solution, but you could remove this to print all permutations and just check them. Example execution:
Enumerate(4, 3) = {[0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0]}
4 < 3? no
4 = 3? no
[0] & Enumerate(3, 3) = [0] & [1,1,1] = [0,1,1,1]
3 = 0? no
3 < 3? no
3 = 3? yes, return [1,1,1]
[1] & Enumerate(3, 2) = [1] & ([0,1,1],[1,0,1],[1,1,0]| = {[1,0,1,1],[1,1,0,1],[1,1,1,0]}
2 = 0? no
3 < 2? no
3 = 3? no
[0] & Enumerate(2, 2) = [0] & [1,1] = [0,1,1]
2 = 0? no
2 < 2? no
2 = 2? yes, return [1,1]
[1] & Enumerate(2, 1) = [1] & {[0,1],[1,0]) = {[1,0,1],[1,1,0]}
1 = 0? no
2 < 1? no
2 = 1? no
[0] & Enumerate(1, 1) = [0] & [1] = [0,1]
1 = 0? no
1 < 1? no
1 = 1? yes, return [1]
[1] & Enumerate(1, 0) = [1] & [0] = [1,0]
0 = 0? yes, return [0]
If you want this to be iterative rather than recursive, add a stack data structure and manage the stack explicitly in a while loop while the stack's not empty.
If you want the position of each solution in the ordered space of all solutions - simply interpret the vector as the sequence of digits of a len-digit binary number and add one. So, [0,1,1,1] becomes (0111)b = (7)d + 1 = (8)d = 8.
With millions of rows, you definitely want to move the selection logic on the database side, or you'll have to make insane amounts of calculations on the PHP side, leading to potential performance & memory issues.
Assuming you have 4 vote columns storing 1 or 0:
SELECT *
FROM votes
WHERE (vote1 + vote2 + vote3 + vote4) = 3
And if you are storing booleans, you can cast it as an integer : WHERE CAST(vote1 AS SIGNED INTEGER) + ...
Suppose I have inside the array this situation:
[0] => 4 - 0
[1] => 0 - 1
[2] => 2 - 2
[3] => 1 - 2
[4] => 0 - 0
The value are organized to be the first column the home team, and the last column the away team, so the first line the home team won for 4 - 0.
Now I'm trying to extract the "best victory" that in this case is 4 - 0 and the "biggest defeat" that is 0 - 1.
What I tried for now is iterate through the array index:
$biggestVictory = array_fill(0, 2, 0);
$biggestDefeat = array_fill(0, 2, 0);
foreach ($results as $result)
{
$score = explode("-", $result);
$home = $score[0];
$away = $score[1];
if($home > $biggestVictory[0] && $away <= $biggestVictory[1])
{
$biggestVictory[0] = $home;
$biggestVictory[1] = $away;
}
if($away > $biggestDefeat [1] && $home <= $biggestDefeat [0])
{
$biggestDefeat [1] = $home;
$biggestDefeat [2] = $away;
}
}
this will return as result 4 - 0 for biggestVictory and 0 - 0 for biggestDefeat, why?
I am a bit unclear about what "biggest victory" is actually supposed to be. Highest difference in score, or most goals scored? Assuming that the difference is what matters, this code should do the trick:
$biggestVictory = array_fill(0, 2, 0);
$biggestDefeat = array_fill(0, 2, 0);
foreach ($results as $result)
{
$score = explode("-", $result);
$home = $score[0];
$away = $score[1];
if( ($home - $away) >= ($biggestVictory[0] - $biggestVictory[1]) )
{
$biggestVictory[0] = $home;
$biggestVictory[1] = $away;
}
if( ($away - $home) >= ($biggestDefeat[1] - $biggestDefeat[0]) )
{
$biggestDefeat [0] = $home;
$biggestDefeat [1] = $away;
//look at the index ^ you had a mistake in here
}
}
Note that your condition if($home > $biggestVictory[0] && $away <= $biggestVictory[1]) is pretty bad, as a 100 - 1 would not replace a 1 - 0 due to the second part of your condition.
You can use Max Function to find max value in an array
max() function returns the highest value in an array, or the highest
value of several specified values.
<?php
echo(max(2,4,6,8,10) . "<br>");
echo(max(22,14,68,18,15) . "<br>");
echo(max(array(4,6,8,10)) . "<br>");
echo(max(array(44,16,81,12)));
?>
And you also can use mini Function to find minimum value in an array
The min() function returns the lowest value in an array, or the lowest
value of several specified values.
<?php
echo(min(2,4,6,8,10) . "<br>");
echo(min(22,14,68,18,15) . "<br>");
echo(min(array(4,6,8,10)) . "<br>");
echo(min(array(44,16,81,12)));
?>
I am still a novice at PHP scripting.
I have an Array
$students = array(1201=>94,1203=>94,1200=>91, 1205=>89, 1209=>83, 1206=>65, 1202=>41, 1207=>38,1208=>37, 1204=>37,1210=>94);
From the associative array, the key are the student's exam no and the values are the student's scores. Then I used the 2 inbult PHP functions array_keys and array_values to separate the exam nos from the scores.
$exam_nos=(array_keys($students));
$marks=(array_values($students));
Then I passed the $marks array through the code below:
$i=0;
$occurrences = array_count_values($marks);
$marks = array_unique($marks);
echo '<table border="1">';
foreach($marks as $grade) {
if($grade == end($marks))$i += $occurrences[$grade]-1;
echo str_repeat('<tr><td>'.$grade.': '.($i+1).'</td></tr>',$occurrences[$grade]);
$i += $occurrences[$grade];
}
echo '</table><br />';
output:
94: 1
94: 1
94: 1
91: 4
89: 5
83: 6
65: 7
41: 8
38: 9
37: 11
37: 11
And this is closer to what I want; to rank the scores such that if a tie is encountered, 1 or more positions are skipped, occurs at the end the position the items at the end are assigned a position equivalent toi the total number of ranked items. However, it would be much helpful if this could be done without separating the Array into 2 ...
Questions:
(1) I am pulling my hair how, from the $student array I could have something like:
Exam No Score Position
1201 94 1
1210 94 1
1203 94 1
1200 91 4
1205 89 5
1209 83 6
1206 65 7
1202 41 8
1207 38 9
1204 37 11
1208 37 11
(2) I would like to be able to pick any student by exam no and be able to echo or print out her position e.g
the student 1207 is number 9.
I think I need to capture the postions in a variable, but how do I capture them? Well I don't know!
Could the experts help me here with a better way to achieve my 2 goals (please see questions 1 and 2)? I will try any suggestion that will help me disolve the 'metal blockage' I have hit.
If you're pulling out the students from a database (mentioned in the comments), you could retrieve them with the desired format directly using SQL.
However, I'm going to assume that that's not an option. You could do as follows:
$students = array(1201=>94,1203=>94,1200=>91, 1205=>89, 1209=>83, 1206=>65, 1202=>41, 1207=>38,1208=>37, 1204=>37,1210=>94);
arsort($students);// It orders high to low by value. You could avoid this with a simple ORDER BY clause in SQL.
$result = array();
$pos = $real_pos = 0;
$prev_score = -1;
foreach ($students as $exam_n => $score) {
$real_pos += 1;// Natural position.
$pos = ($prev_score != $score) ? $real_pos : $pos;// If I have same score, I have same position in ranking, otherwise, natural position.
$result[$exam_n] = array(
"score" => $score,
"position" => $pos,
"exam_no" => $exam_n
);
$prev_score = $score;// update last score.
}
$desired = 1207;
print_r($result);
echo "Student " . $result[$desired]["exam_no"] . ", position: " . $result[$desired]["position"] . " and score: ". $result[$desired]["score"];
Hope it helps you.
I would use a custom object to process the students individually and store them in an array.
$students = array(1201=>94,1203=>94,1200=>91, 1205=>89, 1209=>83, 1206=>65, 1202=>41, 1207=>38,1208=>37, 1204=>37,1210=>94);
arsort($students); // Sort the array so the higher scores are on top.
$newStudents = array();
$pos = 0;
$count = 0;
$holder = -1; // Assuming no negative scores.
foreach($students as $k=>$v){
$count++; // increment real counter
if($v < $holder || $holder == -1){
$holder = $v;
$pos = $count;
}
$newStudents[] = makeStudent($pos, $v, $k);
// If you want the exam # as the array key.
// $newStudents[$k] = $student;
}
$newStudents = fixLast($newStudents);
// outputs
print_r($newStudents);
foreach($newStudents as $v){
echo "position : " . $v->position . "<br>";
echo "score : " . $v->score . "<br>";
echo "exam : " . $v->exam . "<br>";
}
function makeStudent($pos, $score,$examNo){
$student = new stdClass(); // You could make a custom, but keeping it simple
$student->position = $pos;
$student->score = $score;
$student->exam = $examNo;
return $student;
}
function fixLast($students){
$length = count($students) -1;
$count = 0;
$i = $length;
while($students[$i]->position == $students[--$i]->position){
$count++;
}
for($i = 0; $i <= $count; $i++){
$students[$length - $i]->position = $students[$length - $i]->position + $count;
}
return $students;
}
I need to convert an array of numbers and totals into a simple statement.
For example, how can I convert the following, programmatically via PHP, to simple statements like, 1 out of 10, 1 out of 100, and even rounding some (like 2 out of 100 for 9000,400000).
Generate Sample Array:
$arr = array();
for ($i=0; $i < 100; $i++) {
$n = mt_rand(1,1000);
$t = mt_rand(10,100000);
if ($n > $t) continue; // skip!
$arr[] = array($n,$t);
}
/*
// Generates pairs like:
// Array
// (
// [0] => Array ( [0] => 55 [1] => 8774 )
// [1] => Array ( [0] => 814 [1] => 11174 )
// [2] => Array ( [0] => 255 [1] => 32168 )
// ...
// [99] => Array ( [0] => 851 [1] => 24231 )
// )
*/
Run through a function and print simplified results:
foreach ($arr as $a) {
echo $a[0] . '/' . $a[1] . ' ==> ' . simplifyRatio($a[0],$a[1]) . "\r\n";
}
Can you point me in the right direction on how to accomplish this?
Here's the start of a function I'm working on, but the solution is escaping me.
function simplifyRatio($n,$t) {
$p = $n/$t;
if ($p > 0.09) return round($n) . ' out of ' . round($t);
if ($p > 0.009) return round($n) . ' out of ' . round($t);
}
Ideally the denominator should be: 1,2,3...10,20,30...100,200,300...1000,2000,3000...10000,20000,30000...100000 (max)
Assuming always a percentage. You may also want to sprintf $outof before displaying it
function convertPercent($iPercent)
{
// Assume validation on $iPercent
$outof = round(100 / $iPercent);
return "1 out of $outof";
}
For simplicity's sake, I'll assume that you can get your percent in a fraction (ie 25% is 25/100, 0.7% = 7/1000, etc).
You can use Euclid's algorithm to find the GCD of the numerator and the denominator:
http://en.wikipedia.org/wiki/Euclidean_algorithm
In php it'd look something like this:
function gcd ($int1, $int2) {
$tmp = 0;
while ($int1 > 0) {
$tmp = $int1;
$int1 = $int2 % $int1;
$int2 = $tmp;
}
return $int2;
}
This will work as long as $int1 and $int2 are integers greater than 0 (you might want to put in some logic to ensure this). If you need negative numbers, just take the absolute value.
Knowing the GCD, it's easy to figure out the rest:
function reduce($numerator, $denominator) {
$gcd = gcd($numerator, $denominator);
echo ($numerator/$gcd) . " out of " . ($denominator/$gcd);
}
echo reduce(4, 8).'<br>'; // 1 out of 2
echo reduce(38, 897).'<br>'; // 38 out of 897
echo reduce(39, 26).'<br>'; // 3 out of 2
Hope this helps!
I ended up settling for a near match on the pattern 1 out of ___, like so:
function simplifyRatio($n,$t) {
$r = $t/$n;
return '1 out of ' . round($r);
}
// Examples:
$arr = array();
for ($i=0; $i < 100; $i++) {
$n = mt_rand(1,1000);
$t = mt_rand(10,100000);
if ($n > $t) continue; // skip!
$arr[] = array($n,$t);
}
foreach ($arr as $a) {
echo $a[0] . '/' . $a[1] . ' ==> ' . simplifyRatio($a[0],$a[1]) . "\r\n";
}
Example Result:
1000/24819 ==> 1 out of 25
309/50305 ==> 1 out of 163
488/99123 ==> 1 out of 203
322/47610 ==> 1 out of 148
183/54287 ==> 1 out of 297
752/67646 ==> 1 out of 90
240/68854 ==> 1 out of 287
301/81345 ==> 1 out of 270
611/16404 ==> 1 out of 27
522/62992 ==> 1 out of 121
CodePad: http://codepad.org/wu6iOdDq
Initially I had hoped to end up with rounded denominators (10,20...100,200...1000,2000, etc.), but I'm uncertain how to do this well. I'll happily award an answer that cleans up the denominators of the above.