note-tmk

a note of software developer in japan.

RailsとVue.jsを勉強します

7月から新しい会社にお世話になるので、それに向けて有休消化中に勉強を進めようと思います。

現在はFlutterのみでの開発ですが、今後はRailsやVue.jsも扱うことになる予定です。 そこで少しでもキャッチアップを早くするため、7月までにこれらの技術を勉強しようと思います。。

Railsは有名なRailsチュートリアルをやる予定です。 Vue.jsは特に定番の教材などなさそうなので、適当にサービスを作って公開することを目標にします。

【Python】選択ソート、挿入ソートの実装

選択ソート

配列から最小・最大値を探し,先頭要素と交換することを繰り返すことで整列を行う方法。 未整列部分の値を全て確認するので、等差数列的に計算数が加算され、時間計算量は0(n2)必要になる。

def selection_sort(arr):
    # 結果を出力するリスト
    result = arr

    for i in range(len(result)):
        # 未整列部分の中から最小値を探す
        for j in range(i + 1, len(result)):
            if result[i] > result[j]:
                tmp = result[i]
                result[i] = result[j]
                result[j] = tmp

    return result

挿入ソート

配列を「整列済み」と「未整列」の2種類に分け、未整列配列から整列済み配列の適切な場所に要素を挿入する方法。 ソート前に配列が整列されている部分が多いと計算量はO(n)になる。全く整列されていない場合はO(n2)になる。

def insert_sort(arr):
    if len(arr) < 1:return arr
    # 結果返却用
    result = arr

    # ソート前は先頭のみを整列済みとして扱う
    for i in range(1,len(result)):
        current_value = result[i]
        for j in range(i-1,-1,-1):
            print(i, j)
            if current_value < result[j]:
                result[j + 1] = result[j]
                result[j] = current_value
            else:
                break

    return result

【Python】動的計画法

動的計画法

解決するべき問題を簡単に解決できる細かい問題に分割し、その細かい問題の解答を利用して大きな問題を解くこと。

動的計画法に向いている問題

再帰的な問題は向いている。 また最適部分構造(親問題が最適化を問うており、その子問題も同様に最適化を問うている)を持っている問題も向いている。

アプローチ

動的計画法には大きく分けて「タビュレーション」と「メモ化」という2つのアプローチがある。

タビュレーション

タビュレーションとは「表」を表す。つまり計算結果を表に保管しておき、それをキャッシュとして参照し重複した計算を減らすというもの。 計算を行う順序はベースケース(ex. n=0)→目的のケース(ex. n=100)のようにボトムアップ方式で行う。

例えば再帰的なアルゴリズムを想定する。f(n)を求める場合にf(n-1)が必要とすると、 タビュレーションにおける計算順序は f(0)→f(1)→...→f(n)となる。

メモ化

基本的な考えはタビュレーションと同様で、計算結果をキャッシュする。 異なるのは計算順序

タビュレーションがボトムアップであったのに対してメモ化はトップダウン。 つまり上記例だとnが大きいものからキャッシュされているかを確認し、キャッシュされていない場合は それを計算して結果をキャッシュに保存するというもの。

アプローチ選択

全ての下位問題(上記例の場合n=0など)を解く必要がある場合はタビュレーションの方が優れている。 再帰関数をスタックに保存する手間が省けるからである。

一方全ての下位問題を解く必要がない場合はメモ化の方が良い。 最終的な解を求めるために必要な処理のみを行うからである。

【Python】エラトステネスの篩を実装する

エラトステネスの篩

素数を見つけるためのアルゴリズム素数の倍数を除外していき、全ての数値を走査して最後まで除外されなかった数値群が素数となる。

ja.wikipedia.org

実装

# n以内の素数をリストで返す
def sieve_of_eratosthenes(n):
    
    n += 1

    if n == 2: return [2]

    # キャッシュ
    cache = [True] * n

    for i in range(2, n + 1):
        # キャッシュにヒットしたら計算しない
        if not cache[i]: continue

        multiple = 2
        i_multiple = i * multiple

        while i_multiple < n:
            # iの倍数は素数ではないのでFalse
            cache[i_multiple] = False

            # 倍数をインクリメント
            multiple += 1
            i_multiple = i * multiple

    # 素数
    primes = []

    for index, predicate in enumerate(cache):
        if predicate: primes.append(index)
    
    # 0と1は素数に含まない
    return primes[2:]

