IT NoViCe

IT 初心者の勉強備忘録ブログ

氷のダンジョン

っていう問題を解いてみました。

名前がやたらかっこつけてるのは paiza というサイトから持ってきたからです。

paiza.jp

解いてみたのは以下の問題です。

 

 

■問題

H × W の格子形状で表されるダンジョンを探検します。

このダンジョンの各マスには、氷または土の床が存在し、周囲は壁で囲まれています。

あなたは初めに土の床のあるマスにいて、

これから N 回の移動を試みることになりました。

このダンジョンでは氷の床に足を踏み入れると、

土の床のマスにくるか壁にぶつかるまで、足を出した方向に滑り続けてしまいます。

N 回の各移動の方向が与えられるので、

N 回の移動を終えた後にあなたがいるマスの座標を答えてください。

なお、 座標値の y が大きくなる方向を下、 x が大きくなる方向を右であるとします。

 

■入力フォーマット

    H W
    g_1
    g_2
    ...
    g_H
    s_x s_y
     N
    d_1
    d_2
    ...
    d_N

 

■入力

・1行目には、ダンジョンの縦の長さと横の長さを表す H, W が

 この順に半角スペース区切りで与えられます。

・続く H 行のうち i 行目にダンジョンの情報を表す文字列 g_i が与えられます。

 ・g_i の j 番目の文字が座標 (j, i) のマスにある床の種類を表し、

  ”#” であれば氷の床、”.” であれば土の床を表します。

・次の行には、あなたが最初にいるマスの x 座標、y 座標を表す s_x, s_y が

 この順に半角スペース区切りで与えられます。

・次の行には、移動の回数 N が与えられます。

・続く N のうち k 行目に各移動の方向を表す文字が与えられます。

 ・d_k は ”U”, ”R”, ”D”, ”L” のいずれかであり、

  それぞれ上、右、下、左への移動であることを表します。

 ・ただし、 座標値の y が小さくなる方向を上、

  x が大きくなる方向を右であるとします。

・入力は合計で H + N + 3 行となり、入力値最終行の末尾に改行が1つ入ります。

 

■期待する出力

N 回の移動を終えた後にあなたがいるマスの座標 (x, y) を

  x y

のように半角スペース区切りで出力する。

 

■入力例

    5 5
    .###.
    #.#.#
    ##..#
    ..##.
    ##..#
    3 3
    5
    U
    R
    D
    L
    U

 

■出力例

    2 2

 

って問題です。

問題説明のみでだいぶ文字数使っちゃいましたね。

以下私の解答です。

 

■私の解答

# coding: utf-8

 

# 現在位置クラス

class Position():

    # コンストラクタ

    def __init__(self, argX, argY):

        self.x = argX

        self.y = argY

   

#ダンジョンクラス

class Dungeon:

    # コンストラクタ

    def __init__(self, argH, argW):

        # 変数定義

        self.h = argH

        self.w = argW

        self.dungeonMap = {(x, y): False for x in range(argW+2) for y in range(argH+2)}

        self.pos = None

        self.MoveList = []

 

    # 移動メソッド

    def Move(self):

        # 現在位置取得

        pos = self.pos

 

        # 順番に移動

        for moveKind in self.MoveList:

            # 上に移動

            if moveKind == "U":

                pos = self.moveUp(pos)

 

            # 下に移動

            elif moveKind == "D":

                pos = self.moveDown(pos)

 

            # 右に移動

            elif moveKind == "R":

                pos = self.moveRight(pos)

 

            # 左に移動

            elif moveKind == "L":

                pos = self.moveLeft(pos)

 

        # 現在位置を返却

        self.pos = pos

 

    # 上に移動

    def moveUp(self, pos):

        # 一番上以外の場合、y軸位置計算

        if pos.y != 1:

            yPos = max([y for y in range(0, pos.y) if not self.dungeonMap[pos.x, y]])

           # y位置更新

            pos.y = yPos if yPos != 0 else 1

 

        # 位置クラス返却

        return pos

 

    # 下に移動

    def moveDown(self, pos):

        # 一番下以外の場合、y軸位置計算

        if pos.y != self.h:

           yPos = min([y for y in range(pos.y+1, self.h+2) \

                              if not self.dungeonMap[pos.x, y]])

           # y位置更新

            pos.y = yPos if yPos != self.h+1 else self.h

 

        # 位置クラス返却

        return pos

 

    # 右に移動

    def moveRight(self, pos):

        # 一番右以外の場合、x軸位置計算

        if pos.x != self.w:

            xPos = min([x for x in range(pos.x+1, self.w+2) if not self.dungeonMap[x,pos.y]])

            # x位置更新

           pos.x = xPos if xPos != self.w+1 else self.w

 

        # 位置クラス返却

        return pos

 

    # 左に移動

    def moveLeft(self, pos):

        # 一番左以外の場合、x軸位置計算

        if pos.x != 1:

            xPos = max([x for x in range(0, pos.x) \

                                 if not self.dungeonMap[x, pos.y]])

            # x位置更新

            pos.x = xPos if xPos != 0 else 1

 

        # 位置クラス返却

        return pos

 

# メイン処理

# マップサイズ取得

size = input().split(" ")

h = int(size[0])

w = int(size[1])

 

# ダンジョンクラス作成

dungeon = Dungeon(h, w)

 

# ダンジョン地形取得

for row in range(h):

    terrain = input()

    for column in range(w):

        dungeon.dungeonMap[column+1, row+1] = (terrain[column] == "#")

 

# 現在位置取得

CurrentPos = input().split(" ")

dungeon.pos = Position(int(CurrentPos[0]), int(CurrentPos[1]))

 

# 移動回数と移動方向取得

moveN = int(input())

for n in range(moveN):

    dungeon.MoveList.append(str(input().rstrip()))

 

# 移動開始
dungeon.Move()

# 結果出力
pos = dungeon.pos
print(str(pos.x) + " " + str(pos.y) + "\n")

 

頑張って考えた結果こんな感じになりました。

クラス設計とかどうしたらうまくできるようになるんでしょう・・・

たくさんコード書いて慣れないとダメですね。

 

ちなみに標準回答時間40分/制限時間2時間なのですが、

私はハマリまくって二時間かかりました。

 

以下私のハマリどころです。

・range の範囲ミス

・h,w と x,y の対応付けミス

・インデントミス

 

しょうもないですね笑

こんなんで1時間程度持ってかれました。

 

もっときれいにさらっとコードをかけるように頑張ります。