อิฐที่ไม่ซ้ำกันเอียงภายในสี่เหลี่ยมผืนผ้า


13

ฉันกำลังดู Stackoverflow และเห็นคำถามนี้เกี่ยวกับการเรียงสี่เหลี่ยม MxN และฉันคิดว่ามันจะดีสำหรับการเล่นกอล์ฟ นี่คือภารกิจ

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

  1. ไพ่ทั้งหมดเป็น 2x1 หรือ 3x1
  2. ไทล์ทั้งหมดอยู่ในแถวของพวกเขา (เช่นพวกเขาเป็นแนวนอนทั้งหมด)
  3. ไม่ควรจัดแนวระหว่างแผ่นกระเบื้องแถวสองแถวที่ติดกันยกเว้นปลายทั้งสองด้าน
  4. รับประกัน M และ N อย่างน้อย 1

ตัวอย่างเช่นการปูกระเบื้องที่ถูกต้องของเมทริกซ์ 8x3 จะเป็น

  2    3     3
  |    |     |
  v    v     v
 _______________
|___|_____|_____| 
|_____|_____|___|
|___|_____|_____|

แต่ต่อไปนี้จะไม่ถูกต้องเนื่องจากแถวเรียงกัน

  2    3     3
  |    |     |
  v    v     v
 _______________
|___|_____|_____| 
|_____|___|_____|
|_____|_____|___|

กรณีทดสอบ:

8x3: 4

3x1: 1

1x1: 0

9x4: 10

รหัสกอล์ฟคำตอบที่สั้นที่สุดจึงชนะ


2
คำอธิบายขนาดของแผ่นกระเบื้องของคุณดูเหมือนว่าจะใช้แบบแผนที่แตกต่างจากขนาดของสี่เหลี่ยมผืนผ้า กระเบื้องจริง2x1หรือ3x1? เอาท์พุท4x1เป็นศูนย์หรือไม่
FryAmTheEggman

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

@FryAmTheEggman ดูเหมือนว่า OP ได้พยายามที่จะ|ไม่สนับสนุนความยาวของแถวโดยใช้การแสดงเช่นนี้ (โดยที่หากไม่มีท่อ ( |) จะมีช่องว่าง)
Erik the Outgolfer


1
คำถามที่อ้างอิงใน SO นั้นไม่มีอีกแล้ว
Arnauld

คำตอบ:


5

เยลลี่ , 20 ไบต์

2*ḃ€2‘ÄṪ⁼¥Ƈ⁸ṗfƝẸ$€ċ0

ลองออนไลน์!


ฉันรู้ว่าความเร็วไม่ได้เป็นส่วนหนึ่งของข้อมูลจำเพาะ แต่สิ่งนี้หมดเวลาไปแล้วแม้แต่ 11x10 เมื่อวิ่งบน tio ฉันสนใจคำอธิบายเพื่อทำความเข้าใจว่าทำไม
Nick Kennedy

@NickKennedy อินพุตใหญ่เกินไป สำหรับความกว้าง 11 แต่ละแถวสามารถมีหนึ่งใน 9 การเอียงที่แตกต่างกัน สำหรับความกว้าง 11 และความสูง 10 จะมีกำแพงที่เป็นไปได้9¹⁰ = 3486784401 รวมถึงผนังที่ไม่ถูกต้อง นั่นเป็นวิธีที่พลังคาร์ทีเซียนทำงาน เห็นได้ชัดว่า TIO ไม่มีเวลาที่จะให้วิธีการแก้ปัญหาของฉันคำนวณผนังทั้งหมด (มันหมดเวลาหลังจาก 60 วินาที) ฉันจะเพิ่มคำอธิบายเมื่อฉันมีเวลา
Erik the Outgolfer

ขอบคุณ ฉันดูเยลลี่นิดหน่อย แต่ในตอนนี้ฉันพึ่งคำอธิบายที่แสดงความคิดเห็นเพื่อทำความเข้าใจว่าโค้ดของคนทำอะไร ฉันสันนิษฐานว่าปัญหาเรื่องเวลาที่รหัสเดรัจฉานของคุณบังคับให้แก้ปัญหาซึ่งเป็นวิธีที่สมเหตุสมผลในการลดความต้องการโค้ดให้น้อยที่สุด
Nick Kennedy

