The code below solves for the four value of $m_i$ for a given pair of $(N_m,M_m)$.
where $$ m_1+m_2+m_3+m_4 = M_m\\ |m_1|+|m_2|+|m_3|+|m_4| = N_m $$
Edit 2
New Sorting
I have now realised that the sorting I used was not ideal. So I have changed it slightly.
sol2[Nm_, Mm_] :=
SortBy[{m1, m2, m3,
m4} /. (Solve[
m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4},
Integers]), {Count[#, _?Negative] &,Select[#, NonNegative] &,Negative}]
So now with this sorting a few example solutions are as follows:
sol2[1, -1]
(*{{0, 0, 0, -1}, {0, 0, -1, 0}, {0, -1, 0, 0}, {-1, 0, 0, 0}}*)
sol2[3,-1]
(*{{0, 0, 1, -2}, {0, 0, -2, 1}, {0, -2, 0, 1}, {-2, 0, 0, 1}, {0, 1, 0, -2}, {0, 1, -2, 0}, {0, -2, 1, 0}, {-2, 0, 1, 0}, {1, 0, 0, -2}, {1, 0, -2, 0}, {1, -2, 0, 0}, {-2, 1, 0, 0}, {0, 1, -1, -1}, {0, -1, 1, -1}, {0, -1, -1, 1}, {-1, 0, 1, -1}, {-1, 0, -1, 1}, {-1, -1, 0, 1}, {1, 0, -1, -1}, {1, -1, 0, -1}, {1, -1, -1, 0}, {-1, 1, 0, -1}, {-1, 1, -1, 0}, {-1, -1, 1, 0}}*)
sol2[3,1]
(*{{0, 0, 2, -1}, {0, 0, -1, 2}, {0, -1, 0, 2}, {-1, 0, 0, 2}, {0, 1, 1, -1}, {0, 1, -1, 1}, {0, -1, 1, 1}, {-1, 0, 1, 1}, {0, 2, 0, -1}, {0, 2, -1, 0}, {0, -1, 2, 0}, {-1, 0, 2, 0}, {1, 0, 1, -1}, {1, 0, -1, 1}, {1, -1, 0, 1}, {-1, 1, 0, 1}, {1, 1, 0, -1}, {1, 1, -1, 0}, {1, -1, 1, 0}, {-1, 1, 1, 0}, {2, 0, 0, -1}, {2, 0, -1, 0}, {2, -1, 0, 0}, {-1, 2, 0, 0}}*)
sol2[2,2]
(*{{0, 0, 0, 2}, {0, 0, 1, 1}, {0, 0, 2, 0}, {0, 1, 0, 1}, {0, 1, 1, 0}, {0, 2, 0, 0}, {1, 0, 0, 1}, {1, 0, 1, 0}, {1, 1, 0, 0}, {2, 0, 0, 0}}*)
sol2[2,-2]
(*{{0, 0, 0, -2}, {0, 0, -2, 0}, {0, -2, 0, 0}, {-2, 0, 0, 0}, {0, 0, -1, -1}, {0, -1, 0, -1}, {0, -1, -1, 0}, {-1, 0, 0, -1}, {-1, 0, -1, 0}, {-1, -1, 0, 0}}*)
sol2[3,-3]
(*{{0, 0, 0, -3}, {0, 0, -3, 0}, {0, -3, 0, 0}, {-3, 0, 0, 0}, {0, 0, -2, -1}, {0, 0, -1, -2}, {0, -2, 0, -1}, {0, -1, 0, -2}, {0, -2, -1, 0}, {0, -1, -2, 0}, {-2, 0, 0, -1}, {-1, 0, 0, -2}, {-2, 0, -1, 0}, {-1, 0, -2, 0}, {-2, -1, 0, 0}, {-1, -2, 0, 0}, {0, -1, -1, -1}, {-1, 0, -1, -1}, {-1, -1, 0, -1}, {-1, -1, -1, 0}}*)
Original Sorting
sol[Nm_, Mm_] :=
SortBy[{m1, m2, m3,
m4} /. (Solve[
m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4},
Integers]), Negative]
I would like to have a function (findPosition
) which gives the position of the solution given the four $m_i$ values without going over all the solutions.
For e.g.
Based on the original sorting used in sol
findPosition[{0, 0, -1, 0}] = 2
findPosition[{0, 0, 1, 1}] = 2 (* see sol[2,2]*)
findPosition[{0, 0, -1, -1}] = 3 (* see sol[2,-2]*)
findPosition[{0, 0, -2, -1}] = 3 (* see sol[3,-3]*)
Based on the new sorting in sol2
findPosition[{0, 0, -1, 0}] = 2
findPosition[{0, 0, 1, 1}] = 2 (* see sol2[2,2]*)
findPosition[{0, 0, -1, -1}] = 5 (* see sol2[2,-2]*)
findPosition[{0, 0, -2, -1}] = 5 (* see sol2[3,-3]*)
$m_i$ are integers.
Edit 1
Also I'm looking for an answer that should be somewhat faster than the trivial approach shown below where you simply scan over all the results and find the match.
solf[Nm_, Mm_] :=
SortBy[Partition[
Flatten[Permutations /@
Select[IntegerPartitions[Mm, {4},
Range[-Nm - 1,
Nm + 1]], (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]] == Nm) &]], 4], {Count[#, _?Negative] &, Select[#, NonNegative] &, Negative}]
findPosition[mlist_] :=
Position[solf[
Abs[mlist[[1]]] + Abs[mlist[[2]]] + Abs[mlist[[3]]] +
Abs[mlist[[4]]], Total[mlist]], mlist];
findPosition[{-1, 0, -1, 1}] // AbsoluteTiming
(*{0.000282, {{17}}} *)
findPosition
, you don't know ahead of time what theNm
andMm
are, and you want to avoid manually searching all possible values for them? $\endgroup$Nm
andMm
are known as soon as you get the four values ofmi
by definition. I was looking for something which does not useSolve
,FindInstance
and other such commands. $\endgroup$Solve
,FindInstance
,Reduce
, or any other Mathematica built-ins that could solve this, it might be better to ask this first on computer science Stack Exchange to get the right algorithm, and then ask here for the implementation. Someone here could know what the right algorithm is, but it's more unlikely here than on computer science Stack Exchange. $\endgroup$SortBy[ ]
function call, usingNegative[ ]
as the criteria results in a lot of ties between terms (since Negative only gives True or False) that then get broken in a way that makes it hard to come up with a counting scheme. TryMap[Negative, sol[3,-3]] // Boole // TableForm
and you can see how it is just walking up through the binary numbers, with lots of ties to be broken. Recommend you make the implicit explicit by writing `SortBy[list, {Negative, f2,...}] to make it up front and clear and help sort out a counting scheme. $\endgroup$