รอบบนพรู


20

ท้าทาย

ความท้าทายนี้จะมีคุณเขียนโปรแกรมที่จะใช้เวลาในสองจำนวนเต็มnและmและผลจำนวนไม่ใช่ตัดลูปบนnโดยmพรูทำโดยเริ่มต้นที่(0,0)และมีเพียงทำตามขั้นตอนขึ้นและไปทางขวา คุณสามารถนึกถึงพรูเป็นกริดที่มีการพันรอบทั้งที่ด้านบนและด้านล่างและด้านข้าง

นี่คือจำนวนน้อยที่สุดที่จะชนะ

ตัวอย่าง

ตัวอย่างเช่นถ้าอินพุตคือn=m=5หนึ่งเดินที่ถูกต้องคือ

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

ตามที่แสดงในกราฟิก

วนรอบพรู

ตัวอย่างบางส่วนของอินพุต / เอาต์พุต

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
m=n

ฉันคิดว่าพรูก็มีฉากกั้นด้านซ้ายด้วย เราควรสมมติว่ามันมีเพียงแค่การขึ้น - ลงเท่านั้น ภาพตัวอย่างดูเหมือนจะไม่ได้บอกเป็นนัย
Erik the Outgolfer

@EriktheOutgolfer ภาพจะแสดงเส้นทางสีส้มล้อมรอบจากขวาไปซ้ายใช่ไหม
Arnauld

@Annauld ใช่ แต่มันดูไม่สอดคล้องกับคำอธิบายของความท้าทาย ("คุณสามารถนึกถึงทอรัสเป็นกริดที่มีทั้งสองที่ด้านบนและด้านล่าง")
Erik the Outgolfer

@EriktheOutgolfer นั่นเป็นเรื่องจริง และตอนนี้คุณพูดถึงมันแล้วเส้นทางสีน้ำเงินผิด มันควรเริ่มต้นจากด้านขวาไปซ้ายและจากบนลงล่าง
Arnauld

คำตอบ:


4

เยลลี่ขนาด 28 ไบต์

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

ลิงค์แบบ monadic ยอมรับรายการ[m,n]ซึ่งให้ผลการนับ

TIO-jt1qe1v9 ... แม้ว่าจะมีจุดเล็ก ๆ แต่ก็ไม่มีประสิทธิภาพเกินไป
(ฉันไม่สามารถเรียกใช้งาน[2,3]ในพื้นที่ด้วย RAM 16GB)

อย่างไร?

แรงเดรัจฉาน - สร้างพิกัดของกระเบื้องที่มีขนาดใหญ่พอที่จะกรองชุดพลังของจุดเหล่านี้ไปยังเส้นทางเหล่านั้นกับเพื่อนบ้านเพียงเพิ่มขึ้นทีละหนึ่งในทิศทางเดียวจากนั้นกรองไปยังจุดเริ่มต้นที่พิกัดน้อยที่สุด (เช่นแหล่งกำเนิด) และ ในเวลาเดียวกันให้ลบพิกัดเริ่มต้นนี้ออกจากกัน จากนั้นใช้เลขคณิตแบบโมดูโลเพื่อตัดกลับไปที่พรูและกรองพิกัดที่ซ้ำกันใด ๆ (เช่นที่มีจุดตัด) และในที่สุดกรองตัวกรองที่มีพิกัดสิ้นสุดน้อยที่สุด (เช่นสิ้นสุดที่จุดกำเนิด) และให้ความยาวของผลลัพธ์

ạƝ§=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 ไบต์

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

ลองออนไลน์!

สิ่งที่น่าสนใจที่นี่คือการใช้จำนวนเชิงซ้อนzเพื่อจัดเก็บพิกัดของตำแหน่งปัจจุบัน เราสามารถเลื่อนขึ้นโดยการเพิ่มและการย้ายไปทางขวาโดยการเพิ่ม1 1jด้วยความประหลาดใจของฉันโมดูโล่ทำงานกับตัวเลขที่ซับซ้อนในแบบที่ช่วยให้เราจัดการการห่อสำหรับแต่ละมิติแยกจากกัน: การ%mกระทำในส่วนจริงและ%(n*1j)กระทำในส่วนจินตภาพ


