rustedの日記 このページをアンテナに追加 RSSフィード

ruby勉強するよ。
 | 

2006-09-16

[][]Crosswords (#10) 23:10 Crosswords (#10) - rustedの日記 を含むブックマーク はてなブックマーク - Crosswords (#10) - rustedの日記

クロスワードパズルレイアウトをする問題(http://www.rubyquiz.com/quiz10.html)。レイアウトファイルで与えられる。大きくするだけ?と思ったけど、

As a style point, many crosswords drop filled squares on the outer edges. We wouldn't want our Ruby generated crosswords to be unfashionable so we better do that too.

どこの流行か知らないけれど、流行に取り残されないために外側に埋められたマス(■)がある場合はその部分の描画をするなとの通達をいただいたよ。

The final step of laying out a crossword puzzle is to number the squares for word placement. A square is numbered if it is the first square in a word going left to right or top to bottom. Numbers start at 1 and count up left to right, row by row going down.

さらに答えを埋めるための番号(タテ「1」、ヨコ「5」とか)をつけてくれとの注文も。クロスワードパズルには欠かせない要素でした。

で、こんなんでました。

#!/usr/bin/ruby
# Crosswords (#10)

def print_board(board)
 for line in board
   for c in line
     print c
   end
   puts
 end
end

# 最初のマスかどうか
def first_square?(board, x, y)
 if board[y][x] != '_'
   return false
 end
 if (x == 0 || board[y][x - 1] != '_') &&
     (x < board[y].size - 1 && board[y][x + 1] == '_')
   return true
 end
 if (y == 0 || board[y - 1][x] != '_') &&
     (y < board.size - 1 && board[y + 1][x] == '_')
   return true
 end
 return false
end

# 番号を配置
def put_number(board, big)
 cnt = 1
 x = 0
 y = 0
 while y < board.size
   while x < board[y].size
     if first_square?(board, x, y)
       i = 0
       while i < cnt.to_s.size
         big[y * 3 + 1][x * 5+ 1 + i] = cnt.to_s[i].chr
         i += 1
       end
       cnt += 1
     end
     x += 1
   end
   x = 0
   y += 1
 end
end

# でっかくする
def toBig(board)
 big = Array.new
 # まずはそのまま
 for line in board
   l1 = Array.new()
   l2 = Array.new()
   l3 = Array.new()
   l4 = Array.new()
   for c in line
     if c == ' '
       l1.push(' ', ' ', ' ', ' ', ' ', ' ')
       l2.push(' ', ' ', ' ', ' ', ' ', ' ')
       l3.push(' ', ' ', ' ', ' ', ' ', ' ')
       l4.push(' ', ' ', ' ', ' ', ' ', ' ')
     elsif c == '_'
       l1.push('#', '#', '#', '#', '#', '#')
       l2.push('#', ' ', ' ', ' ', ' ', '#')
       l3.push('#', ' ', ' ', ' ', ' ', '#')
       l4.push('#', '#', '#', '#', '#', '#')
     else
       l1.push('#', '#', '#', '#', '#', '#')
       l2.push('#', '#', '#', '#', '#', '#')
       l3.push('#', '#', '#', '#', '#', '#')
       l4.push('#', '#', '#', '#', '#', '#')
     end
   end
   big.push(l1, l2, l3, l4)
 end

 # 重なりをあわせる (縦)
 i = 4
 while i < big.size
   j = 0
   while j < big[i].size
     if big[i-1][j] == '#' || big[i][j] == '#'
       big[i-1][j] = '#'
     else
       big[i-1][j] = ' '
     end
     j += 1
   end
   big.delete_at(i)
   i += 3 # delete で -1
 end

 # 重なりをあわせる (横)
 i = 6
 while i < big[0].size
   j = 0
   while j < big.size
     if big[j][i-1] == '#' || big[j][i] == '#'
       big[j][i-1] = '#'
     else
       big[j][i-1] = ' '
     end
     big[j].delete_at(i)
     j += 1
   end
   i += 5
 end
 return big
end

# 再帰的に外側を外していく
def search(board, x, y)
 if board[y][x] == 'X'
   board[y][x] = ' '
   if x < board[y].size - 1
     search(board, x + 1, y)
   end
   if x > 0
     search(board, x - 1, y)
   end
   if y < board.size - 1
     search(board, x, y + 1)
   end
   if y > 0
     search(board, x, y - 1)
   end
 end
end

# 外側の埋まっているマスをはずす
def remove(board)
 x = 0
 y = 0
 while x < board[y].size
   if board[y][x] == 'X'
     board[y][x] = ' '
     search(board, x, y + 1)
   end
   x += 1
 end
 x = board[y].size - 1
 while y < board.size
   if board[y][x] == 'X'
     board[y][x] = ' '
     search(board, x - 1, y)
   end
   y += 1
 end
 y = board.size - 1
 while x >= 0
   if board[y][x] == 'X'
     board[y][x] = ' '
     search(board, x, y - 1)
   end
   x -= 1
 end
 x = 0
 while y >= 0
   if board[y][x] == 'X'
     board[y][x] = ' '
     search(board, x + 1, y)
   end
   y -= 1
 end
end

# 問題をファイルから読む
board = Array.new()
while line = ARGF.gets
 ary = line.split(' ')
 board.push(ary)
end
remove(board)
big = toBig(board)
put_number(board, big)
print_board(big)

実行結果

crosswords.txt =>
X _ _ _ _ X X
_ _ X _ _ _ _
_ _ _ _ X _ _
_ X _ _ X X X
_ _ _ X _ _ _
X _ _ _ _ _ X
$ ./quiz10.rb crosswords.txt
     #####################
     #1   #    #2   #3   #
     #    #    #    #    #
####################################
#4   #    ######5   #    #6   #7   #
#    #    ######    #    #    #    #
####################################
#8   #    #9   #    #    #10  #    #
#    #    #    #    #    #    #    #
#####################    ###########
#    ######11  #    #
#    ######    #    #
####################################
#12  #13  #    ######14  #15  #    #
#    #    #    ######    #    #    #
####################################
     #16  #    #    #    #    #
     #    #    #    #    #    #
     ##########################

できた!

親しみやすい課題で面白かったよ。でもコードはwhile文とif文だらけでかなり汚い感じ。もっとシンプルに仕上げたいなあ。

 |