質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

6回答

1120閲覧

もっと短いコードにならないか?

wakahide

総合スコア23

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

3クリップ

投稿2020/03/16 23:16

解は得られるのですが、コードが長すぎる気がしており、もっと綺麗に書けるのではないかと悩んでいます。

やりたいこととしては、指定された行列のマス目から、方向を入力すれば、その方向のマス目が表示されるようにしたいです。

正方行列のマス目にはそれぞれ番号が左上から下図のように振られております。
| | A | B | C | D |
|a | 0 | 1 | 2 | 3 |
|b | 4 | 5 | 6 | 7 |
|c | 8 | 9 |10|11|
|d |12|13|14|15|

例えば、スタートが7で、upを入力すれば、3が返ってきます。

選択できる方向は(上、下、右、左、右上、左上、右下、左下)の8方向です。

無効な方向が入力された時は、”無効”を返します。
例えば、2の場合ですと、"上"、もしくは"右上"、もしくは"左上"が入力されると、”無効”になります。

現在、1行目について、以下のコードを書きましたが、
これと同等の長さのコードを1列、grid列、grid行、のために書くのは、長すぎやしないかと思っており、他にいい方法があるのではないかと悩んでいます。

#num:指定のマス目番号 #grid:正方行列のサイズ #direction: 方向 def num_direction(num,grid,direction): while num < grid: if direction == "下": return index + grid_size elif direction == "左": return index - 1 elif direction == "右": return index + 1 elif direction == "左下": return index + grid_size - 1 elif direction == ”右下”: return index + grid_size + 1 else: return "None"

説明がわかりにくいかもしれませんが、アドバイスのほど宜しくお願い致します。

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

8方向の名前と対応する方向(x方向に+1/-1、y方向に+1/-1)を配列に
入れてループする形にすればif~elif~の部分がもう少し短くなります。

投稿2020/03/17 02:41

sage

総合スコア1216

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

num から行方向と列方向のインデクスを作り、それに対して、direction で指定される差分を適用して、その結果を返す、という考え方はいかがでしょうか?

一例を挙げますと、こんな感じです。

python3

1def num_direction(num, grid, direction): 2 row, col = divmod(num, grid) 3 4 delta = [ 5 1 if re.search('下', direction) 6 else (-1 if re.search('上', direction) else 0), 7 1 if re.search('右', direction) 8 else (-1 if re.search('左', direction) else 0) 9 ] 10 11 row += delta[0] 12 col += delta[1] 13 14 return grid * row + col if row in range(grid) and col in range(grid) else None

追記

もう一案、numpy を使ってみました。

python3

1import numpy as np 2 3LEFT_RIGHT = [ 4 ['左', np.array([0, -1])], 5 ['右', np.array([0, 1])] 6] 7 8UP_DOWN = [ 9 ['上', np.array([-1, 0])], 10 ['下', np.array([1, 0])] 11] 12 13DIAGONALS = [ 14 [f'{lr[0]}{ud[0]}', lr[1] + ud[1]] 15 for lr in LEFT_RIGHT 16 for ud in UP_DOWN 17] 18 19DIRECTIONS = {e[0]: e[1] for e in [*LEFT_RIGHT, *UP_DOWN, *DIAGONALS]} 20 21 22def num_direction(num, grid, direction): 23 delta = DIRECTIONS[direction] 24 25 if delta is None: 26 return None 27 28 pos = np.array(divmod(num, grid)) + delta 29 30 if(((pos >= 0) * (pos < grid)).sum() == 2): 31 return grid * pos[0] + pos[1] 32 else: 33 return None 34 35 36print(num_direction(7, 4, '上')) # => 3 37print(num_direction(2, 4, '上')) # => None 38 39print(num_direction(15, 4, '上')) # => 11 40print(num_direction(15, 4, '左')) # => 14 41print(num_direction(15, 4, '左上')) # => 10 42print(num_direction(15, 4, '右')) # => None 43print(num_direction(15, 4, '下')) # => None 44print(num_direction(15, 4, '右上')) # => None 45

投稿2020/03/17 02:15

編集2020/03/17 04:33
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

global変数をいくつか使うことになりますが、num_direction()そのものは簡潔に書くことができます。

Python

