Skip to content

Instantly share code, notes, and snippets.

@ZTGeng
Last active November 17, 2016 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZTGeng/0c47e4de420d2682e7a27e6a8442e67d to your computer and use it in GitHub Desktop.
Save ZTGeng/0c47e4de420d2682e7a27e6a8442e67d to your computer and use it in GitHub Desktop.
import java.util.Arrays;
/**
* 简单测试。
*/
public class Test {
public static void main(String[] args) {
Double[] terms = new Double[] {8.0, null, 13.0, null, null, null, null, null, 8.0, null, null, 6.0};
double[] solution = FourVariablesLinearEquations.solution(terms);
System.out.println(Arrays.toString(solution));
}
}
/**
* 解系数为1的二元一次方程组。
*/
class TwoVariablesLinearEquations {
/**
* @param apb 方程 a + b = m 的右值
* @param amb 方程 a - b = n 的右值
* 注:可通过方程两边取反将 b - a = m 变为 a - b = -m 。
* @return [a, b]
*/
public static double[] solution(double apb, double amb) {
double a = (apb + amb) / 2;
double b = (apb - amb) / 2;
return new double[] {a, b};
}
}
/**
* 解系数为1的三元一次方程组。
*/
class ThreeVariablesLinearEquations {
/**
* @param terms [apb, amb, apc, amc, bpc, bmc],其中:
* apb 是方程 a + b = m 的右值
* amb 是方程 a - b = n 的右值
* apc 是方程 a + c = o 的右值
* amc 是方程 a - c = p 的右值
* bpc 是方程 b + c = q 的右值
* bmc 是方程 b - c = r 的右值
* 以上需有且仅有三项不为null,且不可由其中两项推出第三项。
* 注:可通过方程两边取反将 b - a = m 变为 a - b = -m 。
* @return [a, b, c] 或 null(当方程组没有确定解时)
*/
public static double[] solution(Double[] terms) {
if (!isParamsValid(terms)) {
throw new IllegalArgumentException("参数需有且仅有三项不为null");
}
Double apb = terms[0];
Double amb = terms[1];
Double apc = terms[2];
Double amc = terms[3];
Double bpc = terms[4];
Double bmc = terms[5];
boolean simpleSituation = false;
Double a = null, b = null, c = null;
if (apb != null && amb != null) {
double[] temp = TwoVariablesLinearEquations.solution(apb, amb);
a = temp[0];
b = temp[1];
apb = amb = null;
simpleSituation = true;
} else if (apc != null && amc != null) {
double[] temp = TwoVariablesLinearEquations.solution(apc, amc);
a = temp[0];
c = temp[1];
apc = amc = null;
simpleSituation = true;
} else if (bpc != null && bmc != null) {
double[] temp = TwoVariablesLinearEquations.solution(bpc, bmc);
b = temp[0];
c = temp[1];
bpc = bmc = null;
simpleSituation = true;
}
if (simpleSituation) {
if (apb != null) {
if (a == null) { a = apb - b; }
else { b = apb - a; }
} else if (amb != null) {
if (a == null) { a = amb + b; }
else { b = a - amb; }
} else if (apc != null) {
if (a == null) { a = apc - c; }
else { c = apc - a; }
} else if (amc != null) {
if (a == null) { a = amc + c; }
else { c = a - amc; }
} else if (bpc != null) {
if (b == null) { b = bpc - c; }
else { c = bpc - b; }
} else if (bmc != null) {
if (b == null) { b = bmc + c; }
else { c = b - bmc; }
}
return new double[] {a, b, c};
}
if (apb != null) {
if (apc != null) {
if (bpc != null) {
amb = apc - bpc;
double[] temp = TwoVariablesLinearEquations.solution(apb, amb);
a = temp[0];
b = temp[1];
c = apc - a;
} else { // bmc != null
return null; // 由其中两项可以推出第三项。下同。
}
} else { // amc != null
if (bpc != null) {
return null;
} else { // bmc != null
amb = amc - bmc;
double[] temp = TwoVariablesLinearEquations.solution(apb, amb);
a = temp[0];
b = temp[1];
c = a - amc;
}
}
} else { // amb != null
if (apc != null) {
if (bpc != null) {
return null;
} else { // bmc != null
apb = apc + bmc;
double[] temp = TwoVariablesLinearEquations.solution(apb, amb);
a = temp[0];
b = temp[1];
c = apc - a;
}
} else { // amc != null
if (bpc != null) {
apb = amc + bpc;
double[] temp = TwoVariablesLinearEquations.solution(apb, amb);
a = temp[0];
b = temp[1];
c = a - amc;
} else { // bmc != null
return null;
}
}
}
return new double[] {a, b, c};
}
private static boolean isParamsValid(Double[] terms) {
if (terms == null || terms.length != 6) {
return false;
}
int count = 0;
for (Double term : terms) {
count += term != null ? 1 : 0;
}
return count == 3;
}
}
/**
* 解系数为1的四元一次方程组。
*/
class FourVariablesLinearEquations {
/**
* @param terms [apb, amb, apc, amc, apd, amd, bpc, bmc, bpd, bmd, cpd, cmd],其中:
* apb 是方程 a + b = m 的右值
* amb 是方程 a - b = n 的右值
* apc 是方程 a + c = o 的右值
* amc 是方程 a - c = p 的右值
* apd 是方程 a + d = q 的右值
* amd 是方程 a - d = r 的右值
* bpc 是方程 b + c = s 的右值
* bmc 是方程 b - c = t 的右值
* bpd 是方程 b + d = u 的右值
* bmd 是方程 b - d = v 的右值
* cpd 是方程 c + d = w 的右值
* cmd 是方程 c - d = x 的右值
* 以上需有且仅有四项不为null,且不可由其中任意两项推出第三项。需涵盖 a b c d 四个变量。
* 注:可通过方程两边取反将 b - a = m 变为 a - b = -m 。
* @return [a, b, c, d] 或 null(当方程组没有确定解时)
*/
public static double[] solution(Double[] terms) {
if (!isParamsValid(terms)) {
throw new IllegalArgumentException("参数需有且仅有四项不为null");
}
Double apb = terms[0];
Double amb = terms[1];
Double apc = terms[2];
Double amc = terms[3];
Double apd = terms[4];
Double amd = terms[5];
Double bpc = terms[6];
Double bmc = terms[7];
Double bpd = terms[8];
Double bmd = terms[9];
Double cpd = terms[10];
Double cmd = terms[11];
Double a = null, b = null, c = null, d = null;
if (apb != null && amb != null && cpd != null && cmd != null) {
double[] temp = TwoVariablesLinearEquations.solution(apb, amb);
a = temp[0];
b = temp[1];
temp = TwoVariablesLinearEquations.solution(cpd, cmd);
c = temp[0];
d = temp[1];
return new double[] {a, b, c, d};
}
if (apc != null && amc != null && bpd != null && bmd != null) {
double[] temp = TwoVariablesLinearEquations.solution(apc, amc);
a = temp[0];
c = temp[1];
temp = TwoVariablesLinearEquations.solution(bpd, bmd);
b = temp[0];
d = temp[1];
return new double[] {a, b, c, d};
}
if (apd != null && amd != null && bpc != null && bmc != null) {
double[] temp = TwoVariablesLinearEquations.solution(apd, amd);
a = temp[0];
d = temp[1];
temp = TwoVariablesLinearEquations.solution(bpc, bmc);
b = temp[0];
c = temp[1];
return new double[] {a, b, c, d};
}
boolean computed = false;
int nonNullCount = 0;
Double[] termsWithoutD = new Double[] {apb, amb, apc, amc, bpc, bmc};
nonNullCount = nonNullCount(termsWithoutD);
if (nonNullCount == 4) { return null; }
if (nonNullCount == 3) {
double[] temp = ThreeVariablesLinearEquations.solution(termsWithoutD);
if (temp == null) { return null; }
a = temp[0];
b = temp[1];
c = temp[2];
apb = amb = apc = amc = bpc = bmc = null;
computed = true;
}
if (!computed) {
Double[] termsWithoutC = new Double[] {apb, amb, apd, amd, bpd, bmd};
nonNullCount = nonNullCount(termsWithoutC);
if (nonNullCount == 4) { return null; }
if (nonNullCount == 3) {
double[] temp = ThreeVariablesLinearEquations.solution(termsWithoutC);
if (temp == null) { return null; }
a = temp[0];
b = temp[1];
d = temp[2];
apb = amb = apd = amd = bpd = bmd = null;
computed = true;
}
}
if (!computed) {
Double[] termsWithoutB = new Double[] {apc, amc, apd, amd, cpd, cmd};
nonNullCount = nonNullCount(termsWithoutB);
if (nonNullCount == 4) { return null; }
if (nonNullCount == 3) {
double[] temp = ThreeVariablesLinearEquations.solution(termsWithoutB);
if (temp == null) { return null; }
a = temp[0];
c = temp[1];
d = temp[2];
apc = amc = apd = amd = cpd = cmd = null;
computed = true;
}
}
if (!computed) {
Double[] termsWithoutA = new Double[] {bpc, bmc, bpd, bmd, cpd, cmd};
nonNullCount = nonNullCount(termsWithoutA);
if (nonNullCount == 4) { return null; }
if (nonNullCount == 3) {
double[] temp = ThreeVariablesLinearEquations.solution(termsWithoutA);
if (temp == null) { return null; }
b = temp[0];
c = temp[1];
d = temp[2];
bpc = bmc = bpd = bmd = cpd = cmd = null;
computed = true;
}
}
if (computed) {
if (apb != null) {
if (a == null) { a = apb - b; }
else { b = apb - a; }
} else if (amb != null) {
if (a == null) { a = amb + b; }
else { b = a - amb; }
} else if (apc != null) {
if (a == null) { a = apc - c; }
else { c = apc - a; }
} else if (amc != null) {
if (a == null) { a = amc + c; }
else { c = a - amc; }
} else if (apd != null) {
if (a == null) { a = apd - d; }
else { d = apd - a; }
} else if (amd != null) {
if (a == null) { a = amd + d; }
else { d = a - amd; }
} else if (bpc != null) {
if (b == null) { b = bpc - c; }
else { c = bpc - b; }
} else if (bmc != null) {
if (b == null) { b = bmc + c; }
else { c = b - bmc; }
} else if (bpd != null) {
if (b == null) { b = bpd - d; }
else { d = bpd - b; }
} else if (bmd != null) {
if (b == null) { b = bmd + d; }
else { d = b - bmd; }
} else if (cpd != null) {
if (c == null) { c = cpd - d; }
else { d = cpd - c; }
} else if (cmd != null) {
if (c == null) { c = cmd + d; }
else { d = c - cmd; }
}
return new double[] {a, b, c, d};
}
if (apb == null && amb == null) {
// a - c - b - d 形成环,环上相邻两个未知数之间有且仅有一条方程。下同
if (apc != null) {
if (apd != null) {
cmd = apc - apd;
} else { // amd != null
cpd = apc - amd;
}
} else { // amc != null
if (apd != null) {
cpd = apd - amc;
} else { // amd != null
cmd = amd - amc;
}
}
} else if (apc == null && amc == null) {
// a - b - c - d 形成环
if (apb != null) {
if (apd != null) {
bmd = apb - apd;
} else { // amd != null
bpd = apb - amd;
}
} else { // amb != null
if (apd != null) {
bpd = apd - amb;
} else { // amd != null
bmd = amd - amb;
}
}
} else if (apd == null && amd == null) {
// a - b - d - c 形成环
if (apb != null) {
if (apc != null) {
bmc = apb - apc;
} else { // amc != null
bpc = apb - amc;
}
} else { // amb != null
if (apc != null) {
bpc = apc - amb;
} else { // amc != null
bmc = amc - amb;
}
}
}
Double[] termsWithoutA = new Double[] {bpc, bmc, bpd, bmd, cpd, cmd};
double[] temp = ThreeVariablesLinearEquations.solution(termsWithoutA);
if (temp == null) { return null; }
b = temp[0];
c = temp[1];
d = temp[2];
if (apb != null || amb != null) {
a = apb != null ? apb - b : amb + b;
} else {
a = apc != null ? apc - c : amc + c;
}
return new double[] {a, b, c, d};
}
private static boolean isParamsValid(Double[] terms) {
if (terms == null || terms.length != 12) {
return false;
}
return nonNullCount(terms) == 4;
}
private static int nonNullCount(Double[] nums) {
int count = 0;
for (Double num : nums) {
count += num != null ? 1 : 0;
}
return count;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment