SHOYAN BLOG

I am a pragmatic programmer.

C言語でHello World

たくさんのソフトウェアがC言語で作られており、自分もそういうソフトウェアの仕組みを知ったり自分で作れるようになりたいなと思って、C言語の勉強を始めました。

とりあえず、最初はC言語でHello worldをしてみます。
環境はMac OSXです。
X Codeをいれたら、gccが入るのでC言語はすぐ動くようでした。

gccがインストールされているかの確認

gcc -v と入力して、以下のように表示されたらOKです。

1
2
3
4
5
⇒  gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

Hello Worldする

hello.cを作成して以下のように記入します。

1
2
3
4
5
6
#include <stdio.h>
int main(int argc, char **argv)
{
    printf("hello world\n");
    return 0;
}

コンパイルします。

1
$ gcc hello.c -o hello

helloという実行ファイルができるので、実行します。

1
2
$ ./hello
hello world

天気予報をSlackに通知する on Heroku

@keita_kawamotoが天気予報を見ずに出社して、途中で雨に降られて困っていたので天気予報通知をつくってみました。
Herokuでスケジューラーに登録してSlackに通知するようにしています。

weather-nitify-slack

ソースコードは公開しているので参考にどうぞ。

天気情報を取得する

天気情報の取得はweather_hacksのAPIを利用しました。
APIはjsonでレスポンスが返されます。

以下、サンプルコードです。

slack-weather-notifier.rb

1
2
3
4
5
6
7
8
9
10
11
require 'json'
require 'open-uri'

uri = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400010'

res     = JSON.load(open(uri).read)
title   = res['title']
link    = res['link']
weather = res['forecasts'].first
message = "[#{weather['date']}#{title}](#{link})は「#{weather['telop']}」です。"
puts message

ターミナルでruby slack-weather-notifier.rb と実行すると、今日の天気の情報が表示されます。

Slackに通知する

天気情報の取得ができたので、次はSlackに通知します。
Slackの通知にはIncoming WebHooksを使います。
Incoming WebHooksを使うには、Webhook URLの発行が必要です。

Slackの設定画面にアクセスします。
https://example.slack.com/services/new/incoming-webhook
example.slack.comは自分のSlack Teamのドメインをいれてください。

通知先のチャンネルを選んで、Add Incoming Webhooks Integrationのボタンを押すと発行されます。

slack-setting-example.png

設定画面でWebhook URLが確認できます。
このURLにPOSTすると、Slackに通知できるようになります。

Customize NameやCustomize Iconを変更すると、通知するbotの名前やアイコンが変更できます。

slack-setting-example2.png

では、通知をしてみましょう。
通知はslack-incoming-webhooksというgemを使うと簡単にできるので、今回はそれを使います。

slack-incoming-webhooks をインストール

1
$ gem install slack-incoming-webhooks

先ほどのスクリプトにslack通知の設定を追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'json'
require 'open-uri'
require 'slack/incoming/webhooks'

uri = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400010'

res     = JSON.load(open(uri).read)
title   = res['title']
link    = res['link']
weather = res['forecasts'].first

slack = Slack::Incoming::Webhooks.new "webhook_url"
slack.post "<#{link}|#{weather['date']}#{title}>は「#{weather['telop']}」です。"

ターミナルでruby slack-weather-notifier.rb と実行してみましょう。
Slackに通知されれば成功です。

HerokuでAppを作成

さて、天気情報とSlack通知ができるようになりました。
これが定期的に実行できれば便利ですね。

Herokuを使えば無料でスクリプトを定期実行できます。
Herokuでアカウントを作成します。
https://signup.heroku.com/

アカウント登録をしたら、Toolbeltをインストールします。
Toolbeltは、Herokuをコマンドラインから利用できるようになるツールです。
https://toolbelt.heroku.com/

次に認証を行います。
ターミナルにheroku loginとコマンドを入力します。
メールアドレスとパスワードが聞かれるので、先ほどHerokuで登録したメールアドレスとパスワードを入力してください。

アプリを作成

アプリケーションを登録しましょう。

Herokuにデプロイするには、Gitを使ってリモートリポジトリへプッシュする必要があるので、Gitの登録を行います。

ここでは、slack-weather-notifierというディレクトリを作成し、そこに先ほどのファイルを作成し、Gitで管理します。

また、Herokuでslack-incoming-webhooks gemを使うためにGemfileでgemを管理します。
slack-weather-notifierディレクトリの直下にGemfileを作成します。

Gemfile

1
2
3
source 'https://rubygems.org'

gem 'slack-incoming-webhooks'

ターミナルで bundle installと実行すると、gemがインストールされ、Gemfile.lockファイルが作成されます。

もし、bundlerをインストールしていない場合は、 gem install bundler でインストールしてください。

以下のような構成になります。

1
2
3
4
slack-weather-notifier
├── Gemfile
├── Gemfile.lock
└── slack-weather-notifier.rb