【Python】式内展開、文字列補間(String Interpolation)の方法

fキーワードをクオートの前につける。 変数は{}で括る。

name = "taro"
age = 20

print(f"My name is {name}. I am {age} years old.")
# My name is taro. I am 20 years old.

【Python】2次元の正方行列をリスト内包表記で生成

[[0, 1, 2, 3, 4],
 [5, 6, 7, 8, 9], 
 [10, 11, 12, 13, 14], 
 [15, 16, 17, 18, 19], 
 [20, 21, 22, 23, 24]]

上記の正方行列は次のように記述することで生成できる。

myMatrix = [[i + 5 * j for i in range(5)] for j in range(5)]

print(myMatrix)
# [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23, 24]]

【Python】リスト(List)型データの生成・操作方法まとめ

現在Recursionに取り組んでいる。 そこで学んだことをメモする。


リスト(List)

複数のデータをまとめたデータ構造。 各データにはインデックス(index)と呼ばれる番号が割り振られる。 インデックスは先頭から0で始まり、1つ隣に移動するごとにインデックスが1つ増える

www.python.jp

Pythonにおいてリストは動的配列と呼ばれる形式。 なのでリストに含まれるデータ型は統一されている必要はない

e-words.jp

生成

直接要素を指定

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(myList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

リスト内包表記

myList = [val for val in range(10)]

print(myList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

文字列をリストに変換

myStr = "hello"
myList = list(myStr)

print(myList)
# ['h', 'e', 'l', 'l', 'o']

任意の値を任意個数要素にもつリストを生成

my_list = [0] * 10
print(my_list)

# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 

操作

読み取り

特定インデックスの値

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(myList[5])
# 5

for文を使用して繰り返し処理

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

for val in myList:
    print(val)
    
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9

後ろから数えた特定インデックスの値

追加

末尾に要素を追加(append)

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

myList.append(10)

print(myList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

末尾に複数の要素を追加(extend)

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

myList.extend([10,11])

print(myList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

特定インデックスに値を追加(insert)

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# インデックス5に10を追加
myList.insert(5, 10)

print(myList)
# [0, 1, 2, 3, 4, 10, 5, 6, 7, 8, 9]

特定のインデックスに複数の値を追加(スライスを用いる)

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# インデックス0に10, 11, 12, 13を追加
myList[0:0] = [10, 11,12,13]

print(myList)
# [10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

更新

特定のインデックス範囲の値を更新(スライスを用いる)

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# インデックス0に10を追加
myList[0:0] = [10, 11,12,13]

print(myList)
# [10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

削除

末尾の値を削除(pop)

myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

myList.pop()

print(myList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8]

特定のインデックスの値を削除(pop)

pop(インデックス)で指定した値は元のリストから削除され、 戻り値に渡される。

myList = [0,1,2,3,4,5,6,7,8,9]

removedVal = myList.pop(5)

print(myList)
# [0, 1, 2, 3, 4, 6, 7, 8, 9]

print(removedVal)
# 5

結合

ソート

昇順にソート(sort)

破壊的な変更なので、元のリストの並びが変更される。

myList = [5, 1, 9, 3, 8, 4, 2, 7, 0, 6]

myList.sort()

print(myList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

降順にソート(sort(reverse=True))

破壊的な変更なので、元のリストの並びが変更される。

myList = [5, 1, 9, 3, 8, 4, 2, 7, 0, 6]

myList.sort(reverse=True)

print(myList)
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

その他

素数を数える

myList = [1,1,2,3,4,5,5,5,6]

print(myList.count(5))
# 3

条件式の中でリストが空か判定する

if not my_list:
    print("empty")

# my_listが空ならば```not []```は```True```と判定される。