ที่น่าสนใจฉันได้สร้างวุ้นในวิธีการในรหัส R ของฉันโดยใช้ส่วนแรกของรหัสของคุณ อยู่ที่ลองออนไลน์! และในขณะที่มันยาวกว่าของคุณอย่างมาก โปรดทราบว่าในปัจจุบันไม่จัดการแถวที่ 1 อย่างถูกต้อง ฉันสงสัยว่ามันอาจจะกระชับกว่านี้ แต่ฉันใหม่กับเยลลี่
Nick Kennedy

4

JavaScript (ES6),  119 110 106 96  91 ไบต์

(N,M)

f=(n,m,p=0,g=(w,h=x=>g(p[g[w-=x]=1,w]||w)*g[w]--)=>w>3?h(2)+h(1):w>1&&f(n,m-1,g))=>m?g(n):1

ลองออนไลน์!

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

gfhg

f = (                    // f is a recursive function taking:
  n,                     //   n = number of columns
  m,                     //   m = number of rows
  p = 0,                 //   p = object holding the previous row
  g = (                  //   g = recursive function taking:
    w,                   //     w = remaining width that needs to be filled in the
                         //         current row
    h = x =>             //     h = helper function taking x
                         // h body:
      g(                 //   recursive call to g:
        p[g[w -= x] = 1, //     subtract either 2 or 1 from w and mark this width as used
          w              //     test p[w]
        ]                //     pass p[w] if p[w] = 1 (which will force the next iteration
                         //     to fail immediately)
        || w             //     otherwise, pass w
      )                  //   end of recursive call
      * g[w]--           //   then restore g[w] to 0
  ) =>                   // g body:
    w > 3 ?              //   if w > 3, we need to insert at least 2 more bricks:
      h(2) + h(1)        //     invoke h with x = 2 and x = 1
    :                    //   else:
      w > 1              //     this is the last brick; we just check if it can be inserted
      &&                 //     abort if w is equal to 1 (a brick does not fit in there)
      f(                 //     otherwise, do a recursive call to f:
        n,               //       n is unchanged
        m - 1,           //       decrement m
        g                //       pass g as the new reference row
      )                  //     end of recursive call
) =>                     // f body:
  m ? g(n) : 1           //   yield 1 if we made it to the last row or call g otherwise

1

R , 243 231 ไบต์

function(m,n,i=2*0:(m%/%6)+m%%2,j=i+(m-3*i)/2,M=Map)`if`(m<2,0,sum((e=eigen(lengths(outer(p<-unlist(M(M,list(function(x,y)cumsum(2+1:y%in%x)),M(combn,j,i,s=F),j),F),p,Vectorize(intersect)))<2))$ve%*%diag(e$va^(n-1))%*%solve(e$ve)))

ลองออนไลน์!

เวอร์ชันที่มีตัวแบ่งบรรทัด:

function(m,n,i=2*0:(m%/%6)+m%%2,j=i+(m-3*i)/2,M=Map)`if`(m<2,0,
sum((e=eigen(lengths(outer(p<-unlist(M(M,list(function(x,y)cumsum(2+1:y%in%x)),
M(combn,j,i,s=F),j),F),p,Vectorize(intersect)))<2))$ve%*%diag(e$va^(n-1))%*%solve(e$ve)))

หมายเหตุไม่มีการเรียกซ้ำและจัดการค่า m และ n ค่อนข้างมาก (เช่น 24x20 -> 3.3e19)

ต่อไปนี้เป็นคำตอบที่แสดงความคิดเห็นซึ่งใช้งานได้มากกว่าหรือน้อยกว่า แต่ฉันได้ทำฟังก์ชั่นทั้งหมดเพื่อให้อ่านได้

