乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

プログラミング

今回は音声認識ライブラリの
「Whisper」を用いて
音声の文字起こしを行ってみました

解説動画はこちら


 
Whisperとは

OpenAIの音声認識ライブラリ

68万時間分の大規模なデータセットで
学習された自動音声認識モデル
音声から文字起こしする事ができます

早速使っていきましょう

Google Colabを用いて
コードを動かす事ができます


インストール

インストール方法は次の1行で簡単です
# whisperのインストール
!pip install git+https://github.com/openai/whisper.git

次はライブラリのインポートです
# ライブラリのインポート
import whisper
model = whisper.load_model("base")
これも2行でできます

用意が出来たら
音声ファイルを置きましょう

配置場所はファイル置き場です
スクリーンショット 2023-01-07 16.38.48


こんな感じでファイルを配置しましょう

文字起こしをするのは次のコードです
# 音声ファイルの書き起こし実行
audio_file_path = "ファイルパス"
result = model.transcribe(audio_file_path)
print(result["text"])

音声ファイルの中身によって
結果は変わります

いろいろ試してみて下さい

動画ではいくつかの
音声文字起こしをしているので
そちらも参考にしてみて下さい


今回はここまでです
それでは

今回は2枚の静止画から
クッソかわいい動画を作成してみました

解説動画はこちら





今回使用するのは
FILM(Frame Interpolation for Large Motion)
という技術でs

ニューラルネットワークを用いた
フレーム補間技術になります


2枚の静止画の間を繋ぐ様に静止画を作成して
動画化する事ができます

デモなどはこちらから参照する事ができます

FILMのgit

こちらのサイトのデモを使って
静止画を動画化してみました

1フレーム目はこの画像
frame1


2フレーム目はこの画像です
frame2


この間のフレームを補完してくれる訳ですね

出来上がったのはこんな感じ

71dt0-6t2tb


2枚の間の違和感なく
フレームが保管されているのでは
ないでしょうか!!

めちゃくそカワイイですねーーーーー

こんな感じで
2枚の静止画を用意すれば動画にできるので
たくさん用意すれば、動画作品を
作る事も可能ではありそうですね

うまく使えば面白い技術だと思いますので
試したい方はデモサイトを
覗いてみて下さい

それでは

今回はソーシャルハッキング を用いた
携帯番号推測方法についてです


解説動画はこちら



・今回のテーマ

電話番号が気になっちゃう
っていう人のために

気になる相手の電話番号を
推測する方法についてお伝えします

これはソーシャルハッキング
を用いた電話番号推測法になります

まずは、携帯番号占いに誘う必要があります

・携帯番号占い
琉球風水志シウマさんがやっている
携帯番号を用いた占いのことです

携帯番号下4桁を足した数字で
占いを行い、結果を伝えています

数字が持つパワーで運気が変わるとか
変わらないとか・・・

ただ今回は、占いを行う必要はありません
占いのフリで良いので
占い自体を覚えなくても行えます


・番号推測の方法
「携帯番号占い」出来るていで
相手に数字を聞く事が出来ればOKです

ここでは、進化した「携帯番号占い」を
行うていで進めていきます



・番号を聞く手順
1.「上4桁(4-7桁目)」「下4桁(8-11桁目)」の
合計値と末尾の値の4つを聞く

(上4桁の合計値) , (上4桁の末尾)
(下4桁の合計値) , (下4桁の末尾)

2.占いの結果は適当に答えるも良し
真面目に答えるも良し

3.適当に「ラッキカラー」と
「開運グッズ」とかを答えておけば良い

4.上4桁と下4桁を推測して
最後に080 or 090 をつける


・電番の一部を推測するコード


聞いた数字から、電番を予測していきましょう
合計値と、末尾の数字から
その4桁の候補を出すコードがこれです

例:下4桁の合計値が「30」で末尾が「3」の場合
import itertools

def check_num(num1,num2):
    result = []
    L = [str(i) for i in range(10)]
    for p in itertools.product(L,repeat=4):
        ans = sum([int(a) for a in p])
        if ans==num1 and int(p[3])==num2:
            result.append([int(a) for a in p])
    return result

# (合計値 , 末尾の数字)
check_num(30,3)
[[9, 9, 9, 3]]


こんな感じで関数の引数に
合計値と末尾の数字を入れてあげると
その4桁の候補が出ます

これを上4桁、下4桁で行い
080 or 090 をつければ完成です


・合計値の組み合わせの数

問題になるのは、合計値の組み合わせ数です
どれくらい存在するでしょうか?
import itertools
import matplotlib.pyplot as plt
%matplotlib inline