ทำได้ดีมาก FWIW ความพยายามอย่างดีที่สุดโดยไม่ใช้ตัวเลขที่ซับซ้อนคือ91 ไบต์ใน Python 3.8
Arnauld

ความคิดที่น่าสนใจ @Arnauld k:=x+y*mกับ มันทำให้ฉันสงสัยว่ามันจะสั้นกว่าที่จะใช้kโดยตรงเพื่อ(x,y)ใช้มากกว่าx+y*m x+y*1jแย่มาก Python 3 ไม่อนุญาตโมดูลัสที่ซับซ้อน
xnor


วิธีนี้ช่วยประหยัด 5 ไบต์ใน JS :)
Arnauld

7

JavaScript (ES6), 67 ไบต์

m×n<32ใน JS เท่านั้น

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

ลองออนไลน์!

หากต้องการให้มันทำงานกับอินพุตใด ๆ เราสามารถใช้ BigInts เป็น73 ไบต์ :

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)

ลองออนไลน์!


JavaScript (ES6),  76 73  72 ไบต์

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

ลองออนไลน์!

แสดงความคิดเห็น

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 ไบต์

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

ลองออนไลน์!

แรงเดรัจฉานง่าย ๆ : ลองชุดค่าผสมทั้งหมดขึ้น / ลงวางชุดที่ตัดกัน (เรารักษาทุกตำแหน่งที่เราเคยเข้าชมในรายการa) และนับจำนวนที่เข้ากันได้ในที่สุด(0,0)กลับมาอีกครั้ง

กรณีพื้นฐานของการเรียกซ้ำคือเมื่อเราเข้าชมตำแหน่งครั้งที่สอง ( elem(x,y)a) ผลลัพธ์คือ0^0= 1เมื่อตำแหน่งเป็น(0,0)และนับรวมกับจำนวนของลูปหรือ0( 0^xซึ่งxไม่ใช่ศูนย์) เป็นอย่างอื่นและจะไม่เพิ่มจำนวนของลูป

แก้ไข: -8 ไบต์ขอบคุณ @xnor


1
กรณีฐานสามารถรวมกันเป็น|elem(x,y)a=0^(x+y)และสามารถ(0!0)[] 0!0$[]
xnor



1

CJam (50 ตัวอักษร)

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

สาธิตออนไลน์ นี่คือโปรแกรมที่รับสองอินพุตจาก stdin

ในที่สุดเราก็มีคำตอบสำหรับคำถาม

สงครามใช่มั้ยมันดีอะไรเหรอ?


การผ่า

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

เยลลี่ , 54 39 ไบต์

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

ลองออนไลน์!

ฉันโพสต์สิ่งนี้เป็นคำตอบที่แยกจาก Jelly หนึ่งตัวอื่นเพราะเป็นวิธีที่แตกต่างอย่างสิ้นเชิง นี่เป็นหลักการที่ใกล้เคียงกับคำตอบของ @ Arnauld มันใช้ฟังก์ชั่นวนซ้ำที่ทำงานผ่านทุกเส้นทางที่เป็นไปได้จนกว่าจะถึงจุดที่มันได้ไปถึงแล้วส่งกลับผลลัพธ์ของการตรวจสอบว่ามันกลับไปที่จุดเริ่มต้นหรือไม่ ฉันสงสัยว่าอีกไม่กี่ไบต์จะถูกกำจัด ตอนนี้เปลี่ยนเป็นใช้โอเปอเรเตอร์สไลซ์ มันทำงานได้ดีมากถึง 5x5 ความลึกการวนซ้ำควรอยู่ที่สูงสุด mx n

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.