【发布时间】:2018-03-27 17:25:46
【问题描述】:
在我开始之前,我只想说这是一个家庭作业。我最近在这门课上遇到的一个问题是能够有效地测试我的代码,这样当我提交我的解决方案时,我可以确信所有输入组合都会被覆盖。有人告诉我,很多测试都是主观的,需要对实现有实际的了解……一种尺寸永远不会适合所有人。话虽这么说,是否有关于如何有效测试的指导方针?
我目前正在努力解决的一个例子是最长子序列 if 元素的动态编程实现。我所有的测试都有效,但是当我提交给评分者时,我陷入了我认为是边缘情况的问题(我们不允许在某个测试之后看到失败测试用例的输入或输出)。
import java.util.Arrays;
import java.util.Scanner;
public class LCS2 {
int [][] solutionMatrix;
public int lcs2(int[] a, int[] b) {
final int aARRAY_LENGTH = a.length + 1;
final int bARRAY_LENGTH = b.length + 1;
solutionMatrix = new int[aARRAY_LENGTH][bARRAY_LENGTH];
//set endge indexes equal to i
for (int i = 1; i < aARRAY_LENGTH; i++) {
solutionMatrix[i][0] = i;
}
for (int i = 1; i < bARRAY_LENGTH; i++) {
solutionMatrix[0][i] = i;
}
//fill in matrix to determine if each element is a insert, delete, match or mismatch
for (int i = 1; i < aARRAY_LENGTH; i++) {
for (int j = 1; j < bARRAY_LENGTH; j++) {
int insertion = solutionMatrix[i ][j - 1] + 1;
int deletion = solutionMatrix[i - 1][j ] + 1;
int match = solutionMatrix[i - 1][j - 1];
int mismatch = solutionMatrix[i - 1][j - 1] + 1;
//System.out.println("i: " + i + " j: " + j + " [" +insertion + " " + deletion + " " + match + " " + mismatch + "] ");
if (a[i - 1] == b[j - 1])
solutionMatrix[i][j] = Math.min(insertion, Math.min(deletion,match));
else
solutionMatrix[i][j] = Math.min(insertion, Math.min(deletion,mismatch));
}
}
//print out matrix for visualization
System.out.println(" " + Arrays.toString(b));
for (int i = 0; i < aARRAY_LENGTH; i++) {
if (i - 1 < 0)
System.out.println(" " + Arrays.toString(solutionMatrix[i]));
else
System.out.println("[" + a[i -1] + "] " + Arrays.toString(solutionMatrix[i]));
}
return outputAlignment(a.length, b.length, 0);
}
private int outputAlignment(int i, int j, int ret){
//recursive call.. if indexes are 0 then return
if (i == 0 && j == 0)
return ret;
//find pointer.. is this a insert, deletion, match or mismatch
int backtrack = backtrack(i, j);
//change current index based on result of backtrack
if (backtrack == 3)
//if matched then add one to the longest sequence
ret = outputAlignment(i - 1, j - 1, ret) + 1;
else if (backtrack == 2)
ret = outputAlignment(i - 1, j , ret);
else if (backtrack == 1)
ret = outputAlignment(i , j - 1, ret);
else
ret = outputAlignment(i - 1, j - 1, ret);
return ret;
}
private int backtrack(int i, int j){
//System.out.println("i: " + i + " j: " + j);
int currValue = solutionMatrix[i][j];
// System.out.println(currValue);
if ( currValue == solutionMatrix[i ][j - 1] + 1)
return 1; // insertion
else if (currValue == solutionMatrix[i - 1][j ] + 1)
return 2; //deletion
else if (currValue == solutionMatrix[i - 1][j - 1] )
return 3; //match
else if (currValue == solutionMatrix[i - 1][j - 1] + 1)
return 4; //mismatch
return 5;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
int m = scanner.nextInt();
int[] b = new int[m];
for (int i = 0; i < m; i++) {
b[i] = scanner.nextInt();
}
LCS2 lcs = new LCS2();
System.out.println(lcs.lcs2(a, b));
}
}
这是我整理的一些 junit 测试,无需额外设置即可运行。
@Test
public void testLCS2(){
LCS2 lcs = new LCS2();
int[] a = {2,7,5};
int[] b = {2,5};
assertEquals("Testing Longest Common SubSequence for [2,7,5] --> [2,5]", 2,lcs.lcs2(a,b));
a = new int[] {2,3,9};
b = new int[] {2,9,7,8};
assertEquals("Testing Longest Common SubSequence for [2,3,9] --> [2,9,7,8]", 2,lcs.lcs2(a,b));
a = new int[] {1,2,3,4};
b = new int[] {1,2,3,4};
assertEquals("Testing Longest Common SubSequence for [1,2,3,4] --> [1,2,3,4]", 4,lcs.lcs2(a,b));
a = new int[] {7};
b = new int[] {1,2,3,4};
assertEquals("Testing Longest Common SubSequence for [7] --> [1,2,3,4]", 0,lcs.lcs2(a,b));
a = new int[] {2,7,8,3};
b = new int[] {5,2,8,7};
assertEquals("Testing Longest Common SubSequence for [2,7,8,3] --> [5,2,8,7]", 2,lcs.lcs2(a,b));
a = new int[] {1,1,1,1};
b = new int[] {1,2,3,4};
assertEquals("Testing Longest Common SubSequence for [2,7,8,3] --> [5,2,8,7]", 1,lcs.lcs2(a,b));
a = new int[] {1,1,1,1};
b = new int[] {1,2,3,4,1};
assertEquals("Testing Longest Common SubSequence for [2,7,8,3] --> [5,2,8,7]", 2,lcs.lcs2(a,b));
}
【问题讨论】:
-
你说的我们不能看到失败的测试用例的输入或输出是什么意思?如果评分者无法提供有用的反馈来帮助您学习,请与教授交谈。
-
是的,关键是我们看不到评分器的输出。它是为了让我们“思考”和调试自己。
-
我认为评分员是个混蛋。在现实世界中,您要做的第一件事是获取导致错误的输入,以便您可以重新创建错误以便对其进行调试。与教授交谈。
-
制作一个随机生成小子序列的函数,并制作一个蛮力求解器并针对蛮力求解器测试您的解决方案。如果它给了你正确的答案,那么你的解决方案很可能是正确的。现在考虑较大序列的错误-> 内存不足、整数溢出、堆栈溢出过多递归、超时等。制作一些超大序列来测试它,直到它崩溃。玩得开心。
标签: java algorithm dynamic-programming