f <- function(m,n) {
  # First work out what potential combinations of 2s and 3s add up to m
  i <- 2*0:(m %/% 6) + m %% 2 # Vector with numbers of possible 3s
  j <- i + (m - 3 * i) / 2 # Vector with total number of 2s and 3s
  if (m < 2) {
    0 # If wall less than 2 wide, no point in continuing because answer is 0
  } else {
    # Work out all possible positions of threes for each set
    positions_of_threes <- Map(combn, j, i, simplify = FALSE)
    # Function to work out the cumulative distance along the wall for a given
    # Set of three positions and number of bricks
    make_cumulative_bricks <- function(pos_threes, n_bricks) {
      bricks <- 1:n_bricks %in% pos_threes
      cumsum(2 + bricks)
    }
    # Find all possible rows with cumulative width of wall
    # Note because this is a `Map` with depth two that needs to be vectorised
    # for both `positions_of_threes` and `j`, and we're using base R, the
    # function `make_cumulative_bricks` needs to be placed in a list
    cum_bricks <- Map(Map, list(make_cumulative_bricks), positions_of_threes, j)
    # Finally we have the list of possible rows of bricks as a flat list
    cum_bricks_unlisted <- unlist(cum_bricks, recursive = FALSE)
    # Vectorise the intersect function
    intersect_v <- Vectorize(intersect, SIMPLIFY = FALSE)
    # Find the length of all possible intersects between rows
    intersections <- outer(cum_bricks_unlisted, cum_bricks_unlisted, intersect_v)
    n_intersections <- lengths(intersections)
    # The ones not lined up will only have a single intersect at `m`
    not_lined_up <- n_intersections == 1
    # Now use method described at /programming//a/9459540/4998761
    # to calculate the (matrix of TRUE/FALSE for lined-up) to the power of `n`
    eigen_nlu <- eigen(not_lined_up)
    final_mat <- eigen_nlu$vectors %*%
      diag(eigen_nlu$values ^ (n - 1)) %*%
      solve(eigen_nlu$vectors)
    # The sum of this matrix is what we're looking for
    sum(final_mat)
  }
}
f(20,20)

วิธีการรับเมทริกซ์และคูณมันด้วยตัวเองซ้ำ ๆ นั้นมาจากคำถามที่เกี่ยวกับสแต็คโอเวอร์โฟลว์ วิธีการนี้ใช้งานได้ที่นี่เพราะมันจะคำนวณจำนวนสาขาอย่างมีประสิทธิภาพผ่านแถวต่าง ๆ ของอิฐที่เป็นไปได้

หากได้รับอนุญาตให้ใช้แพ็คเกจภายนอกฉันสามารถลงไปที่ 192:

function(m,n,i=2*0:(m%/%6)+m%%2,j=i+(m-3*i)/2,M=purrr::map2)`if`(m<2,0,sum(expm::`%^%`(lengths(outer(p<-unlist(M(M(j,i,combn,s=F),j,M,~cumsum(2+1:.y%in%.)),F),p,Vectorize(intersect)))<2,n-1)))

1

เยลลี่ 26 ไบต์

2*ḃ€2‘ÄṪ⁼¥Ƈ⁸œ&L¬ɗþ`æ*⁴’¤SS

ลองออนไลน์!

ทำลายลง:

สร้างรายการของกำแพงที่เป็นไปได้เป็นผลรวมสะสมเมื่อสิ้นสุดการลบ:

2*ḃ€2‘ÄṪ⁼¥Ƈ⁸

ค้นหาตารางด้านนอกของกำแพงที่เป็นไปได้ทั้งหมดกับแต่ละอื่น ๆ ที่ไม่มีทางแยก:

œ&L¬ɗþ`

นำเมทริกซ์นี้ไปใช้กับกำลังของ (N-1) แล้วรวมมันทั้งหมด:

æ*⁴’¤SS

ใช้บิตแรกจากคำตอบของ @ EriktheOutgolfer เพื่อสร้างรายการของกำแพงที่เป็นไปได้จากนั้นใช้การแยกเมทริกซ์และวิธีการยกกำลังเมทริกซ์จากคำตอบ R ของฉัน เช่นนี้มันใช้งานได้ดีแม้กับ N ขนาดใหญ่นี่เป็นคำตอบแรกของฉันใน Jelly และฉันสงสัยว่ามันสามารถเล่นกอล์ฟได้มากขึ้น ฉันยังต้องการเปลี่ยนส่วนแรกเพื่อให้ความต้องการด้านเวลาและหน่วยความจำไม่ได้ขยายตัวอย่างมากด้วย M


0

05AB1E , 42 ไบต์

