d_tail's memo

プログラミングについて勉強したことや行ったこと,その他気になったことを記録するブログ(予定)

【Python】部分文字列(N-Gram)を列挙したリストを得る

コード

def getCharNGram(n,s):
    charGram = [''.join(s[i:i+n]) for i in range(len(s)-n+1)]
    return charGram

サンプル

def getCharNGram(n,s):
    charGram = [''.join(s[i:i+n]) for i in range(len(s)-n+1)]
    return charGram

for i in range(1,4):
    print(getCharNGram(i,"abc"))

'''
#実行結果
['a', 'b', 'c']
['ab', 'bc']
['abc']
'''

【Python】文字列からリストや辞書型に変換・文字列をコードとして実行【eval】

文字列からリストに変換

コード

a = '[1,2,3]'
b = eval('[1,2,3]')

print(a)
print(type(a))
print(b)
print(type(b))

実行結果

[1,2,3]
<class 'str'>
[1, 2, 3]
<class 'list'>

文字列から辞書型に変換

コード

dic_str = "{'a':'1', 'b':'2', 'c':'3'}"
dic = eval(dic_str)
 
print(dic['a'],dic['b'],dic['c'])

実行結果

1 2 3

文字列をコードとして実行する

コード

a = 1
b = 2
str_cal = 'a + b'

print(eval(str_cal))

実行結果

3

参考記事

PyCharmをインストールする際に参考にしたサイト

PythonIDEであるPyCharmをインストールしました.

参考にさせていただいたサイトをメモしておこうと思います.

参考にさせていただいたサイト

学生だと機能無制限版も無料で使えます.

初期設定をする際に参考にさせていただきました.

これから読みたいサイト

パターン認識と機械学習(上)を読む際に参考にしたサイトや資料まとめ

輪講の題材としてパターン認識機械学習(PRLM)の上巻が選択されたのですが,この本は,私にとっては自力で読むにはかなり難しい本であったので,いくつかのサイトを参考にしました.そのサイトをまとめておこうと思います.

[1] インターネット各地に散逸する「パターン認識機械学習」の解説資料を集約するリポジトリ

このサイトには,様々な団体などの勉強会や読書会で作成された,パターン認識機械学習(PRLM)のスライド資料が集められています.

[2] もし天鳳鳳凰民がビショップの『パターン認識機械学習』を読んだら

この資料はcritter様が作成したもので,PRMLの内容が数式をメインとしてまとめられています.

[3] 『パターン認識機械学習の学習 普及版』

『パターン認識と機械学習の学習 普及版』(PDF)

この資料は,PRMLで必要とされる数学的知識についてまとめられたものです.
書籍としても販売されています.

パターン認識と機械学習の学習―ベイズ理論に挫折しないための数学

パターン認識と機械学習の学習―ベイズ理論に挫折しないための数学

[4] 【機械学習勉強会】パターン認識機械学習(PRML)第1章のまとめ Part.1

この記事では,PRML1章の内容についてわかりやすく簡潔にまとめられています.

APIの知識ゼロからPythonでWebAPIを叩いてみる【なろう小説API】

今までAPIというものを使ったことがなかったので,PythonAPIを使ってデータを取得することを試みてみようと思います.
今回使用するAPIは,小説家になろうに掲載されている小説の情報が取得できる,なろう小説APIです.

なろう小説API

PythonAPIを利用する方法

使い方を調べる

とりあえず,PythonAPIを利用する方法が分からなかったのでググってみたところ,シンプルに使用方法を説明してくださっている記事を発見しました.この記事を参考にさせて頂こうと思います.

tabilike.hatenablog.com

urllib3というライブラリを使うのが良いそうです.
というわけでインストールします.

pip install urllib3

接続する

先ほどの記事に従い,とりあえずなろう小説APIのページにAPIのURLと書かれているURLをそのまま入れて実行してみます.

APIのURL
https://api.syosetu.com/novelapi/api/
GETで送信。POSTでは受信できません。
日本語などマルチバイト文字送信時は文字コードUTF-8にし、URLエンコードしてください。

import urllib3
r = http.request('GET','https://api.syosetu.com/novelapi/api/')

実行結果

NameError: name 'http' is not defined

エラーが出て失敗してしまいました.
そこで公式っぽいドキュメントを見たところ,このように書かれていました.

>>> import urllib3
>>> http = urllib3.PoolManager()
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.status
200
>>> r.data
'User-agent: *\nDisallow: /deny\n'

urllib3 — urllib3 dev documentation
こちらも参考に,コードを書き換えて実行します.

import urllib3
http = urllib3.PoolManager()
r = http.request('GET','https://api.syosetu.com/novelapi/api/')

実行結果

InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning)

すると安全ではないよ,というような警告が出ましたが,今回は試すだけなのでひとまず置いておくことにします.

繋がったかの確認

次は繋がったかの確認を行います.

r.status

実行結果

200

この数字はHTTPステータスコードというものっぽいです.200の場合は成功のようです.

2xx Success 成功 リクエストは受け取られ、理解され、受理された。

