技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

久々にと思い出した UML の入門書が実に入門してた件

日が空きました…いや、昨日はUターンラッシュの中でくたばってたのですよ(苦笑

本日やったこと。

入社直後位に UMTP L1 試験(2008年)受けて受かってるのだけど、気づけば UML 2.5 (2015)までバージョンアップしてるらしい。
ということで、振り返りもかねて読んでみようかと Amazon 先生を漁ったわけです。

ちなみにライブラリは Web でいいやん派ですが、言語やフレームワークアーキテクチャは本を読むようにしてます。

  • 本は、体系的に記述されているため、全体像が見えやすい
  • Web 記事は一部に着目して、代わりに深い内容をしているモノが多い

という所で、使い分けですね。

かんたん UML入門 [改訂2版] (プログラミングの教科書)

かんたん UML入門 [改訂2版] (プログラミングの教科書)

尚、選択理由は割と新しくて評価の高いものという適当具合。

とはいえ、確かにこれは「かんたん」で、死ぬほど単純に必要最小限にとどめている。
思い出しながら読む位なら、かなりスラスラ行く。

逆に言えば、深みが無いので、しれっと読んで分かった気になりやすそうという危険もありそうです。

これはこれで、入門者にとてもオススメできるのですが、あんまり警戒せずにもう少しガチ本買うべきだったかもしれないとも思った(汗

機械学習と深層学習実習 4 章

※随時更新

ニューロンの実装…ても基礎中の基礎で、ゼロDeep本でも実装したのだけど

import math
import sys

INPUTNO = 2
MAX_INPUTNO = 100


def get_data(e: list) -> int:
    line_no = 0
    for line in sys.stdin:
        e[line_no] = [float(num) for num in line.split()]
        line_no += 1
    return line_no


def forward(w: list, e: list) -> float:
    u = 0.0
    for i in range(INPUTNO):
        u += e[i] * w[i]
    u -= w[INPUTNO]
    o = f(u)
    return o


def f(u: float) -> float:
    # ステップ
    #if u >= 0:
    #    return 1.0
    #else:
    #    return 0.0
    # シグモイド
    return 1.0 / (1.0 + math.exp(-u))


w = [1.0, 1.0, 1.5]
e = [[0.0 for i in range(INPUTNO)] for j in range(MAX_INPUTNO)]

n_of_e = get_data(e)
print(f'Data size: {n_of_e}')

for i in range(n_of_e):
    print(f'{i} : {e[i]} -> {forward(w, e[i])}')

シグモイド関数と、ステップ関数はコード内での切り替え。
ここでは学習ロジックがないので、重み付けは固定値。

ここにデータ(下記)を加えて、重みを弄ると、動作が変わるよーという実験。

0 0
0 1
1 0
1 1

プログラマ脳を鍛える数学パズル 20

「受難のサファードの魔法陣」という問題の回答

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

from itertools import combinations

numns = [
    1, 14, 14, 4,
    11, 7, 6, 9,
    8, 10, 10, 5,
    13, 2, 3, 15
]

counts = {}

for i in range(1, len(numns) + 1):
    for c in combinations(numns, i):
        sum_val = sum(c)
        if sum_val in counts.keys():
            counts[sum_val] += 1
        else:
            counts[sum_val] = 1

sum_value = 0
counter = 0

for key in counts.keys():
    if counter < counts[key]:
        counter = counts[key]
        sum_value = key

print(f'Sum: {sum_value}, Counts: {counter}')

プログラマ脳を鍛える数学パズル 19

続きです。

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

これを 20 分とか言語によるでしょ…マジで。
ヒントで素数を作っておけば…みたいな事は書いていますが、そもそもこのジェネレータが存在するのか分からん…。

仕方ないので、作ったのが以下の prime_generator で、メモリの続く限りは素数を生成する。

きちんと追いかけると分かるが、取り出すたびに stream の中に is_individable のスタックが溜まっていくので、どこかでフローする。
あと、論理的には判定対象の数字 N を割って試す数は N/2 まででいいはずだが、この論理だと、過去出た全ての素数を判定するので、利用しやすさはまだしも無駄は多い。

import itertools
import functools


def prime_generator():
    stream = itertools.count(2)
    def is_individable(x, y): return x % y != 0

    while True:
        prime = next(stream)
        stream = filter(functools.partial(is_individable, y=prime), stream)
        yield prime


if __name__ == "__main__":
    prime_gen = prime_generator()
    prime_nums = [next(prime_gen) for _ in range(6)]
    min_value = prime_nums[-1] ** 2
    min_datas = []

    for prime in itertools.permutations(prime_nums):
        friends = []

        # Head/Tail
        head = prime[0]
        tail = prime[-1]

        # Calc head*head, head*(head+1)...(tail-1)*tail
        for n in prime:
            friends.append(head * n)
            head = n

        # tail
        friends = friends + [tail**2]

        # update current result
        if min_value > max(friends):
            min_value = max(friends)
            min_datas = friends

    print(f'Minimum: {min_value} at Datas: {min_datas}')

プログラマ脳を鍛える数学パズル 18

今日も今日とて。

平方数というのがめんどくさい…

from math import sqrt


def is_square_pairs(n: int, cuts: list, squares: list) -> bool:
    prev = cuts[-1]
    if n == len(cuts):
        # 全要素が埋まった
        if (1 + prev) in squares:
            # 最初の一つ(固定 1)と最後の一つの合計がが平方数である
            print(f'Count: {n}, Cuts: {cuts}')
            return True
    else:
        # 接続し得る候補の計算
        maybe = [x for x in range(1, n + 1) if x not in cuts]
        # 候補を順に試していく
        for i in maybe:
            # 前回の値と今回の値の合計が
            if (prev + i) in squares:
                if is_square_pairs(n, cuts + [i], squares):
                    return True
    return False


n = 2

while True:
    sqrts = [x ** 2 for x in range(2, int(sqrt(n * 2) + 1))]
    if is_square_pairs(n, [1], sqrts):
        break
    n += 1

print(n)

プログラマ脳を鍛える数学パズル 17

今回はコードをみれば何がしたいか分かるかと

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

とまぁ愚直に再起すればよく、前回並んだ性別と、後何人並べるかで残りのパターン数は決定される(後述)ので、メモを取りながら再起すればいい。

例えば、男性スタートで 3 人並ぶとすれば、BBB, BGB, BBG, GBB, GBG の5通りだが、女性スタートなら BBB, BGB, BBG の 3 通りしか存在しない。
逆にそれより前が何人、どう並んでようと、このパターン数は変わらないので、直前に並んでいる男女と、残りの人数でパターン数が決定できる。

BOY = 'B'
GIRL = 'G'

n = 30
memo = {}


def add(current: list) -> int:
    counts = len(current)

    # 30 人並んだら終了
    if counts >= n:
        return 1

    # 前回並んだ人
    last = current[-1] if counts > 0 else 'N'

    # メモがあればそこから応答
    if (last, counts) in memo:
        return memo[(last, counts)]

    # 男女を繋げる
    cnt = 0
    for cur in [BOY, GIRL]:
        # 女性は連続して並べない
        if last == GIRL and cur == GIRL:
            continue
        # パターンをカウント
        cp = current[:]
        cp.append(cur)
        cnt += add(cp)

    # メモ化
    memo[(last, counts)] = cnt

    # カウント応答
    return cnt


print(add([]))

プログラマ脳を鍛える数学パズル 16

3本の紐があって、1本を正方形、2本を長方形にしたとき…と言う様な問題。

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

式変換をした跡が残ってるけどそのまま記載。
ただし、問題の制約条件で、同じ比率の組み合わせを除外すると言ってるのが実は引っ掛け。

ここを読み飛ばすと、170 個超えて、結果が合わなくて「ん?」ってなる(というか踏んだ)

from itertools import combinations
from math import gcd

N = 500
count = 0

# sq * sq
#   = ((sq - x) + (sq + x)) + ((sq - y) * (sq * y))
#   = (sq*sq - x*x) + (sq*sq - y*y)
# -sq^2 = -x^2 -y^2
# sq^2 = x^2 + y^2

for n in range(1, int(N / 4) + 1):
    sqrt = n * n
    # 正方形に一辺を超えない範囲で二つの四角の一辺補正値を選ぶ
    # モノが四角形の一辺の為、正方形の一辺を超えると、
    # 四角形のくせに1辺がマイナス長とか意味不明な事象が起きるので
    for x, y in combinations(range(1, n), 2):
        if sqrt == x*x + y*y:
            if gcd(x, y) == 1:  # 同じ比率の整数倍を弾く
                count += 1

print(count)