Webhook Urlは外部に公開すべきではないので、環境変数に登録して、それを使うようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'json'
require 'open-uri'
require 'slack-incoming-webhooks'

uri = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400010'

res     = JSON.load(open(uri).read)
title   = res['title']
link    = res['link']
weather = res['forecasts'].first

slack = Slack::Incoming::Webhooks.new ENV['WEBHOOK_URL']
slack.post "<#{link}|#{weather['date']}#{title}>は「#{weather['telop']}」です。"

Gitに登録しましょう。

1
2
3
$ git init
$ git add .
$ git commit -m "first commit"

Herokuにpushします。

1
$ git push heroku master

WEBHOOK URLを登録します。

1
heroku config:set WEBHOOK_URL=ここにwebhook_urlを入力

スケジューラーを登録

### カード登録
スケジューラーを利用するにはカード登録が必要です。
無料利用枠を超過した場合は料金が発生しますが、数秒で終わるスクリプトなので大丈夫です。

以下でカードを登録できます。
https://dashboard.heroku.com/account/billing

スケジューラーを登録

カード登録ができたらAdd-onsにスケジューラーを追加します。

以下のコマンドでコンソールから登録できます。

1
heroku addons:add scheduler:standard

またはaddonページから登録してください。
https://addons.heroku.com/scheduler

スケジュール管理画面を開く

https://heroku-scheduler.herokuapp.com/dashboard

コンソールからも開けます。

1
$ heroku addons:open scheduler

スケジューラーの設定

Select an appで登録したアプリケーションを選び ‘Add Standard for free’ のボタンをクリックすると登録できます。
登録したら、ダッシュボードのアプリケーションのページのAdd-onsにHeroku Schedulerが表示されています。

クリックすると、設定ページに飛ぶので、コマンドと時間を登録します。
ちなみに時間はUTCなので気をつけてください。
0:00で登録すると日本時間の9:00に通知されます。

heroku-scheduler

ソースコードは公開しているので参考にどうぞ。

RubyでSlack通知をする

Slackは使っていますか?
僕は会社やプライベートはもっぱらSlackを使っています。

SlackにはAPIが備わっていて、APIを使えばSlack通知が簡単にできます。

今回はRubyでSlackに通知する方法を紹介します。

RubyでSlack通知をするには、以下の作業が必要です。

  1. webhook urlの発行
  2. webhook urlに対してpostする

1. webhook urlの発行

まずは、webhook urlを発行します。
https://yourteam.slack.com/services/new/incoming-webhook のページで発行できます。
Post先のチャンネルを選んで、Add Incoming Webhooks Integrationのボタンを押すと発行されます。

slack-setting-example

channelや通知するbotの名前を決めれるので、適当に決めます。

slack-setting-example2

これでSlack側の準備は完了です。

2. webhook urlに対してpostする

webhook urlの発行ができたら、Slackに通知をしてみましょう。

今回、Slack通知にはslack-incoming-webhooksというgemを使います。

インストール

インストールは以下のコマンドでできます。

1
gem install slack-incoming-webhooks

Slackへ通知

使い方はシンプルです。

1
2
3
4
require 'slack/incoming/webhooks'

slack = Slack::Incoming::Webhooks.new "WEBHOOK_URL"
slack.post "Hello World"

もし、通知先のチャンネルや通知するユーザーネームを変更したいときは指定できます。

1
2
3
4
slack = Slack::Incoming::Webhooks.new "WEBHOOK_URL", channel: '#other-channel', username: 'monkey-bot'

# Direct message
slack = Slack::Incoming::Webhooks.new "WEBHOOK_URL", channel: '@shoyan'

アクセサメソッドも用意されています。

1
2
slack.channel = '#other-channel'
slack.icon_emoji = ':ghost:'

Attachmentsを使う

さて、単純な通知ができたら次はもっとリッチなフォーマットで通知をしてみましょう。
それにはattachmentsを使います。

Example1

slack-example

1
2
3
4
5
6
7
attachments = [{
  title: "Ticket #1943: Can't reset my password",
  title_link: "https://groove.hq/path/to/ticket/1943",
  text: "Help! I tried to reset my password but nothing happened!",
  color: "#7CD197"
}]
slack.post "New ticket from Andrea Lee", attachments: attachments

Example2

slack-example2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
attachments = [{
  text: "<https://honeybadger.io/path/to/event/|ReferenceError> - UI is not defined",
  fields: [
    {
      title: "Project",
      value: "Awesome Project",
      short: true
    },
    {
      title: "Environment",
      value: "production",
      short: true
    }
  ],
  color: "#F35A00"
}]
slack.post "", attachments: attachments

Example3

slack-example3

1
2
3
4
5
6
7
8
attachments = [{
  title: "Network traffic (kb/s)",
  title_link: "https://datadog.com/path/to/event",
  text: "How does this look? @slack-ops - Sent by Julie Dodd",
  image_url: "https://api.slack.com/img/api/attachment_example_datadog.png",
  color: "#764FA5"
}]
slack.post "", attachments: attachments