1""" 2https://teratail.com/questions/247619 3 4周囲が-1で囲まれた番兵付きの拡大版gridを用意する。 5num_direction()では、移動後が0-15の場合はその数字を, -1 (番兵)の場合はNoneを返す。 6 7grid: 8 -1, -1, -1, -1, -1, -1 9 -1, 0, 1, 2, 3, -1 10 -1, 4, 5, 6, 7, -1 11 -1, 8, 9, 10, 11, -1 12 -1, 12, 13, 14, 15, -1 13 -1, -1, -1, -1, -1, -1 14""" 15from typing import Optional 16 17grid_size = 4 18extended_grid_size = grid_size + 2 # 左右に番兵付きのgrid_size 19 20# gridを作成 21grid = [-1] * extended_grid_size 22for i in range(4): 23 row = [-1] + list(range(i * 4, (i + 1) * 4)) + [-1] 24 grid.extend(row) 25grid.extend([-1] * (grid_size + 2)) 26 27direction_converter = { 28 "上": -extended_grid_size, 29 "下": extended_grid_size, 30 "右": 1, 31 "左": -1, 32 "右上": -extended_grid_size + 1, 33 "左上": -extended_grid_size - 1, 34 "右下": extended_grid_size + 1, 35 "左下": extended_grid_size - 1, 36} 37 38 39def num_direction(num: int, direction: str) -> Optional[int]: 40 if num < 0 or num >= grid_size ** 2: # numが不正な値のとき 41 return None 42 elif direction not in direction_converter: # directionが不正な値のとき 43 return None 44 next_index = grid.index(num) + direction_converter[direction] 45 if (next_num := grid[next_index]) != -1: 46 return next_num 47 return None 48 49 50def main(): 51 # 入力例 52 print(num_direction(0, "右")) # 1 53 print(num_direction(2, "右上")) # None 54 print(num_direction(7, "上")) # 3 55 print(num_direction(-1, "下")) # None 56 print(num_direction(16, "下")) # None 57 print(num_direction(16, "斜め")) # None 58 59 60if __name__ == "__main__": 61 main() 62

投稿2020/03/17 00:46

編集2020/03/17 04:41
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

コードを見ていて思ったのは「これwhile文なくても良くない」ですね。
このコードならif文で代用出来ます。

otnさんも仰っているようにdict型を使って少し行数を減らし、メンテナンス性を向上させると共に、numがgrid以上の場合のreturn値の設定もお願い致します。

投稿2020/03/17 00:44

stdio

総合スコア3307

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

dict型を使って、"左"をキーにして-1を得るとかすると、もう少し行数は減ります。

あと、コードに全角記号が紛れ込んでますね。

投稿2020/03/16 23:38

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

全体としては短くなっていませんが、num_direction() は 短く そして、 if の羅列でない形にすることはできます。
wc.py

python3

1DELTAS = [ 2 ["左上", "上", "右上"], 3 ["左", None, "右"], 4 ["左下", "下", "右下"] 5] 6 7def direction_to_dxdy(direction, big_num): 8 for y in range(3): 9 for x in range(3): 10 if direction == DELTAS[y][x]: 11 return [x - 1, y - 1] 12 return [big_num, big_num] 13 14 15def num_direction(num, size, direction): 16 x0, y0 = [num % size, num // size] 17 if (0 <= x0 <= size and 0 <= y0 <= size): 18 dx, dy = direction_to_dxdy(direction, size * 10) 19 x1, y1 = [x0 + dx, y0 + dy] 20 if 0 <= x1 <= size and 0 <= y1 <= size: 21 return y1 * size + x1 22 return None 23 24# 入力例 25SIZE = 4 26print(num_direction(0, SIZE, "左")) # => None 27print(num_direction(0, SIZE, "上")) # => None 28print(num_direction(0, SIZE, "右")) # => 1 29print(num_direction(0, SIZE, "下")) # => 4 30print() 31 32print(num_direction(5, SIZE, "左")) # => 4 33print(num_direction(5, SIZE, "上")) # => 1 34print(num_direction(5, SIZE, "右")) # => 6 35print(num_direction(5, SIZE, "下")) # => 9 36print() 37 38print(num_direction(-1, SIZE, "")) # => None 39print(num_direction(16, SIZE, "")) # => None 40print(num_direction(1, SIZE, "斜")) # => None

実行例
イメージ説明

移動先の名前を変更したり、
1 つ隣だけでなく 2 つ隣の場合も扱うようにするといったことが
DELTAS の設定の変更と direction_to_dxdy() の少しの変更だけで行えます。

投稿2020/03/18 15:37

編集2020/03/18 15:47
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問