1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【非推奨】日本語でプログラムを書いたら幅優先探索(BFS)がメチャクチャ分かりやすくなった件【Python】【初心者】

1
Posted at

プログラムというか変数名を日本語にしてみた話ですが、ご存じのようにPythonでは(たぶん他のほとんどの言語も?)非推奨です。
この記事はあくまで自分が幅優先探索(BFS)を理解する目的でやってみたネタということでご笑納ください(日本語変数名ぜったい許さん!という方もいるかもしれないので事前の言い訳w)

背景

  • そろそろ「〇〇法」のように名前の付いているアルゴリズムを覚えないと競プロで行き詰まってきた(AtCoder茶色)
  • でもDP/動的計画法は怖いし(?)、DFS/深さ優先探索はどうも再帰ってのが苦手で1・・・
  • 比較的とっつきやすそうで、苦手のグラフ攻略プラス他にも応用範囲の広そうな幅優先探索を勉強する事にした
  • 探したらQiitaにけんちょんさんのとても分かりやすい記事を発見!2
    • C++わからんなりにサンプルコード見ながら Python で1行1行書いてみて3、理解できた!
  • 理解できた、と思ったのだけど 白紙から自分で書けない(変数は何と何が要るんだっけ?この配列変数の要素は数値だっけ配列だっけ?・・・的な)
    • 注:リンク先けんちょんさんの記事は本当に丁寧でわかりやすいです。実際は手を動かして何度も書かないと空(そら)で打てるほど覚えられなくて当然、なのだと思いますが4自分は斜め方向に行っちゃいまして。

傾向と対策

  • ニワトリ並み記憶力なので、記号的な短い変数名だと10行下に行っただけで変数が何を表してたかコケッと忘れる(歳のせいも?)
    ➡ とりあえず長くてもいいから分かりやすい変数名にした!
まず書いてみた長めの英語変数名のコード(畳んであります)
BFS.py
from collections import deque

n, m = map(int, input().split())
graph = [[] for _ in range(n)]    # これが「グラフ」
for _ in range(m):
    a, b = map(int, input().split())
    graph[a].append(b)
    graph[b].append(a)  # (有向グラフの時はコメントアウトする)

que = deque()                # これが「キュー」
dist_of_v = [-1] * n         # 答えが入るリスト

starting_v = 2
que.appendleft(starting_v)
dist_of_v[starting_v] = 0      # 始点の自分自身への距離は'0'

while que:   # リストに「次に見る頂点」が入っている間は続ける
    curr_v = que.popleft()
    neighbors = graph[curr_v]
    for neighbor_v in neighbors:
        if dist_of_v[neighbor_v] == -1:
            dist_of_v[neighbor_v] = dist_of_v[curr_v] + 1
            que.append(neighbor_v)

print(dist_of_v)
まあ、だいぶ分かりやすくはなった。これで良いといえば良いかも?
  • とは言ったものの変数名やはり長いと感じる(例:dist_of_vとかneighbor_vとか)
  • で、やっぱりパッと見て直感的には頭に入って来ずらい(英語は得意分野なんですがやはり日本人なので)

でどうした

いやどうせならもう変数名を日本語しちゃったらもっと分かりやすいんじゃね? とやってみたのがこれ5

日本語でBFS.py
from collections import deque

頂点の数, 辺の数 = map(int, input().split())
繋がりリスト = [[] for _ in range(頂点の数)]    # これが「グラフ」
for _ in range(辺の数):
    各辺の始点, 各辺の終点 = map(int, input().split())
    繋がりリスト[各辺の始点].append(各辺の終点)
    繋がりリスト[各辺の終点].append(各辺の始点)  # (有向グラフの時はコメントアウトする)

これから見る頂点リスト = deque()                # これが「キュー」
各頂点の始点からの距離 = [-1] * 頂点の数         # 答えが入るリスト

始点にする頂点 = 8
これから見る頂点リスト.appendleft(始点にする頂点)
各頂点の始点からの距離[始点にする頂点] = 0      # 始点の自分自身への距離は'0'

# リストに「次に見る頂点」が入っている間は続ける
while len(これから見る頂点リスト) > 0:   # (Pythonicじゃないですがあえて)
    今の頂点 = これから見る頂点リスト.popleft()
    隣の頂点たち = 繋がりリスト[今の頂点]
    for お隣さん in 隣の頂点たち:
        if 各頂点の始点からの距離[お隣さん] == -1:
            各頂点の始点からの距離[お隣さん] = 各頂点の始点からの距離[今の頂点] + 1
            これから見る頂点リスト.append(お隣さん)

print(各頂点の始点からの距離)


めちゃくちゃわかりやすいじゃん!!    (個人の感想です)

ちょっと真面目に考察

  • 適切な変数名を付けていればコメントはあまり要らないという話があるけど、本当にそんな気がしてきた
    • 英語ネイティブの連中はデフォルトでこの世界に居るのか・・・ ハンデはデカい(かも?)
  • 表意文字「漢字」ってすごいね

その他

  • そもそも変数って数が多いのね:
    • 制御構造= 5回 出現(if x 1, while x 1, for x 3)
      関数・メソッド等= 7 種類 (input(), range(), map等)
      変数= 11種類  重複含めた出現回数= 36回
      考えてみるとそういうもんでしょうね・・・変数やっぱ大事だ
  • あと、このコードぱっと見て文字のほとんどが日本語(=変数)に見えるのはPythonだからというのもありそう

追記

  • 3か月前にほぼ書き終えて、推敲しようとしたまま投稿忘れてました
    • 実はその後、覚えてるだけでも ABC427-CABC436-D と2回「もろBFSキター!」があったんですがAC取れませんでした(泣) 多始点BFSだとか応用はまだなのです~
  1. DFS=再帰必須という訳ではないようですが

  2. アルゴリズムの分かりやすい解説をたくさん書いてくれていて本当に感謝です。「中高生を応援したい」とのお話しですが実は老年も勝手に世話になってます

  3. この書き換え自体とても良い勉強になりました

  4. 本稿の趣旨から外れますが結局は英語変数のまま5回くらい1から打って手で覚えました(2025/12注:また忘れてきた・・・)

  5. Pythonicには while これから見る頂点リスト: でしょうがこの場合意味が分かりにくい気がしてこの書き方にしてます・・・ 突っ込み来そうなので事前に言い訳w

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?