LoginSignup
0

More than 5 years have passed since last update.

「オフラインリアルタイムどう書く第29回(サイコロの展開図)」の問題を解いてみた

Posted at

横浜へなちょこプログラミング勉強会にて過去に出題されたサイコロの展開図を解いてみた。
回答にかかった時間は120分程度と大幅オーバー。

ほとんどは自前で全パターンを列挙するExpandedDice#patternsを実装する時間なので、全パターンをハードコーディングすればもっと早く出来上がったものと思われる。
メソッドの名前は上段が正面、右側、裏面、下段が下側、左側、上側と仮定した場合に回す方向で考えている。

  • ExpandedDice#rotate_topdown: 上を12時、右側を3時、下を6時、左側を9時方向として時計回りに90度回転させる
  • ExpandedDice#rotate_side: 裏面を12時、右側を3時、正面を6時、左側を9時方向として時計回りに90度 * 指定回数回転させる
  • ExpandedDice#rotate_face: 上を12時、裏面を3時、下を6時、正面を9時方向として時計回りに90度回転させる

多分手元にサイコロがあればもっと考えがまとまりやすかったと思われる。

class ExpandedDice
  Dice = "12S/453"

  def initialize
    @patterns = patterns
  end

  def masked_cell input
    r = /#{input.gsub(/[wxyz]/, ".")}/
    list = @patterns.select{|pattern| r === pattern}
    case list.size
    when 0
      "none"
    when 1
      input.scan(/[wxyz]/).map{|m|
        "#{m}=#{list[0][input.index(m)]}"
      }.join(",")
    else
      "many"
    end
  end

  private
  def patterns
    [Dice, rotate_topdown(Dice)].each_with_object([]){|dice, r|
      3.times{|i|
        pattern = rotate_side dice, i
        rev_pattern = pattern.reverse
        [
          pattern, rev_pattern,
          rotate_face(pattern), rotate_face(rev_pattern)
        ].each{|pat| r << pat}
      }
    }
  end

  def rotate_cell cell
    case cell
    when "2" then "D"
    when "D" then "2"
    when "3" then "T"
    when "T" then "3"
    when "6" then "S"
    when "S" then "6"
    else          cell
    end
  end

  def rotate_topdown dice
    [
      dice[0], dice[6], dice[2],
      "/",
      dice[1], dice[4], dice[5]
    ].map{|c| rotate_cell(c)}.join
  end

  def rotate_side dice, count
    side = (dice[0..2] + dice[5]).chars.rotate(count)
    [
      side[0..2],
      "/",
      (count % 2).zero? ? dice[4] : rotate_cell(dice[4]),
      (count % 2).zero? ? rotate_cell(side.last) : side.last,
      (count % 2).zero? ? dice[6] : rotate_cell(dice[6])
    ].flatten.join
  end

  def rotate_face dice
    dice[4..6] + "/" + dice[0..2]
  end
end