200 OK
OK。リクエストは成功し、レスポンスとともに要求に応じた情報が返される。
ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返している。
HTTPステータスコード - Wikipedia

データの中を確認

次はデータの中身を見てみます.

r.data

実行結果 (とても長かったので一部だけ記載)

b'---\n- \n allcount: 563448\n- \n title: >\n \xe7\x95\xb0\xe4\xb8\x96\xe7\x95\x8c\xe3\x81\xab\xe6\x9d\xa5\xe3\x81\x9f\xe3\x81\xbf\xe3\x81\x9f\xe3\x81\x84\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xa9\xe5\xa6\x82\xe4\xbd\x95\xe3\x81\x99\xe3\x82\x8c\xe3\x81\xb0\xe8\x89\xaf\xe3\x81\x84\xe3\x81\xae\xe3\x81\xa0\xe3\x82\x8d\xe3\x81\x86\n ncode: N0885DC\n userid: 615833\n writer: \xe8\x88\x9e\n story: |\n 35\xe6\xad\xb3\xe3\x83\xa1\xe3\x82\xbf\xe3\x83\x9c\xe3\x81\xae\xe3\x82\xb5\xe3\x83\xa9\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\x9e\xe3\x83\xb3\xe3\x81\x8c\xe3\x81\x82\xe3\x82\x8b\xe6\x9c\x9d\xe5\x94\x90\xe7\xaa\x81\xe3\x81\xab\xe7\x95\xb0\xe4\xb8\x96\xe7\x95\x8c\xe3\x81\xab\xe9\xa3\x9b\xe3\x81\xb0\xe3\x81\x95\xe3\x82\x8c\xe3\x81\x9f\xe3\x80\x82\n

長くてよく分からない文字の羅列ですが,とにかくAPIからデータを得ることができました.

データの中身の詳細となろう小説APIの利用方法(少々)

得られたよく分からない羅列ですが,なろう小説APIの説明によるとYAML形式というものだそうです.パラメータを変えることによって他の形式にも変更できるようです.

・出力形式
JSON形式、JSONP形式またはYAML形式、PHPのserialize
標準はYAML形式となっていますが、outパラメータで変更できます。
文字コードUTF-8です。

そこで,実際によく聞くことがあるJSON形式で取得してみようと思います.

JSON形式で取得してみる

パラメータを変える方法は,APIのURLに設定を付け足して行うようです.
「?」の後に「out=json」を付け足し,outパラメータをjsonと設定します.

https://api.syosetu.com/novelapi/api/?out=json

先ほどのソースコードURLをこのURLにしてデータを確認してみます.

import urllib3
http = urllib3.PoolManager()
r = http.request('GET','https://api.syosetu.com/novelapi/api/?out=json')
r.data

ところで,参考にさせて頂いてる記事によると,このような書き方が可能なようです.

r = http.request('GET','https://api.syosetu.com/novelapi/api',fields={'out': 'json'})

実行結果(一部)

b'[{"allcount":563448},{"title":"\u9b3c\u4eba\u751f\u5f92\u306e\u30cf\u30c1\u30e3\u30e1\u30c1\u30e3\u9b54\u6cd5\u5b66\u5712\u751f\u6d3b","ncode":"N5131ES","userid":1191901,"writer":"Taiyou","story":"\u3053\u306e\u4e16\u754c\u306b\u306f4\u3064\u306e\u7a2e\u65cf\u304c\u5b58\u5728\u3057\u3066\u3044\u308b\u3002\u8056\u4eba\u3001\u9b54\u4eba\u3001\u4eba\u3001\u305d\u3057\u3066\u9b3c\u4eba\u2026\u2026\u305d\u3057\u3066\u9b3c\u4eba\u306e\u4e2d\u3067\u3082\u3063\u3068\u3082\u6050\u308c\u3089\u308c\u3066\u3044\u308b\u306e\u304c\u9b3c\u4eba\u306e\u5909\u7570\u7a2e\u300e\u5438\u8840\u9b3c\u300f\u3060\u3002\n\u5438\u8840\u9b3c\u3068\u306f\u9577\u304f\u3066500\u5e74\u306f\u751f\u304d\u3001\u305d\u306e\

明らかに先ほどとは違う結果になりました.
得られたデータの「\u9b3c\u4eba\u751f ...」などのuから始まる文字の羅列はUnicodeエスケープシーケンスというものだそうです.

実際に「"title"」の後の文字列を変換サイトで変換してみるとタイトルらしき文字列が得られました.

\u9b3c\u4eba\u751f\u5f92\u306e\u30cf\u30c1\u30e3\u30e1\u30c1\u30e3\u9b54\u6cd5\u5b66\u5712\u751f\u6d3b

↓変換

\鬼\人\生\徒\の\ハ\チ\ャ\メ\チ\ャ\魔\法\学\園\生\活

Unicode Escape Sequence | KWONLINE.ORG

JSON形式でタイトル情報だけ取得する

さらにオプションを追加して,タイトル情報だけ取得してみるように変更してみます.

r = http.request('GET','https://api.syosetu.com/novelapi/api',fields={'out':'json','of':'t'})

