Bộ giải câu đố HappyCube


9

Thử thách này được lấy cảm hứng từ một câu đố tôi đã chơi, bao gồm những mảnh xốp như thế này:

mảnh ghép

mà phải được lắp ráp thành các khối 3D, như thế này:

giải khối

Các mảnh ghép có thể được xem như là lưới của các ô vuông 5 * 5, có các ô vuông 3 * 3 ở giữa luôn luôn chắc chắn, trong khi 16 ô vuông trên các cạnh có thể là hình khối hoặc rỗng.

Một mảnh sẽ được mô tả bằng chuỗi 16 ký tự ( 0s và 1s), đại diện cho cấu hình của các cạnh của nó ( 0= trống, 1= solid), theo thứ tự theo chiều kim đồng hồ, bắt đầu từ góc trên cùng bên trái.

Ví dụ: chuỗi:

0101001000101101

đại diện cho tác phẩm này:

 # #
####
 ####
####
# #

Để khớp các mảnh lại với nhau để tạo thành khối lập phương, mọi mảnh có thể được xoay theo bất kỳ hướng nào. Ví dụ, đây là các phép quay hợp lệ của mảnh được hiển thị ở trên:

 # #    # #     #    ## # 
 ####  ####    ####   ####
####    ####  ####   #### 
 ####  ####    ####   ####
  # #  # #    ## #     #  

# #      # #   # ##    #  
####    ####  ####   #### 
 ####  ####    ####   ####
####    ####  ####   #### 
 # #    # #     #     # ##

Thử thách

Viết chương trình hoặc hàm lấy 6 mảnh ghép đầu vào và in hoặc trả về biểu diễn 2D của khối đã giải.

Đầu vào

Đầu vào sẽ là một chuỗi gồm 6 hàng, trong đó mỗi hàng gồm 16 0hoặc 1ký tự, đại diện cho các cạnh của một mảnh (theo định dạng được mô tả ở trên).

Có thể giả định rằng có một giải pháp cho đầu vào.

Các dòng mới là tùy chọn.

Đầu ra

Kết quả sẽ là một đại diện ASCII của khối đã giải, được mở ra dưới dạng 2D, như thế này (sơ đồ sử dụng ký hiệu Cube của Rubik cho tên bên):

    +---+
    |BA |
    |CK |
    |   |
+---+---+---+---+
|LE |DO |RI |UP |
|FT |WN |GHT|   |
|   |   |   |   |
+---+---+---+---+
    |FR |
    |ONT|
    |   |
    +---+

Để tránh khả năng trình bày giải pháp theo nhiều cách, phần được đặt DOWN sẽ luôn là phần đầu tiên có trong đầu vào, trong cùng một vòng quay như được chỉ định ở đó.

Mỗi phần sẽ được biểu thị bằng đồ họa dưới dạng ma trận 5 * 5, sử dụng khoảng trắng để biểu thị các ô vuông trống. Đối với hình vuông rắn, bạn có thể sử dụng bất kỳ ký tự không phải không gian nào bạn muốn, miễn là:

  • bất kỳ mảnh ghép nào cũng sẽ có hình vuông rắn được biểu diễn bằng cùng một ký tự
  • bất kỳ hai mảnh liền kề sử dụng các ký tự khác nhau

Không gian đệm ở bên phải và dòng mới theo dõi là tùy chọn.

Các trường hợp thử nghiệm

1.

Đầu vào:

0010010101010101
0010001011011010
0101001001010010
0010110100101101
0010110110101101
0010001011010101

Đầu ra:

     @ @         
     @@@         
    @@@@@        
     @@@         
** **@#@** *# #  
 ***#####***#####
*****###*****### 
 ***#####***#####
  * @#@#** ** # #
    @@@@         
     @@@@        
    @@@@         
     @ @         

2.

Đầu vào:

0001110110101101
1010010111011101
0101010101010010
1010001000100011
1010001001010001
0110010100100010

Đầu ra:

      @          
     @@@@        
    @@@@         
     @@@@        
** **@@## * *# # 
****#####****### 
 ****###*****####
****#####***#### 
** *#@#@# * # #  
     @@@@        
    @@@@         
     @@@@        
     @ @         

3.

Đầu vào:

0101001011011010
0010001000100010
0101001011010010
0101010101011010
0101101001011101
1010001001011101

Đầu ra:

     @ @@        
    @@@@@        
     @@@         
    @@@@@        
* * @#@#* *   #  
*****###*****### 
 ***#####***#####
*****###*****### 
  * ##@##* *  #  
    @@@@         
     @@@@        
    @@@@         
    @@ @@        

Đây là codegolf, vì vậy chương trình ngắn nhất tính bằng byte sẽ thắng.


