Cycles on the torus Unicorn Meta Zoo #1: Why another podcast? Announcing the arrival of Valued Associate #679: Cesar Manara The PPCG Site design is on its way - help us make it awesome! Sandbox for Proposed ChallengesDecompose a permutation into cyclesMoore IterationGoogle Code Jam - New Lottery GameCo-primality and the number piRotate every row and column in a matrixRotate every 2x2 block in a matrixFire propagation simulatorWord Search on a Torus2D Array Middle PointPolite Near-Sighted Drunk Bot on a Minefield

With indentation set to `0em`, when using a line break, there is still an indentation of a size of a space

What ability score does a Hexblade's Pact Weapon use for attack and damage when wielded by another character?

"My boss was furious with me and I have been fired" vs. "My boss was furious with me and I was fired"

Trumpet valves, lengths, and pitch

Do I need to protect SFP ports and optics from dust/contaminants? If so, how?

How to open locks without disable device?

Split coins into combinations of different denominations

c++ diamond problem - How to call base method only once

What do you call the part of a novel that is not dialog?

Expansion//Explosion and Siren Stormtamer

What *exactly* is electrical current, voltage, and resistance?

A Paper Record is What I Hamper

How to avoid introduction cliches

How do I check if a string is entirely made of the same substring?

Is a 5 watt UHF/VHF handheld considered QRP?

Additive group of local rings

What is it called when you ride around on your front wheel?

Implementing 3DES algorithm in Java: is my code secure?

Can I criticise the more senior developers around me for not writing clean code?

Where did Arya get these scars?

Could moose/elk survive in the Amazon forest?

Will I lose my paid in full property

Justification for leaving new position after a short time

Is there any hidden 'W' sound after 'comment' in : Comment est-elle?



Cycles on the torus



Unicorn Meta Zoo #1: Why another podcast?
Announcing the arrival of Valued Associate #679: Cesar Manara
The PPCG Site design is on its way - help us make it awesome!
Sandbox for Proposed ChallengesDecompose a permutation into cyclesMoore IterationGoogle Code Jam - New Lottery GameCo-primality and the number piRotate every row and column in a matrixRotate every 2x2 block in a matrixFire propagation simulatorWord Search on a Torus2D Array Middle PointPolite Near-Sighted Drunk Bot on a Minefield










20












$begingroup$


Challenge



This challenge will have you write a program that takes in two integers n and m and outputs the number non-intersecting loops on the n by m torus made by starting at (0,0) and only taking steps up and to the right. You can think of torus as the grid with wraparound both at the top and the bottom and on the sides.



This is code-golf so fewest bytes wins.



Example



For example, if the input is n=m=5, one valid walk is



