Mapping Values to 14 categories (Math and permutations stuff) - php

My app has people put 24 groups of 4 statements in order. In each group of 4 one is the "D" statement, one is the "I" statement, one is the "S" statement, and one is the "C" statement.
So the end result looks something like ['ISCD','CISD','DISC',CISD,'CISD','ISCD'...] because the are essentially rearranging the 4 letters
In the end, they get a "score" for each letter using the following algorithm.
For each of I,S,C and D
Find the number of times that letter is first and multiply by 3
Find the number of times that letter is second and multiply by 2
Find the number of times that letter is third and muliply by 1
Total it up, and that is the score for that letter
The end result is that each letter (I,S,D,C) gets a score from 0 to 72, and there are always 144 total points given out:
I want to map the results to 14 reports:
D
I
S
C
DI
IS
SC
CD
DS
IC
DIS
ISC
SCD
CDI
The idea is that if S is dominant, we choose the S report. If Both D and I are dominant, we choose the DI report. If none is particularly dominant, we choose the top 3. (there is no difference between DI and ID meaning which one is most dominant is irrelevant if they are both high)
So if the scores are D=50, I=48, S=20,C=26 then I want it to choose "DI" since D and I are dominant. There are 24^(4!) possible responses from the user, that I need to map to 14 reports
I understand that I will have to set the thresholds for what "dominant" means, but for starters, I want to assume all possible responses are equally likely, and to map all possible responses to the 14 reports to where each of the 14 reports is equally likely, given random input.
I expect it's 1 to 5 lines of code. It'll be in php but any language including math or pseudo code should be fine.
UPDATE:
I figured out a way to do it in one line of code, but it's not evenly distributed. here's the php (no dependencies)
<?php
$totals=array();
$lets=array('D','I','S','C');
for($j=0;$j<100000;$j++)
{
$vals=array('D'=>0,'I'=>0,'S'=>0,'C'=>0);
for($i=0;$i<24;$i++)
{
shuffle($lets);
$vals[$lets[0]]+=3;
$vals[$lets[1]]+=2;
$vals[$lets[2]]+=1;
}
$D=$vals['D'];$I=$vals['I'];$S=$vals['S'];$C=$vals['C'];
//calculate which report
$reportKey=($D>36?'D':'').($I>36?'I':'').($S>36?'S':'').($C>36?'C':'');
if(!$reportKey)
$reportKey="DIS";
if(isset($totals[$reportKey]))
$totals[$reportKey]+=1;
else
$totals[$reportKey]=1;
echo $reportKey." $D $I $S $C <br>";
}
echo "<br>";
foreach ($totals as $k=>$v)
echo "$k: $v<br>";
The magic line is
$reportKey=($D>36?'D':'').($I>36?'I':'').($S>36?'S':'').($C>36?'C':'');
That line says if any value is over 36, include that letter. the output of the script is like this:
SC 35 33 38 38
IC 33 42 32 37
DI 44 39 29 32
...
...
DC 46 21 35 42
DIS 38 37 40 29
IC 36 39 28 41
DS 41 36 42 25
C 36 34 29 45
IS 29 41 38 36
IS 28 46 41 29
DS 38 33 40 33
DS 41 33 40 30
DS: 1444
D: 889
IS: 1466
S: 910
C: 874
SC: 1442
IC: 1467
DI: 1569
ISC: 407
DSC: 386
DIS: 388
DC: 1487
DIC: 396
I: 875
As you can see, it automatically split it into 14 categories, but the distribution varies with the 2 letter ones being way more likely.

You can do this recursively using Haskell e.g. as follows:
combinationsOf _ 0 = [[]]
combinationsOf [] _ = []
combinationsOf (x:xs) k = map (x:) (combinationsOf xs (k-1) ) ++ combinationsOf xs k
The results from GHCI:
*Main> concatMap (combinationsOf "DISC") [1,2,3]
["D","I","S","C","DI","DS","DC","IS","IC","SC","DIS","DIC","DSC","ISC"]

Related

Multiple elements in the array having the same value, will get a different percentile

