งูนั่นกำลังจะไปไหน


35

เขียนฟังก์ชั่น (ใช้น้อยที่สุดเท่าที่เป็นไปได้ไบต์) ที่ใช้อาร์เรย์สองมิติของจำนวนคอลัมน์และแถวใด ๆ ที่:

  • 0 แสดงถึงบล็อกว่างเปล่า
  • 1 แสดงถึงบล็อกงู

ฟังก์ชั่นจะต้องคืนค่าจำนวนเส้นทางที่เป็นไปได้ที่งูเดินทางไป

ตัวอย่างที่ 1:

การป้อนข้อมูล:

[
  [1,1,1,1,1],
  [0,0,0,0,1],
  [0,0,0,0,1],
]

เอาท์พุท: 2

ในตัวอย่างด้านบนฟังก์ชันจะส่งคืน2เนื่องจากคำตอบเป็นอย่างใดอย่างหนึ่ง:

ป้อนคำอธิบายรูปภาพที่นี่

ตัวอย่างที่ 2:

การป้อนข้อมูล:

[
  [1,1,1,1],
  [0,0,1,1],
  [0,0,1,1],
]

เอาท์พุท: 6

ในตัวอย่างนี้ฟังก์ชั่นจะกลับมา6เพราะคำตอบเป็นหนึ่งใน:

ป้อนคำอธิบายรูปภาพที่นี่

บันทึก:

เมื่อประเมินอินพุตคุณสามารถสมมติได้ว่า:

  • อาร์เรย์ที่แสดงคอลัมน์จะมีขนาดเท่ากันเสมอ (ดังนั้นอาร์เรย์จึงเป็นรูปสี่เหลี่ยม)
  • มีเส้นทางที่ถูกต้องอย่างน้อย 1 เส้นทาง;
  • งูไม่สามารถเดินผ่านขอบ (เช่นอาจเกิดขึ้นในบางรุ่นของงู);
  • งูจะมีอย่างน้อย 2 ช่วงตึกเสมอ
  • งูไม่สามารถเคลื่อนที่ได้ในแนวทแยงมุม
  • เส้นทางถูกนำไป (ดังนั้นทั้งสองเส้นทางที่ลงท้ายด้วยตำแหน่งที่แตกต่างกัน แต่ไม่เช่นนั้นการค้นหาที่เหมือนกันไม่ใช่เส้นทางเดียวกันมันจะรวมกันทั้งหมด)

13
ยินดีต้อนรับสู่ PPCG! ความท้าทายแรกที่ดี
Laikoni

5
หมายเหตุเล็กน้อย: "จะมีอย่างน้อยหนึ่งแถวและหนึ่งคอลัมน์" ซ้ำซ้อนเนื่องจากงูจะมีบล็อกอย่างน้อย 2 บล็อกเสมอ
Stewie Griffin

2
แนะนำกรณีทดสอบหนึ่งที่ได้รับจาก @StewieGriffin [[0,0,1,1],[0,0,1,1],[0,0,1,1]]และ คำตอบส่วนใหญ่ให้ 16 แต่อย่างใดอย่างหนึ่งให้ 15
Kevin Cruijssen

2
ดูเหมือนว่าทุกคนจนถึงตอนนี้ (รวมถึงฉัน) ได้ตั้งสมมติฐานว่า 2 เส้นทางที่ลงท้ายด้วยตำแหน่งที่แตกต่างกัน แต่ไม่อย่างนั้นการมองที่เหมือนกันนั้นไม่ใช่เส้นทางเดียวกัน ฉันคิดว่าสิ่งนี้จะต้องระบุอย่างชัดเจน
Arnauld

2
@Annauld - ถูกต้อง เส้นทางสองเส้นทางที่ลงท้ายด้วยตำแหน่งที่แตกต่างกัน แต่หากมองอย่างเดียวกันนั้นไม่เหมือนเส้นทางเดียวกันมันจะรวมกันเป็นยอดรวม ในตัวอย่างของคุณผลรวมควรเป็น 16 ถ้าฉันไม่ผิด - ฉันไม่สามารถคำนวณได้อย่างถูกต้องตอนนี้ แต่คุณได้คะแนน
Adelin

คำตอบ:


11

ภาษา Wolfram (Mathematica) , 16 + 83 = 99 ไบต์

คำสั่งการนำเข้าไลบรารี (16 ไบต์):

