Can this be solved even faster?












12














So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?










share|improve this question
























  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    Dec 10 at 8:13
















12














So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?










share|improve this question
























  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    Dec 10 at 8:13














12












12








12


1





So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?










share|improve this question















So I would like to solve the following set of equation for $m_i$ given a set of ${M_m,N_m}$.



$$
m_1 +m_2 +m_3 +m_4 =M_m \
|m_1| +|m_2| +|m_3| +|m_4| =N_m
$$



All variables are integers.
Also $N_m ge M_m$ and their maximum value can reach up-to 30.
I only need the total number of possible solution not the solutions themselves. So my first trivial attempt was to just use Solve



dimNM1[Nm_, Mm_] :=
Length[(Solve[m1 + m2 + m3 + m4 == Mm &&
Abs[m1] + Abs[m2] + Abs[m3] + Abs[m4] == Nm, {m1, m2, m3, m4}, Integers])]


My second slightly non-trivial attempt is the following:-



dimNM2[Nm_, Mm_] :=
Which[Nm === Mm,
Length[Partition[
Flatten[Permutations /@ IntegerPartitions[Nm, {4}, Range[0, Nm]]],
4]], True,
Module[{res},
res = Partition[
Flatten[Permutations /@ IntegerPartitions[Mm, {4}, Range[-Nm, Nm]]],
4];
Length[
Select[res, (Abs[#[[1]]] + Abs[#[[2]]] + Abs[#[[3]]] +
Abs[#[[4]]]) == Nm &]]]]


The second method is much faster than the first specially for $N_m=M_m$.
But I would like to increase the speed further for $N_mge M_m$ case if possible.



dimNM1[2, 2] // AbsoluteTiming
(*{0.177768, 10}*)

dimNM2[2, 2] // AbsoluteTiming
(*{0.0000899056, 10}*)


So is there any other way to solve these equation faster?







equation-solving performance-tuning






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 9 at 13:00









Henrik Schumacher

48.4k467137




48.4k467137










asked Dec 9 at 11:40









Hubble07

2,947719




2,947719












  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    Dec 10 at 8:13


















  • Note that N has built-in meanings.
    – Αλέξανδρος Ζεγγ
    Dec 9 at 12:34










  • OK I have changed it.
    – Hubble07
    Dec 9 at 12:46










  • Nice problem. No need to generate candidates... see my reply.
    – ciao
    Dec 10 at 8:13
















Note that N has built-in meanings.
– Αλέξανδρος Ζεγγ
Dec 9 at 12:34




Note that N has built-in meanings.
– Αλέξανδρος Ζεγγ
Dec 9 at 12:34












OK I have changed it.
– Hubble07
Dec 9 at 12:46




OK I have changed it.
– Hubble07
Dec 9 at 12:46












Nice problem. No need to generate candidates... see my reply.
– ciao
Dec 10 at 8:13




Nice problem. No need to generate candidates... see my reply.
– ciao
Dec 10 at 8:13










3 Answers
3






active

oldest

votes


















10














ClearAll[num];

num[n_, m_] /; OddQ[n + m] = 0;
num[n_, n_] := Binomial[n + 3, 3];
num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


Testing vs fastest answer here at writing (Henrik Schumacher):



stop = 100;

res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

res == res2



169.203



0.0219434



True




Large cases are a non-issue:



num[123423456, 123412348] // AbsoluteTiming



{0.0000247977, 30468069908023290}




Some quick timings:



enter image description here






share|improve this answer



















  • 3




    Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
    – Henrik Schumacher
    Dec 10 at 8:49








  • 3




    @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
    – ciao
    Dec 10 at 9:29






  • 2




    Chapeaux for recognizing the patterns! =D
    – Henrik Schumacher
    Dec 10 at 10:14






  • 3




    @ciao - You Sir are a genius. Thank you.
    – Hubble07
    Dec 10 at 14:02






  • 1




    Answers from ciao are generally great reads, +1.
    – Marius Ladegård Meyer
    Dec 11 at 14:19



















13














It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



dimNM3[n_, m_] := Total[
Map[
Length@*Permutations,
Pick[#, Abs[#].ConstantArray[1, 4], n] &[
IntegerPartitions[m, {4}, Range[-n, n]
]
]
]
];

m = 20;
n = 40;
dimNM1[n, m] // AbsoluteTiming
dimNM2[n, m] // AbsoluteTiming
dimNM3[n, m] // AbsoluteTiming



{0.116977, 3802}



{0.995365, 3802}



{0.005579, 3802}







share|improve this answer































    2














    Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



    def count_solutions(Nm, Mm):
    firsthalves = dict()
    for m1 in range(-Nm,Nm+1):
    for m2 in range(-Nm,Nm+1):
    m = m1+m2
    n = abs(m1)+abs(m2)
    key = (m,n)
    if key in firsthalves:
    firsthalves[key] += 1
    else:
    firsthalves[key] = 1

    solutions = 0
    for m3 in range(-Nm,Nm+1):
    for m4 in range(-Nm,Nm+1):
    m = m3+m4
    n = abs(m3)+abs(m4)
    key = (Mm-m, Nm-n)
    if key in firsthalves:
    solutions += firsthalves[key]
    return solutions


    This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



    Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



    The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






    share|improve this answer























      Your Answer





      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("mathjaxEditing", function () {
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
      });
      });
      }, "mathjax-editing");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "387"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f187608%2fcan-this-be-solved-even-faster%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      10














      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here






      share|improve this answer



















      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        Dec 10 at 8:49








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        Dec 10 at 9:29






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        Dec 10 at 10:14






      • 3




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        Dec 10 at 14:02






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        Dec 11 at 14:19
















      10














      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here






      share|improve this answer



















      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        Dec 10 at 8:49








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        Dec 10 at 9:29






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        Dec 10 at 10:14






      • 3




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        Dec 10 at 14:02






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        Dec 11 at 14:19














      10












      10








      10






      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here






      share|improve this answer














      ClearAll[num];

      num[n_, m_] /; OddQ[n + m] = 0;
      num[n_, n_] := Binomial[n + 3, 3];
      num[n_, m_] /; OddQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 3)/2 + 2 z - (2 z^2)];
      num[n_, m_] /; EvenQ[n] := With[{z = Ceiling[m/2]}, (5*n^2 + 4)/2 - (2 z^2)];


      Testing vs fastest answer here at writing (Henrik Schumacher):



      stop = 100;

      res = Table[{n, m, dimNM3[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First
      res2 = Table[{n, m, num[n, m]}, {n, 1, stop}, {m, 1, n}]; // AbsoluteTiming//First

      res == res2



      169.203



      0.0219434



      True




      Large cases are a non-issue:



      num[123423456, 123412348] // AbsoluteTiming



      {0.0000247977, 30468069908023290}




      Some quick timings:



      enter image description here







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 10 at 10:19

























      answered Dec 10 at 8:11









      ciao

      17.3k137108




      17.3k137108








      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        Dec 10 at 8:49








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        Dec 10 at 9:29






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        Dec 10 at 10:14






      • 3




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        Dec 10 at 14:02






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        Dec 11 at 14:19














      • 3




        Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
        – Henrik Schumacher
        Dec 10 at 8:49








      • 3




        @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
        – ciao
        Dec 10 at 9:29






      • 2




        Chapeaux for recognizing the patterns! =D
        – Henrik Schumacher
        Dec 10 at 10:14






      • 3




        @ciao - You Sir are a genius. Thank you.
        – Hubble07
        Dec 10 at 14:02






      • 1




        Answers from ciao are generally great reads, +1.
        – Marius Ladegård Meyer
        Dec 11 at 14:19








      3




      3




      Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
      – Henrik Schumacher
      Dec 10 at 8:49






      Pretty impressive. Would you mind to elaborate where these formulas come from or at least to provide an (accessible) source?
      – Henrik Schumacher
      Dec 10 at 8:49






      3




      3




      @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
      – ciao
      Dec 10 at 9:29




      @HenrikSchumacher - I derived them, looking at a set of results: I recognized the pattern(s). Neat that the tetrahedral numbers and coordination sequences popped out. See e.g. Sloan, "Low-Dimensional Lattices VII: Coordination Sequences".
      – ciao
      Dec 10 at 9:29




      2




      2




      Chapeaux for recognizing the patterns! =D
      – Henrik Schumacher
      Dec 10 at 10:14




      Chapeaux for recognizing the patterns! =D
      – Henrik Schumacher
      Dec 10 at 10:14




      3




      3




      @ciao - You Sir are a genius. Thank you.
      – Hubble07
      Dec 10 at 14:02




      @ciao - You Sir are a genius. Thank you.
      – Hubble07
      Dec 10 at 14:02




      1




      1




      Answers from ciao are generally great reads, +1.
      – Marius Ladegård Meyer
      Dec 11 at 14:19




      Answers from ciao are generally great reads, +1.
      – Marius Ladegård Meyer
      Dec 11 at 14:19











      13














      It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



      dimNM3[n_, m_] := Total[
      Map[
      Length@*Permutations,
      Pick[#, Abs[#].ConstantArray[1, 4], n] &[
      IntegerPartitions[m, {4}, Range[-n, n]
      ]
      ]
      ]
      ];

      m = 20;
      n = 40;
      dimNM1[n, m] // AbsoluteTiming
      dimNM2[n, m] // AbsoluteTiming
      dimNM3[n, m] // AbsoluteTiming



      {0.116977, 3802}



      {0.995365, 3802}



      {0.005579, 3802}







      share|improve this answer




























        13














        It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



        dimNM3[n_, m_] := Total[
        Map[
        Length@*Permutations,
        Pick[#, Abs[#].ConstantArray[1, 4], n] &[
        IntegerPartitions[m, {4}, Range[-n, n]
        ]
        ]
        ]
        ];

        m = 20;
        n = 40;
        dimNM1[n, m] // AbsoluteTiming
        dimNM2[n, m] // AbsoluteTiming
        dimNM3[n, m] // AbsoluteTiming



        {0.116977, 3802}



        {0.995365, 3802}



        {0.005579, 3802}







        share|improve this answer


























          13












          13








          13






          It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



          dimNM3[n_, m_] := Total[
          Map[
          Length@*Permutations,
          Pick[#, Abs[#].ConstantArray[1, 4], n] &[
          IntegerPartitions[m, {4}, Range[-n, n]
          ]
          ]
          ]
          ];

          m = 20;
          n = 40;
          dimNM1[n, m] // AbsoluteTiming
          dimNM2[n, m] // AbsoluteTiming
          dimNM3[n, m] // AbsoluteTiming



          {0.116977, 3802}



          {0.995365, 3802}



          {0.005579, 3802}







          share|improve this answer














          It is more efficient to first pick the integer partitions whose absolute values sum up to n before generating the permutations.



          dimNM3[n_, m_] := Total[
          Map[
          Length@*Permutations,
          Pick[#, Abs[#].ConstantArray[1, 4], n] &[
          IntegerPartitions[m, {4}, Range[-n, n]
          ]
          ]
          ]
          ];

          m = 20;
          n = 40;
          dimNM1[n, m] // AbsoluteTiming
          dimNM2[n, m] // AbsoluteTiming
          dimNM3[n, m] // AbsoluteTiming



          {0.116977, 3802}



          {0.995365, 3802}



          {0.005579, 3802}








          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 10 at 8:45

























          answered Dec 9 at 13:20









          Henrik Schumacher

          48.4k467137




          48.4k467137























              2














              Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



              def count_solutions(Nm, Mm):
              firsthalves = dict()
              for m1 in range(-Nm,Nm+1):
              for m2 in range(-Nm,Nm+1):
              m = m1+m2
              n = abs(m1)+abs(m2)
              key = (m,n)
              if key in firsthalves:
              firsthalves[key] += 1
              else:
              firsthalves[key] = 1

              solutions = 0
              for m3 in range(-Nm,Nm+1):
              for m4 in range(-Nm,Nm+1):
              m = m3+m4
              n = abs(m3)+abs(m4)
              key = (Mm-m, Nm-n)
              if key in firsthalves:
              solutions += firsthalves[key]
              return solutions


              This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



              Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



              The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






              share|improve this answer




























                2














                Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



                def count_solutions(Nm, Mm):
                firsthalves = dict()
                for m1 in range(-Nm,Nm+1):
                for m2 in range(-Nm,Nm+1):
                m = m1+m2
                n = abs(m1)+abs(m2)
                key = (m,n)
                if key in firsthalves:
                firsthalves[key] += 1
                else:
                firsthalves[key] = 1

                solutions = 0
                for m3 in range(-Nm,Nm+1):
                for m4 in range(-Nm,Nm+1):
                m = m3+m4
                n = abs(m3)+abs(m4)
                key = (Mm-m, Nm-n)
                if key in firsthalves:
                solutions += firsthalves[key]
                return solutions


                This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



                Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



                The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






                share|improve this answer


























                  2












                  2








                  2






                  Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



                  def count_solutions(Nm, Mm):
                  firsthalves = dict()
                  for m1 in range(-Nm,Nm+1):
                  for m2 in range(-Nm,Nm+1):
                  m = m1+m2
                  n = abs(m1)+abs(m2)
                  key = (m,n)
                  if key in firsthalves:
                  firsthalves[key] += 1
                  else:
                  firsthalves[key] = 1

                  solutions = 0
                  for m3 in range(-Nm,Nm+1):
                  for m4 in range(-Nm,Nm+1):
                  m = m3+m4
                  n = abs(m3)+abs(m4)
                  key = (Mm-m, Nm-n)
                  if key in firsthalves:
                  solutions += firsthalves[key]
                  return solutions


                  This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



                  Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



                  The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.






                  share|improve this answer














                  Sorry for not knowing much Mathematica, but I have a Python solution you might be able to follow. I'm putting this on the community wiki for anyone who wants to translate it.



                  def count_solutions(Nm, Mm):
                  firsthalves = dict()
                  for m1 in range(-Nm,Nm+1):
                  for m2 in range(-Nm,Nm+1):
                  m = m1+m2
                  n = abs(m1)+abs(m2)
                  key = (m,n)
                  if key in firsthalves:
                  firsthalves[key] += 1
                  else:
                  firsthalves[key] = 1

                  solutions = 0
                  for m3 in range(-Nm,Nm+1):
                  for m4 in range(-Nm,Nm+1):
                  m = m3+m4
                  n = abs(m3)+abs(m4)
                  key = (Mm-m, Nm-n)
                  if key in firsthalves:
                  solutions += firsthalves[key]
                  return solutions


                  This is a meet in the middle strategy. I enumerate all the possible $m1,m2$ combinations and record how many times each $m1+m2,|m1|+|m2|$ combination occurs in a dictionary.



                  Then I go through all the possible $m3,m4$ combinations and for each combination I calculate the necessary $m1+m2,|m1|+|m2|$ combination to make $Mm,Nm$, and I refer to the dictionary to find out how many $m1,m2$ combinations can make that.



                  The difference is that you go through the $m1,m2$ combination then the $m3,m4$ combinations, and the number of operations is roughly a square root of going through every $m1,m2,m3,m4$ combination. You should be able to solve for $Nm = 1000,Mn = 0$ in a few seconds.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 9 at 23:42


























                  community wiki





                  2 revs
                  James Hollis































                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Mathematica Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f187608%2fcan-this-be-solved-even-faster%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                      Alcedinidae

                      Can an atomic nucleus contain both particles and antiparticles? [duplicate]