実行結果 (一部)

b'[{"allcount":563448},{"title":"\u5149\u3042\u308b\u6982\u5ff5\u306eLAST DAY"},{"title":"\u30a8\u30e1\u30e9\u30eb\u30c9\u30b0\u30ea\u30fc\u30f3\u306e\u6c34\u3067\u6cf3\u3050\u91d1\u9b5a"},{"title":"\u8056\u9280\u3068\u5de8\u5927\u90fd\u5e02\u300a\u30e1\u30ac\u30ed\u30dd\u30ea\u30b9\u300b"},{"title":"\u30b2\u30fc\u30e0\u30f2\u30bf\u30af\u306e\u30cb\u30fc\u30c8\u306e\u4ffa\u3060\u304c\u3001\u3053\u306e\u4e16\u754c\u3060\u3068\u82f1\u96c4\u3089\u3057\u3044"},{"title":"EMPEROR"},{"title":"\u5148\u751f\u306a\u3093\u304b\u3000\u5927\u3063\u5acc\u3044"},{"title":"\u65e5\u5e30\u308a\u3067\u7570\u4e16\u754c\u306b\u884c\u3063\u3066\u307f\u3088\u3046\uff01"},{"title":"\u79c1\u306e\u8a00\u8449\u306f\u3001\u307b\u308d\u307b\u308d\u3068\u3002"}

無事にJSON形式でタイトル情報のみを取得できたようです.
このように,URLのパラメータを変更することで様々な条件でデータを取得できるようです.

まとめ

今回は,とりあえずWebAPIを用いたデータの取得までは行うことができました.
なろう小説APIが特殊で,他のAPIの場合に応用できないという事態がないことを祈りたいです.
今後は得られたデータの扱い方(JSON形式)学んだり,実際に得られたデータを使って何かしらできないかを考えたいです.

【Python】高速かつ簡単にNまでの素数を求めるプログラム【エラトステネスの篩】

Pythonの練習課題として,Nまでの素数を求めるプログラムを「エラトステネスの篩」というアルゴリズムを用いて実装しました.

エラトステネスの篩(ふるい)とは

今回は,wikipediaの解説を元にプログラムを実装しました.
エラトステネスの篩 - Wikipedia

アルゴリズム
指定された整数x以下の全ての素数を発見するアルゴリズム。右のアニメーションでは以下のステップにそって2 から 120 までの数に含まれる素数をさがしている。
ステップ 1
探索リストに2からxまでの整数を昇順で入れる。
ステップ 2
探索リストの先頭の数を素数リストに移動し、その倍数を探索リストから篩い落とす。
ステップ 3
上記の篩い落とし操作を探索リストの先頭値がxの平方根に達するまで行う。
ステップ 4
探索リストに残った数を素数リストに移動して処理終了。

非常にシンプルなアルゴリズムで,個人的には速さよりも実装の簡単さの方が今回はありがたかったです.
エラトステネスの篩の速さについてはこちらのサイトがわかりやすく参考になりそうです.

プログラム

実際にPythonで実装したコードがこちらです.

実行結果

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

正直正しく実装できているかは不安ですが,100までの素数は正しく得られました.

プログラムで解く数学の問題 -Project Eulerをやってみた-

最近学び始め,今後使う予定があるpythonの練習のために,以前に存在を知って気になっていた「Project Euler」に登録してみました.

Project Eulerとは

Project Eulerは,プログラムで解く数学的な問題が掲載されているサイトです.
全て英語で書かれていますが,日本語に翻訳しているwikiも存在しています.
Project Euler - PukiWiki

実際に,アカウント登録をしてから問題を解く手順などは,こちらで詳しく解説されています.

実際に問題を2問だけ解いてみました.

問題1

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.
Problem 1 - Project Euler

日本語訳

10未満の自然数のうち, 3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり, これらの合計は 23 になる.

同じようにして, 1000 未満の 3 か 5 の倍数になっている数字の合計を求めよ. Problem 1 - PukiWiki

解くために書いたソースコード

i = 0
total = 0
for i in range(1000):
    if i % 3 == 0 or i % 5 == 0 :
        total += i
print(total)

実行結果

233168

問題2

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

Problem 2 - Project Euler

日本語訳

フィボナッチ数列の項は前の2つの項の和である. 最初の2項を 1, 2 とすれば, 最初の10項は以下の通りである.

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 数列の項の値が400万以下の, 偶数値の項の総和を求めよ.

Note:この問題は最近更新されました. お使いのパラメータが正しいかどうか確認してください.
Problem 2 - PukiWiki

解くために書いたソースコード

f = 0
pre = [1,2]
total = 2
while f < 4000001:
    f = pre[0] + pre[1]
    pre[0] = pre[1]
    pre[1] = f
    if f % 2 == 0 :
        total += f
print(total)

実行結果

4613732

最初の問題だけあって,私でもなんとか解けるような簡単な問題ですが,問題が進んでいくにつれてどんどん難しい問題も出てくるようです.
問題を解くことで力が身につきそうなので,時間を見つけて出来るだけやっていきたいと思います.