As mentioned before, I am a beginner when it comes to PHP coding. I have made a text file which has my students information, as per below - this includes their name, marks for subjects, e-mail address and date of registration:
Ann Thompson : 50,90,82,64,75 : ann#amuniversity.com: 2016-02-01
Jeremiah Hanson: 80, 75, 88 : jeremiah#amuniversity.com: 2016-03-02
Billy Jones: 89, 72, 46, 54 : billy#amuniversity.com: 2016-04-12
and I have also made a form which inputs a field which takes in the filename which the user wishes to read from and a field for the filename which the user wishes to write to.
Where do I start to get the output below?
Summary for students:
Ann Thompson enrolled in 2016-02-01, has an average of 48, with a symbol F.
Jeremiah Hanson enrolled in ....
Billy Jones enrolled in ....
It should also show the date at the bottom when it was last modified.
Please kindly help
Please check the following code. I commented on the code wherever I thought needed. Let me know if you don't understand something from it. And obviously, you need to update the checkGrade function as per your grade system, but you get the idea :)
<?php
// Read the input file line by line into "input" array
$filename = "input.txt";
$input = explode("\n", file_get_contents($filename));
// Go through each line
for($i = 0; $i < sizeOf($input); $i++){
// split line by :
$line = explode(":", $input[$i]);
// Initialize variables based on position
$name = $line[0];
$numbers = $line[1];
$email = $line[2];
$registration = $line[3];
// Calculate average
// Remove any spaces first from the numbers
$numbers = str_replace(' ', '', $numbers);
// Split the numbers by ,
$numbersArray = explode(",", $numbers);
$sum = 0;
// Calculate sum
for($j = 0; $j < sizeOf($numbersArray); $j++){
$num = (int)$numbersArray[$j];
$sum += $num;
}
$avg = $sum/sizeof($numbersArray);
// Print it
echo "$name enrolled in $registration, has an average of $avg, with a symbol ". checkGrade($avg) ."<br>";
}
// Last modified date of the input file
echo "<br><br><br>";
if (file_exists($filename)) {
echo "This file was last modified: " . date ("F d Y H:i:s.", filemtime($filename));
}
function checkGrade($num){
if ($num < 65){
$grad = 'F';
}
else if ($num<= 66 && $num >=65){
$grad = 'D';
}
else if ($num <= 69 && $num >=67){
$grad = 'D+';
}
else if ($num <= 73 && $num >=70){
$grad = 'C-';
}
else if ($num <= 76 && $num >=74){
$grad = 'C';
}
else if ($num<= 79 && $num >=77 ){
$grad = 'C+';
}
else if ($num <= 83 && $num >=80){
$grad = 'B-';
}
else if ($num <= 86 && $num >=84){
$grad = 'B';
}
else if ($num <= 89 && $num >=87){
$grad = 'B+';
}
else if ($num <= 93 && $num >=90){
$grad = 'A-';
}
else if ($num <= 96 && $num >=94){
$grad = 'A';
}
else if ($num >= 97){
$grad = 'A+';
}
return $grad;
}
?>
Here is the output:
Ann Thompson enrolled in 2016-02-01, has an average of 72.2, with a symbol C-
Jeremiah Hanson enrolled in 2016-03-02, has an average of 81, with a symbol B-
Billy Jones enrolled in 2016-04-12, has an average of 65.25, with a symbol D
This file was last modified: May 03 2017 13:12:13.
Related
In Excel, column names are characters from A to Z, if there are more columns needed, it continues with AA, AB ...
I want to write a function, that converts integers to those excel column names.
0 .... A
25 ... Z
26 ... AA
702 ... AAA
.
.
.
The solution I came up with is working up to AZ, but I want it to work further.
function indexToXlxsColumn($index, $prefix="")
{
if($index < 26)
{
return $prefix.chr($index+65);
}else{
return indexToXlxsColumn($index % 26, "A");
}
}
How to adapt this function to work for every index without producing spaghetti code?
Here is the probleme
return indexToXlxsColumn($index % 26, "A");
You away set the next floor prefix to A , what happends when u have
input = 53 , the resultat should be "BB"
Code on paper
function indexToXlxsColumn($index, $prefix="")
{
if($index < 26) // 53 isnt less then 26
// second loop , 1 is less then 26
{
return $prefix.chr($index+65);
// $prefix = A
// chr($index+65) = B
// return "A"."B" ;
}else{
return indexToXlxsColumn($index % 26, "A");
// indexToXlxsColumn(53 % 26, "A") -> (1, "A")
}
}
---UPDATE---
Follow the ask here is the answer
function indexToXlxsColumn($index, $suffix ="")
{
if($index < 26){
return chr($index+65).$suffix ;
}
return indexToXlxsColumn(($index - $index%26)/26-1, chr($index%26+65).$suffix );
}
One of the implementations:
function indexToXlxsColumn($index)
{
$name = '';
while($index > 0) {
$mod = ($index - 1) % 26;
$name = chr(65 + $mod).$name;
$index = (int)(($index - $mod) / 26);
}
return $name;
}
// echo indexToXlxsColumn(26); // Z
echo indexToXlxsColumn(33); // AG
// echo indexToXlxsColumn(800); // ADT
I would do it a little differently. It bothered me to work with chr(). So I once stored the alphabet in a string and iterated over it until the index was successfully resolved.
max "zz"
<?php
function getIn($i) {
$str = 'abcdefghijklmnopqrstuvwxyz';
$r = (int) floor($i / 26) ;
$c = $i % 26;
return ($r) < 1 ? $str[$c] : $str[$r-1] . $str[$c];
}
echo getIn(52); // output: "ba"
Update with max "zzz"
function getIn($i) {
$str = 'abcdefghijklmnopqrstuvwxyz';
$r = (int) floor($i / 26);
$rr = $r >= 27 ? $r - 27 : null;
$c = $i % 26;
if ( $rr !== null) {
return $str[$c] : $str[$r-1] . $str[$c];
}
return ($r) < 1 ? $str[$c] : $str[$r-1] . $str[$c];
}
echo getIn(800); // ddu
echo getIn(1377); // zzz
PLACEHOLDER parts of the code return squiffy values! Needs review before using in the wild!!
In case anyone wants a utility function that does this, here's a python implementation:
n2AA performs the calculation from numeric to "AA" format.
def n2AA(n):
n=n-1
alphabet=["_"] + [chr(c+65) for c in range(0,26)]
w=len(alphabet)-1
accum=[]
for e in range(5,-1,-1):
expon=w**e
s=(n//expon)
r=n%expon
n=n-(s*expon)
if e>0:
accum.append(alphabet[s])
else:
accum.append(alphabet[s+1])
return "".join([a for a in accum if a != "_"])
And AA2n performs the inverse function, starting with "AA" format and returning the column number (starting at 1).
def AA2n(AA):
alphabet=["_"] + [chr(c+65) for c in range(0,26)]
w=len(alphabet)-1
accum=[]
for c in range(0,len(AA)):
expon=w**(len(AA)-1-c)
accum.append((alphabet.index(AA[c]))*expon)
return sum(accum)
I am trying to automatically create student IDs and the ID looks like this "MILE/001/5". The 'mile' is the school name and the '001' is the class number and the '5' is the ID. There can only be 40 students in one class and after 40 the next student will go to the second class e.g 'Mile/002/41'. I have done this using hard coded if stemements meaning i stopped somewhere but i want to automatically do this in a few lines of code without all the if statements. I am getting the $count variable from the database and i increment it after each registered student. Here is the code:
if ($count <= 40) {
$class = '001';
$student_id = "MILE/".$class."/".$count;
} elseif($count >= 41 && $count <= 80 ) {
$class = '002';
$student_id = "MILE/".$class."/".$count;
} elseif($count >= 81 && $count <= 120 ) {
$class = '003';
$student_id = "MILE/".$class."/".$count;
} elseif($count >= 121 && $count <= 160 ) {
$class = '004';
$student_id = "MILE/".$class."/".$count; } }
Check out intdiv https://www.php.net/manual/en/function.intdiv.php
It will perform an integer division (discards fractional part), i.e. 1/2 => 0, 3/2 => 1.
Here's an implementation using intdiv
function generateId($school, $capacity, $id) {
$classIndex = intdiv($id - 1, $capacity) + 1;
$class = sprintf("%03d", $classIndex);
return "$school/$class/$id";
}
$CLASS_CAPACITY = 40;
$SCHOOL = 'MILE';
for ($id=38; $id < 42; $id++) {
$studentId = generateId($SCHOOL, $CLASS_CAPACITY, $id);
var_dump($studentId);
}
output:
string(11) "MILE/001/38"
string(11) "MILE/001/39"
string(11) "MILE/001/40"
string(11) "MILE/002/41"
I created this function to converting numbers to words. And how I can convert words to number using this my function:
Simple function code:
$array = array("1"=>"ЯК","2"=>"ДУ","3"=>"СЕ","4"=>"ЧОР","5"=>"ПАНҶ","6"=>"ШАШ","7"=>"ҲАФТ","8"=>"ХАШТ","9"=>"НӮҲ","0"=>"НОЛ","10"=>"ДАҲ","20"=>"БИСТ","30"=>"СИ","40"=>"ЧИЛ","50"=>"ПАНҶОҲ","60"=>"ШАСТ","70"=>"ҲАФТОД","80"=>"ХАШТОД","90"=>"НАВАД","100"=>"САД");
$n = "98"; // Input number to converting
if($n < 10 && $n > -1){
echo $array[$n];
}
if($n == 10 OR $n == 20 OR $n == 30 OR $n == 40 OR $n == 50 OR $n == 60 OR $n == 70 OR $n == 80 OR $n == 90 OR $n == 100){
echo $array[$n];
}
if(mb_strlen($n) == 2 && $n[1] != 0)
{
$d = $n[0]."0";
echo "$array[$d]У ".$array[$n[1]];
}
My function so far converts the number to one hundred. How can I now convert text to a number using the answer of my function?
So, as #WillParky93 assumed, your input has spaces between words.
<?php
mb_internal_encoding("UTF-8");//For testing purposes
$array = array("1"=>"ЯК","2"=>"ДУ","3"=>"СЕ","4"=>"ЧОР","5"=>"ПАНҶ","6"=>"ШАШ","7"=>"ҲАФТ","8"=>"ХАШТ","9"=>"НӮҲ","0"=>"НОЛ","10"=>"ДАҲ","20"=>"БИСТ","30"=>"СИ","40"=>"ЧИЛ","50"=>"ПАНҶОҲ","60"=>"ШАСТ","70"=>"ҲАФТОД","80"=>"ХАШТОД","90"=>"НАВАД","100"=>"САД");
$postfixes = array("3" => "ВУ");
$n = "98"; // Input number to converting
$res = "";
//I also optimized your conversion of numbers to words
if($n > 0 && ($n < 10 || $n%10 == 0))
{
$res = $array[$n];
}
if($n > 10 && $n < 100 && $n%10 != 0)
{
$d = intval(($n/10));
$sd = $n%10;
$ending = isset($postfixes[$d]) ? $postfixes[$d] : "У";
$res = ($array[$d * 10]).$ending." ".$array[$sd];
}
echo $res;
echo "\n<br/>";
$splitted = explode(" ", $res);
//According to your example, you use only numerals that less than 100
//So, to simplify your task(btw, according to Google, the language is tajik
//and I don't know the rules of building numerals in this language)
if(sizeof($splitted) == 1) {
echo array_search($splitted[0], $array);
}
else if(sizeof($splitted) == 2) {
$first = $splitted[0];
$first_length = mb_strlen($first);
if(mb_substr($first, $first_length - 2) == "ВУ")
{
$first = mb_substr($first, 0, $first_length - 2);
}
else
{
$first = mb_substr($splitted[0], 0, $first_length - 1);
}
$second = $splitted[1];
echo (array_search($first, $array) + array_search($second, $array));
}
You didn't specify the input specs but I took the assumption you want it with a space between the words.
//get our input=>"522"
$input = "ПАНҶ САД БИСТ ДУ";
//split it up
$split = explode(" ", $input);
//start out output
$c = 0;
//set history
$history = "";
//loop the words
foreach($split as &$s){
$res = search($s);
//If number is 9 or less, we are going to check if it's with a number
//bigger than or equal to 100, if it is. We multiply them together
//else, we just add them.
if((($res = search($s)) <=9) ){
//get the next number in the array
$next = next($split);
//if the number is >100. set $nextres
if( ($nextres = search($next)) >= 100){
//I.E. $c = 5 * 100 = 500
$c = $nextres * $res;
//set the history so we skip over it next run
$history = $next;
}else{
//Single digit on its own
$c += $res;
}
}elseif($s != $history){
$c += $res;
}
}
//output the result
echo $c;
function search($s){
global $array;
if(!$res = array_search($s, $array)){
//grab the string length
$max = strlen($s);
//remove one character at a time until we find a match
for($i=0;$i<$max; $i++ ){
if($res = array_search(mb_substr($s, 0, -$i),$array)){
//stop the loop
$i = $max;
}
}
}
return $res;
}
Output is 522.
I'd like to convert currency values like this:
4 000 000 000 => 4b
2 000 000 => 2m
2 250 000 => 2.25m
195 000 => 195k
10 000 => 10k
Anyone know of an existing library/function that does this, or do I need to write this myself by means of conditionals that cater for 0-9999, 10000-999999, and so on..?
You can create a custom function for this. The below one, firstly removes everything but numbers from string. Then it formats the number according how big is it and to the digit provided.
function shorten($num, $digits = 1) {
$num = preg_replace('/[^0-9]/','',$num);
if ($num >= 1000000000) {
$num = number_format(($num / 1000000000), $digits, '.', '') + 0;
$num = $num . "b";
}
if ($num >= 1000000) {
$num = number_format(($num / 1000000), $digits, '.', '') + 0;
$num = $num . 'm';
}
if ($num >= 1000) {
$num = number_format(($num / 1000), $digits, '.', '') + 0;
$num = $num . 'k';
}
return $num;
}
echo shorten("4 000 000 000");
echo shorten("3 200 000 000");
echo shorten("195 000");
Demo: http://codepad.org/K971MzVx
You can create a function like this to display shorten the values but it would miss the exact value
function shortifyCurrency($var){
$var=doubleval($var);
if($var>=1000000000){
$var=($var/1000000000)."b";
}else if($var>=1000000){
$var=($var/1000000)."m";
}else if($var>=1000){
$var=($var/1000)."k";
}
return $var;
}
//Output 4b
echo shortifyCurrency(4000000000);
Or you could use the following function to display more detailed information about the value
function shortifyCurrencyXtream($var){
$var=doubleval($var);
$print_str="";
if($var>=1000000000){
$print_str.=round($var/1000000000)."b";
$var=$var%1000000000;
}
if($var>=1000000){
if($print_str!="") $print_str.=" ";
$print_str.=round($var/1000000)."m";
$var=$var%1000000;
}
if($var>=1000){
if($print_str!="") $print_str.=" ";
$print_str.=($var/1000)."k";
}
return $print_str;
}
//Output 4b 101m 500.3k
echo shortifyCurrencyXtream(4100500300);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I want to write a program to find the maximum gap between two 1s in a binary equivalent of a decimal number. For example for 100101: the gap is 2 and for 10101: the gap is 1.
<?php
$numberGiven = 251;
$binaryForm = decbin($numberGiven);
$status = false;
$count = 0;
for($i = 0; $i < strlen($binaryForm); $i++)
{
var_dump($binaryForm[$i]);
if($binaryForm[$i] == 1)
{
$status = false;
$count = 0;
}
else
{
$status = true;
$count += 1;
}
}
echo "count = " . $count . "<br>";
echo $binaryForm;
?>
but i was not successfull..
First use regex to find "0" groups, then sort by length, descending—take the first one in the list, and get it's length:
$numberGiven = 37;
$binaryForm = decbin($numberGiven);
// get all groups of "0", put list in $matches
preg_match_all('/(0+)/', $binaryForm, $matches_all);
$matches = $matches_all[0];
// sort descending
rsort($matches, SORT_STRING);
// get first `$matches[0]` and print string length
echo 'count = ' . strlen($matches[0]) . '<br>';
echo $binaryForm;
UPDATED: based on Mark Baker's comments below.
UPDATE #2: As brought up by afeijo in the comments below, the above does not exclude ending zeros. Here's a solution for that:
preg_match_all('/(0+)1/', $binaryForm, $matches_all);
$matches = $matches_all[1];
I would use the binary right-shift operator >> and iteratively shift by 1 bit and check if the current rightmost bit is a 1 until I've checked all the bits. If a 1 was found, the gap between the previous 1 is calculated:
foreach(array(5,17,25,1223243) as $number) {
$lastpos = -1;
$gap = -1; // means there are zero or excatly one '1's
// PHP_INT_SIZE contains the number of bytes an integer
// will consume on your system. The value * 8 is the number of bits.
for($pos=0; $pos < PHP_INT_SIZE * 8; $pos++) {
if(($number >> $pos) & 1) {
if($lastpos !== -1) {
$gap = max($gap, $pos - $lastpos -1);
}
$lastpos = $pos;
}
}
echo "$number " . decbin($number) . " ";
echo "max gap: {$gap}\n";
}
Output:
5 101 max gap: 1
17 10001 max gap: 3
25 11001 max gap: 2
1223243 100101010101001001011 max gap: 2
What you currently are doing is reseting the count each time you find a 1.
You need to keep track of the current max value:
$count = 0;
$maxCount = 0;
and where you set $count = 0 you should also do
if ($count > $maxCount)
$maxCount = $count;
$count = 0;
then
echo "count = " . $maxCount . "<br>";
In all:
<?php
$numberGiven = 251;
$binaryForm = decbin($numberGiven);
$status = false;
$count = 0;
$maxCount = 0;
for($i = 0; $i < strlen($binaryForm); $i++)
{
// Don't count leading zeroes.
if ($status == false && $binaryForm[$i] == 0) continue;
$status = true;
var_dump($binaryForm[$i]);
// We've found a 1. Remember the count.
if($binaryForm[$i] == 1)
{
if ($count > $maxCount)
$maxCount = $count;
$count = 0;
}
// We found a 0. Add one to count.
else
{
$count += 1;
}
}
echo "count = " . $count . "<br>";
echo $binaryForm;
?>
Disclaimer: Code not tested