いかがでしたでしょうか。
今回紹介できなかったオプションもあるので、詳細はSlackのattachmentsのドキュメントを参考にしてください。

では、よいSlack Lifeを!

相関サブクエリを使って次回契約を取得する

相関サブクエリを使って次回契約を取得します。

Contract table

| id | account_id | start_date | end_date |
| — | — | — | — |
| 1 | 1 | 20140101 | 20141231 |
| 2 | 1 | 20150101 | 20151231 |
| 3 | 1 | 20160101 | 20161231 |
| 4 | 1 | 20170101 | 20171231 |
| 5 | 2 | 20150101 | 20151231 |
| 6 | 2 | 20160101 | 20161231 |

上記のようなaccount_idと開始日、終了日の登録してあるテーブルがあるとします。
現在の契約を取得するのは簡単ですね。

1
2
# 現在契約を取得する
SELECT * FROM contracts WHERE start_date >= 現在日付 AND end_date <= 現在日付

現在契約を取得するのは簡単ですが、その次の契約を取得するとなるとそう単純にはいきません。

そこで、相関サブクエリを使います。
相関サブクエリを使うことで次回契約を取得できます。

1
2
3
4
5
6
7
8
9
10
11
12
# 次回契約を取得する
SELECT *
  FROM contracts As cont
 WHERE start_date = (SELECT MIN(start_date)
                       FROM contracts as c1
                     WHERE c1.start_date > ( SELECT end_date
                                               FROM contracts as c2
                                             WHERE c2.start_date <= '20150528'
                                               AND c2.end_date >= '20150528'
                                               AND c1.account_id = c2.account_id)
                       AND cont.account_id = c1.account_id
                     GROUP BY c1.account_id);

結果

| id | account_id | start_date | end_date |
| — | — | — | — |
| 3 | 1 | 20160101 | 20161231 |
| 6 | 2 | 20160101 | 20161231 |

クエリの説明

クエリの説明をします。

クエリは内側からみていきます。
まずは、一番内側にある、 SELECT end_date ... AND c1.account_id = c2.account_idのクエリです。
このクエリでは現在の契約(ここでは2015/5/28とします)を取得します。

2つめのクエリで、次回以降の契約を取得します。
SELECT MIN(start_date) を使うことで、次回契約のなかで直近の契約を取得できます。
アカウントごとに直近の次回契約を取得したいので、GROUP BY account_id をしています。

c1.account_id = c2.account_id と cont.account_id = c1.account_id は行と行を比較するために必要です。

3つめのクエリ(SELECT * ... WHERE start_date =)で直近の次回契約を条件として、データを取得します。

手元で試したい方は以下のクエリでデータをつくれます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE `contracts` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `account_id` int(11) DEFAULT NULL,
  `start_date` int(11) DEFAULT NULL,
  `end_date` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `contracts` (`id`, `account_id`, `start_date`, `end_date`)
VALUES
    (1, 1, 20140101, 20141231),
    (2, 1, 20150101, 20151231),
    (3, 1, 20160101, 20161231),
    (4, 1, 20170101, 20171231),
    (5, 2, 20150101, 20151231),
    (6, 2, 20160101, 20161231);

プログラマのための数学勉強会@福岡に登壇してきました

プログラマのための数学勉強会@福岡が2015/9/4にLINE Fukuokaで開催されました。
今回はスピーカーとして参加させていただきました。

「暗号技術を支える素数」というタイトルで、暗号で使われている数式とその仕組みを説明しつつ、素因数分解の困難性が暗号の要だということを説明しました。

他の登壇者のかたのスライド

他の登壇者のかたのスライドを紹介します。

主催者の@tkengo氏のスライドです。
プロジェクトオイラーの問題の紹介と効率的な解き方の解説をされています。

きしださん のスライドです。
画像の機械学習の話しです。
最弱といいながら高度なことをやっているというギャップがおもしろいです。

圏論超絶基礎の基礎の基礎入門

資料はあがっていないようですが、@nobkz先生の独特なプレゼンテーションは圧倒的でした。

会場の様子

暗号技術を支える素数についての発表

Balloonbrosさん(@balloonbros)が投稿した写真 -

当日は多くのかたに参加いただきました。

LINEで勉強会でした

Balloonbrosさん(@balloonbros)が投稿した写真 -

今回、カメラマンとして参加してくれた@keita_kawamoto

主催者tkengo。楽しかった!ありがとう!

Balloonbrosさん(@balloonbros)が投稿した写真 -

主催者の@tkengo氏。
最近、ブログをリニューアルしたとのことです。

Twiterまとめ

プログラマのための数学勉強会@福岡まとめ

会場を提供してくださったLINE Fukuokaのみなさん、忙しい中足を運んでくださった参加者、登壇者のみなさん、主催の@tkengo氏、ありがとうございました!