docker-composeでdenoの環境を作る
はじめに
お久しぶりです、からすさんです。タイトル通りdocker-composeでdenoを試すための環境を作る記事です。本記事の環境は次の通りです。
Ubuntu 20.04.3 LTS (Focal Fossa) Docker version 20.10.8 docker-compose version 1.26.0
docker-compose
次のようにdocker-compose.yml
を作成します。
version: '3' services: app: image: denoland/deno:1.15.1 ports: - "8000:8000" volumes: - .:/app command: /bin/bash tty: true
command: /bin/bash
とtty: true
はコンテナを起動させ続けるために記述しています。
コンテナ起動
次のコマンドで起動させます。
$ docker-compose up -d
コンテナが実行中であるかを次で確認します。
$ docker-compose ps Name Command State Ports ----------------------------------------------------------------------------------------------------- deno-docker_app_1 /tini -- docker-entrypoint ... Up 0.0.0.0:8000->8000/tcp,:::8000->8000/tcp
コンテナ内でdenoを試す
先ほど起動させたコンテナ内でコマンド実行を行うために、次のコマンドを実行させます。
$ docker-compose exec app bash root@xxx:/#
コンテナ内でdeno --version
と実行させて、次のような出力がされ、denoの環境作りが終えました。
root@xxx:/# deno --version deno 1.15.1 (release, x86_64-unknown-linux-gnu) v8 9.5.172.19 typescript 4.4.2
備考
tty
ttyは、UNIXで同名のコマンドがあり、「標準入出力となっている端末デバイスの名前を表示する」コマンドみたいです。
$ tty /dev/pts/1
同じ計算機上で複数ターミナルを起動しているときに/dev/pts/1
と/dev/pts/2
があった時に/dev/pts/1
側のターミナル上で
$ echo "hello" > /dev/pts/2
とコマンドを実行させると/dev/pts/2
側のターミナル上にhello
と出力させることができるみたいです。
Dockerにおけるtty
run — Docker-docs-ja 19.03 ドキュメント
によると
疑似ターミナル (pseudo-TTY) を割り当て
だそうです。
tty: ture
やcommand: /bin/bash
docker-compose.yml
内でtty: ture
やcommand: /bin/bash
の処理を行わなければ、コンテナを起動させた時に、コンテナがすぐに終了してしまいます。これは、コンテナを起動させ続けるためのプロセスが存在しないため、コンテナが正常終了してしまうからです。そのため、今回はコンテナを動かし続けるため、ターミナル上でbashを実行させプロセスが無くならないようにしています。
おわりに
間違った内容等があったら、こっそり教えてください!
BMS始めた
久しぶりの投稿です。BMS熱が出てきて始めました。
使っているBMSプレイヤーについて
使っているBMSプレイヤーは beatoraja を使っています。もともと Lunatic Rave 2 を(3年前ぐらいに)使っていたのですが HD 化するのにいろいろとめんどうごとがあるみたいで、すぐに HD で遊べるように選択しました。次のサイトで色々と調べれます。
スキンは LITONE5 を使っています。次のサイトで取得できます。
見た目は次のような感じで
プレイ中だと
のようになっています。(フレームや背景とかは見やすいように黒に染めています。ここは調整可能です。)
曲の入手について
BMSは曲が豊富ですので、探すのが一苦労です。特に、自分の実力にあった曲をたくさん入手するのは難しいと思っています。そんな中で 第2通常難易度表 という beatmaniaIIDX の難易度に合わせた難易度表がありこれを参考に曲を集めようと思います。探した中で便利だったのが以下の Twitter のアカウントにあるリンクでBMS第2通常難易度表の曲をまとめてダウンロードできます。
全部が全部集めれるとは限らないようです...
その他
コントローラーはキーボードで、s/d/f/space/j/k/l で皿は a/; で設定しています。
段位は GENOCIDE2018六段 が取れるぐらいでまだまだ練習中です。
生協食堂のメニューをコスパ良く選んでみた
こんにちわ、からすさんです。お題通りに生協のメニューをコスパ良く選んでみました。
じゃあまずどういうことかってことを以下にまとめてみました。
- 1食分の食品群(赤、緑、黄)を1食でちゃんと満たす
- 1食に2品同じものが選ばれない
- 食品群の他にも脂質や塩分の条件をつけくわえれる
以上の3点を満たしかつ値段を最小にしてくれるコスパのいいメニューを選びましょう!
問題設定
以下のような問題を最適化問題で表していきます。
- 1品1回まで選択可
- 食品群(赤、緑、黄)はそれぞれ(2点、1点、5点)以上とする。(これは男版)
- 任意の栄養も調整可
以上を踏まえて今回解いていく最適化問題は次の通りです。
これは、線形計画問題でその中でも0-1整数計画問題と呼ばれる問題です。
解き方
解き方を書こうと思ったけどPythonにPuLPというフリーのソルバーがあり、これにぶっこむだけで答えが返ってきます!この手のブログは解き方がメインだけど今回は「答えが出ればいい」だからね
PuLPは次のサイトからサンプルコードやいろいろを学んできました。
ソースコード
今回使用したコードはgithubに置いときますね。
いくつか注意しなければならない点があります。今回使用したソルバーPuLPをインストールする際に
pip install PuLP==1.6.0
とバージョンを1.6.0で使用しています。最新のバージョンでは動きませんでしたX(
使用例
python solver.py
でsolver.pyを実行します。そこで、いくつか入力を求められるので以下の入力を参考に使ってみてください。(なお答えがでなければ「not solve」が出ます。)
次のような条件で候補を出してみます。
- エネルギーは1kcal以上1000klca以下
- タンパク質は2g以上2000g以下
- 脂質は3g以上3000g以下
- 炭水化物は4g以上4000g以下
- 塩分は0.5g以上50g以下
- 赤は2以上200以下
- 緑は1以上100以下
- 黄は5以上50以下
1 1000 2 2000 3 3000 4 4000 0.5 50 2 200 1 100 5 50
これを入力して出力されるのは
['あじフライ', '肉じゃが', '春雨サラダ(しそ風味)', '大根おろし'] 352.0
となります。1行目は品のリストで2行目はその合計金額です。実際に合ってるのかを調べてみて次に示します。
上の画像より、3点群やほかの栄養素の条件、金額があってることが確認できました。
もうすぐしたら新学期です。楽しい大学院ライフを送りましょう!
二郎的なサムシング
本記事は「UEC Advent Calendar 2019」15日目の記事です.
昨日はおひげPさんの記事でした.
これでみなさんも深層学習の準備ができたので
なんとかできそうですね!
はじめに
はじめましての方は初めまして.僕は一類MIのB4のからすさんです.卒論が近くてボスに「君は文章書くのが苦手だから心配だよ」ってご心配かけてしまって泣きそうです;;.
みなさん二郎って知ってますか?(画像は前に府中二郎で撮ってきたもの)
具体的な二郎の内容は延べませんが,二郎のwebアプリってあるといいなーって思いました.どんな機能があるといい...?
・現在位置から最寄りの二郎店までの距離
・店舗ごとの掲示板
...今の自分の実力で作れそうな範囲で考えてみました.
ちなみに,今回のwebアプリ作るのにGo言語,Go言語のWebフレームワークのginとDBはSQLite3を用いました.
この記事では制作の過程ではなく,初歩的な内容を書いてます.
初めてのGo言語とwebアプリ制作でしたので間違ってるところも多いと思いますが温かい目で見て頂ければ幸いです.
ソースコードや活動記録?はこちらです.下の内容すっとばしたい方向けなのでどうぞ.
環境
Windows 10 Home go version go1.13.4 windows/amd64 SQLite version 3.28.0
基本
基本的なことを書いていきたいと思います.
ひな形を作ろう!
Go / Gin で超簡単なWebアプリを作る - Qiita
を参考にまずひな形を作って,それにいろいろと付け足していこうと思います.
main.go
ファイルとindex.html
ファイルを以下の作ります.(index.html
はmain.go
内のrouter.LoadHTMLGlob("templates/*.html")
で場所を指定するのでそこに作っておいてください.)
main.go
package main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.LoadHTMLGlob("templates/*.html") router.GET("/", func(ctx *gin.Context){ ctx.HTML(200, "index.html", gin.H{}) }) router.Run() }
index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Sample App</title> </head> <body> <h1>Hello World!!!</h1> </body> </html>
go run main.go
で起動し
ブラウザでhttp://localhost:8080/
を表示すると
上のように表示されたかと思います.
これでひな形(と動作確認)ができました.
次からはGoとhtmlとの挙動を見ていきたいと思います.
aタグ
index.html
に
<a href="/test">ここをクリック</a>
を追加しこれをクリックするとどうなるかを見ていきます.
main.go
を起動した後に「ここをクリック」を押したら
404 page not found
と表示されたかと思います.
index.html
からmain.go
に「/test
だお~」って送ったけども無いものは無いんで✋( ͡° ͜ʖ ͡°)
無かったなら作ればいい!ってことなのでmain.go
内のmain
関数内に
router.GET("/test", func(ctx *gin.Context){ fmt.Println("クリックされたお") ctx.HTML(200, "index.html", gin.H{}) })
とimport "fmt"
も忘れずに書きます.そして先ほどのタグをクリックすると
(ターミナルの方で)「クリックされたお」が表示され,ブラウザではindex.html
が表示されたのではないかと思います.
先ほどの追加した
ctx.HTML(200, "index.html", gin.H{})
でindex.html
を別の(例えば)hoge.html
にするとhoge.html
を表示させることができます.
200
に関しては勉強不足なのであまり触れれないです.
gin.H{}
って?
上の
ctx.HTML(200, "index.html", gin.H{})
で「gin.H{}
ってなんぞや?」ってなりますよね.(なりますよね.)
簡単に説明するとhtml側に送る変数の中身です.
main.go
内で
router.GET("/test", func(ctx *gin.Context){ ctx.HTML(200, "index.html", gin.H{ "text" : "クリックされたお", "number" : 16, }) })
index.html
で
<a href="/test">ここをクリック</a> <p>{{.text}}</p> <p>{{.number}}</p>
と追加しときます.先ほどと同様にクリックすると
↓↓↓↓↓↓↓↓
と表示させることができました.
もう少し詳しい話は
Gin(Golang)におけるHTMLテンプレート記述方法 - Qiita
を参考にするといいと思います.
リクエストの話
GETリクエストとPOSTリクエストの話を同時にしたいと思います.
index.html
で
<p>GET</p> <form method="GET" action="/"> <input type="text" name="get_text"> <p><input type="submit"></p> </form> ここに入力した文字が出力されるよ「{{.get_text}}」 <p>POST</p> <form method="POST" action="/"> <input type="text" name="post_text"> <p><input type="submit"></p> </form> ここに入力された文字が出力されるよ「{{.post_text}}」
main.go
で
router.GET("/", func(ctx *gin.Context){ text := ctx.Query("get_text") ctx.HTML(200, "index.html", gin.H{ "get_text" : text, }) }) router.POST("/", func(ctx *gin.Context){ text := ctx.PostForm("post_text") ctx.HTML(200, "index.html", gin.H{ "post_text" : text, }) })
としてください.
起動すると
method="GET"
のform
で入力すると
URLを見てみると
name="get_text"
としてたので/?get_text=hogehoge
となってますね.
GETリクエストされた後のmain.go
ではtext := ctx.Query("get_text")
で値を取得していきます.
POSTの方も同様にURLには表示されませんが,text := ctx.PostForm("post_text")
で取得してることがわかりますね.
データベースの話
Go言語のORMであるGORMを使ってSQLiteを操作しています.
まずはテーブルを作りたいので,例として以下のようなのを目指そうと思います.
main.go
で構造体を次のように定義します.
type Student struct { gorm.Model Name string Num int Units int Gpa float64 }
テーブル名は構造体名が複数形になるのでStudents
になり,gorm.Model
にはid,created_at,updated_at,deleted_atのカラムが備わってます.
続いてmain.go
内でDBを作ります.
func dbInit() { db, err := gorm.Open("sqlite3", "test.db") db.AutoMigrate(&Student{}) defer db.Close() }
gorm.Open
の第二引数で作成するDBの名前,db.AutoMigrate()
で構造体からテーブルを作成します.
次に値を入れてみましょう.
func dbinsert(){ db, err := gorm.Open("sqlite3", "test.db") db.Create(&Student{Name: "からすさん", Num: 16000000, Units: 108, Gpa: 1.6357}) defer db.Close() }
やばいっすね...db.Create()
で構造体とその中身の入ってるもので挿入してくれるみたいです.
まとめ
「これさえあればできる!」の(たぶん)最低限な内容を書いてみました.
さいごに
ボスの口癖に「違うよ」ってのがあります.(たぶん違います.)
読んでいただいた方の多くに「違うよ」って思うところがあったかと思いますが,後でこっそりと教えてくれると嬉しかったりします.
明日は mu_uec さんです.布教活動をされるみたいですけど技術系ではないって言ってるのが逆に怖いですね...((((;゚Д゚))))
前回の切手の問題をまた解く
お久しぶりです。プロジェクトオイラーの問題をときながら前回の記事の解決案を見つけたのでまた記事にさせていただきます。
参考とさせていただいた記事は次のもので、
nantonaku-shiawase.hatenablog.com
前回の解き方の間違ってる点ですが、例えば手元に「1円」と「2円」の切手があるとします。そこで3円分を作るときに、0円分の作り方、1円分の作り方、・・・、と0円から考えていくやりかたでした。そこで3円分を作る際に2円分の組み合わせと1円分の組み合わせを足してたため「2円」と「1円」それぞれ一つずつの組み合わせの重複を余分に足してしまっていました。
そこで、1円を使って何通り、1円と2円を使って何通り・・・と使う切手の枚数を徐々に増やしていく考え方を学びました。コードで書くと次のとおりです。
K = [1,2] N = 3 KN = [[0]*(N+1) for i in range(len(K))] for n in range(N+1): KN[0][n] = 1 for k in range(len(K)): KN[k][0] = 1 for k in range(1,len(K)): for n in range(N+1): if n//K[k]==0: KN[k][n] = KN[k-1][n] else: KN[k][n] = KN[k-1][n]+KN[k][n-K[k]] for k in KN:print(k)
まず0円分を作るのはどの値段の切手を使っても1通りです。次に、1円切手だけ使っても全部1とおりです。
では、2円切手を使うとどうなるのか、KN[1][1]から考えていきたいと思います。KN[1][1]は1円分にたいして1円切手と2円切手の組み合わせで2円切手は1枚も使わず1円切手だけを使うのでKN[0][1]の値と同値。次にKN[1][2]に対しては、2円切手を1枚使う方法(KN[1][0])と1円切手だけを使う方法(KN[0][2])があるのでその和と同値。これを繰り返していきます。
そこで本題について書いていきたい。
上の雛形を用いて
K = [1,2,3,5,10,20,30,50,62,82,92,100,120,140,205,280,310,500,1000] N = 1000 KN = [[0]*(N+1) for i in range(len(K))] for n in range(N+1): KN[0][n] = 1 for k in range(len(K)): KN[k][0] = 1 for k in range(1,len(K)): for n in range(N+1): if n//K[k]==0: KN[k][n] = KN[k-1][n] else: KN[k][n] = KN[k-1][n]+KN[k][n-K[k]] for k in KN:print(k)
となり、答えは1141266126310(約1.14兆)通りあることがわかった。(すげえ)
1000円渡されたら何種類の切手を買えるのか?
ことのほったん(と思われるの)は以下のツイートから
そしてこういう考えを思いついた人もいた(伝え方が完全に悪かったのだけど、)インターンの大学生に1,000円分の切手を買ってきてとお願いしたら、1,000円切手1枚を渡された……。
— 大木 一真|モジカクしごと (@ooki_kazuma) 2019年6月10日
聞いたら、そもそも切手を買ったことなんて今までなかったそう。これが令和……。 pic.twitter.com/FxZrEIJiy0
「1000円分の切手を買ってきて」と言われたときの買い方が何パターンあるかはプログラミングの練習問題に良さそうだ、と試しにやってみたら再帰計算しすぎて死んだ
— 柞刈湯葉(いすかりゆば) (@yubais) 2019年6月11日
以下ここに書かれることは筆者の自己満足と自分の考えが正しいかがよくわからないため他人による評価を(ちょびっとだけ)もらいたいために書かれた記事であることを先に言っておく。
タイトルにもある通り「1000円で何種類の切手を買えるか」とあるがここでは「N円で何種類買えるか」という問題にしておく。
日本郵便さんによると切手は
1円、2円、3円、5円、10円、・・・、500円、1000円とあるそうだ。 www.post.japanpost.jp
この問題をDP問題として、次にPythonで書いたものを示す。
kinds = [1,2,3,5,10,20,30,50,62,82,92,100,120,140,205,280,310,500,1000] dp = [1] N = 10 for i in range(1,N+1): s = [dp[i-j] for j in kinds if i-j>=0] print(s) dp.append(sum(s)) print(i,"円の時",dp[i],"通り。")
まずは考え方から、この問題を0円からスタートし1円を買うには切手のうちどれを使い1円未満の値段での買い方から選ぶという方針でやっている。
上のコードを出力すると
[1] 1 円の時 1 通り。 [1, 1] 2 円の時 2 通り。 [2, 1, 1] 3 円の時 4 通り。 [4, 2, 1] 4 円の時 7 通り。 [7, 4, 2, 1] 5 円の時 14 通り。 [14, 7, 4, 1] 6 円の時 26 通り。 [26, 14, 7, 2] 7 円の時 49 通り。 [49, 26, 14, 4] 8 円の時 93 通り。 [93, 49, 26, 7] 9 円の時 175 通り。 [175, 93, 49, 14, 1] 10 円の時 332 通り。
となり、配列sを出力することで思い通りに計算されてるかを確認することができる。例えば10円渡されて買うとき
残り1円切手で10円ぶんになる切手の種類から残り10円切手で10円ぶんになる切手の種類までを足せばいい
つまり、最後に買う切手を[1円切手、2円切手、3円切手、5円切手、10円切手]と考えたとき、この配列は
切手の種類が[9円のとき、8円のとき、7円のとき、5円のとき、0円のとき]と考えることができる。これらの種類を足せば10円渡されて買える切手の種類が出せる、と私は考えた。
おまちかね、1000円のときだが、上のNを1000にしたときの出力が
1000 円の時 2018816696222847406903248298783095971003454597950956950486814286870151769566638334351695889582461204439244633372769436724665312005396075530178629791204098410261766867285766690432361030106623128263952566362440060615017667935586334548238897367080748492851021980966669336418640390 通り。
恐ろしい数が出てしまって正直自分の考えがあってるとは思えなくなってしまった。
追伸:僕なら1000円渡されたら50円切手を20枚買うね。
追記(2019/06/12)
上の計算の仕方には問題点があった。
たとえば、3円渡された時を考える。
上のコードでは「1円切手、2円切手」と「2円切手、1円切手」を別々に計算している点だ。これでは切手の買う種類が爆上がりするのも納得いく。
まだ思いつかないけどね