Åœʒ23yåP}€œ€`Ùε.¥¦¨}IиI.ÆÙεøyíø‚€€üQOO_P}O

ฉันเกือบละอายเกินไปที่จะโพสต์สิ่งนี้และแน่นอนสามารถเล่นกอล์ฟได้ด้วยวิธีการที่แตกต่างกันมาก แต่เนื่องจากมันใช้เวลาสักครู่กว่าจะเสร็จสมบูรณ์ฉันตัดสินใจที่จะโพสต์ต่อไปและเล่นกอล์ฟจากที่นี่ ความท้าทายดูง่ายกว่า imo แต่ฉันใช้แนวทางที่ผิดที่นี่และฉันรู้สึกว่า 05AB1E สามารถทำได้ประมาณ 25 ไบต์ ..

ลองออนไลน์ หมายเหตุ: ไม่เพียง แต่จะยาวเท่านั้น แต่ยังไม่มีประสิทธิภาพเนื่องจาก9x4เคสทดสอบทำงานในเวลาประมาณ 40 วินาทีสำหรับ TIO ..

คำอธิบาย:

Ŝ             # Get all possible ways to sum to the (first) implicit input
               #  i.e. 8 → [[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,2],[1,1,1,1,1,3],[1,1,1,1,2,2],[1,1,1,1,4],[1,1,1,2,3],[1,1,1,5],[1,1,2,2,2],[1,1,2,4],[1,1,3,3],[1,1,6],[1,2,2,3],[1,2,5],[1,3,4],[1,7],[2,2,2,2],[2,2,4],[2,3,3],[2,6],[3,5],[4,4],[8]]
  ʒ23yåP}      # Only leave those consisting of 2s and/or 3s
               #  → [[2,2,2,2],[2,3,3]]
         €œ    # For each: get all permutations
           €`  # Flatten this list of lists once
             Ù # And uniquify it (leaving all possible distinct rows of bricks)
               #  → [[2,2,2,2],[3,3,2],[3,2,3],[2,3,3]]
ε    }         # For each:
             #  Get the cumulative sum
   ¦¨          #  With the leading 0 and trailing first input removed
               #   → [[2,4,6],[3,6],[3,5],[2,5]]
      Iи       # Repeat this list the second input amount of times
               #  i.e. 3 → [[2,4,6],[3,6],[3,5],[2,5],[2,4,6],[3,6],[3,5],[2,5],[2,4,6],[3,6],[3,5],[2,5]]
        I    # Get all combinations of lists the size of the second input
           Ù   # And uniquify the result (leaving all possible distinct walls)
               #  → [[[2,4,6],[3,6],[3,5]],[[2,4,6],[3,6],[2,5]],[[2,4,6],[3,6],[2,4,6]],[[2,4,6],[3,6],[3,6]],[[2,4,6],[3,5],[2,5]],[[2,4,6],[3,5],[2,4,6]],[[2,4,6],[3,5],[3,6]],[[2,4,6],[3,5],[3,5]],[[2,4,6],[2,5],[2,4,6]],[[2,4,6],[2,5],[3,6]],[[2,4,6],[2,5],[3,5]],[[2,4,6],[2,5],[2,5]],[[2,4,6],[2,4,6],[3,6]],[[2,4,6],[2,4,6],[3,5]],[[2,4,6],[2,4,6],[2,5]],[[2,4,6],[2,4,6],[2,4,6]],[[3,6],[3,5],[2,5]],[[3,6],[3,5],[2,4,6]],[[3,6],[3,5],[3,6]],[[3,6],[3,5],[3,5]],[[3,6],[2,5],[2,4,6]],[[3,6],[2,5],[3,6]],[[3,6],[2,5],[3,5]],[[3,6],[2,5],[2,5]],[[3,6],[2,4,6],[3,6]],[[3,6],[2,4,6],[3,5]],[[3,6],[2,4,6],[2,5]],[[3,6],[2,4,6],[2,4,6]],[[3,6],[3,6],[3,5]],[[3,6],[3,6],[2,5]],[[3,6],[3,6],[2,4,6]],[[3,6],[3,6],[3,6]],[[3,5],[2,5],[2,4,6]],[[3,5],[2,5],[3,6]],[[3,5],[2,5],[3,5]],[[3,5],[2,5],[2,5]],[[3,5],[2,4,6],[3,6]],[[3,5],[2,4,6],[3,5]],[[3,5],[2,4,6],[2,5]],[[3,5],[2,4,6],[2,4,6]],[[3,5],[3,6],[3,5]],[[3,5],[3,6],[2,5]],[[3,5],[3,6],[2,4,6]],[[3,5],[3,6],[3,6]],[[3,5],[3,5],[2,5]],[[3,5],[3,5],[2,4,6]],[[3,5],[3,5],[3,6]],[[3,5],[3,5],[3,5]],[[2,5],[2,4,6],[3,6]],[[2,5],[2,4,6],[3,5]],[[2,5],[2,4,6],[2,5]],[[2,5],[2,4,6],[2,4,6]],[[2,5],[3,6],[3,5]],[[2,5],[3,6],[2,5]],[[2,5],[3,6],[2,4,6]],[[2,5],[3,6],[3,6]],[[2,5],[3,5],[2,5]],[[2,5],[3,5],[2,4,6]],[[2,5],[3,5],[3,6]],[[2,5],[3,5],[3,5]],[[2,5],[2,5],[2,4,6]],[[2,5],[2,5],[3,6]],[[2,5],[2,5],[3,5]],[[2,5],[2,5],[2,5]]]