Có, ít nhất trên màn hình của tôi, "trở lại", "xuống" và "phía trước" trông giống như màu sắc / ký tự.
Reto Koradi

"Để tránh khả năng trình bày giải pháp theo nhiều cách, phần được đặt DOWN sẽ luôn là phần đầu tiên có trong đầu vào, trong cùng một vòng quay như được chỉ định ở đó." Ngay cả khi bạn giữ mảnh ghép đầu tiên không đổi, tôi không nghĩ rằng năm mảnh còn lại được đảm bảo có vị trí độc nhất.
Rainbolt

@Rainbolt Đối với các đầu vào tôi sử dụng, điều đó đúng - chỉ có một cách sắp xếp đầu ra. Nói chung, mặc dù, bạn đã đúng; rõ ràng có những đầu vào mà nhiều sự sắp xếp hợp lệ là có thể,
Cristian Lupascu

Câu trả lời:


6

Haskell, 1007 Một nghìn và một byte 923 900 830 byte

Tôi tình cờ đã thực hiện một bộ giải happycube, bây giờ tôi chỉ cần đánh golf nó. Nhận một hình phạt mười byte cho việc sử dụng các yếu tố khối ưa thích:

import Data.List
r=reverse;z=zipWith;f=foldl1;t=take;g=t 4;d=drop;m=map
n x=t 5x:n(d 4x)
u v a b=init a++v max(last a)(b!!0):d 1b
a!b|k<- \x y->last$' ':[a|b!!x!!y>0]=(k 0<$>[0..4]):((\i->k 3(4-i):[a,a,a]++[k 1i])<$>[1..3])++[k 2<$>[4,3..0]]
p y|(e:v)<-m(g.n.cycle.m(read.pure))$"0":(lines$y),[j,k,l,x,y,r]<-x v=mapM putStrLn$f(u z)$f(z(u id))<$>z(z(!))[a,"▒█▒█",a][[e,k,e,e],[l,j,x,r],[e,y,e,e]];a=" ░  "
x(p:q)=[p:u|x<-permutations q,u@[e,g,y,k,l]<-sequence$(\c->nub$[c,r.m r$c]>>=g.m g.tails.cycle)<$>x,and$zipWith4(\a n b m->all(==1).init.d 1$z(+)(a!!n)$r$b!!m)([l,e,p,p,p,p,e]++u)[3,3,0,3,1,2,0,1,2,2,2,1](y:g:u++[y,k,k,l,g])[1,0,2,1,3,0,0,0,3,1,2,3]++z((((==1).sum.m(!!0)).).z(!!))[[p,e,g],[y,p,e],[k,p,g],[k,p,y],[l,y,e],[l,y,k],[l,g,e],[l,g,k]][[0,3,1],[0..2],[0,3,2],[1..3],[0,1,1],[3,2,2],[1,0,0],[2,3,3]]]!!0

Đó là một câu nói miệng. Sử dụng:

*Main> mapM_ (\s->p s>>putStrLn"")["0010010101010101\n0010001011011010\n0101001001010010\n0010110100101101\n0010110110101101\n0010001011010101","0001110110101101\n1010010111011101\n0101010101010010\n1010001000100011\n1010001001010001\n0110010100100010","0101001011011010\n0010001000100010\n0101001011010010\n0101010101011010\n0101101001011101\n1010001001011101"]
            
     ░░░      
    ░░░░░     
     ░░░      
▒▒ ▒▒░█░▒▒ ▒█ 
 ▒▒▒█████▒▒▒█████
▒▒▒▒▒███▒▒▒▒▒███
 ▒▒▒█████▒▒▒█████
   ░█░█▒▒ ▒▒  
    ░░░░      
     ░░░░     
    ░░░░      
            

             
     ░░░░     
    ░░░░      
     ░░░░     
▒▒ ▒▒░░██  ▒█ 
▒▒▒▒█████▒▒▒▒███
 ▒▒▒▒███▒▒▒▒▒████
▒▒▒▒█████▒▒▒████
▒▒ ▒█░█░█   
     ░░░░     
    ░░░░      
     ░░░░     
            

    ░░       
    ░░░░░     
     ░░░      
    ░░░░░     
   ▒█░█░   
▒▒▒▒▒███▒▒▒▒▒███
 ▒▒▒█████▒▒▒█████
▒▒▒▒▒███▒▒▒▒▒███
  ▒██░██    
     ░░░░     
    ░░░░      
     ░░░░     
    ░░ ░░     

Một số ví dụ có nhiều hơn một giải pháp, đó là lý do tại sao một số kết quả đầu ra trông khác nhau. Ung dung:

import Data.List (nub, transpose, (\\))
import Control.Monad (guard)