result = {}
L = [str(i) for i in range(10)]
for p in itertools.product(L,repeat=4):
    ans = sum([int(a) for a in p])
    if ans in result:
        result[ans] +=1
    else:
        result[ans] = 1

plt.figure(figsize=(10,5))
X = [k for k,v in sorted(result.items())]
Y = [v for k,v in sorted(result.items())]
plt.bar(X,Y)
plt.show()
download

合計値は0 - 36までの37通りあり
合計値18の組み合わせが一番多いです

この付近に当たってしまうと
組み合わせ数が多すぎて特定できないかもしれません

ただ合計値1桁や30以上は
組み合わせが少なくなるので
一意に特定できる事もあります




・まとめ
うまく話術を磨いて、数字を聞き出せないと
ダメだけど・・・頑張りましょう!!!!

合計値が5以下や30以上の場合は大チャンス!!!

合計値が13-23あたりだった場合は、キツ目

合計値が18あたりだった場合は、あきらめよう

さらに末尾2桁教えて貰えば、勝てるかも

プログラミング技術が無くても
話術があれば何とかなる

ってか、直接電番を聞ければ
占いをする必要も無いので
小細工しない方が早いかもしれません

まあ、聞けない方々のための
姑息な方法になりますので
是非試して遊んでみて下さい

それでは

今回は日本で一番人気の漫画である
Hunter x Hunterに登場するアイテム
「リスキーダイス」をMatplotlibで
制作してみました

解説動画はこちら



リスキーダイスについての説明は
改めてする必要も無いでしょうけども
一応やっておきますね

HUNTER × HUNTER に出てくる
アイテムの一つで20面体のサイコロ

19面が大吉で、1面が大凶
大吉が出るととてもいいことが起こる
ただし大凶が出るとそれまでに出た
大吉分がチャラになるほどの不幸が起きる

という素敵なアイテムです

これを作っていくのを考えましょう

正20面体は正三角形が
20個組み合わさった多面体です

これを展開したものを
Matplotlibで描写していきます

正三角形を描くには
3点が必要です

三角形

頂点の座標
正三角形の高さは
公式で求められます

それぞれの座標を求めて3角形を描き
展開図になるように3角形を
配置すれば良いですね

ただそれだけだと組み立てられないので
余白、のり代部分を作ってあげます

Matplotlibで描画する際には
三角形を描くメソッド
matplotlib.patches.Polygon
というのが有ります

これに3点を渡してあげれば
三角形が描画出来ます

あとは「大吉」などの文字を
ax.text で描画してあげれば
20面体のサイコロとなりますが
Matplotlibは初期状態だと
日本語フォントに対応してないので
別途インストールが必要です


リスキーダイスの展開図を描画するコードはこちら
import matplotlib.pyplot as plt
import matplotlib.patches as pat

fig = plt.figure(figsize=(16, 16))
ax = plt.axes()

# 正20面体
l=1
h = (l**2 - (l/2)**2) ** 0.5
for i in range(5):
    x=l*i
    # 1段目
    p = pat.Polygon(xy = [(x,0), (x+1,0), (x+l/2 , h)],fc = "gray",ec = "black")
    ax.add_patch(p)
    p = pat.Polygon(xy = [(x+l/2,h), (x+l/2+l,h), (x+l , 0)],fc = "white",ec = "black")
    ax.add_patch(p)
    # 2段目
    p = pat.Polygon(xy = [(x+l/2,h), (x+l/2+l,h), (x+l , h*2)],fc = "gray",ec = "black")
    ax.add_patch(p)
    p = pat.Polygon(xy = [(x,h*2), (x+l,h*2), (x+l/2 , h)],fc = "gray",ec = "black")
    ax.add_patch(p)
    # 3段目
    p = pat.Polygon(xy = [(x,h*2), (x+1,h*2), (x+l/2 , h*3)],fc = "white",ec = "black")
    ax.add_patch(p)
    p = pat.Polygon(xy = [(x+l/2,h*3), (x+l/2+l,h*3), (x+l , h*2)],fc = "gray",ec = "black")
    ax.add_patch(p)

# のり代
p = pat.Polygon(xy = [(l*5,h*2), (l*5+l,h*2), (l*5+l/2 , h)],fc = "white",ec = "black")
ax.add_patch(p)

# 切り取りライン
for i in range(4):
    x=l*i + l
    plt.plot([x, x+l/2], [0, h],color="red")
    plt.plot([x, x+l/2], [h*2, h*3],color="red")

