Torustaki döngüler


20

Meydan okuma

Bu zorluk iki tamsayılar alır bir program yazmak zorunda kalacak nve mve numara kesişmeyen döngüler verir ntarafından mbaşlayarak yapılan torus (0,0)ve sadece adımlar kaplıyor ve sağa. Torusu hem üstte hem de altta ve yanlarda sarımlı ızgara olarak düşünebilirsiniz .

Bu kadar az bayt kazanır.

Misal

Örneğin, giriş, n=m=5geçerli bir yürüyüş

(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)

şekilde gösterildiği gibi.

Torusta bir döngü.

Bazı örnek giriş / çıkışlar

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

1
Bu dizinin en az için OEIS'de olduğuna bahse girmeye istekliydim , ama görünüşe göre değil (henüz). m=n
Arnauld

Bence bir torusun sağ-sol bir sarmalaması var. Onun yerine sadece yukarı-aşağı sarmalama olduğunu varsaymalı mıyız? Örnek görüntü böyle ima etmiyor.
Outgolfer Erik

@EriktheOutgolfer Resimde sağdan sola dolanan turuncu yol gösteriliyor değil mi?
Arnauld

@ Arnauld Evet, ancak mücadelenin açıklamasıyla tutarlı görünmüyor ("
Torus'u

@EriktheOutgolfer Bu doğru. Ve şimdi bahsettiğinize göre, mavi yol yanlış. Önce sağdan sola ve sonra yukarıdan aşağıya doğru sarılmalıdır.
Arnauld

Yanıtlar:


4

Jöle , 28 bayt

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

Sayıyı veren bir liste kabul eden monadik bir Bağlantı [m,n].

TIO-jt1qe1v9 ... çok az nokta olmasına rağmen, çok verimsiz.
([2,3]Yerel olarak 16GB ram ile çalışamıyorum)!

Nasıl?

Kaba kuvvet - döşenmiş bir versiyonun koordinatlarını yeterince büyük oluşturur, ardından bu noktaların güç setini komşuların tek bir yönde artan bir yolla filtreler, daha sonra minimum bir koordinatta (yani başlangıç ​​noktası) başlayanlara filtre uygular ve, aynı zamanda, bu başlangıç ​​koordinatını her birinden kaldırır. Daha sonra bir torusa geri sarmak için modulo aritmetiği kullanır ve yinelenen koordinatları içeren (yani kesişme içerenleri) filtreler ve son olarak, minimum bitiş koordinatlarına (yani başlangıç ​​noktasında sonlanan) filtreler ve sonucun uzunluğunu verir.

ạƝ§=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

12

Python 2 , 87 bayt

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))

Çevrimiçi deneyin!

Buradaki ilginç şey z, mevcut konumun koordinatını saklamak için karmaşık bir sayı kullanmaktır . Ekleyerek yukarı hareket edebilir 1ve ekleyerek sağa hareket edebiliriz 1j. Şaşırtıcı bir şekilde, modulo, karmaşık sayılar üzerinde, her bir boyutun sargısını ayrı ayrı ele almamızı sağlayacak şekilde çalışır: %mgerçek parça %(n*1j)üzerinde hareket eder ve hayali parça üzerinde hareket eder.


Güzel yapılmış. FWIW, karmaşık bir sayı kullanmadan en iyi girişimim Python 3.8'de 91 bayt .
Arnauld

@Arnauld ile ilginç bir fikir k:=x+y*m. Beni kullanmak yerine kdoğrudan kullanmanın daha kısa olup olmayacağını merak ediyor . Çok kötü Python 3 karmaşık modüllere izin vermiyor. (x,y)x+y*mx+y*1j
xnor


Bu yaklaşım JS'ye 5 bayt kazandırır. :)
Arnauld

7

JavaScript (ES6), 67 bayt

Bu kısa versiyon, @xnor tarafından bulunan Python 3.8 alternatif versiyonundan türetilmiştir . Ancak, bu yalnızca JS'de için çalışır .m×n<32

Girişi alır (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))``

Çevrimiçi deneyin!

Herhangi bir girdi için çalışmasını sağlamak için 73 bayt için BigInts'i kullanabiliriz :

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)

Çevrimiçi deneyin!


JavaScript (ES6),  76 73  72 bayt

Girişi alır (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)

Çevrimiçi deneyin!

Yorumlananlar

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)

3

Haskell, 88 80 bayt

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$[]

Çevrimiçi deneyin!

Basit kaba kuvvet: kesişenleri (listede ziyaret ettiğimiz tüm pozisyonları atutarız) bırakarak ve sonunda (0,0)tekrar pozitife vuranları sayarak tüm yukarı / sağ kombinasyonlarını deneyin .

Özyinelemenin temel durumu, bir konumu ikinci kez ziyaret ettiğimiz zamandır ( elem(x,y)a). Sonucudur 0^0= 1konumunda olduğunda (0,0)ve döngüler veya sayıları yönelik sayımları 0( 0^xile xsıfır olmayan) olarak ve döngülerin sayısını arttırmaz.

Düzenleme: @xnor sayesinde -8 bayt.


1
Temel durumlar birleştirilebilir |elem(x,y)a=0^(x+y)ve (0!0)[]olabilir 0!0$[].
xnor

2

Jöle , 44 bayt

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

Çevrimiçi deneyin!

4,4 için çalışır, ancak karmaşıklığına sahiptir, bu yüzden o kadar iyi ölçeklenmez.O(2mn)

Bu, uzunluğuna kadar tüm olası yolları bularak , 0,0 ile bitmeyenleri filtreleyerek ve daha sonra aynı noktayı iki kez geçenler hariç tutarak çalışır.mn



1

CJam (50 karakter)

q~]:M:!a{9Yb2/\f{_W=@.+M.%a+_)a#g"WAR"=~}}:R~e_We=

Çevrimiçi demo . Bu, stdin'den iki girdi alan bir programdır.

Sonunda soruya bir cevabımız var

Savaş, ha, ne işe yarar?


teşrih

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

1

Jöle , 54 39 bayt

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

Çevrimiçi deneyin!

Bunu diğer Jelly'ime ayrı bir cevap olarak gönderdim çünkü tamamen farklı bir yöntem. Bu prensipte @ Arnauld'un cevabına daha yakın. Zaten ulaştığı bir noktaya ulaşıncaya kadar mümkün olan her yol boyunca çalışan özyinelemeli bir işlev kullanır ve ardından denetimin sonucunu başlangıca geri dönüp dönmediğini döndürür. Birkaç baytın tıraş olabileceğinden şüpheleniyorum. Şimdi dilim işleci olarak değiştirildi. 5x5'e kadar iyi çalışır. Özyineleme derinliği en fazla mx n olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.