newtype CubePiece = CubePiece [[Int]] deriving Eq
newtype Solution = Solution [CubePiece]

side :: Int -> CubePiece -> [Int]
side n (CubePiece c) = c!!n

corner :: Int -> CubePiece -> Int
corner n (CubePiece c) = head $ c!!n

strToCube str = CubePiece $ hs' . (\x@(a:_)->x++[a]) $ l
  where
    l = map (read.pure) str
    hs' [a] = []
    hs' x = take 5 x : hs' (drop 4 x)

orientations :: CubePiece -> [CubePiece]
orientations (CubePiece cube) = map CubePiece $ nub $ (take 4 . iterate rotate $ cube) ++
  (take 4 . iterate rotate . reverse . map reverse $ cube)
  where
  rotate (a:as) = as++[a]

sideFits ::  (CubePiece, Int) -> (CubePiece, Int) -> Bool
sideFits (c1,n1) (c2,n2) = case (zipWith (+) a b) of
  [_,1,1,1,_] -> True
  _ -> False
  where
  a = side n1 c1
  b = reverse $ side n2 c2

cornerFits :: (CubePiece, Int) -> (CubePiece, Int) -> (CubePiece, Int) -> Bool
cornerFits (c1,n1) (c2,n2) (c3,n3) = a + b + c == 1
  where
  a = corner n1 c1
  b = corner n2 c2
  c = corner n3 c3

printSolution str = putStrLn . specialUnlines . map rivi $
  [[empty,gshow '░' c2,empty,empty],[gshow '▒' c3,gshow '█'c1,gshow '▒'c4,gshow '█'c6],[empty,gshow '░'c5,empty,empty]]
  where
  Solution [c1,c2,c3,c4,c5,c6] = solve . map strToCube . lines $ str
  empty = replicate 5 "     "
  rivi = map (foldl1 specialConcat) . transpose
  specialUnlines = unlines . foldl1(\a b->init a++[zipWith max(last a)(head b)]++tail b)
  specialConcat a b
    | last a==' '=init a++b
    | otherwise = a++tail b

gshow char (CubePiece c) =
  [ map (k 0) [0..4]
  , (k 3 3) : m ++ [(k 1 1)]
  , (k 3 2) : m ++ [(k 1 2)]
  , (k 3 1) : m ++ [(k 1 3)]
  , map (k 2)[4,3..0]
  ]
  where
  k n1 n2 = if (c!!n1)!!n2 == 1 then char else ' '
  m=replicate 3 char

solve :: [CubePiece] -> Solution
solve pieces = Solution $ head $ do
  let c1' = pieces!!0
  let c1 = c1'

  c2'  <- pieces \\ [c1']
  c2   <- orientations c2'
  guard $ sideFits (c1,0) (c2,2)

  c3'  <- pieces \\ [c1',c2']
  c3   <- orientations c3'
  guard $ sideFits (c1,3) (c3,1)
  guard $ sideFits (c2,3) (c3,0)
  guard $ cornerFits (c1,0) (c2,3) (c3,1)

  c4'  <- pieces \\ [c1',c2',c3']
  c4   <- orientations c4'
  guard $ sideFits (c1,1) (c4,3)
  guard $ sideFits (c2,1) (c4,0)
  guard $ cornerFits (c1,1) (c2,2) (c4,0)
  c5' <- pieces \\ [c1',c2',c3',c4']
  c5 <- orientations c5'
  guard $ sideFits (c1,2) (c5,0)
  guard $ sideFits (c4,2) (c5,1)
  guard $ sideFits (c3,2) (c5,3)
  guard $ cornerFits (c5,0) (c1,3) (c3,2)
  guard $ cornerFits (c5,1) (c1,2) (c4,3)

  c6' <- pieces \\ [c1',c2',c3',c4',c5']
  c6 <- orientations c6'
  guard $ sideFits (c6,0) (c2,0)
  guard $ sideFits (c6,1) (c3,3)
  guard $ sideFits (c6,2) (c5,2)
  guard $ sideFits (c6,3) (c4,1)
  guard $ cornerFits (c6,0) (c4,1) (c2,1)
  guard $ cornerFits (c6,3) (c4,2) (c5,2)
  guard $ cornerFits (c6,1) (c3,0) (c2,0)
  guard $ cornerFits (c6,2) (c3,3) (c5,3)
  return $ [c1,c2,c3,c4,c5,c6]

main = mapM_ printSolution ["0010010101010101\n0010001011011010\n0101001001010010\n0010110100101101\n0010110110101101\n0010001011010101","0001110110101101\n1010010111011101\n0101010101010010\n1010001000100011\n1010001001010001\n0110010100100010","0101001011011010\n0010001000100010\n0101001011010010\n0101010101011010\n0101101001011101\n1010001001011101"]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.