プログラミングをしなくては!

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 先生の回答でした.

Last modified: Monday, 4 September 2023, 1:25 AM