test = <<_TEST
/*0*/ test( "Tx4/5yz", "x=1,y=S,z=2" );    
/*1*/ test( "14S/xyz", "none" );    
/*2*/ test( "1w6/xyz", "many" );    
/*3*/ test( "4w3/12S", "w=5" );    
/*4*/ test( "4w3/S51", "w=D" );    
/*5*/ test( "15S/wD4", "w=3" );    
/*6*/ test( "54D/6Tw", "w=1" );    
/*7*/ test( "S21/35w", "w=4" );    
/*8*/ test( "w2x/354", "w=S,x=1" );    
/*9*/ test( "wx1/54D", "w=6,x=T" );    
/*10*/ test( "45w/12x", "w=3,x=S" );    
/*11*/ test( "5w2/x14", "w=S,x=T" );    
/*12*/ test( "Dw5/x41", "w=3,x=6" );    
/*13*/ test( "w4x/1y6", "w=D,x=5,y=T" );    
/*14*/ test( "15w/xy4", "w=S,x=3,y=D" );    
/*15*/ test( "D35/wxy", "w=6,x=4,y=1" );    
/*16*/ test( "4wx/51y", "w=6,x=T,y=2" );    
/*17*/ test( "wTx/D4y", "w=1,x=6,y=5" );    
/*18*/ test( "wxy/z3D", "w=1,x=4,y=6,z=5" );    
/*19*/ test( "wx5/1yz", "w=D,x=4,y=T,z=6" );    
/*20*/ test( "w53/xyz", "w=4,x=1,y=2,z=S" );    
/*21*/ test( "wx1/yzD", "w=6,x=T,y=5,z=4" );    
/*22*/ test( "wxS/3yz", "w=1,x=5,y=D,z=4" );    
/*23*/ test( "wx2/y1z", "w=5,x=S,y=T,z=4" );    
/*24*/ test( "4wx/2yz", "w=1,x=T,y=S,z=5" );    
/*25*/ test( "T6w/xyz", "w=4,x=2,y=1,z=5" );    
/*26*/ test( "Swx/yDz", "w=5,x=1,y=4,z=3" );    
/*27*/ test( "wDx/yzS", "w=3,x=4,y=1,z=5" );    
/*28*/ test( "wxy/5Sz", "w=T,x=1,y=4,z=2" );    
/*29*/ test( "wSx/4yz", "w=2,x=5,y=1,z=T" );    
/*30*/ test( "wxS/y5z", "w=1,x=2,y=4,z=3" );    
/*31*/ test( "wxy/35z", "w=S,x=2,y=1,z=4" );    
/*32*/ test( "wxy/T6z", "w=2,x=1,y=5,z=4" );    
/*33*/ test( "wxD/yz1", "w=5,x=4,y=6,z=T" );    
/*34*/ test( "1wx/yz5", "w=T,x=6,y=D,z=4" );    
/*35*/ test( "wx3/y5z", "w=4,x=D,y=S,z=1" );    
/*36*/ test( "6wx/y3z", "w=4,x=1,y=D,z=5" );    
/*37*/ test( "5wx/4yz", "w=1,x=2,y=6,z=T" );    
/*38*/ test( "wx4/Syz", "w=3,x=5,y=2,z=1" );    
/*39*/ test( "w3D/xyz", "w=5,x=1,y=4,z=6" );    
/*40*/ test( "w3x/6yz", "w=D,x=5,y=4,z=1" );    
/*41*/ test( "wxy/z12", "w=4,x=6,y=T,z=5" );    
/*42*/ test( "1wS/xyz", "many" );    
/*43*/ test( "wxy/Dz5", "many" );    
/*44*/ test( "3w4/xyz", "many" );    
/*45*/ test( "wxy/5zD", "many" );    
/*46*/ test( "wxy/Tz4", "many" );    
/*47*/ test( "5wD/xyz", "many" );    
/*48*/ test( "wDx/y5z", "many" );    
/*49*/ test( "wxy/3z4", "many" );    
/*50*/ test( "wxy/5z2", "many" );    
/*51*/ test( "Dyz/S1x", "none" );    
/*52*/ test( "w1z/xyS", "none" );    
/*53*/ test( "15x/T6y", "none" );    
/*54*/ test( "zy4/5x6", "none" );    
/*55*/ test( "2xy/4Tz", "none" );    
/*56*/ test( "xzS/y1w", "none" );    
/*57*/ test( "Syx/4z5", "none" );    
/*58*/ test( "xwS/Tzy", "none" );    
/*59*/ test( "D5z/xwy", "none" );    
/*60*/ test( "yxD/z35", "none" );
_TEST

require 'minitest/autorun'

describe 'ExpandedDice' do
  dice = ExpandedDice.new
  test.split("\n").each do |line|
    t, n, input, expect = line.match(/^\/\*(\d+)\*\/\s*test\(\s*"([^"]+)",\s*"([^"]+)"\s*\);*\s*$/).to_a
    it input do
      assert_equal expect, dice.masked_cell(input)
    end
  end
end

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0