I am calculating the number that falls into a specific percentile. However, the problem with my equation is that if multiple elements in the array having the same value, this code will assign a different percentile number to each of those elements.
$percentile_50 = $array[round((50/100) * $count_array -.5)];
For example, first column is the percentile, and second is the score. You can see that same second gets different percentile, but in fact it should be the same.
How can I avoid this?
5-1
10-1
15-1
20-1
25-2
30-2
35-3
40-4
45-4
50-5
55-6
60-7
65-9
70-11
75-14
80-17
85-23
90-32
95-53
To calculate the kth percentile, you should :
Order all the values in the data set from smallest to largest.
Multiply k percent by the total number of values, n.
This number is called the index.
If the index obtained in Step 2 is not a whole number, round it up to the nearest whole number and go to Step 4. If the index obtained in Step 2 is a whole number, go to Step 5.
Count the values in your data set from left to right (from the smallest to the largest value) until you reach the number indicated by Step 3.
The corresponding value in your data set is the kth percentile
Count the values in your data set from left to right until you reach the number indicated by Step 2.
The kth percentile is the average of that corresponding value in your data set and the value that directly follows it.
( from here)
Translated to PHP:
$sData = sort($data);
$percentile = 50/100;
$index = ceil($percentile * count($sData));
$value = $sData[$index-1];
Or shorter:
$sData = sort($data);
$value = $sData[ceil((50/100) * count($sData)) - 1]
However, in a small dataset, sometimes the percentiles end up the same. For example, the following code produces the following output.
Code
$data = array(74, 15, 25, 62, 45, 9, 16, 63, 60, 76, 7, 20, 67, 30, 12);
sort($data);
for($i=5;$i<100;$i+=5){
echo $i . " - " . $data[ceil(($i/100) * count($data)) - 1];
echo PHP_EOL;
}
Output
5 - 7
10 - 9
15 - 12
20 - 12 //same as aboce
25 - 15
30 - 16
35 - 20
40 - 20 //same as above
45 - 25
50 - 30
55 - 45
60 - 45 //same as above
65 - 60
70 - 62
75 - 63
80 - 63 //same as above
85 - 67
90 - 74
95 - 76

PHP str_replace bug

I'm running simple PHP code
$myVariable = 1;
$myVariable2 = str_replace(array(1, 2, 3), array('do 25 lat', 'od 26 do 35 lat', 'pow. 35 r.z.'), $myVariable);
echo $myVariable2;
And result is:
do od 26 do pow. 35 r.z.5 lat5 lat
I checked on different PHP versions. Any ideas?
You're falling victim to the gotcha specified in the documentation - look under "notes" on the str_replace documentation
Replacement order gotcha
Because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements. See also the examples in this document.
Essentially what's happening is the sequential replacements, as you passed an array as the second parameter:
1 is replaced with do 25 lat
In that string, 2 is replaced with od 26 do 35 lat, giving you do od 26 do 35 lat5 lat
In that string, 3 is replaced with pow. 35 r.z. giving you the final result you're seeing.
This is because str_replace array pairs are applied one after the other.
Try strtr:
$myVariable = 1;
$replacePairs = array(
1 => "do 25 lat",
2 => "od 26 do 35 lat",
3 => "pow. 35 r.z."
);
$myVariable2 = strtr($myVariable,$replacePairs);
echo $myVariable2;
It's not a bug, this is the normal behavior of str_replace. What happens is the function iterates through your search array and each time it finds an occurrence, it replaces it with relevant replace.
Thus:
(search and match 1) 1 -> "do 25 lat"
(search and match 2) "do 25 lat" -> "do od 26 do 35 lat5 lat"
(search and match 3) "do od 26 do 35 lat5 lat" -> "do od 26 do pow. 35 r.z.5 lat5 lat"

Display current import file (html table form) from database into cakephp

Cakephp version 2.5.1, import file (csv format), database (mssql)
i have imported the csv file and saved into database, after save i want to display each of the 'current' import data using html table in cakephp. My problem is i don't have idea to code for find current batch upload where each batch start point from L01-0-00-00-000
until end L01-0-00-00-999.The L01 on each string will change to L02, L03 and so on.
i try to use this function in mycontroller, it will only show all the table with Line=01
My controller:
function index () {
$this->set('uploads', $this->Upload->getColumnTypes('all', array('conditions' => array('RAS_Off_Upload.RAS_Code' => ' L01-0-00-00-000' && ' L01-0-00-00-999' ))));
}
Thank you for any of the suggestion.
Output table in database:
RAS_Off_Upload table
No RAS_Code Value Remark SF Create_by CLN Lot Prod Time Date
1 L01-0-00-00-000 0 test H D123 CLN12345 SLTC123M LN2CPW 7:10 25JUN
2 L01-1-01-01-111 68 test L D123 7:15 25JUN
3 L01-0-01-01-222 40 test L D123 7:18 25JUN
4 L01-0-01-01-333 82 test L D123 7:20 25JUN
5 L01-0-00-00-444 59 test L D123 7:21 25JUN
6 L01-0-00-00-555 59 test L D123 7:23 25JUN
7 L01-0-00-00-666 59 test L D123 7:34 25JUN
8 L01-0-00-00-777 59 test L D123 7:37 25JUN
9 L01-0-00-00-888 59 test L D123 7:40 25JUN
10 L01-0-00-00-999 0 test E D123 7:41 25JUN
I am considering RasOffUpload is your model correspond to RAS_Off_Upload table.
Try the following:
function index () {
$this->set('uploads', $this->RasOffUpload->find('all',
array('conditions' => array('RasOffUpload.RAS_Code REGEXP' => '^L01-0-00-00-[0-9]*$'))));
}
Use find method instead of getColumnTypes. You can also try to use ^L01-0-00-00-[[:digit:]][[:digit:]][[:digit:]]$.
If in the middle digit is also varies from 0 to 9, then you can use like:
^L01-[[:digit:]]-00-00-[[:digit:]][[:digit:]][[:digit:]]$.

