-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolver.cs
108 lines (67 loc) · 2.55 KB
/
Solver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using AngouriMath;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using static AngouriMath.Entity.Set;
namespace ResistorSearch;
public class Solver {
public struct Info {
public double x; // R1
public double y; // R2
public double v; // Voltage
public Info(double x, double y, double v) {
this.x = x;
this.y = y;
this.v = v;
}
}
public required List<double> resistorValues { get; set; }
public List<Info> SolveAll(string formula, double v) {
(var main, var equality) = NormalizeFormula(formula);
var solveList = GetSolvedList(main, equality, v);
var sortedList = Sort(solveList, v);
return sortedList;
}
public List<Info> GetSolvedList(string mainPart, string equalityPart, double v) {
ConcurrentBag<Info> resultsBag = new();
Entity mainFormula = mainPart;
Entity fullFormula = $"{equalityPart} = {mainPart}";
Entity voltageFormula = ((FiniteSet)fullFormula.Solve("v")).Elements.First();
resistorValues.AsParallel().ForAll(r1 => {
var mainFn = mainFormula.Compile("x", "y", "v");
var voltageFn = voltageFormula.Compile("x", "y");
foreach (var r2 in resistorValues) {
double mainSolve = mainFn.Call(r1, r2, v).Real;
double voltageSolve = mainSolve;
if (equalityPart != "v") {
voltageSolve = voltageFn.Call(r1, r2).Real;
}
resultsBag.Add(new(r1, r2, voltageSolve));
}
});
return resultsBag.ToList();
}
public static List<Info> Sort(List<Info> values, double v) {
return values
.OrderBy(p => Math.Abs(p.v - v))
.ToList();
}
public static (string, string) NormalizeFormula(string formula) {
formula = formula.ToLower().Replace("r1", "x").Replace("r2", "y");
var sides = formula
.Split('=')
.Select(c => c.Trim())
.ToArray();
if (sides.Count() != 2) {
throw new Exception("Incorrect formula");
}
bool IsMainPart(string side) => !Regex.IsMatch(side, @"^[xyv]$");
bool[] types = {
IsMainPart(sides[0]),
IsMainPart(sides[1])
};
if (types.Count(c => c) != 1) {
throw new Exception("Incorrect formula");
}
return types[0] ? (sides[0], sides[1]) : (sides[1], sides[0]);
}
}