バブルソートと線形探索
プログラミングをしなくては!
python を学ぼうと,学習を始めたのが昨年の春.魔法陣を表示するプログラムを作成した後,約1年半のオサボリ.数日前,C言語を中心にアルゴリズムから学習を再開したものの,気の利いた python には大抵のことを可能にするメソッド用意されています.プログラミングの機会がありません.
ないのであれば,その機会を作りましょう.ということで,メソッドに頼らずバブルソートと線形探索をする関数を作ってみました.sampleSortSearch.py のファイル名で保存してあります.
import random
def makeData():
data = []
for i in range(50):
data.append(int(101 * random.random()))
return data
def showData(*data):
print("50個のデータ [")
for i in range(5):
for j in range(10):
print(f"{data[10 * i + j]: >4}", end = "")
print("")
print("] があります.")
def bubbleSort(*data):
a = list(data)
for i in range(50):
for j in range(49 - i):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
print("このデータを昇順に並べ替えると [")
for i in range(5):
for j in range(10):
print(f"{a[10 * i + j]: >4}", end = "")
print("")
print("] となります.")
def linerSearch(target, *data):
result = []
for i in range(50):
if data[i] == target:
result.append(i)
l = len(result)
if l == 0:
print(target, end = "")
print(" はデータリストの中に見つかりませんでした.")
else:
print(target, end = "")
print(" はデータリストのインデックス ", end = "")
print(result, end = "")
print(" の位置に見つかりました.")
次の4つの関数を書いています.
makeData() は 0 ~ 100 の 50 個の乱数を返します.
showData() は,与えられたリストの 50 個の要素を 10 × 5 で表示します.
bubbleSort() は,与えられたリストを昇順にバブルソートして表示します.
linerSearch() は,与えられたリスト中に特定の要素があるかを調べます.
難しいものは何も使っていませんが,新たに気付いた部分や叱られた部分などを解説します.
import random と random()
関数 random() は,Javascript の random() と同じく,0 以上 1 未満の乱数を返します.seed も不要です.そのようなこともあり,お気楽に random() と書いたところ叱られました.
実のところ,random() は random ライブラリ中に定義されているのです.したがって,import random が必要ですし,この書き方では random.random() としなければなりません.
python には random 関連の機能が多数用意されているようです.今のところ,私には random() 一つで OK ですが・・・
return data (in makeData())
関数の戻り値として data を返しているだけです.ここでは,data がリスト(配列)であることに注目してください.これは便利です.python はリストを関数の戻り値にすることができるのですね.C言語がポインタでやり繰りしたものを,python は一行で実現します.
showData(*data)
関数の引数としてリストを渡すことも当然できます.ただし,リストを渡すときには,リスト名の前にアスタリスクを付けなければなりません.
リストを関数に渡す場合,もっと重要なことがあります.上の例で showData(*data) には何の問題も起こりませんでした.
ところが,bubbleSort(*data) でバッチリ叱られました.何を叱られたのかというと,要素を入れ替えようとした部分で「タプルではできない」旨の警告.ナ~ニ~?タプル~?リストだろうが!と怒り心頭に発したのですが・・・.調べてみますと,リストを関数に渡した場合「内部でタプルに変換される」となっていました.
成程ね!リストは弄らず,そのままにして置きたいことがあります.sorted() 関数もリストそのものに変化はありません.そこで
a = list(data)
として,data と同じ構造のリスト a を新たに作り,a の要素をソートしました.data = list(data) でも良いのですが,data を線形探索でも使いたかったので,敢えて別の名前のリストを作りました.
インクリメント,デクリメント演算子が使えない
叱られて初めて知りました.i++,i-- などは使えません.これに関しては i += 1 などと書けば済むことです.全然気になりません.
何分,初めてのこと故,あちらこちらで叱られます.その度にエラーメッセージを読みます.これが,結構英語の勉強になりますねぇ(と強がり).強がりは兎も角,間違えてミスを指摘され,その指摘を基に検索をかけるとドンピシャで正解が得られます.やはり,実践は強い.何も分からなくても問題ありませんね.
実行結果
In [1]: from sampleSortSearch import *
In [2]: a = makeData(); showData(*a)
50個のデータ [
74 40 67 79 45 60 79 47 23 60
35 36 39 64 59 2 41 70 78 23
6 46 33 43 0 21 5 15 44 5
19 71 14 48 61 50 16 98 54 13
10 41 29 95 95 29 32 10 33 2
] があります.
In [3]: bubbleSort(*a)
このデータを昇順に並べ替えると [
0 2 2 5 5 6 10 10 13 14
15 16 19 21 23 23 29 29 32 33
33 35 36 39 40 41 41 43 44 45
46 47 48 50 54 59 60 60 61 64
67 70 71 74 78 79 79 95 95 98
] となります.
In [4]: linerSearch(60, *a)
60 はデータリストのインデックス [5, 9] の位置に見つかりました.
In [5]: a.index(60)
Out[5]: 5
a.index(60)
In [5]: で実行した a.index(60) は,リストの index() メソッドです.リスト a に 60 という要素が含まれているか?含まれているならばどの位置にあるか?を調べます.探索ですね.Out[5]: 5 ということは,a[5] が 60 ですね.確かにそうですし,linerSearch(60, *a) の結果とも一致しています.ただし,先にある一つしか示しませんが.
python の探索アルゴリズムは,整列のように一種類ではないようです.使うライブラリや探索を行う状況により適切なものを選んでいる,というのが chatGPT 先生の回答でした.