using PHP to find exact value in a string

the current tasks at hand is using PHP to check if data exists
to make things short the problem is:
i am trying to search some of the available sizes in a unorganized string.
sizes are
SM/M M/L L/XL XS S M L XL XXL 28 30 31 32 33 34 35 36 28 X 30 28 X 32
currently most of the issues are solved by utilizing whitespaces to disgtinush unique variable, but when it comes to (number X number) as a phrase it becomes very difficult.
when I search for "28" it also detect as found when seeing "28 X 30"
or when I search for unique number " 30 " with the whitespaces included, it still detects the 28 X "30"
Is there any method to tackle this issue?
What you could do is make the string easier to deal with by first transforming the nnn X nnn strings and removing spaces from them:
//BEFORE: SM/M M/L L/XL XS S M L XL XXL 28 30 31 32 33 34 35 36 28 X 30 28 X 32
//AFTER: SM/M M/L L/XL XS S M L XL XXL 28 30 31 32 33 34 35 36 28X30 28X32
$sizes=preg_replace('/(\d+) X (\d+)/', '$1X$2', $sizes);
Now you can explode the string on spaces
$sizeArray=explode(' ', $sizes);
With all the distinct sizes in an array, you can use in_array to look for a specific size code.
//we want to find this
$searchFor='28 X 30';
//our codes no longer have spaces...
$searchFor=str_replace(' ', '', $searchFor);
if (in_array($searchFor, $sizeArray)) {
//great!
}

create pdf of rows in a database on a new page

i am creating a student management system and i want to be able to generate a pdf report that will contain every students data in its own page i.e . studentId, Math, English, Science, Class, totals, Rank, myClass and myTotals.for example, in the table below i would expect the pdf to have 6 pages. each containing only details of a particular student. how do i go about doing this?
Thank you in advance
studentId Math English Science Class totals Rank myClass myTotals
2 75 83 84 3p1 242 1 3p1 242
5 88 77 77 3p1 242 1 3p1 242
1 80 66 85 3p1 231 2 3p1 231
6 92 97 96 5p2 285 1 5p2 285
3 70 88 90 5p2 248 2 5p2 248
4 50 82 50 5p2 182 3 5p2 182
loop through the rows and create a new page for every row. How to do that exactly depends on with what you create the pdf.
You could output the information to a LaTeX file (assuming the machine has it installed). I assume you get all your student details from a database into an array of arrays called students. If you are using mySQL or similar to store the data, this should be simple enough.
This should generate a report.tex file and then execute pdflatex to generate report.pdf file.
<?
$f = fopen('report.tex','w');
$out = '\documentclass{article}
\usepackage{a4wide}
\begin{document}
';
fwrite($f,$out);
//Example array
$students = array(array('studentId'=> 1, 'Math'=> 1, 'English'=> 5 , 'Science' => 5, 'Class' =>6, 'totals'=>6 , 'Rank'=>7 , 'myClass' =>7, 'myTotals'=>9));
foreach($students as $x){
$out = '\begin{table}[htbp]'."\n".' \centering'."\n";
$out .= '\begin{tabular}{|r|r|r|r|r|r|r|r|r|}'."\n";
$out .= '\hline'."\n";
$out .= 'studentId & Math & English & Science & Class & totals & Rank & myClass & myTotals \\\\ '."\n \\hline \n";
$out .= "{$x['studentId']} & {$x['Math']} & {$x['English']} & {$x['Science']} & {$x['Class']} & {$x['totals']} & {$x['Rank']} & {$x['myClass']} & {$x['myTotals']} ";
$out .= '\\\\'."\n \\hline";
$out .= '\end{tabular} '."\n".' \end{table}'."\n".'\newpage' ."\n";
fwrite($f,$out);
}
fwrite($f,"\n".'\end{document}');
fclose($f);
echo (exec('pdflatex report.tex'));
echo "\ndone";
?>
The script works properly now, that produces a correct file. Having the server send the pdf to you shouldn't be too difficult.

Categories