# テキスト
for i in range(5):
    x=l*i
    if i!=0:
        ax.text(x + l/2 , h/3 , '大吉',color="white",size=30,va='center', ha='center')
    else:
        ax.text(x + l/2 , h/3 , '大凶',color="red",size=30,va='center', ha='center')
    ax.text(x + l , h/3+h , '大吉',color="white",size=30,va='center', ha='center')
    
    # 逆さ文字
    ax.text(x + l , h*3-h/3 , '大吉',color="white",size=30,va='center', ha='center',rotation = 180)
    ax.text(x + l/2 , h*2-h/3 , '大吉',color="white",size=30,va='center', ha='center',rotation = 180)

plt.axis('scaled')
plt.axis('off')
plt.show()

実行すると・・・
こんな感じのが出来上がります

リスキーダイス

リスキーダイス


これをカラー印刷すると・・・
リスキーダイス展開図

いらない部分を切り取って
赤い線は切り取り線で
白い部分がのり代です

いい感じに糊付けすると・・・

リスキーダイス完成形

いい感じにサイコロになりました

W杯
日本 vs クロアチア

何度か振った結果・・・

大吉しか出ませんでしたーーー


なので、クロアチアにも
勝ってくれる事でしょうwww

今回はリスキーダイスを
Matplotlibで制作してみました

作りたい方は画像をダウンロードして
印刷して工作してみて下さい

それでは
 

今回はプロジェクトオイラーの
数学の問題を解いてみました

解説動画はこちら


 
さて
プロジェクト・オイラー

は、英語で書かれた
数学的/コンピューター プログラミングの問題集です
リンクから色々な問題をみる事ができます

レオンハルト・オイラーは
18世紀の数学者・天文学者のことですね

今回はこれを解いていきたいと思います
数学の問題をプログラムを
駆使して解いてみましょう

問題を考えたい人は
動画を止めて考えてみて下さい

解答そのものは動画をご覧ください






問題1

1000未満の3か5の倍数の合計値を求めよ






・・・・・

・・・・

・・・

・・










解答1

比較的簡単な問題です

1000未満の数値の生成
3と5の倍数の判定
合計値を求める

これらが達成出来ていれば
解けると思います

sum([i for i in range(1,1000) if i%3==0 or i%5==0])





問題2

400万未満のフィボナッチ数で

偶数の物の合計値を求めよ

フィボナッチ数とは

1, 2, 3, 5, 8, 13, 21, 34, 55, 89 のように

どの数字も前2つの数字を足した数字のこと




・・・・・

・・・・

・・・

・・



解答2

フィボナッチ数を求める関数を作って
400万までのリストを作り
偶数のものを抜き出せば解けます

フィボナッチ数のリストを返す関数
# その数までのフィボナッチ数を求める
def fib(num):
    a , b , fib_l = 0 , 1 , []
    while b <= num:
        fib_l.append(b)
        a , b = b , a+b
    return fib_l

sum(([f for f in fib(4000000) if f%2==0]))

ジェネレーター式でも同様に出来ます
# ジェネレーター形式
def fib_gen(num):
    a , b = 1 , 1
    while b <= num:
        yield b
        a , b = b , a+b
        
sum(([f for f in fib_gen(4000000) if f%2==0]))




問題3

600851475143 の最大の素因数を求めよ

素因数分解をして、その最大値を求める


・・・・・

・・・・

・・・

・・






解答3

素因数分解をする手法はたくさん有りますが
中でも簡単な試し割り法を使って
素因数分解してみましょう

素因数分解しようとする整数nを
小さい順に割ってみて
割り切れるかどうかを調べる手法です


num = 600851475143

# 3から奇数で割っていく
f , a = 3 , []
while f * f <= num:
    
    # 割り切れたら素因数に採用
    if num % f == 0:
        a.append(f)
        
        # 次の数は、素因数で割った数で探す
        num //= f
    
    # 割り切れなければ次の素数へ
    else:
        f += 2
        
if num != 1:
    a.append(num)

# 素因数の組み合わせ
print(a)

# 素因数の最大値 
print(sorted(a,reverse=True)[0])


なお、ライブラリを用いれば
簡単に素因数分解できてしまいます
# ライブラリで素因数分解
import sympy

num = 600851475143
sympy.factorint(num)





問題4

2 つの 3 桁の数の積から作られる

最大の回文数値を求めよ

101*101 = 10201 のような

回文になる数値の最大値を求める


・・・・・

・・・・

・・・

・・






解答4

数値を文字列に直してひっくり返せば
回文の出来上がりです

answer = {}

for a in range(100,1000):
    for b in range(100,1000):
        s_num = str(a * b)
        if s_num == s_num[::-1]:
            answer[a * b] = [a,b]

for k,v in sorted(answer.items(),reverse=True):
    print(k,v)
    break








問題5