ε              # Map all walls `y` to:
 ø             #  Zip/transpose; swapping rows and columns
 yí            #  Reverse each row in a wall `y`
   ø           #  Also zip/transpose those; swapping rows and columns
              #  Pair both
              #  For both:
              #   For each column:
    ü          #    For each pair of bricks in a column:
     Q         #     Check if they are equal to each other (1 if truthy; 0 if falsey)
    O          #    Then take the sum of these checked pairs for each column
   O           #   Take the sum of that entire column
   _           #   Then check which sums are exactly 0 (1 if 0; 0 if anything else)
   P           #   And check for which walls this is only truthy by taking the product
}O             # After the map: sum the resulting list
               # (and output it implicitly as result)

0

ถ่าน , 89 ไบต์

Nθ⊞υ⟦⟧≔⟦⟧ηFυF⟦²¦³⟧«≧⁺∧Lι§ι⁰κ¿⁼κθ⊞ηι¿‹κθ⊞υ⁺⟦κ⟧ι»≔Eη⟦ι⟧ζF⊖N«≔ζι≔⟦⟧ζFιFη¿¬⊙§κ⁰№λμ⊞ζ⁺⟦λ⟧κ»ILζ

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด ใช้งานได้กับสี่เหลี่ยมที่มีขนาดสูงสุดประมาณ 12 บน TIO แต่สามารถทำได้เร็วขึ้นประมาณสามเท่าในราคา 2 ไบต์โดยใช้การบิดสองบิตแทนการแยกรายการ คำอธิบาย:

Nθ

ป้อนความกว้าง

⊞υ⟦⟧

เริ่มด้วยแถวที่ไม่มีก้อนอิฐ

≔⟦⟧η

เริ่มต้นด้วยไม่มีแถวที่เสร็จสมบูรณ์

Fυ

วนรอบแถว

F⟦²¦³⟧«

วนรอบก้อนอิฐ

≧⁺∧Lι§ι⁰κ

เพิ่มความกว้างของอิฐให้กับความกว้างของแถวปัจจุบัน

¿⁼κθ⊞ηι

หากนี่เป็นผลลัพธ์ในความกว้างอินพุตให้เพิ่มแถวนี้ในรายการของแถวที่เสร็จสมบูรณ์

¿‹κθ⊞υ⁺⟦κ⟧ι»

มิฉะนั้นถ้านี่ยังน้อยกว่าความกว้างของอินพุตให้เพิ่มแถวใหม่ลงในรายการของแถวจึงทำให้เกิดการรับซ้ำในภายหลัง

≔Eη⟦ι⟧ζ

ทำรายการผนังของหนึ่งแถว

F⊖N«

วนซ้ำมากกว่าหนึ่งความสูง

≔ζι

บันทึกรายการของกำแพง

≔⟦⟧ζ

ล้างรายการของกำแพง

Fι

วนซ้ำในรายการกำแพงที่บันทึกไว้

Fη

วนซ้ำแถวที่เสร็จสมบูรณ์

¿¬⊙§κ⁰№λμ⊞ζ⁺⟦λ⟧κ»

หากสามารถเพิ่มแถวในกำแพงนี้ได้ให้เพิ่มเข้าไปในรายการผนัง

ILζ

เอาท์พุทความยาวของรายการสุดท้ายของกำแพง

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