<<Combinatorica`

ฟังก์ชันของฟังก์ชันจริง (83 ไบต์):

Length@HamiltonianCycle[MakeGraph[#~Position~1~Join~{1>0},##||Norm[#-#2]==1&],All]&

ลองออนไลน์!


โปรดทราบว่าคำถามนั้นถามจำนวนเส้นทางแฮมิลโตเนียนในกราฟ

อย่างไรก็ตาม (ด้วยเหตุผลบางอย่าง) HamiltonianPathฟังก์ชั่นนี้ใช้ไม่ได้กับกราฟกำกับ ( ตัวอย่าง ) ดังนั้นฉันใช้วิธีแก้ปัญหาที่อธิบายไว้ในคำถามMathematica.SE นี้ :

  • เพิ่มจุดสุดยอด (เรียกว่าTrue) ที่เชื่อมต่อกับจุดยอดอื่น ๆ ทั้งหมด
  • นับจำนวนรอบมิลโตเนียนในกราฟผลลัพธ์

กราฟถูกสร้างโดยใช้MakeGraph(รำคาญไม่มีเทียบเท่าโดยตรงในตัว) โดยใช้ฟังก์ชั่นบูล##||Norm[#-#2]==1&ซึ่งผลตอบแทนTrueและถ้าหากหนึ่งของการขัดแย้งเป็นหรือระยะห่างระหว่างสองจุดที่มีTrue1


Tr[1^x]ไม่สามารถนำมาใช้แทนLength@xและไม่สามารถนำมาใช้แทน<2==1


HamiltonianPathสามารถใช้งานได้หากกราฟไม่ได้ถูกบอกทิศทางโดยที่ฟังก์ชั่นนั้นใช้เวลา84ไบต์ (ตรงกับการส่งปัจจุบันมากกว่า 1 ไบต์):

Length@HamiltonianPath[MakeGraph[#~Position~1,Norm[#-#2]==1&,Type->Undirected],All]&

ลองออนไลน์!


10

JavaScript (ES6), 154 134 ไบต์

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>r&&r[x]&&[-1,0,1,2].map(d=>r[r[x]=0,/1/.test(m)?g(_,x+d%2,y+~-d%2):++n,x]=1)),n=0)|n/4

ลองออนไลน์!

อย่างไร?

วิธี

เริ่มต้นจากแต่ละเซลล์ที่เป็นไปได้เราเติมเมทริกซ์ให้เต็มโดยล้างเซลล์ทั้งหมดตามทางของเรา เมื่อไรก็ตามที่เมทริกซ์ไม่มี1เราจะเพิ่มจำนวนnของเส้นทางที่เป็นไปได้

แต่ละเส้นทางที่ถูกต้องจะถูกนับ 4 ครั้งเนื่องจากทิศทางที่เลือกในเซลล์สุดท้ายซึ่งไม่สำคัญ ดังนั้นผลสุดท้ายคือn / 4

ฟังก์ชั่นวนซ้ำ

แทนที่จะเรียกฟังก์ชั่นวนซ้ำ g ()จากการเรียกกลับของแผนที่ที่สอง()เช่นนี้ ...

m=>m.map((r,y)=>r.map((_,x)=>(g=(x,y,r=m[y])=>...g(x+dx,y+dy)...)(x,y)))

... เรากำหนดฟังก์ชันแบบเรียกซ้ำg () โดยตรงเป็น callback of map () :

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>...g(_,x+dx,y+dy)...))

แม้จะมีสูตรy=1/y?y:Yที่ค่อนข้างยาวซึ่งจำเป็นต้องมีเพื่อตั้งค่าเริ่มต้นของyแต่จะช่วยประหยัดทั้ง 2 ไบต์โดยรวม

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

m =>                           // given the input matrix m[][]
  m.map((r, Y) =>              // for each row r[] at position Y in m[][]:
    r.map(g = (                //   for each entry in r[], use g() taking:
      _,                       //     - the value of the cell (ignored)
      x,                       //     - the x coord. of this cell
      y,                       //     - either the y coord. or an array (1st iteration),
                               //       in which case we'll set y to Y instead
      r = m[y = 1 / y ? y : Y] //     - r = the row we're currently located in
    ) =>                       //       (and update y if necessary)
      r && r[x] &&             //     do nothing if this cell doesn't exist or is 0
      [-1, 0, 1, 2].map(d =>   //     otherwise, for each direction d,
        r[                     //     with -1 = West, 0 = North, 1 = East, 2 = South:
          r[x] = 0,            //       clear the current cell
          /1/.test(m) ?        //       if the matrix still contains at least one '1':
            g(                 //         do a recursive call to g() with:
              _,               //           a dummy first parameter (ignored)
              x + d % 2,       //           the new value of x
              y + ~-d % 2      //           the new value of y
            )                  //         end of recursive call
          :                    //       else (we've found a valid path):
            ++n,               //         increment n
          x                    //       \_ either way,
        ] = 1                  //       /  do r[x] = 1 to restore the current cell to 1
      )                        //     end of map() over directions
    ),                         //   end of map() over the cells of the current row
    n = 0                      //   start with n = 0
  ) | n / 4                    // end of map() over the rows; return n / 4

10

เจลลี่ , 12 11 ไบต์

ŒṪŒ!ạƝ€§ÐṂL

ลองออนไลน์!


คำอธิบาย

ŒṪ               Positions of snake blocks.
  Œ!             All permutations.
                 For each permutation:
    ạƝ€             Calculate the absolute difference for each neighbor pair
       §            Vectorized sum.
                 Now we have a list of Manhattan distance between snake
                    blocks. Each one is at least 1.
        ÐṂL      Count the number of minimum values.
                    Because it's guaranteed that there exists a valid snake,
                    the minimum value is [1,1,1,...,1].

คุณสมบัติใหม่พิสูจน์แล้วว่ามีประโยชน์อย่างยิ่ง
user202729

แล้ว§ỊMLแทนที่จะ§ỊP€Sบันทึกเป็นไบต์ฉันคิดว่าควรใช้งานได้หรือไม่
Jonathan Allan

... หรือ§ÐṂLเร็วกว่านิดหน่อย
Jonathan Allan

@JonathanAllan ใช้งานได้เฉพาะในกรณีที่ผลลัพธ์ไม่ใช่ศูนย์
user202729

@JanathanAllan ดังนั้นมันจึงใช้งานได้จริง
user202729

8

Python 2 , 257 246 241 234 233 227 214 210 ไบต์

lambda b:sum(g(b,i,j)for j,l in e(b)for i,_ in e(l))
e=enumerate
def g(b,x,y):d=len(b[0])>x>-1<y<len(b);c=eval(`b`);c[d*y][d*x]=0;return d and b[y][x]and('1'not in`c`or sum(g(c,x+a,y)+g(c,x,y+a)for a in(1,-1)))

ลองออนไลน์!


ที่บันทึกไว้

  • -8 ไบต์ขอบคุณ Kevin Cruijssen
  • -14 ไบต์ขอบคุณ user202729


1
ภาษาที่เหมาะสมกับงานหรือไม่
Neil


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