(0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (2,3) -> (2,4) -> 
(2,0) -> (3,0) -> (4,0) -> (4,1) -> (4,2) -> (4,3) ->
(0,3) -> (1,3) -> (1,4) ->
(1,0) -> (1,1) -> (2,1) -> (3,1) -> (3,2) -> (3,3) -> (3,4) -> (4,4) ->
(0,4) -> (0,0)


as shown in the graphic.



A loop on the torus.



Some example input/outputs



f(1,1) = 2 (up or right)
f(1,2) = 2 (up or right-right)
f(2,2) = 4 (up-up, up-right-up-right, right-right, right-up-right-up)
f(2,3) = 7
f(3,3) = 22
f(2,4) = 13
f(3,4) = 66
f(4,4) = 258









share|improve this question











$endgroup$







  • 1




    $begingroup$
    I was willing to bet that this sequence was on OEIS for at least $m=n$, but apparently it's not (yet).
    $endgroup$
    – Arnauld
    Mar 9 at 9:24










  • $begingroup$
    I think a torus also has a left-right wraparound. Should we assume it only has up-down wraparound instead? The example image doesn't seem to imply as such.
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:12











  • $begingroup$
    @EriktheOutgolfer The image does show the orange path wrapping around from right to left, doesn't it?
    $endgroup$
    – Arnauld
    Mar 9 at 11:19










  • $begingroup$
    @Arnauld Yes, but it doesn't look consistent with the challenge's description ("You can think of torus as the grid with wraparound both at the top and the bottom.")
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:20










  • $begingroup$
    @EriktheOutgolfer That's true. And now that you mention it, the blue path is wrong. It should first wraparound from right to left and then from top to bottom.
    $endgroup$
    – Arnauld
    Mar 9 at 11:24















20












$begingroup$


Challenge



This challenge will have you write a program that takes in two integers n and m and outputs the number non-intersecting loops on the n by m torus made by starting at (0,0) and only taking steps up and to the right. You can think of torus as the grid with wraparound both at the top and the bottom and on the sides.



This is code-golf so fewest bytes wins.



Example



For example, if the input is n=m=5, one valid walk is



(0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (2,3) -> (2,4) -> 
(2,0) -> (3,0) -> (4,0) -> (4,1) -> (4,2) -> (4,3) ->
(0,3) -> (1,3) -> (1,4) ->
(1,0) -> (1,1) -> (2,1) -> (3,1) -> (3,2) -> (3,3) -> (3,4) -> (4,4) ->
(0,4) -> (0,0)


as shown in the graphic.



A loop on the torus.



Some example input/outputs



f(1,1) = 2 (up or right)
f(1,2) = 2 (up or right-right)
f(2,2) = 4 (up-up, up-right-up-right, right-right, right-up-right-up)
f(2,3) = 7
f(3,3) = 22
f(2,4) = 13
f(3,4) = 66
f(4,4) = 258









share|improve this question











$endgroup$







  • 1




    $begingroup$
    I was willing to bet that this sequence was on OEIS for at least $m=n$, but apparently it's not (yet).
    $endgroup$
    – Arnauld
    Mar 9 at 9:24










  • $begingroup$
    I think a torus also has a left-right wraparound. Should we assume it only has up-down wraparound instead? The example image doesn't seem to imply as such.
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:12











  • $begingroup$
    @EriktheOutgolfer The image does show the orange path wrapping around from right to left, doesn't it?
    $endgroup$
    – Arnauld
    Mar 9 at 11:19










  • $begingroup$
    @Arnauld Yes, but it doesn't look consistent with the challenge's description ("You can think of torus as the grid with wraparound both at the top and the bottom.")
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:20










  • $begingroup$
    @EriktheOutgolfer That's true. And now that you mention it, the blue path is wrong. It should first wraparound from right to left and then from top to bottom.
    $endgroup$
    – Arnauld
    Mar 9 at 11:24













20












20








20


2



$begingroup$


Challenge



This challenge will have you write a program that takes in two integers n and m and outputs the number non-intersecting loops on the n by m torus made by starting at (0,0) and only taking steps up and to the right. You can think of torus as the grid with wraparound both at the top and the bottom and on the sides.



This is code-golf so fewest bytes wins.



Example



For example, if the input is n=m=5, one valid walk is



(0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (2,3) -> (2,4) -> 
(2,0) -> (3,0) -> (4,0) -> (4,1) -> (4,2) -> (4,3) ->
(0,3) -> (1,3) -> (1,4) ->
(1,0) -> (1,1) -> (2,1) -> (3,1) -> (3,2) -> (3,3) -> (3,4) -> (4,4) ->
(0,4) -> (0,0)


as shown in the graphic.



A loop on the torus.



Some example input/outputs



f(1,1) = 2 (up or right)
f(1,2) = 2 (up or right-right)
f(2,2) = 4 (up-up, up-right-up-right, right-right, right-up-right-up)
f(2,3) = 7
f(3,3) = 22
f(2,4) = 13
f(3,4) = 66
f(4,4) = 258









share|improve this question











$endgroup$




Challenge



This challenge will have you write a program that takes in two integers n and m and outputs the number non-intersecting loops on the n by m torus made by starting at (0,0) and only taking steps up and to the right. You can think of torus as the grid with wraparound both at the top and the bottom and on the sides.



This is code-golf so fewest bytes wins.



Example



For example, if the input is n=m=5, one valid walk is



(0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (2,3) -> (2,4) -> 
(2,0) -> (3,0) -> (4,0) -> (4,1) -> (4,2) -> (4,3) ->
(0,3) -> (1,3) -> (1,4) ->
(1,0) -> (1,1) -> (2,1) -> (3,1) -> (3,2) -> (3,3) -> (3,4) -> (4,4) ->
(0,4) -> (0,0)


as shown in the graphic.



A loop on the torus.



Some example input/outputs



f(1,1) = 2 (up or right)
f(1,2) = 2 (up or right-right)
f(2,2) = 4 (up-up, up-right-up-right, right-right, right-up-right-up)
f(2,3) = 7
f(3,3) = 22
f(2,4) = 13
f(3,4) = 66
f(4,4) = 258






code-golf combinatorics grid topology






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 11 at 20:57









Sriotchilism O'Zaic

35.8k10161370




35.8k10161370










asked Mar 9 at 2:19









Peter KageyPeter Kagey

825523




825523







  • 1




    $begingroup$
    I was willing to bet that this sequence was on OEIS for at least $m=n$, but apparently it's not (yet).
    $endgroup$
    – Arnauld
    Mar 9 at 9:24










  • $begingroup$
    I think a torus also has a left-right wraparound. Should we assume it only has up-down wraparound instead? The example image doesn't seem to imply as such.
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:12











  • $begingroup$
    @EriktheOutgolfer The image does show the orange path wrapping around from right to left, doesn't it?
    $endgroup$
    – Arnauld
    Mar 9 at 11:19










  • $begingroup$
    @Arnauld Yes, but it doesn't look consistent with the challenge's description ("You can think of torus as the grid with wraparound both at the top and the bottom.")
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:20










  • $begingroup$
    @EriktheOutgolfer That's true. And now that you mention it, the blue path is wrong. It should first wraparound from right to left and then from top to bottom.
    $endgroup$
    – Arnauld
    Mar 9 at 11:24












  • 1




    $begingroup$
    I was willing to bet that this sequence was on OEIS for at least $m=n$, but apparently it's not (yet).
    $endgroup$
    – Arnauld
    Mar 9 at 9:24










  • $begingroup$
    I think a torus also has a left-right wraparound. Should we assume it only has up-down wraparound instead? The example image doesn't seem to imply as such.
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:12











  • $begingroup$
    @EriktheOutgolfer The image does show the orange path wrapping around from right to left, doesn't it?
    $endgroup$
    – Arnauld
    Mar 9 at 11:19










  • $begingroup$
    @Arnauld Yes, but it doesn't look consistent with the challenge's description ("You can think of torus as the grid with wraparound both at the top and the bottom.")
    $endgroup$
    – Erik the Outgolfer
    Mar 9 at 11:20










  • $begingroup$
    @EriktheOutgolfer That's true. And now that you mention it, the blue path is wrong. It should first wraparound from right to left and then from top to bottom.
    $endgroup$
    – Arnauld
    Mar 9 at 11:24







1




1




$begingroup$
I was willing to bet that this sequence was on OEIS for at least $m=n$, but apparently it's not (yet).
$endgroup$
– Arnauld
Mar 9 at 9:24




$begingroup$
I was willing to bet that this sequence was on OEIS for at least $m=n$, but apparently it's not (yet).
$endgroup$
– Arnauld
Mar 9 at 9:24












$begingroup$
I think a torus also has a left-right wraparound. Should we assume it only has up-down wraparound instead? The example image doesn't seem to imply as such.
$endgroup$
– Erik the Outgolfer
Mar 9 at 11:12





$begingroup$
I think a torus also has a left-right wraparound. Should we assume it only has up-down wraparound instead? The example image doesn't seem to imply as such.
$endgroup$
– Erik the Outgolfer
Mar 9 at 11:12













$begingroup$
@EriktheOutgolfer The image does show the orange path wrapping around from right to left, doesn't it?
$endgroup$
– Arnauld
Mar 9 at 11:19




$begingroup$
@EriktheOutgolfer The image does show the orange path wrapping around from right to left, doesn't it?
$endgroup$
– Arnauld
Mar 9 at 11:19












$begingroup$
@Arnauld Yes, but it doesn't look consistent with the challenge's description ("You can think of torus as the grid with wraparound both at the top and the bottom.")
$endgroup$
– Erik the Outgolfer
Mar 9 at 11:20




$begingroup$
@Arnauld Yes, but it doesn't look consistent with the challenge's description ("You can think of torus as the grid with wraparound both at the top and the bottom.")
$endgroup$
– Erik the Outgolfer
Mar 9 at 11:20












$begingroup$
@EriktheOutgolfer That's true. And now that you mention it, the blue path is wrong. It should first wraparound from right to left and then from top to bottom.
$endgroup$
– Arnauld
Mar 9 at 11:24




$begingroup$
@EriktheOutgolfer That's true. And now that you mention it, the blue path is wrong. It should first wraparound from right to left and then from top to bottom.
$endgroup$
– Arnauld
Mar 9 at 11:24










8 Answers
8






active

oldest

votes


















4












$begingroup$


Jelly, 28 bytes



ạƝ§=1Ȧ
²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL


A monadic Link accepting a list, [m,n], which yields the count.



TIO-jt1qe1v9 ...although there is little point, it's way too inefficient.

(I can't even run [2,3] locally with 16GB ram)!



How?



Brute force - creates coordinates of a tiled version big enough then filters the power-set of these points to those paths with neighbours only increasing by one in a single direction, then filters to those starting at a minimal coordinate (i.e. the origin) and, at the same time, removes this start coordinate from each. Then uses modulo arithmetic to wrap back to a torus and filters out any containing duplicate coordinates (i.e. those containing intersections) and, finally, filters to those with minimal ending coordinates (i.e. ending back at the origin) and yields the result's length.



ạƝ§=1Ȧ - Link 1: all neighbours differ by 1 in exactly one direction
Ɲ - for neighbours:
ạ - absolute difference
§ - sum each
=1 - equal to one (vectorises)
Ȧ - any and all? (falsey if empty or contains a falsey value when flattened)

²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL - Main Link: list of integers, [m,n]
² - square (vectorises) -> [m*m, n*n]
‘ - increment (vectorises) -> [m*m+1, n*n+1]
/ - reduce with:
p - Cartesian product
’ - decrement (vectorises) -> all the coordinates of an m*m by n*n grid
- including [0, 0] and [m*m, n*n]
ŒP - power-set -> all paths going either up OR right at each step, but not
- necessarily by only 1, and
- necessarily both up and right (e.g. [...[1,3],[5,7],[6,2],...])
Ƈ - filter keep those for which:
Ç - call last Link (1) as a monad
- ...now all remaining paths do only go in steps
- of one up or one right
ÐṂ - filter keep those minimal under:
Ḣ - head - removes the 1st coordinate from each and yields them for the filter
- ...so only those which started at [0,0] but without it
%⁸ - modulo by the left argument ([m,n]) (vectorises)
Ƈ - filter keep those for which:
Ƒ - is invariant when:
Q - de-duplicated
- ...so no repetitions of torus coordinates (and we already removed
- the first [0,0] which must be present exactly twice)
ÐṂ - filter keep those minimal under:
Ṫ - tail
- ...so only those which ended at [0,0]
L - length





share|improve this answer









$endgroup$




















    12












    $begingroup$


    Python 2, 87 bytes





    f=lambda m,n,z=0,l=[]:z==0if z in l else sum(f(m,n,(z+d)%m%(n*1j),l+[z])for d in(1,1j))


    Try it online!



    The interesting thing here is using a complex number z to store the coordinate of the current position. We can move up by adding 1 and move right by adding 1j. To my surprise, modulo works on complex numbers in a way that lets us handle the wrapping for each dimension separately: doing %m acts on the real part, and %(n*1j) acts on the imaginary part.






    share|improve this answer









    $endgroup$












    • $begingroup$
      Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
      $endgroup$
      – Arnauld
      Mar 9 at 9:53











    • $begingroup$
      @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
      $endgroup$
      – xnor
      Mar 9 at 9:59






    • 1




      $begingroup$
      @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
      $endgroup$
      – xnor
      Mar 9 at 10:11











    • $begingroup$
      This approach saves 5 bytes in JS. :)
      $endgroup$
      – Arnauld
      Mar 9 at 10:57


















    7












    $begingroup$

    JavaScript (ES6), 67 bytes



    This shorter version is derived from a Python 3.8 alternate version found by @xnor. However, this works only for $mtimes n<32$ in JS.



    Takes input as (m)(n).





    m=>n=>(g=(k,l)=>l>>k&1?!k:g((k+m)%(m*n),l|=1<<k)+g(k-~k%m-k%m,l))``


    Try it online!



    To have it work for any input, we could use BigInts for 73 bytes:



    m=>n=>(g=(k,l=k)=>l&(b=1n<<k)?!k:g((k+m)%(m*n),l|=b)+g(k-~k%m-k%m,l))(0n)


    Try it online!




    JavaScript (ES6),  76 73  72 bytes



    Takes input as (m)(n).





    m=>n=>(g=(x,y)=>g[x+=y*m]?!x:g(-~x%m,y,g[x]=1)+g(x%m,-~y%n)+--g[x])(0,0)


    Try it online!



    Commented



    m => n => ( // m = width; n = height
    g = ( // g is a recursive function taking:
    x, y // the current coordinates (x, y) on the torus
    ) => //
    g[ // the surrounding object of g is also used for storage
    x += y * m // turn x into a key for the current coordinates
    ] ? // if this cell was already visited:
    !x // return 1 if we're back to (0, 0), or 0 otherwise
    : // else:
    g( // first recursive call:
    -~x % m, // move to the right
    y, // leave y unchanged
    g[x] = 1 // mark the current cell as visited by setting the flag g[x]
    ) + // add the result of
    g( // a second recursive call:
    x % m, // restore x in [0...m-1]
    -~y % n // move up
    ) + //
    --g[x] // clear the flag on the current cell
    )(0, 0) // initial call to g with (x, y) = (0, 0)





    share|improve this answer











    $endgroup$




















      3












      $begingroup$

      Haskell, 88 80 bytes



      n#m|let(x!y)a|elem(x,y)a=0^(x+y)|b<-(x,y):a=(mod(x+1)n!y)b+(x!mod(y+1)m)b=0!0$[]


      Try it online!



      Simple brute force: try all up/right combinations, dropping those which intersect (we keep all positions we've visited in list a) and counting those which eventually hit positition (0,0) again.



      The base case of the recursion is when we visit a position a second time (elem(x,y)a). The result is 0^0 = 1 when the position is (0,0) and counts towards the numbers of loops or 0 (0^x, with x non-zero) otherwise and doesn't increase the number of loops.



      Edit: -8 bytes thanks to @xnor.






      share|improve this answer











      $endgroup$








      • 1




        $begingroup$
        The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
        $endgroup$
        – xnor
        Mar 9 at 17:56


















      2












      $begingroup$


      Jelly, 44 bytes



      ×ƝṪ2*Ḥ_2Rḃ€2ċⱮؽ%³¬ẠƲƇịØ.Ṛ,Ø.¤ZÄZ%€ʋ€³ŒQẠ$€S


      Try it online!



      Works for 4,4, but has complexity $O(2^m^n)$ so won’t scale that well.



      This works by finding all possible routes of up to $mn$ length, filtering out those that don’t end at 0,0, and then excluding those that pass the same point twice.






      share|improve this answer









      $endgroup$




















        1












        $begingroup$

        Java 8, 120 bytes





        n->m->g(n,m,0,0);int g(int n,int m,int k,int l)=1<<k)+g(n,m,k-~k%m-k%m,l);


        Port of @Arnauld's JavaScript answer, and also only works for inputs where $n*m<32$.



        Try it online.






        share|improve this answer









        $endgroup$




















          1












          $begingroup$

          CJam (50 chars)



          q~]:M:!a9Yb2/f_W=@.+M.%a+_)a#g"WAR"=~:R~e_We=


          Online demo. This is a program which takes two inputs from stdin.



          Finally we have an answer to the question




          War, huh, what is it good for?





          Dissection



          q~]:M e# Parse input, collect in array, store in M (for moduli)
          :!a e# Zero and wrap in array for starting position (0, 0)
          e# Define recursive block R
          9Yb2/ e# Push [[1 0][0 1]], an array of movements
          f e# For each of those movements, with the current path,
          _W=@.+ e# Add the movement to the last position in the path
          M.% e# Apply the wrapping
          a+ e# Add to one copy of the path
          _)a# e# And find its index in another copy
          g"WAR"=~ e# Switch on the sign of the index:
          e# If the sign is -1, position not found, make a recursive call
          e# If the sign is 0, found at start, push -1 to the stack
          e# If the sign is 1, we have a self-intersection. We push 10 to
          e# the stack for no other reason than to make the bad joke above

          :R
          ~ e# Execute R
          e_We= e# Count the -1s which we pushed as sentinels





          share|improve this answer









          $endgroup$




















            1












            $begingroup$


            Jelly, 54 39 bytes



            ḣ2æ.2ị³¤+4
            ‘Ç;¥¦%³Ç=4ƊÑÇị$?
            çⱮؽS
            ’Ñ0xÇ


            Try it online!



            I’ve posted this as a separate answer to my other Jelly one because it’s a completely different method. This is closer in principle to @Arnauld’s answer. It uses a recursive function that works through every possible path until it reaches a point it’s already got to, and then returns the result of a check whether it’s back to the start. I suspect a few more bytes could be shaved off. Now changed to using slice operator. It works well for up to 5x5. The recursion depth should be at most m x n.






            share|improve this answer











            $endgroup$













              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "200"
              ;
              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%2fcodegolf.stackexchange.com%2fquestions%2f181203%2fcycles-on-the-torus%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              8 Answers
              8






              active

              oldest

              votes








              8 Answers
              8






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              4












              $begingroup$


              Jelly, 28 bytes



              ạƝ§=1Ȧ
              ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL


              A monadic Link accepting a list, [m,n], which yields the count.



              TIO-jt1qe1v9 ...although there is little point, it's way too inefficient.

              (I can't even run [2,3] locally with 16GB ram)!



              How?



              Brute force - creates coordinates of a tiled version big enough then filters the power-set of these points to those paths with neighbours only increasing by one in a single direction, then filters to those starting at a minimal coordinate (i.e. the origin) and, at the same time, removes this start coordinate from each. Then uses modulo arithmetic to wrap back to a torus and filters out any containing duplicate coordinates (i.e. those containing intersections) and, finally, filters to those with minimal ending coordinates (i.e. ending back at the origin) and yields the result's length.



              ạƝ§=1Ȧ - Link 1: all neighbours differ by 1 in exactly one direction
              Ɲ - for neighbours:
              ạ - absolute difference
              § - sum each
              =1 - equal to one (vectorises)
              Ȧ - any and all? (falsey if empty or contains a falsey value when flattened)

              ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL - Main Link: list of integers, [m,n]
              ² - square (vectorises) -> [m*m, n*n]
              ‘ - increment (vectorises) -> [m*m+1, n*n+1]
              / - reduce with:
              p - Cartesian product
              ’ - decrement (vectorises) -> all the coordinates of an m*m by n*n grid
              - including [0, 0] and [m*m, n*n]
              ŒP - power-set -> all paths going either up OR right at each step, but not
              - necessarily by only 1, and
              - necessarily both up and right (e.g. [...[1,3],[5,7],[6,2],...])
              Ƈ - filter keep those for which:
              Ç - call last Link (1) as a monad
              - ...now all remaining paths do only go in steps
              - of one up or one right
              ÐṂ - filter keep those minimal under:
              Ḣ - head - removes the 1st coordinate from each and yields them for the filter
              - ...so only those which started at [0,0] but without it
              %⁸ - modulo by the left argument ([m,n]) (vectorises)
              Ƈ - filter keep those for which:
              Ƒ - is invariant when:
              Q - de-duplicated
              - ...so no repetitions of torus coordinates (and we already removed
              - the first [0,0] which must be present exactly twice)
              ÐṂ - filter keep those minimal under:
              Ṫ - tail
              - ...so only those which ended at [0,0]
              L - length





              share|improve this answer









              $endgroup$

















                4












                $begingroup$


                Jelly, 28 bytes



                ạƝ§=1Ȧ
                ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL


                A monadic Link accepting a list, [m,n], which yields the count.



                TIO-jt1qe1v9 ...although there is little point, it's way too inefficient.

                (I can't even run [2,3] locally with 16GB ram)!



                How?



                Brute force - creates coordinates of a tiled version big enough then filters the power-set of these points to those paths with neighbours only increasing by one in a single direction, then filters to those starting at a minimal coordinate (i.e. the origin) and, at the same time, removes this start coordinate from each. Then uses modulo arithmetic to wrap back to a torus and filters out any containing duplicate coordinates (i.e. those containing intersections) and, finally, filters to those with minimal ending coordinates (i.e. ending back at the origin) and yields the result's length.



                ạƝ§=1Ȧ - Link 1: all neighbours differ by 1 in exactly one direction
                Ɲ - for neighbours:
                ạ - absolute difference
                § - sum each
                =1 - equal to one (vectorises)
                Ȧ - any and all? (falsey if empty or contains a falsey value when flattened)

                ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL - Main Link: list of integers, [m,n]
                ² - square (vectorises) -> [m*m, n*n]
                ‘ - increment (vectorises) -> [m*m+1, n*n+1]
                / - reduce with:
                p - Cartesian product
                ’ - decrement (vectorises) -> all the coordinates of an m*m by n*n grid
                - including [0, 0] and [m*m, n*n]
                ŒP - power-set -> all paths going either up OR right at each step, but not
                - necessarily by only 1, and
                - necessarily both up and right (e.g. [...[1,3],[5,7],[6,2],...])
                Ƈ - filter keep those for which:
                Ç - call last Link (1) as a monad
                - ...now all remaining paths do only go in steps
                - of one up or one right
                ÐṂ - filter keep those minimal under:
                Ḣ - head - removes the 1st coordinate from each and yields them for the filter
                - ...so only those which started at [0,0] but without it
                %⁸ - modulo by the left argument ([m,n]) (vectorises)
                Ƈ - filter keep those for which:
                Ƒ - is invariant when:
                Q - de-duplicated
                - ...so no repetitions of torus coordinates (and we already removed
                - the first [0,0] which must be present exactly twice)
                ÐṂ - filter keep those minimal under:
                Ṫ - tail
                - ...so only those which ended at [0,0]
                L - length





                share|improve this answer









                $endgroup$















                  4












                  4








                  4





                  $begingroup$


                  Jelly, 28 bytes



                  ạƝ§=1Ȧ
                  ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL


                  A monadic Link accepting a list, [m,n], which yields the count.



                  TIO-jt1qe1v9 ...although there is little point, it's way too inefficient.

                  (I can't even run [2,3] locally with 16GB ram)!



                  How?



                  Brute force - creates coordinates of a tiled version big enough then filters the power-set of these points to those paths with neighbours only increasing by one in a single direction, then filters to those starting at a minimal coordinate (i.e. the origin) and, at the same time, removes this start coordinate from each. Then uses modulo arithmetic to wrap back to a torus and filters out any containing duplicate coordinates (i.e. those containing intersections) and, finally, filters to those with minimal ending coordinates (i.e. ending back at the origin) and yields the result's length.



                  ạƝ§=1Ȧ - Link 1: all neighbours differ by 1 in exactly one direction
                  Ɲ - for neighbours:
                  ạ - absolute difference
                  § - sum each
                  =1 - equal to one (vectorises)
                  Ȧ - any and all? (falsey if empty or contains a falsey value when flattened)

                  ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL - Main Link: list of integers, [m,n]
                  ² - square (vectorises) -> [m*m, n*n]
                  ‘ - increment (vectorises) -> [m*m+1, n*n+1]
                  / - reduce with:
                  p - Cartesian product
                  ’ - decrement (vectorises) -> all the coordinates of an m*m by n*n grid
                  - including [0, 0] and [m*m, n*n]
                  ŒP - power-set -> all paths going either up OR right at each step, but not
                  - necessarily by only 1, and
                  - necessarily both up and right (e.g. [...[1,3],[5,7],[6,2],...])
                  Ƈ - filter keep those for which:
                  Ç - call last Link (1) as a monad
                  - ...now all remaining paths do only go in steps
                  - of one up or one right
                  ÐṂ - filter keep those minimal under:
                  Ḣ - head - removes the 1st coordinate from each and yields them for the filter
                  - ...so only those which started at [0,0] but without it
                  %⁸ - modulo by the left argument ([m,n]) (vectorises)
                  Ƈ - filter keep those for which:
                  Ƒ - is invariant when:
                  Q - de-duplicated
                  - ...so no repetitions of torus coordinates (and we already removed
                  - the first [0,0] which must be present exactly twice)
                  ÐṂ - filter keep those minimal under:
                  Ṫ - tail
                  - ...so only those which ended at [0,0]
                  L - length





                  share|improve this answer









                  $endgroup$




                  Jelly, 28 bytes



                  ạƝ§=1Ȧ
                  ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL


                  A monadic Link accepting a list, [m,n], which yields the count.



                  TIO-jt1qe1v9 ...although there is little point, it's way too inefficient.

                  (I can't even run [2,3] locally with 16GB ram)!



                  How?



                  Brute force - creates coordinates of a tiled version big enough then filters the power-set of these points to those paths with neighbours only increasing by one in a single direction, then filters to those starting at a minimal coordinate (i.e. the origin) and, at the same time, removes this start coordinate from each. Then uses modulo arithmetic to wrap back to a torus and filters out any containing duplicate coordinates (i.e. those containing intersections) and, finally, filters to those with minimal ending coordinates (i.e. ending back at the origin) and yields the result's length.



                  ạƝ§=1Ȧ - Link 1: all neighbours differ by 1 in exactly one direction
                  Ɲ - for neighbours:
                  ạ - absolute difference
                  § - sum each
                  =1 - equal to one (vectorises)
                  Ȧ - any and all? (falsey if empty or contains a falsey value when flattened)

                  ²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL - Main Link: list of integers, [m,n]
                  ² - square (vectorises) -> [m*m, n*n]
                  ‘ - increment (vectorises) -> [m*m+1, n*n+1]
                  / - reduce with:
                  p - Cartesian product
                  ’ - decrement (vectorises) -> all the coordinates of an m*m by n*n grid
                  - including [0, 0] and [m*m, n*n]
                  ŒP - power-set -> all paths going either up OR right at each step, but not
                  - necessarily by only 1, and
                  - necessarily both up and right (e.g. [...[1,3],[5,7],[6,2],...])
                  Ƈ - filter keep those for which:
                  Ç - call last Link (1) as a monad
                  - ...now all remaining paths do only go in steps
                  - of one up or one right
                  ÐṂ - filter keep those minimal under:
                  Ḣ - head - removes the 1st coordinate from each and yields them for the filter
                  - ...so only those which started at [0,0] but without it
                  %⁸ - modulo by the left argument ([m,n]) (vectorises)
                  Ƈ - filter keep those for which:
                  Ƒ - is invariant when:
                  Q - de-duplicated
                  - ...so no repetitions of torus coordinates (and we already removed
                  - the first [0,0] which must be present exactly twice)
                  ÐṂ - filter keep those minimal under:
                  Ṫ - tail
                  - ...so only those which ended at [0,0]
                  L - length






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Mar 9 at 17:41









                  Jonathan AllanJonathan Allan

                  54.9k537176




                  54.9k537176





















                      12












                      $begingroup$


                      Python 2, 87 bytes





                      f=lambda m,n,z=0,l=[]:z==0if z in l else sum(f(m,n,(z+d)%m%(n*1j),l+[z])for d in(1,1j))


                      Try it online!



                      The interesting thing here is using a complex number z to store the coordinate of the current position. We can move up by adding 1 and move right by adding 1j. To my surprise, modulo works on complex numbers in a way that lets us handle the wrapping for each dimension separately: doing %m acts on the real part, and %(n*1j) acts on the imaginary part.






                      share|improve this answer









                      $endgroup$












                      • $begingroup$
                        Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
                        $endgroup$
                        – Arnauld
                        Mar 9 at 9:53











                      • $begingroup$
                        @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
                        $endgroup$
                        – xnor
                        Mar 9 at 9:59






                      • 1




                        $begingroup$
                        @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
                        $endgroup$
                        – xnor
                        Mar 9 at 10:11











                      • $begingroup$
                        This approach saves 5 bytes in JS. :)
                        $endgroup$
                        – Arnauld
                        Mar 9 at 10:57















                      12












                      $begingroup$


                      Python 2, 87 bytes





                      f=lambda m,n,z=0,l=[]:z==0if z in l else sum(f(m,n,(z+d)%m%(n*1j),l+[z])for d in(1,1j))


                      Try it online!



                      The interesting thing here is using a complex number z to store the coordinate of the current position. We can move up by adding 1 and move right by adding 1j. To my surprise, modulo works on complex numbers in a way that lets us handle the wrapping for each dimension separately: doing %m acts on the real part, and %(n*1j) acts on the imaginary part.






                      share|improve this answer









                      $endgroup$












                      • $begingroup$
                        Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
                        $endgroup$
                        – Arnauld
                        Mar 9 at 9:53











                      • $begingroup$
                        @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
                        $endgroup$
                        – xnor
                        Mar 9 at 9:59






                      • 1




                        $begingroup$
                        @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
                        $endgroup$
                        – xnor
                        Mar 9 at 10:11











                      • $begingroup$
                        This approach saves 5 bytes in JS. :)
                        $endgroup$
                        – Arnauld
                        Mar 9 at 10:57













                      12












                      12








                      12





                      $begingroup$


                      Python 2, 87 bytes





                      f=lambda m,n,z=0,l=[]:z==0if z in l else sum(f(m,n,(z+d)%m%(n*1j),l+[z])for d in(1,1j))


                      Try it online!



                      The interesting thing here is using a complex number z to store the coordinate of the current position. We can move up by adding 1 and move right by adding 1j. To my surprise, modulo works on complex numbers in a way that lets us handle the wrapping for each dimension separately: doing %m acts on the real part, and %(n*1j) acts on the imaginary part.






                      share|improve this answer









                      $endgroup$




                      Python 2, 87 bytes





                      f=lambda m,n,z=0,l=[]:z==0if z in l else sum(f(m,n,(z+d)%m%(n*1j),l+[z])for d in(1,1j))


                      Try it online!



                      The interesting thing here is using a complex number z to store the coordinate of the current position. We can move up by adding 1 and move right by adding 1j. To my surprise, modulo works on complex numbers in a way that lets us handle the wrapping for each dimension separately: doing %m acts on the real part, and %(n*1j) acts on the imaginary part.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Mar 9 at 4:12









                      xnorxnor

                      94.5k18193454




                      94.5k18193454











                      • $begingroup$
                        Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
                        $endgroup$
                        – Arnauld
                        Mar 9 at 9:53











                      • $begingroup$
                        @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
                        $endgroup$
                        – xnor
                        Mar 9 at 9:59






                      • 1




                        $begingroup$
                        @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
                        $endgroup$
                        – xnor
                        Mar 9 at 10:11











                      • $begingroup$
                        This approach saves 5 bytes in JS. :)
                        $endgroup$
                        – Arnauld
                        Mar 9 at 10:57
















                      • $begingroup$
                        Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
                        $endgroup$
                        – Arnauld
                        Mar 9 at 9:53











                      • $begingroup$
                        @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
                        $endgroup$
                        – xnor
                        Mar 9 at 9:59






                      • 1




                        $begingroup$
                        @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
                        $endgroup$
                        – xnor
                        Mar 9 at 10:11











                      • $begingroup$
                        This approach saves 5 bytes in JS. :)
                        $endgroup$
                        – Arnauld
                        Mar 9 at 10:57















                      $begingroup$
                      Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
                      $endgroup$
                      – Arnauld
                      Mar 9 at 9:53





                      $begingroup$
                      Nicely done. FWIW, my best attempt without using a complex number is 91 bytes in Python 3.8.
                      $endgroup$
                      – Arnauld
                      Mar 9 at 9:53













                      $begingroup$
                      @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
                      $endgroup$
                      – xnor
                      Mar 9 at 9:59




                      $begingroup$
                      @Arnauld Interesting idea with the k:=x+y*m. It makes me wonder if it would be shorter to use k directly for (x,y), using x+y*m rather than x+y*1j. Too bad Python 3 doesn't allow complex modulus.
                      $endgroup$
                      – xnor
                      Mar 9 at 9:59




                      1




                      1




                      $begingroup$
                      @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
                      $endgroup$
                      – xnor
                      Mar 9 at 10:11





                      $begingroup$
                      @Arnauld 87 bytes: tio.run/##XckxDoIwFIDh3VN0wfTRR0JbBkMsJ@ASGGkkry0NspgYr14lDhaHf/…
                      $endgroup$
                      – xnor
                      Mar 9 at 10:11













                      $begingroup$
                      This approach saves 5 bytes in JS. :)
                      $endgroup$
                      – Arnauld
                      Mar 9 at 10:57




                      $begingroup$
                      This approach saves 5 bytes in JS. :)
                      $endgroup$
                      – Arnauld
                      Mar 9 at 10:57











                      7












                      $begingroup$

                      JavaScript (ES6), 67 bytes



                      This shorter version is derived from a Python 3.8 alternate version found by @xnor. However, this works only for $mtimes n<32$ in JS.



                      Takes input as (m)(n).





                      m=>n=>(g=(k,l)=>l>>k&1?!k:g((k+m)%(m*n),l|=1<<k)+g(k-~k%m-k%m,l))``


                      Try it online!



                      To have it work for any input, we could use BigInts for 73 bytes:



                      m=>n=>(g=(k,l=k)=>l&(b=1n<<k)?!k:g((k+m)%(m*n),l|=b)+g(k-~k%m-k%m,l))(0n)


                      Try it online!




                      JavaScript (ES6),  76 73  72 bytes



                      Takes input as (m)(n).





                      m=>n=>(g=(x,y)=>g[x+=y*m]?!x:g(-~x%m,y,g[x]=1)+g(x%m,-~y%n)+--g[x])(0,0)


                      Try it online!



                      Commented



                      m => n => ( // m = width; n = height
                      g = ( // g is a recursive function taking:
                      x, y // the current coordinates (x, y) on the torus
                      ) => //
                      g[ // the surrounding object of g is also used for storage
                      x += y * m // turn x into a key for the current coordinates
                      ] ? // if this cell was already visited:
                      !x // return 1 if we're back to (0, 0), or 0 otherwise
                      : // else:
                      g( // first recursive call:
                      -~x % m, // move to the right
                      y, // leave y unchanged
                      g[x] = 1 // mark the current cell as visited by setting the flag g[x]
                      ) + // add the result of
                      g( // a second recursive call:
                      x % m, // restore x in [0...m-1]
                      -~y % n // move up
                      ) + //
                      --g[x] // clear the flag on the current cell
                      )(0, 0) // initial call to g with (x, y) = (0, 0)





                      share|improve this answer











                      $endgroup$

















                        7












                        $begingroup$

                        JavaScript (ES6), 67 bytes



                        This shorter version is derived from a Python 3.8 alternate version found by @xnor. However, this works only for $mtimes n<32$ in JS.



                        Takes input as (m)(n).





                        m=>n=>(g=(k,l)=>l>>k&1?!k:g((k+m)%(m*n),l|=1<<k)+g(k-~k%m-k%m,l))``


                        Try it online!



                        To have it work for any input, we could use BigInts for 73 bytes:



                        m=>n=>(g=(k,l=k)=>l&(b=1n<<k)?!k:g((k+m)%(m*n),l|=b)+g(k-~k%m-k%m,l))(0n)


                        Try it online!




                        JavaScript (ES6),  76 73  72 bytes



                        Takes input as (m)(n).





                        m=>n=>(g=(x,y)=>g[x+=y*m]?!x:g(-~x%m,y,g[x]=1)+g(x%m,-~y%n)+--g[x])(0,0)


                        Try it online!



                        Commented



                        m => n => ( // m = width; n = height
                        g = ( // g is a recursive function taking:
                        x, y // the current coordinates (x, y) on the torus
                        ) => //
                        g[ // the surrounding object of g is also used for storage
                        x += y * m // turn x into a key for the current coordinates
                        ] ? // if this cell was already visited:
                        !x // return 1 if we're back to (0, 0), or 0 otherwise
                        : // else:
                        g( // first recursive call:
                        -~x % m, // move to the right
                        y, // leave y unchanged
                        g[x] = 1 // mark the current cell as visited by setting the flag g[x]
                        ) + // add the result of
                        g( // a second recursive call:
                        x % m, // restore x in [0...m-1]
                        -~y % n // move up
                        ) + //
                        --g[x] // clear the flag on the current cell
                        )(0, 0) // initial call to g with (x, y) = (0, 0)





                        share|improve this answer











                        $endgroup$















                          7












                          7








                          7





                          $begingroup$

                          JavaScript (ES6), 67 bytes



                          This shorter version is derived from a Python 3.8 alternate version found by @xnor. However, this works only for $mtimes n<32$ in JS.



                          Takes input as (m)(n).





                          m=>n=>(g=(k,l)=>l>>k&1?!k:g((k+m)%(m*n),l|=1<<k)+g(k-~k%m-k%m,l))``


                          Try it online!



                          To have it work for any input, we could use BigInts for 73 bytes:



                          m=>n=>(g=(k,l=k)=>l&(b=1n<<k)?!k:g((k+m)%(m*n),l|=b)+g(k-~k%m-k%m,l))(0n)


                          Try it online!




                          JavaScript (ES6),  76 73  72 bytes



                          Takes input as (m)(n).





                          m=>n=>(g=(x,y)=>g[x+=y*m]?!x:g(-~x%m,y,g[x]=1)+g(x%m,-~y%n)+--g[x])(0,0)


                          Try it online!



                          Commented



                          m => n => ( // m = width; n = height
                          g = ( // g is a recursive function taking:
                          x, y // the current coordinates (x, y) on the torus
                          ) => //
                          g[ // the surrounding object of g is also used for storage
                          x += y * m // turn x into a key for the current coordinates
                          ] ? // if this cell was already visited:
                          !x // return 1 if we're back to (0, 0), or 0 otherwise
                          : // else:
                          g( // first recursive call:
                          -~x % m, // move to the right
                          y, // leave y unchanged
                          g[x] = 1 // mark the current cell as visited by setting the flag g[x]
                          ) + // add the result of
                          g( // a second recursive call:
                          x % m, // restore x in [0...m-1]
                          -~y % n // move up
                          ) + //
                          --g[x] // clear the flag on the current cell
                          )(0, 0) // initial call to g with (x, y) = (0, 0)





                          share|improve this answer











                          $endgroup$



                          JavaScript (ES6), 67 bytes



                          This shorter version is derived from a Python 3.8 alternate version found by @xnor. However, this works only for $mtimes n<32$ in JS.



                          Takes input as (m)(n).





                          m=>n=>(g=(k,l)=>l>>k&1?!k:g((k+m)%(m*n),l|=1<<k)+g(k-~k%m-k%m,l))``


                          Try it online!



                          To have it work for any input, we could use BigInts for 73 bytes:



                          m=>n=>(g=(k,l=k)=>l&(b=1n<<k)?!k:g((k+m)%(m*n),l|=b)+g(k-~k%m-k%m,l))(0n)


                          Try it online!




                          JavaScript (ES6),  76 73  72 bytes



                          Takes input as (m)(n).





                          m=>n=>(g=(x,y)=>g[x+=y*m]?!x:g(-~x%m,y,g[x]=1)+g(x%m,-~y%n)+--g[x])(0,0)


                          Try it online!



                          Commented



                          m => n => ( // m = width; n = height
                          g = ( // g is a recursive function taking:
                          x, y // the current coordinates (x, y) on the torus
                          ) => //
                          g[ // the surrounding object of g is also used for storage
                          x += y * m // turn x into a key for the current coordinates
                          ] ? // if this cell was already visited:
                          !x // return 1 if we're back to (0, 0), or 0 otherwise
                          : // else:
                          g( // first recursive call:
                          -~x % m, // move to the right
                          y, // leave y unchanged
                          g[x] = 1 // mark the current cell as visited by setting the flag g[x]
                          ) + // add the result of
                          g( // a second recursive call:
                          x % m, // restore x in [0...m-1]
                          -~y % n // move up
                          ) + //
                          --g[x] // clear the flag on the current cell
                          )(0, 0) // initial call to g with (x, y) = (0, 0)






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Mar 9 at 12:55

























                          answered Mar 9 at 8:23









                          ArnauldArnauld

                          82.1k798337




                          82.1k798337





















                              3












                              $begingroup$

                              Haskell, 88 80 bytes



                              n#m|let(x!y)a|elem(x,y)a=0^(x+y)|b<-(x,y):a=(mod(x+1)n!y)b+(x!mod(y+1)m)b=0!0$[]


                              Try it online!



                              Simple brute force: try all up/right combinations, dropping those which intersect (we keep all positions we've visited in list a) and counting those which eventually hit positition (0,0) again.



                              The base case of the recursion is when we visit a position a second time (elem(x,y)a). The result is 0^0 = 1 when the position is (0,0) and counts towards the numbers of loops or 0 (0^x, with x non-zero) otherwise and doesn't increase the number of loops.



                              Edit: -8 bytes thanks to @xnor.






                              share|improve this answer











                              $endgroup$








                              • 1




                                $begingroup$
                                The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
                                $endgroup$
                                – xnor
                                Mar 9 at 17:56















                              3












                              $begingroup$

                              Haskell, 88 80 bytes



                              n#m|let(x!y)a|elem(x,y)a=0^(x+y)|b<-(x,y):a=(mod(x+1)n!y)b+(x!mod(y+1)m)b=0!0$[]


                              Try it online!



                              Simple brute force: try all up/right combinations, dropping those which intersect (we keep all positions we've visited in list a) and counting those which eventually hit positition (0,0) again.



                              The base case of the recursion is when we visit a position a second time (elem(x,y)a). The result is 0^0 = 1 when the position is (0,0) and counts towards the numbers of loops or 0 (0^x, with x non-zero) otherwise and doesn't increase the number of loops.



                              Edit: -8 bytes thanks to @xnor.






                              share|improve this answer











                              $endgroup$








                              • 1




                                $begingroup$
                                The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
                                $endgroup$
                                – xnor
                                Mar 9 at 17:56













                              3












                              3








                              3





                              $begingroup$

                              Haskell, 88 80 bytes



                              n#m|let(x!y)a|elem(x,y)a=0^(x+y)|b<-(x,y):a=(mod(x+1)n!y)b+(x!mod(y+1)m)b=0!0$[]


                              Try it online!



                              Simple brute force: try all up/right combinations, dropping those which intersect (we keep all positions we've visited in list a) and counting those which eventually hit positition (0,0) again.



                              The base case of the recursion is when we visit a position a second time (elem(x,y)a). The result is 0^0 = 1 when the position is (0,0) and counts towards the numbers of loops or 0 (0^x, with x non-zero) otherwise and doesn't increase the number of loops.



                              Edit: -8 bytes thanks to @xnor.






                              share|improve this answer











                              $endgroup$



                              Haskell, 88 80 bytes



                              n#m|let(x!y)a|elem(x,y)a=0^(x+y)|b<-(x,y):a=(mod(x+1)n!y)b+(x!mod(y+1)m)b=0!0$[]


                              Try it online!



                              Simple brute force: try all up/right combinations, dropping those which intersect (we keep all positions we've visited in list a) and counting those which eventually hit positition (0,0) again.



                              The base case of the recursion is when we visit a position a second time (elem(x,y)a). The result is 0^0 = 1 when the position is (0,0) and counts towards the numbers of loops or 0 (0^x, with x non-zero) otherwise and doesn't increase the number of loops.



                              Edit: -8 bytes thanks to @xnor.







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Mar 9 at 23:18

























                              answered Mar 9 at 11:42









                              niminimi

                              32.9k32490




                              32.9k32490







                              • 1




                                $begingroup$
                                The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
                                $endgroup$
                                – xnor
                                Mar 9 at 17:56












                              • 1




                                $begingroup$
                                The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
                                $endgroup$
                                – xnor
                                Mar 9 at 17:56







                              1




                              1




                              $begingroup$
                              The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
                              $endgroup$
                              – xnor
                              Mar 9 at 17:56




                              $begingroup$
                              The base cases can be combined into |elem(x,y)a=0^(x+y), and (0!0)[] can be 0!0$[].
                              $endgroup$
                              – xnor
                              Mar 9 at 17:56











                              2












                              $begingroup$


                              Jelly, 44 bytes



                              ×ƝṪ2*Ḥ_2Rḃ€2ċⱮؽ%³¬ẠƲƇịØ.Ṛ,Ø.¤ZÄZ%€ʋ€³ŒQẠ$€S


                              Try it online!



                              Works for 4,4, but has complexity $O(2^m^n)$ so won’t scale that well.



                              This works by finding all possible routes of up to $mn$ length, filtering out those that don’t end at 0,0, and then excluding those that pass the same point twice.






                              share|improve this answer









                              $endgroup$

















                                2












                                $begingroup$


                                Jelly, 44 bytes



                                ×ƝṪ2*Ḥ_2Rḃ€2ċⱮؽ%³¬ẠƲƇịØ.Ṛ,Ø.¤ZÄZ%€ʋ€³ŒQẠ$€S


                                Try it online!



                                Works for 4,4, but has complexity $O(2^m^n)$ so won’t scale that well.



                                This works by finding all possible routes of up to $mn$ length, filtering out those that don’t end at 0,0, and then excluding those that pass the same point twice.






                                share|improve this answer









                                $endgroup$















                                  2












                                  2








                                  2





                                  $begingroup$


                                  Jelly, 44 bytes



                                  ×ƝṪ2*Ḥ_2Rḃ€2ċⱮؽ%³¬ẠƲƇịØ.Ṛ,Ø.¤ZÄZ%€ʋ€³ŒQẠ$€S


                                  Try it online!



                                  Works for 4,4, but has complexity $O(2^m^n)$ so won’t scale that well.



                                  This works by finding all possible routes of up to $mn$ length, filtering out those that don’t end at 0,0, and then excluding those that pass the same point twice.






                                  share|improve this answer









                                  $endgroup$




                                  Jelly, 44 bytes



                                  ×ƝṪ2*Ḥ_2Rḃ€2ċⱮؽ%³¬ẠƲƇịØ.Ṛ,Ø.¤ZÄZ%€ʋ€³ŒQẠ$€S


                                  Try it online!



                                  Works for 4,4, but has complexity $O(2^m^n)$ so won’t scale that well.



                                  This works by finding all possible routes of up to $mn$ length, filtering out those that don’t end at 0,0, and then excluding those that pass the same point twice.







                                  share|improve this answer












                                  share|improve this answer



                                  share|improve this answer










                                  answered Mar 9 at 23:12









                                  Nick KennedyNick Kennedy

                                  1,89149




                                  1,89149





















                                      1












                                      $begingroup$

                                      Java 8, 120 bytes





                                      n->m->g(n,m,0,0);int g(int n,int m,int k,int l)=1<<k)+g(n,m,k-~k%m-k%m,l);


                                      Port of @Arnauld's JavaScript answer, and also only works for inputs where $n*m<32$.



                                      Try it online.






                                      share|improve this answer









                                      $endgroup$

















                                        1












                                        $begingroup$

                                        Java 8, 120 bytes





                                        n->m->g(n,m,0,0);int g(int n,int m,int k,int l)=1<<k)+g(n,m,k-~k%m-k%m,l);


                                        Port of @Arnauld's JavaScript answer, and also only works for inputs where $n*m<32$.



                                        Try it online.






                                        share|improve this answer









                                        $endgroup$















                                          1












                                          1








                                          1





                                          $begingroup$

                                          Java 8, 120 bytes





                                          n->m->g(n,m,0,0);int g(int n,int m,int k,int l)=1<<k)+g(n,m,k-~k%m-k%m,l);


                                          Port of @Arnauld's JavaScript answer, and also only works for inputs where $n*m<32$.



                                          Try it online.






                                          share|improve this answer









                                          $endgroup$



                                          Java 8, 120 bytes





                                          n->m->g(n,m,0,0);int g(int n,int m,int k,int l)=1<<k)+g(n,m,k-~k%m-k%m,l);


                                          Port of @Arnauld's JavaScript answer, and also only works for inputs where $n*m<32$.



                                          Try it online.







                                          share|improve this answer












                                          share|improve this answer



                                          share|improve this answer










                                          answered Mar 11 at 15:26









                                          Kevin CruijssenKevin Cruijssen

                                          43.5k573222




                                          43.5k573222





















                                              1












                                              $begingroup$

                                              CJam (50 chars)



                                              q~]:M:!a9Yb2/f_W=@.+M.%a+_)a#g"WAR"=~:R~e_We=


                                              Online demo. This is a program which takes two inputs from stdin.



                                              Finally we have an answer to the question




                                              War, huh, what is it good for?





                                              Dissection



                                              q~]:M e# Parse input, collect in array, store in M (for moduli)
                                              :!a e# Zero and wrap in array for starting position (0, 0)
                                              e# Define recursive block R
                                              9Yb2/ e# Push [[1 0][0 1]], an array of movements
                                              f e# For each of those movements, with the current path,
                                              _W=@.+ e# Add the movement to the last position in the path
                                              M.% e# Apply the wrapping
                                              a+ e# Add to one copy of the path
                                              _)a# e# And find its index in another copy
                                              g"WAR"=~ e# Switch on the sign of the index:
                                              e# If the sign is -1, position not found, make a recursive call
                                              e# If the sign is 0, found at start, push -1 to the stack
                                              e# If the sign is 1, we have a self-intersection. We push 10 to
                                              e# the stack for no other reason than to make the bad joke above

                                              :R
                                              ~ e# Execute R
                                              e_We= e# Count the -1s which we pushed as sentinels





                                              share|improve this answer









                                              $endgroup$

















                                                1












                                                $begingroup$

                                                CJam (50 chars)



                                                q~]:M:!a9Yb2/f_W=@.+M.%a+_)a#g"WAR"=~:R~e_We=


                                                Online demo. This is a program which takes two inputs from stdin.



                                                Finally we have an answer to the question




                                                War, huh, what is it good for?





                                                Dissection



                                                q~]:M e# Parse input, collect in array, store in M (for moduli)
                                                :!a e# Zero and wrap in array for starting position (0, 0)
                                                e# Define recursive block R
                                                9Yb2/ e# Push [[1 0][0 1]], an array of movements
                                                f e# For each of those movements, with the current path,
                                                _W=@.+ e# Add the movement to the last position in the path
                                                M.% e# Apply the wrapping
                                                a+ e# Add to one copy of the path
                                                _)a# e# And find its index in another copy
                                                g"WAR"=~ e# Switch on the sign of the index:
                                                e# If the sign is -1, position not found, make a recursive call
                                                e# If the sign is 0, found at start, push -1 to the stack
                                                e# If the sign is 1, we have a self-intersection. We push 10 to
                                                e# the stack for no other reason than to make the bad joke above

                                                :R
                                                ~ e# Execute R
                                                e_We= e# Count the -1s which we pushed as sentinels





                                                share|improve this answer









                                                $endgroup$















                                                  1












                                                  1








                                                  1





                                                  $begingroup$

                                                  CJam (50 chars)



                                                  q~]:M:!a9Yb2/f_W=@.+M.%a+_)a#g"WAR"=~:R~e_We=


                                                  Online demo. This is a program which takes two inputs from stdin.



                                                  Finally we have an answer to the question




                                                  War, huh, what is it good for?





                                                  Dissection



                                                  q~]:M e# Parse input, collect in array, store in M (for moduli)
                                                  :!a e# Zero and wrap in array for starting position (0, 0)
                                                  e# Define recursive block R
                                                  9Yb2/ e# Push [[1 0][0 1]], an array of movements
                                                  f e# For each of those movements, with the current path,
                                                  _W=@.+ e# Add the movement to the last position in the path
                                                  M.% e# Apply the wrapping
                                                  a+ e# Add to one copy of the path
                                                  _)a# e# And find its index in another copy
                                                  g"WAR"=~ e# Switch on the sign of the index:
                                                  e# If the sign is -1, position not found, make a recursive call
                                                  e# If the sign is 0, found at start, push -1 to the stack
                                                  e# If the sign is 1, we have a self-intersection. We push 10 to
                                                  e# the stack for no other reason than to make the bad joke above

                                                  :R
                                                  ~ e# Execute R
                                                  e_We= e# Count the -1s which we pushed as sentinels





                                                  share|improve this answer









                                                  $endgroup$



                                                  CJam (50 chars)



                                                  q~]:M:!a9Yb2/f_W=@.+M.%a+_)a#g"WAR"=~:R~e_We=


                                                  Online demo. This is a program which takes two inputs from stdin.



                                                  Finally we have an answer to the question




                                                  War, huh, what is it good for?





                                                  Dissection



                                                  q~]:M e# Parse input, collect in array, store in M (for moduli)
                                                  :!a e# Zero and wrap in array for starting position (0, 0)
                                                  e# Define recursive block R
                                                  9Yb2/ e# Push [[1 0][0 1]], an array of movements
                                                  f e# For each of those movements, with the current path,
                                                  _W=@.+ e# Add the movement to the last position in the path
                                                  M.% e# Apply the wrapping
                                                  a+ e# Add to one copy of the path
                                                  _)a# e# And find its index in another copy
                                                  g"WAR"=~ e# Switch on the sign of the index:
                                                  e# If the sign is -1, position not found, make a recursive call
                                                  e# If the sign is 0, found at start, push -1 to the stack
                                                  e# If the sign is 1, we have a self-intersection. We push 10 to
                                                  e# the stack for no other reason than to make the bad joke above

                                                  :R
                                                  ~ e# Execute R
                                                  e_We= e# Count the -1s which we pushed as sentinels






                                                  share|improve this answer












                                                  share|improve this answer



                                                  share|improve this answer










                                                  answered Mar 12 at 14:39









                                                  Peter TaylorPeter Taylor

                                                  40.3k456144




                                                  40.3k456144





















                                                      1












                                                      $begingroup$


                                                      Jelly, 54 39 bytes



                                                      ḣ2æ.2ị³¤+4
                                                      ‘Ç;¥¦%³Ç=4ƊÑÇị$?
                                                      çⱮؽS
                                                      ’Ñ0xÇ


                                                      Try it online!



                                                      I’ve posted this as a separate answer to my other Jelly one because it’s a completely different method. This is closer in principle to @Arnauld’s answer. It uses a recursive function that works through every possible path until it reaches a point it’s already got to, and then returns the result of a check whether it’s back to the start. I suspect a few more bytes could be shaved off. Now changed to using slice operator. It works well for up to 5x5. The recursion depth should be at most m x n.






                                                      share|improve this answer











                                                      $endgroup$

















                                                        1












                                                        $begingroup$


                                                        Jelly, 54 39 bytes



                                                        ḣ2æ.2ị³¤+4
                                                        ‘Ç;¥¦%³Ç=4ƊÑÇị$?
                                                        çⱮؽS
                                                        ’Ñ0xÇ


                                                        Try it online!



                                                        I’ve posted this as a separate answer to my other Jelly one because it’s a completely different method. This is closer in principle to @Arnauld’s answer. It uses a recursive function that works through every possible path until it reaches a point it’s already got to, and then returns the result of a check whether it’s back to the start. I suspect a few more bytes could be shaved off. Now changed to using slice operator. It works well for up to 5x5. The recursion depth should be at most m x n.






                                                        share|improve this answer











                                                        $endgroup$















                                                          1












                                                          1








                                                          1





                                                          $begingroup$


                                                          Jelly, 54 39 bytes



                                                          ḣ2æ.2ị³¤+4
                                                          ‘Ç;¥¦%³Ç=4ƊÑÇị$?
                                                          çⱮؽS
                                                          ’Ñ0xÇ


                                                          Try it online!



                                                          I’ve posted this as a separate answer to my other Jelly one because it’s a completely different method. This is closer in principle to @Arnauld’s answer. It uses a recursive function that works through every possible path until it reaches a point it’s already got to, and then returns the result of a check whether it’s back to the start. I suspect a few more bytes could be shaved off. Now changed to using slice operator. It works well for up to 5x5. The recursion depth should be at most m x n.






                                                          share|improve this answer











                                                          $endgroup$




                                                          Jelly, 54 39 bytes



                                                          ḣ2æ.2ị³¤+4
                                                          ‘Ç;¥¦%³Ç=4ƊÑÇị$?
                                                          çⱮؽS
                                                          ’Ñ0xÇ


                                                          Try it online!



                                                          I’ve posted this as a separate answer to my other Jelly one because it’s a completely different method. This is closer in principle to @Arnauld’s answer. It uses a recursive function that works through every possible path until it reaches a point it’s already got to, and then returns the result of a check whether it’s back to the start. I suspect a few more bytes could be shaved off. Now changed to using slice operator. It works well for up to 5x5. The recursion depth should be at most m x n.







                                                          share|improve this answer














                                                          share|improve this answer



                                                          share|improve this answer








                                                          edited Mar 13 at 14:09

























                                                          answered Mar 12 at 8:45









                                                          Nick KennedyNick Kennedy

                                                          1,89149




                                                          1,89149



























                                                              draft saved

                                                              draft discarded
















































                                                              If this is an answer to a challenge…



                                                              • …Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.


                                                              • …Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
                                                                Explanations of your answer make it more interesting to read and are very much encouraged.


                                                              • …Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.


                                                              More generally…



                                                              • …Please make sure to answer the question and provide sufficient detail.


                                                              • …Avoid asking for help, clarification or responding to other answers (use comments instead).




                                                              draft saved


                                                              draft discarded














                                                              StackExchange.ready(
                                                              function ()
                                                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f181203%2fcycles-on-the-torus%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

                                                              Save data to MySQL database using ExtJS and PHP [closed]2019 Community Moderator ElectionHow can I prevent SQL injection in PHP?Which MySQL data type to use for storing boolean valuesPHP: Delete an element from an arrayHow do I connect to a MySQL Database in Python?Should I use the datetime or timestamp data type in MySQL?How to get a list of MySQL user accountsHow Do You Parse and Process HTML/XML in PHP?Reference — What does this symbol mean in PHP?How does PHP 'foreach' actually work?Why shouldn't I use mysql_* functions in PHP?

                                                              Compiling GNU Global with universal-ctags support Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!Tags for Emacs: Relationship between etags, ebrowse, cscope, GNU Global and exuberant ctagsVim and Ctags tips and trickscscope or ctags why choose one over the other?scons and ctagsctags cannot open option file “.ctags”Adding tag scopes in universal-ctagsShould I use Universal-ctags?Universal ctags on WindowsHow do I install GNU Global with universal ctags support using Homebrew?Universal ctags with emacsHow to highlight ctags generated by Universal Ctags in Vim?

                                                              Add ONERROR event to image from jsp tldHow to add an image to a JPanel?Saving image from PHP URLHTML img scalingCheck if an image is loaded (no errors) with jQueryHow to force an <img> to take up width, even if the image is not loadedHow do I populate hidden form field with a value set in Spring ControllerStyling Raw elements Generated from JSP tagds with Jquery MobileLimit resizing of images with explicitly set width and height attributeserror TLD use in a jsp fileJsp tld files cannot be resolved