1 から 20 までのすべての数で割り切れる

最小の正の数を求めよ

最小公倍数を求める問題


・・・・・

・・・・

・・・

・・







解答5

最小公倍数は
次の様な計算式で求められます

最小公倍数 = 数値の積 ÷ 最大公約数


最大公約数を求めるには
ユークリッドの互除法を用います

ユークリッドの互除法は
2つの自然数の最大公約数を求める
手法の一つですが
比較的実装が楽です

# ユークリッドの互除法
# 最大公約数を求める
def gcd(a, b):
    if a == 0:
        return b
    m = b % a
    return gcd(m, a)

# 最小公倍数 = 数値の積 / 最大公約数
from functools import reduce

# 最小公倍数を計算する(2つ)
def lcm_base(x, y):
    return (x * y) // gcd(x, y)

# 最小公倍数を計算する(複数)
def lcm(*nums):
    return reduce(lcm_base , nums, 1)


s = [i for i in range(2,21)]
# 最小公倍数をリストで求める際は * を付ける
lcm(*s)



python3.8以降なら
ライブラリでも求められます
# 最小公倍数を求める
import math
s = [i for i in range(2,21)]

# 最小公倍数をリストで求める際は * を付ける
math.lcm(*s)






問題6

100 個の自然数の

和の 2 乗と 2 乗の和の差を求めよ

例1,2,3

(1 + 2 + 3)^2 − (1^2 + 2^2 + 3^2) 

= 36 −14 

= 22



・・・・・

・・・・

・・・

・・






解答6


和の2乗は比較的楽に計算できますが
2乗の和は少しコツがいります

map関数は関数を引数に指定できるので
リストの要素に
関数を適応した結果を求めるのに
すごく役立ちます
nums = [i for i in range(1,101)]

# 和の2乗
sum_square = sum(nums) ** 2
print(sum_square)

# 2乗の和
sum_of_squares = sum(map(lambda n : n**2 , nums))
print(sum_of_squares)

# 2乗の和と和の2乗の差
print(sum_square - sum_of_squares)





問題7

10001 番目の素数を求めよ





・・・・・

・・・・

・・・

・・





解答7

素数を求めるのは流石に面倒くさいので
ライブラリの力を借りましょう

isprimeメソッドは
実行速度がめちゃくちゃ速いので
大抵の人が実装したものよりも
速いだろうと思います
# 素数を求めるライブラリ
from sympy import isprime

primes = [2,3]
for i in range(5,200001,2):
    if isprime(i):
        primes.append(i)
    if len(primes)==10001:
        answer = i
        print(answer)
        break


ライブラリでその数値までの
素数の個数を数える事も出来ます
# ライブラリで素数の個数を数える
from sympy import primepi

print(primepi(answer))







問題8

次の1000 桁の数の中で

最大の積を持つ隣接する13桁は何か

数値は下記をお使いください

73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450






・・・・・

・・・・

・・・

・・





解答8


まずは文字列をデータ化しますが
きちんとゴミを取り除いておきましょう

文字列を数値に直して
計算すればOKです

総積を求めるのは
for文を使っても良いですが
reduce関数などを使って
まとめる事ができます


data = '''
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
'''.replace('\n','')

import operator
from functools import reduce

answer = {}
for i in range(0 , len(data)-12):
    nums = data[i : i+13]
    if '0' in nums:
        continue
    
    # 総積を求める
    a = reduce(operator.mul, [int(n) for n in nums],1)
    answer[a] = nums
    
for k,v in sorted(answer.items(),reverse=True):
    print('数値 :  {0} , 文字列 : {1}'.format(k,v))
    break







問題9

a < b < c で a + b + c = 1000である時

ピタゴラスのトリプレットとなる数値の

 a * b * c の値を求める

ピタゴラスのトリプレットとは

a^2 + b^2 = c^2






・・・・・

・・・・

・・・

・・




解答9

a<b<c かつ a+b+c=1000 なので
abcの数値の最大値はおのずと決まってきます

あとはピタゴラスの定理のような
関係性になる数値を探し当てれば
それが答えです


# aの最大値は1000の3分の1より小さい
for a in range(1, 332):
    
    # bの最小値は a+1、最大値は 1000から a を引いた半分
    for b in range(a + 1 , (1000 - a)//2):
        c = 1000 - (a + b)
        if a**2 + b**2 == c**2:
            print(a * b * c , a , b , c)
            break
    else:
        continue
    break





さて、ここまでが今回の内容です
なかなか面白い問題ばかりですねえ


まだまだプロジェクトオイラーには
たくさんの問題が残っているので
これからも問題を解いていきたいと思います

それでは

このページのトップヘ