I have a table that contains all the employees in a company (hr_employees). In addition to this table, is another table that has all their start dates and end dates, plus which type of contract they have (hr_employees_status).
With the data I get, I write a 1 or a 0 (1 permanent based, 0 other) to an excel spreadsheet, colour coded as determined by the type of contract (1 = black, 0 = blue, green, grey or red), in each month (from May 2005 up to present). How I determine what should go in which cell is by a case clause, looking at the current status in the hr_employee_status table.
It loops fine, and does 99% of what it should correctly. The only issue is that, as soon as an employee moves over from a temporary contract to a permanent basis, it sometimes doesn't write the correct value to a cell.
I have changed the code a bit to only pull month and year from the database (and set the day to 01), out of hopes that, since the month and year is all that is needed to write to a cell, it would write the correct data in the correct cell. But to no avail.
I don't know what code to post, so here is the loop that determines the type of contract and writes it to the excel sheet:
switch ($dates['status']) {
case '0':
$color = 'blue';
$cellcontent="0";
break;
case '1':
$color = 23;
$cellcontent="0";
break;
case '2':
$color = 'black';
$cellcontent="1";
break;
case '3':
$color = 'green';
$cellcontent="0";
break;
case '4':
$color = 'red';
if(mysql_num_rows($query) > 2)
$cellcontent = "0";
else {
$cellcontent="1";
}
break;
}
if($s['state'] == '4')
$color = 'red';
$format_content =& $workbook->addFormat(array('align' => 'center', 'size' => 11, 'numformat' => '#', 'fontfamily' => 'Calibri', 'left' => 1, 'bottom' => 1, 'right' => 1, 'color' => $color));
for($f = $start_at; $f <= $start_at+$count; $f++) {
$totalmonths = $totalmonths + $cellcontent;
$worksheet->write($k,15+$f,$cellcontent,$format_content);
}
$date is the results as received from the DB.
$start_at is the date the employee started with a contract type (and thus determines which month to mark).
$count is the difference between the start date, and the end date (amount of months).
I would like to know WHY does it not start at the correct date when switching form a temporary contract, to a permanent one.
If any other info is required, please let me know.
EDIT 1: - Response to feedback from DaveRandom and Oleg
#DaveRandom:
hr_employees looks like this:
------------------------------------------
|employee_id|name|surname|otherinfo|state|
|1 |Foo |Bar | ******* | 1 |
|2 |Ben |Smith | ******* | 1 |
------------------------------------------
hr_employees_status looks like this:
------------------------------------------
|employee_id|from_date |to_date |status|
|1 |2006-07-12|2009-08-11| 0 |
|1 |2009-08-12|0000-00-00| 1 |
|2 |2009-07-01|0000-00-00| 1 |
------------------------------------------
And then the excel sheet will output
Name Surname Start Date *dates* June-06 July06 ->- July09 Aug09 Sep09
Foo Bar 2006-07-12 *empty* 0 ->- 0 1 1
Ben Smith 2009-07-01 *empty* *empty* ->- 1 1 1
#Oleg
$start_at is as follows:
round(((substr($dates['from_date'],0,4) * 12) + substr($dates['from_date'],5,2)) - ((substr($start_date,0,4) * 12) + substr($start_date,5,2))) + 1;
// $dates is a loop through the hr_employee_status table
See above. $dates is a loop through the hr_employee_status table. I'm 100% sure that status is in there.
Please explain type juggling? All the values in status is varchar (and don't ask me why, looking at it now, it seems like a stupid thing to do...)
We are missing some crucial part of your code, so until you provide more details (could you show us where you define $start_at for example?) I can only guess...
You ask "why does it not start at the correct date" but you never provide the code where $start_at is defined. It could be useful to us.
Why are you switching $dates['status']? Are you sure it's in $dates?
The switch statement compares values after type juggling...
Example from php.net:
switch ("a") {
case 0:
echo "0";
break;
case "a": // never reached because "a" is already matched with 0
echo "a";
break;
}
This might be your case where the permanent contract status 1 is never reached in your switch statement because of incorrect type of $dates['status'] making it stop at case '0':.
Try using var_dump() to see the exact types and values of variables you're operating on in your code.
Related
Firstly, i am a php newbie... so i still code and understand php procedurally. that said,
i have a collection of numbers (amount) stored in a database.
Question: Using PHP and mySQL,
Whats the best way to spool this info out of a database such that the amount will be associated with its transaction ID
Most importantly, i need to find a matching set of numbers in the db that equals a sum of 29.
Below is the Transaction Table , Transaction_tlb, for my Database mydb
Transaction_ID | Name | Date | Amount
---------------|------------------|-----------------|------------
11012 | Jonathan May | 6/12/2016 | 84
21012 | John Pedesta | 6/12/2016 | 38
31012 | Mary Johnson | 1/01/2017 | 12
41012 | John Johnson | 8/01/2017 | 13
51012 | Keith Jayron | 8/01/2017 | 17
61012 | Brenda Goldson | 8/01/2017 | 2
71012 | Joshua Traveen | 8/01/2017 | 78
81012 | Remy ma Goldstein| 8/01/2017 | 1
91012 | Barbie Traveen | 8/01/2017 | 1
Now, i have an idea..but its not efficient. I am going to try every possible case. meaning if i have n values to check, the time complexity is going to be about 2^n. this is highly inefficient (plus, i dont even know if my code makes any sense. (see below)
I saw a similar example in this YouTube video: https://www.youtube.com/watch?v=XKu_SEDAykw&t
but, Im not sure exactly how to write the code in php.
The code:
<?php
if (!mysql_connect("localhost", "mysql_user", "mysql_password") || !mysql_select_db("mydb")) {
die("Could not connect: " . mysql_error()); } //End DB Connect
$capacity = 29; //Knapsack Capacity or Sum
//Select Transact ID and Value from the Database where Amount is <= Capacity
$fetchQuery = "SELECT 'Transaction_ID', 'Amount' FROM 'Transaction_tlb' WHERE 'Amount' <= $capacity";
$components = array(); //new array to hold components
if ($queryResults = mysql_query($fetchQuery)) {
//check if data was pulled
if (mysql_num_row($queryResults) != NULL) {
while ($row = mysqli_fetch_assoc($queryResults) {
$components[$row['Transaction_ID']] = $row['Amount'];
}
}
}
/* Correct me if i am wrong, but, Components associative array Should be something like
$components = array('11012'=> 84, '21012'=> 38, '31012'=> 12, '41012'=> 13, '51012'=> 17,
'61012'=> 2, '71012'=> 78, '81012'=> 1, '91012'=> 1);
*/
$components = asort($components) // sort array in ascending order
$componentCount = count($component)
function match ($componentCount, $capacity) {
$temp = match (($componentCount - 1), $capacity);
$temp1 = $component[$componentCount] + match (($componentCount - 1), ($capacity - $component[$componentCount]));
$result = max($temp, $temp1);
return $result;
}
}?>
can anyone please point me in the right direction? this code doesn work... and even if it works... the method is not efficient at all. what happens when Ive got 3 million records to work with? i need help please.
You can formulate your problem in terms of the 0/1 Knapsack problem. Ready-to-use implementation in PHP is available.
Using the function knapSolveFast2 defined in the linked page, one could proceed as in the example below. The idea here is that you set the "weights" entering the Knapsack algorithm equal to the values themselves.
$components = array(84, 38, 12, 13, 17, 2, 78, 1, 1);
$m = array();
list($m4, $pickedItems) = knapSolveFast2($components, $components, sizeof($components)-1, 29, $m);
echo "sum: $m4\n";
echo "selected components:\n";
foreach($pickedItems as $idx){
echo "\t$idx --> $components[$idx]\n";
}
which yields:
sum: 29
selected components:
2 --> 12
4 --> 17
Notes:
you could modify your SQL query in order to skip rows with amount larger than the required sum (29)
the function above will pick one solution (assuming that it exists), it won't provide all of them
one should check whether the return value $m4 is indeed equal to the specified sum (29) - as the algorithm works, the specified amount is only the upper limit which is not guaranteed to be attained (for example for 37 instead of 29, the return value is only 34 since there is no combination of the input numbers the sum of which would yield 37)
This is really a knapsack problem, but I will try to give a full solution which isn't optimal, but illustrates a full strategy for solving your problem.
First of all, you can do this with just one iteration over the array of numbers with no recursion and no pre-sorting needed. Dynamic programming is all you need, keeping track of all previously possible partial-sum 'paths'. The idea is somewhat similar to your described recursive method, but we can do it iteratively and without presorting.
Assuming an input array of [84, 38, 12, 13, 17, 2, 78, 1, 1] and a target of 29, we loop over the numbers like so:
* 84 - too big, move on
* 38 - too big, move on
* 12 - gives us a subtarget of 29-12 = 17
subtargets:
17 (paths: 12)
* 13 - gives us a subtarget of 29-13=16
subtargets:
16 (paths: 13)
17 (paths: 12)
* 17 - is a subtarget, fulfilling the '12' path;
and gives us a subtarget of 29-17=12
subtargets:
12 (paths: 17)
16 (paths: 13)
17 (paths: 12)
solutions:
12+17
etc.
The trick here is that while looping over the numbers, we keep a lookup table of subTargets, which are the numbers which would give us a solution using one or more combinations ('paths') of previously seen numbers. If a new number is a subTarget, we add to our list of solutions; if not then we append to existing paths where num<subTarget and move on.
A quick and dirty PHP function to do this:
// Note: only positive non-zero integer values are supported
// Also, we may return duplicate addend sets where the only difference is the order
function findAddends($components, $target)
{
// A structure to hold our partial result paths
// The integer key is the sub-target and the value is an array of string representations
// of the 'paths' to get to that sub-target. E.g. for target=29
// subTargets = {
// 26: { '=3':true },
// 15: { '=12+2':true, '=13+1':true }
// }
// We are (mis)using associative arrays as HashSets
$subTargets = array();
// And our found solutions, stored as string keys to avoid duplicates (again using associative array as a HashSet)
$solutions = array();
// One loop to Rule Them All
echo 'Looping over the array of values...' . PHP_EOL;
foreach ($components as $num) {
echo 'Processing number ' . $num . '...' . PHP_EOL;
if ($num > $target) {
echo $num . ' is too large, so we skip it' . PHP_EOL;
continue;
}
if ($num == $target) {
echo $num . ' is an exact match. Adding to solutions..' . PHP_EOL;
$solutions['='.$num] = true;
continue;
}
// For every subtarget that is larger than $num we get a new 'sub-subtarget' as well
foreach ($subTargets as $subTarget => $paths) {
if ($num > $subTarget) { continue; }
if ($num == $subTarget) {
echo 'Solution(s) found for ' . $num . ' with previous sub-target. Adding to solutions..' . PHP_EOL;
foreach ($paths as $path => $bool) {
$solutions[$path . '+' . $num] = true;
}
continue;
}
// Our new 'sub-sub-target' is:
$subRemainder = $subTarget-$num;
// Add the new sub-sub-target including the 'path' of addends to get there
if ( ! isset($subTargets[$subRemainder])) { $subTargets[$subRemainder] = array(); }
// For each path to the original sub-target, we add the $num which creates a new path to the subRemainder
foreach ($paths as $path => $bool) {
$subTargets[$subRemainder][$path.'+'.$num] = true;
}
}
// Subtracting the number from our original target gives us a new sub-target
$remainder = $target - $num;
// Add the new sub-target including the 'path' of addends to get there
if ( ! isset($subTargets[$remainder])) { $subTargets[$remainder] = array(); }
$subTargets[$remainder]['='.$num] = true;
}
return $solutions;
}
Run the code like so:
$componentArr = array(84, 38, 12, 13, 17, 2, 78, 1, 1);
$addends = findAddends($componentArr, 29);
echo 'Result:'.PHP_EOL;
foreach ($addends as $addendSet => $bool) {
echo $addendSet . PHP_EOL;
}
which outputs:
Looping over the array of values...
Processing number 84...
84 is too large, so we skip it
Processing number 38...
38 is too large, so we skip it
Processing number 12...
Processing number 13...
Processing number 17...
Solution(s) found for 17 with previous sub-target. Adding to solutions..
Processing number 2...
Processing number 78...
78 is too large, so we skip it
Processing number 1...
Processing number 1...
Solution(s) found for 1 with previous sub-target. Adding to solutions..
Result:
=12+17
=12+13+2+1+1
I need to generate an invoice number from an integer of a table with an auto incrementing ID of the database where the user purchases saved.
Example of the table invoice database:
The invoice number format floor do one of two ways.
Example 1: of the number of invoices without prefix:
0000001 |
0000002 |
0000003 |
0000004 |
0000005
Example 2: the number of invoices with prefixes:
F-0000001 |
F-0000002 |
F-0000003 |
F-0000004 |
F-0000005
Question:
1) ¿What is the best way to do this, you can do directly from MySQL or PHP?
2) ¿What is the most appropriate format Example 1 or Example 2?
I appreciate your support as always!
Thanks to Gordon Linoff, I could get a way to solve this.
I will share an example, perhaps someone may be interested.
SQL - Invoice without prefix: SELECT id, LPAD(id,7,'0') FROM invoice WHERE id = 1;
Result: 0000001
SQL - Invoice with prefix: SELECT id, CONCAT( 'F-', LPAD(id,7,'0') ) FROM invoice;
Result: F-0000001
You can write a good helper function in PHP to use it wherever you want in your application to return an invoice number. The following helper function can simplify your process.
function invoice_num ($input, $pad_len = 7, $prefix = null) {
if ($pad_len <= strlen($input))
trigger_error('<strong>$pad_len</strong> cannot be less than or equal to the length of <strong>$input</strong> to generate invoice number', E_USER_ERROR);
if (is_string($prefix))
return sprintf("%s%s", $prefix, str_pad($input, $pad_len, "0", STR_PAD_LEFT));
return str_pad($input, $pad_len, "0", STR_PAD_LEFT);
}
// Returns input with 7 zeros padded on the left
echo invoice_num(1); // Output: 0000001
// Returns input with 10 zeros padded
echo invoice_num(1, 10); // Output: 0000000001
// Returns input with prefixed F- along with 7 zeros padded
echo invoice_num(1, 7, "F-"); // Output: F-0000001
// Returns input with prefixed F- along with 10 zeros padded
echo invoice_num(1, 10, "F-"); // Output: F-0000000001
Once you are done writing the helper function, you don't need to use LPAD or CONCAT MySQL functions every time in your query to return ID with padding zeros or zeros with prefix. If you have global access to the helper function in the entire application, you only need to invoke it wherever you want to generate an invoice number.
1 - 0000001 | 0000002 | 0000003 | 0000004 | 0000005
$dbValue = 1;
echo $dbValue = str_pad($dbValue, 7, "0", STR_PAD_LEFT); // it will give 0000001;
2 - F-0000001 | F-0000002 | F-0000003 | F-0000004 | F-0000005
$dbValue = 1;
echo $dbValue = "F-".str_pad($dbValue, 7, "0", STR_PAD_LEFT); // it will produce F-0000001;
Fetch last ID from database and store it in a PHP variable.
For example, if last record is 100, then increment it by 1.
$last = 100; // This is fetched from database
$last++;
$invoice_number = sprintf('%07d', $last);
Finally, the answer for second question is,
$number = "F-". $number;
Ans 1):
You can do this with PHP(directly by concat or use str-pad ) as well as with MySQL( LPAD ) also
But as per my view you should do this by PHP, so that you can change it according to your requirements e.g. extend zeroes as per number of id's in DB.So that not to change SQL queries and make it heavy.
Ans 2):
You can use both formats but if you want to be more specific about particular user or any thing else, then use second format.
I think second format can give you more information about data
Let's assume I have a table similar to this:
Id Name Value1 Value2 Value3
1 Bla 1 5 1
2 Blu 4 0 2
How to I put this into a matrix format (or similar) in PHP so I can work with it?
I wanted to do some calculations and sorting with the part that contains:
1 5 1
4 0 2
So I could then order and permantely change the main matrix. For example:
Assign a weight of 50% (or other) to each column and then move the columns associated with the lower values to the left.
Example:
1*0.5 + 4*0.5 = 2.5
5*0.5 + 0*0.5 = 2.5
1*0.5 + 2*0.5 = 1.5
Final output:
Id Name Value3 Value2 Value1
1 Bla 1 5 1
2 Blu 2 0 4
In C this was very easy to do but in PHP seems to me it's very complicated to do this because there isn't an object like M[i,j].
You need to access the column in each iteration of your query, you can't access it directly like you can with a row result:
$values = array();
$multiplier = 0.5;
foreach($result as $row) {
$values[1] += $row['value1'] * $multiplier;
$values[2] += $row['value2'] * $multiplier;
$values[3] += $row['value3'] * $multiplier;
}
print_r($values);
Depending on the names of your columns though, you could loop through them in PHP to define variables or array keys instead of doing it by hand (especially if you have lots of them). Depends on your column names. If you have lots that aren't related by numbers etc, you could loop through the column names and exclude certain ones e.g. id, name etc from your processing. In that case, you'd leave the first line above, insert a variable in place of 1 and value1, and check to make sure the array key exists before using the += operator as it will often throw an error if it's not already defined:
if(!array_key_exists($yourfield, $values))
$values[$yourfield] = 0;
// continue...
Basically on my website there are checkboxes for each day of the week. If a user checks them, those are the days to be saved (in a field) in their user account.
How would I go about saving these dates? For example, if someone checks Saturday and Wednesday, another saves Monday and Tuesday, what's a good pattern to keep this info?
Someone suggested saving it as a bit string like 0001001 the 1's representing the days of the week check marked, out of the 7 bits representing each day. Any ideas?
The table would look like this:
user_id | days
10 | 0010010 (Wednesday and Saturday, week starts on Monday)
The only issue with is how would I output this info from php?
(I'm trying to do this in the most optimal way both on the mysql and php side)
The suggestion to use a bit field type in MySQL with a length of seven sounds fair to keep storage requirements low (BIT(7)).
The only issue with is how would I output this info from php?
The first step would be to define a mapping of each bit to a weekday-name:
$days = array(
'Monday',
'Tuesday',
...
'Sunday'
);
Then you first need to select the binary value from the database, e.g. as a decimal (integer) value:
SELECT days+0 FROM table;
In PHP you can convert this to a fixed-width binary number string using decbin and substr:
$binary = substr('000000'.decbin($integer), -7);
or probably more convenient sprintf:
$binary = sprintf('%07b', $integer);
As each of those characters is either 0 or 1 you can iterate over them and create an array for all set days:
$array = array();
foreach (range(0, 7) as $day)
{
if (! $set = (int) $binary[$day])
continue;
$array[] = $days[$day];
}
The resulting $array contains now all weekday names that the user checked. You can then output them:
$output = '(none)';
if (1 === $count = count($array)
{
$output = $array[0]; # one day
}
elseif ($count)
{
$last = array_pop($array); # last day
$output = implode(', ', $array) . ' and ' . $last;
}
That was the output of the database value. Hope this is helpful.
You can store the days in a serialized array, and that way, get it back easily when you want it.
$days = array('wednesday','saturday');
$store = serialize($days);
and then store $store for that user_id
I think it would be easier to store like this:
user_id | sun | mon | tues | wed |...
01 | 1 | 0 | 0 | 1 |
And leave the day columns as tinyint(1)'s. That way, in PHP, you could just go like this:
if($row['sun'] == 1)
Do sunday stuff
I would suggest a table like this:
id user_id day
1 1 1
2 1 4
3 2 1
4 3 7
I am doing this programming challenge which can be found at www.interviewstreet.com (its the first challenge worth 30 points).
When I submitted the solution, I was returned a result which said that the answer was wrong because it only passed 1/11 test cases. However, I feel have tested various cases and do not understand what I am doing wrong. It would be helpful to know what those test cases could be so that I can test my program.
Here is the question (in between the grey lines below):
Quadrant Queries (30 points)
There are N points in the plane. The ith point has coordinates (xi, yi). Perform the following queries:
1) Reflect all points between point i and j both including along the X axis. This query is represented as "X i j"
2) Reflect all points between point i and j both including along the Y axis. This query is represented as "Y i j"
3) Count how many points between point i and j both including lie in each of the 4 quadrants. This query is represented as "C i j"
Input:
The first line contains N, the number of points. N lines follow.
The ith line contains xi and yi separated by a space.
The next line contains Q the number of queries. The next Q lines contain one query each, of one of the above forms.
All indices are 1 indexed.
Output:
Output one line for each query of the type "C i j". The corresponding line contains 4 integers; the number of points having indices in the range [i..j] in the 1st,2nd,3rd and 4th quadrants respectively.
Constraints:
1 <= N <= 100000
1 <= Q <= 100000
You may assume that no point lies on the X or the Y axis.
All (xi,yi) will fit in a 32-bit signed integer
In all queries, 1 <=i <=j <=N
Sample Input:
4
1 1
-1 1
-1 -1
1 -1
5
C 1 4
X 2 4
C 3 4
Y 1 2
C 1 3
Sample Output:
1 1 1 1
1 1 0 0
0 2 0 1
Explanation:
When a query says "X i j", it means that take all the points between indices i and j both including and reflect those points along the X axis. The i and j here have nothing to do with the co-ordinates of the points. They are the indices. i refers to point i and j refers to point j
'C 1 4' asks you to 'Consider the set of points having index in {1,2,3,4}. Amongst those points, how many of them lie in the 1st,2nd,3rd and 4th quads respectively?'
The answer to this is clearly 1 1 1 1.
Next we reflect the points between indices '2 4' along the X axis. So the new coordinates are :
1 1
-1 -1
-1 1
1 1
Now 'C 3 4' is 'Consider the set of points having index in {3,4}. Amongst those points, how many of them lie in the 1st,2nd,3rd and 4th quads respectively?' Point 3 lies in quadrant 2 and point 4 lies in quadrant 1.
So the answer is 1 1 0 0
I'm coding in PHP and the method for testing is with STDIN and STDOUT.
Any ideas on difficult test cases to test my code with? I don't understand why I am failing 10 / 11 test cases.
Also, here is my code if you're interested:
// The global variable that will be changed
$points = array();
/******** Functions ********/
// This function returns the number of points in each quadrant.
function C($beg, $end) {
// $quad_count is a local array and not global as this gets reset for every C operation
$quad_count = array("I" => 0, "II" => 0, "III" => 0, "IV" => 0);
for($i=$beg; $i<$end+1; $i++) {
$quad = checkquad($i);
$quad_count[$quad]++;
}
return $quad_count["I"]." ".$quad_count["II"]." ".$quad_count["III"]." ".$quad_count["IV"];
}
// Reflecting over the x-axis means taking the negative value of y for all given points
function X($beg, $end) {
global $points;
for($i=$beg; $i<$end+1; $i++) {
$points[$i]["y"] = -1*($points[$i]["y"]);
}
}
// Reflecting over the y-axis means taking the negative value of x for all given points
function Y($beg, $end) {
global $points;
for($i=$beg; $i<$end+1; $i++) {
$points[$i]["x"] = -1*($points[$i]["x"]);
}
}
// Determines which quadrant a given point is in
function checkquad($i) {
global $points;
$x = $points[$i]["x"];
$y = $points[$i]["y"];
if ($x > 0) {
if ($y > 0) {
return "I";
} else {
return "IV";
}
} else {
if ($y > 0) {
return "II";
} else {
return "III";
}
}
}
// First, retrieve the number of points that will be provided. Make sure to check constraints.
$no_points = intval(fgets(STDIN));
if ($no_points > 100000) {
fwrite(STDOUT, "The number of points cannot be greater than 100,000!\n");
exit;
}
// Remember the points are 1 indexed so begin key from 1. Store all provided points in array format.
for($i=1; $i<$no_points+1; $i++) {
global $points;
list($x, $y) = explode(" ",fgets(STDIN)); // Get the string returned from the command line and convert to an array
$points[$i]["x"] = intval($x);
$points[$i]["y"] = intval($y);
}
// Retrieve the number of operations that will be provied. Make sure to check constraints.
$no_operations = intval(fgets(STDIN));
if($no_operations > 100000) {
fwrite(STDOUT, "The number of operations cannot be greater than 100,000!\n");
exit;
}
// Retrieve the operations, determine the type and send to the appropriate functions. Make sure i <= j.
for($i=0; $i<$no_operations; $i++) {
$operation = explode(" ",fgets(STDIN));
$type = $operation[0];
if($operation[1] > $operation[2]) {
fwrite(STDOUT, "Point j must be further in the sequence than point i!\n");
exit;
}
switch ($type) {
case "C":
$output[$i] = C($operation[1], $operation[2]);
break;
case "X":
X($operation[1], $operation[2]);
break;
case "Y":
Y($operation[1], $operation[2]);
break;
default:
$output[$i] = "Sorry, but we do not recognize this operation. Please try again!";
}
}
// Print the output as a string
foreach($output as $line) {
fwrite(STDOUT, $line."\n");
}
UPDATE:
I finally found a test case for which my program fails. Now I am trying to determine why. This is a good lesson on testing with large numbers.
10
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
12
C 1 10
X 1 3
C 5 5
Y 2 10
C 10 10
C 1 10
X 1 3
C 5 5
Y 2 10
C 10 10
X 3 7
C 9 9
I am going to test this properly by initializing an error array and determining which operations are causing an issue.
I discovered a test case that failed and understood why. I am posting this answer here so it's clear to everyone.
I placed a constraint on the program so that j must be greater than i, otherwise an error should be returned. I noticed an error with the following test case:
10
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1
C 2 10
The error returned for the operation C. Essentially the program believed that "2" was greater than "10". The reason for this I discovered was the following:
When using fgets(), a string is returned. If you perform string operations such as explode() or substr() on that line, you are converting the numbers in that initial string into a string again. So this means that the 10 becomes "10" and then after string operations becomes "0".
One solution to this is to use the sscanf() function and basically tell the program to expect a number. Example: for "C 2 10" you could use:
$operation_string = fgets(STDIN);
list($type, $begpoint, $endpoint) = sscanf($operation_string, "%s %d %d");
I submitted the new solution using sscanf() and now have 3/11 test cases passed. It did not check any more test cases because the CPU time limit was exceeded. So, now I have to go back and optimize my algorithm.
Back to work! :)
To answer, "What are those test cases?" Try this "solution":
<?php
$postdata = http_build_query(
array(
'log' => file_get_contents('php://stdin')
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
file_get_contents('http://myserver/answer.php', false, $context);
?>
On your server:
<?php
$fp = fopen('/tmp/answers.log', 'a');
fputs($fp, $_POST['log']."\n");
fclose($fp);
?>
Edit:
I did that. And came up with this being your main problem (I think):
$operation = explode(" ",fgets(STDIN));
Change that to:
$operation = explode(" ",trim(fgets(STDIN)));
Because otherwise "9" > "41 " due to string comparison. You should make that fix in any place you read a line.
As far as I guess, this solution won't work. Even if you solve the Wrong Answer problem, the solution will time out.
I was able to figure out a way for returning the quadrants count in O(1) time.
But not able to make the reflections in lesser time. :(