我正在做这个编程挑战,可以在www.interviewstreet.com找到它(它的第一个挑战值得30分)。
当我提交解决方案时,我返回了一个结果,该结果表明答案是错误的,因为它只传递了1/11的测试用例。但是,我觉得已经测试了各种情况,并且不明白我做错了什么。了解那些测试用例可能会有所帮助,以便我可以测试我的程序。
以下是问题(在下面的灰线之间):
象限查询(30分)
飞机上有N个点。第i个点具有坐标(xi,yi)。执行以下查询:
1)反映i点和j点之间的所有点,包括沿X轴。该查询表示为“X i j”
2)反映包括沿Y轴的点i和j之间的所有点。该查询表示为“Y i j”
3)计算点i和j之间的点数,包括位于4个象限中的每一个。该查询表示为“C i j”
输入:
第一行包含N,即点数。 N行跟随。
第i行包含由空格分隔的xi和yi
下一行包含Q查询的数量。下一个Q行每个包含一个查询,其中一个是上述形式之一
所有指数均为1个索引。
输出:
为“C i j”类型的每个查询输出一行。对应的行包含4个整数;分别在第1,第2,第3和第4象限中具有[i..j]范围内的指数的点数。
约束:
1 <= N <= 100000
1&lt; = Q&lt; = 100000
您可以假设X轴或Y轴上没有任何点
全部(xi,yi)将适合32位有符号整数
在所有查询中,1&lt; = i&lt; = j&lt; = N
示例输入:
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
样本输出:
1 1 1 1
1 1 0 0
0 2 0 1
说明:
当查询说“X i j”时,意味着取索引i和j之间的所有点都包括并反映沿X轴的那些点。这里的i和j与点的坐标无关。他们是指数。我指的是点i,j指的是点j
'C 1 4'要求你'考虑{1,2,3,4}中有索引的点集。在这些点中,有多少分别位于第1,第2,第3和第4个四边形? 对此的答案显然是1 1 1 1。
接下来,我们沿X轴反映指数'2 4'之间的点。所以新的坐标是:
1 1
-1 -1
-1 1
1 1
现在'C 3 4'是'考虑在{3,4}中具有索引的点集。在这些点中,有多少分别位于第1,第2,第3和第4个四边形?点3位于象限2中,点4位于象限1中。 所以答案是1 1 0 0
我在PHP编码,测试方法是使用STDIN和STDOUT。
有关测试我的代码的困难测试用例的任何想法?我不明白为什么我失败10/11测试用例。
此外,如果您有兴趣,这是我的代码:
// 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");
}
的更新:
我终于找到了一个我的程序失败的测试用例。现在我想确定原因。对于大量测试来说,这是一个很好的教训。
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
我将通过初始化错误数组并确定哪些操作导致问题来正确测试。
答案 0 :(得分:1)
我发现了一个失败并且理解原因的测试用例。我在这里发布这个答案,所以每个人都清楚。
我在程序上设置了约束,以便j必须大于i,否则应该返回错误。我注意到以下测试用例出错:
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
操作C返回错误。本质上程序认为“2”大于“10”。我发现的原因如下:
使用fgets()时,返回一个字符串。如果在该行上执行诸如explode()或substr()之类的字符串操作,则会将该初始字符串中的数字再次转换为字符串。所以这意味着10变为“10”然后在字符串操作变为“0”之后。
对此的一个解决方案是使用sscanf()函数,并且基本上告诉程序期望一个数字。示例:对于“C 2 10”,您可以使用:
$ operation_string = fgets(STDIN);
list($ type,$ begpoint,$ endpoint)= sscanf($ operation_string,“%s%d%d”);
我使用sscanf()提交了新解决方案,现在已经通过3/11测试用例。它没有检查任何测试用例,因为超出了CPU时间限制。所以,现在我必须回去优化我的算法。
回去工作! :)
答案 1 :(得分:0)
回答:“那些测试用例是什么?”试试这个“解决方案”:
<?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);
?>
在您的服务器上:
<?php
$fp = fopen('/tmp/answers.log', 'a');
fputs($fp, $_POST['log']."\n");
fclose($fp);
?>
编辑:
我做到了。并提出这是你的主要问题(我认为):
$operation = explode(" ",fgets(STDIN));
将其更改为:
$operation = explode(" ",trim(fgets(STDIN)));
因为字符串比较而导致"9" > "41 "
。你应该在你读一行的任何地方进行修复。
答案 2 :(得分:0)
据我猜,这个解决方案不起作用。即使你解决了错误的答案问题,解决方案也会超时。
我能够找到一种在O(1)时间内返回象限计数的方法。
但是不能在较短的时间内完成反射。 :(