INPUTしたらOUTPUT!

忘れっぽいんでメモっとく

Rでポケモンスタンプラリー(3/3) {TSP}で巡回セールスマン問題

estrellita.hatenablog.comの続き。最後は{TSP}を利用して移動距離が最短となるようスタンプ設置駅を周回する順番を求める。


  1. データ準備
    • 路線ネットワークに必要なノードとエッジのデータを作成
  2. {tidygraph}でスタンプ設置駅間の最短経路探索
    • 路線ネットワークデータからスタンプ設置駅の最短距離を探索
  3. {TSP}で巡回セールスマン問題を解く( ← イマココ)
    • 各スタンプ設置駅間の距離行列から移動距離が最短となるような巡回順を探索


目次

  • 距離行列の作成
  • 巡回セールスマン問題
  • 結果の確認


続きを読む

Rでポケモンスタンプラリー(2/3) {tidygraph}で最短経路検索

estrellita.hatenablog.com の続き。今回は{tidygraph}を利用してスタンプ設置駅間の最短経路を取得する。


  1. データ準備
    • 路線ネットワークに必要なノードとエッジのデータを作成
  2. {tidygraph}でスタンプ設置駅間の最短経路探索( ← イマココ)
    • 路線ネットワークデータからスタンプ設置駅の最短距離を探索
  3. {TSP}で巡回セールスマン問題を解く
    • 各スタンプ設置駅間の距離行列から移動距離が最短となるような巡回順を探索


目次

  • グラフオブジェクトの作成
  • ネットワークグラフの可視化
  • 最短経路の取得


続きを読む

Rでポケモンスタンプラリー(1/3) データ準備編

最後のー 休みがー 今年もー 終わったなー♪


9月に入り、今年の夏休みも終わりましたがみなさまいかがお過ごしでしょうか。 夏休みの風物詩といえばJR東日本が毎年催すポケモンスタンプラリー。

https://www.jreast.co.jp/press/2019/tokyo/20190628_to02.pdf


昨年より減ったものの43駅あるので全ての駅を制覇しようとするといかに効率的に回るかよく考える必要があり、それだけで酒が呑める!という方々と最近を仕事をしているのですが自分はそこまで鉄道に興味がないのでRで楽したい。というわけで以下の流れでスタンプ設置駅間の移動距離が最小となるように巡回セールスマン問題で解いて巡回する順番を求める。


  1. データ準備( ← イマココ)
    • 路線ネットワークに必要なノードとエッジのデータを作成
  2. {tidygraph}でスタンプ設置駅間の最短経路探索
    • 路線ネットワークデータからスタンプ設置駅の最短距離を探索
  3. {TSP}で巡回セールスマン問題を解く
    • 各スタンプ設置駅間の距離行列から移動距離が最短となるような巡回順を探索


目次

  • データの取得
    • 路線情報の取得
    • 隣接駅情報を取得
    • 乗り換え駅データの取得
  • ネットワークデータの作成
    • スタンプ設置駅のデータ作成
    • ノード情報の作成
    • エッジ情報の作成


続きを読む

people analytics tokyo #1に参加してきました。

以前、以下の本を読んで人と人とのつながりが組織のパフォーマンスに影響するということを知り、ちょうど勉強会が開催されたので無理をお願いして参加させていただきました。

職場の人間科学: ビッグデータで考える「理想の働き方」

職場の人間科学: ビッグデータで考える「理想の働き方」

以下メモ


続きを読む

「サイゼリヤで1000円あれば最大何kcal摂れるのか」を{lpSolve}で解いてみた。

こんな話がある。

qiita.com

qiita.com

qiita.com

後者の2つはシンプルなナップサック問題なのでRでもできそうなので以下を参考にやってみた。

momonoki2017.blogspot.com


続きを読む

{lexRankr}で文章要約を試す

長期休暇中に消化するはずだった積ん読が全く消化できていない。全部真面目に読もうとするから消化できないわけだけど、 そもそも本を読むときに読むべき場所は7〜11%しかないらしい。*1


ということで文章要約で書籍の中から読むべき部分を抽出したい。文章要約については以下が非常に参考になる。

qiita.com

抽出型のアプローチでグラフベースのアルゴリズムであるLexRankのRパッケージが提供されているので試してみる。


続きを読む

LINE Messaging APIでLINE botを作る(4) センサー連携

estrellita.hatenablog.com

の続き。

スマート家電コントローラRS-WFIREX3には気温・湿度・照度をGoogleスプレッドシートに記録してくれるIFTTTアプレットがある。せっかくなのでこれらのセンサーデータをリプライするようにechoman()を修正する。


センサーデータの記録

RATOC SystemsからセンサーデータをGoogleスプレッドシートに記録するアプレットが公開されているのでそのまま利用する。

  1. IFTTTのトップページ検索欄に「ratoc」を入力
    • f:id:tak95:20190531165636p:plain
  2. 検索結果から「センサー情報をスプレッドシートへ記録」を選択
    • f:id:tak95:20190531165742p:plain
  3. 歯車アイコンを選択
    • f:id:tak95:20190531165759p:plain
  4. 計測するリモコンを選択し、記録するスプレッドシートのフォルダ・ファイル名を設定し「Save」
    • f:id:tak95:20190531165818p:plain


node参照用のGoogleスプレッドシートの作成

node.jsからGoogleスプレッドシートを参照する際にあらかじめセルの範囲を把握しておく必要があるようだが、上記の設定だとシートに行が追加されていくため、入力されているセル範囲がわからない。そのため上記で作成したスプレッドシートに行が追加されたら別のシートに追加された行の値を保持するIFTTTアプレットを作成する。

  1. 「+this」を選択
    • f:id:tak95:20190531002346p:plain
  2. 検索欄に「sheets」を入力し「Google Sheets」を選択
    • f:id:tak95:20190531172932p:plain
  3. 「New row added to spreadsheet」を選択
    • f:id:tak95:20190531172948p:plain
  4. 前節で設定したスプレッドシートのフォルダ・ファイル名を入力し、「Create trigger」を選択
    • f:id:tak95:20190531173005p:plain
  5. 「+that」を選択
    • f:id:tak95:20190531173020p:plain
  6. 検索欄に「sheets」を入力し「Google Sheets」を選択
    • f:id:tak95:20190531173032p:plain
  7. 「Update cell in spreadsheet」を選択
    • f:id:tak95:20190531173052p:plain
  8. 最新データのみ保持するシートのフォルダ・ファイル名を入力し、「Which cell?」には"A1", 「Value」には"{{ColumnA}},{{ColumnB}},{{ColumnC}},{{ColumnD}},{{ColumnE}}"
    • f:id:tak95:20190531173103p:plain
  9. 「Finish」を選択して設定完了
    • f:id:tak95:20190531173120p:plain


Googleスプレッドシートへのアクセス設定

node.jsからGoolgeスプレッドシートにアクセスするにはあらかじめアクセス権の設定などが必要となる。リンク先を参考に鍵ファイルの作成およびシートの共有設定を行う。

techblog.lclco.com


echoman()の更新

node.jsからGoogleスプレッドシートが参照できるようになったのでメッセージに「何度」「温度」といった単語が含まれる場合、センサーデータを返すように更新する。

センサーデータを取得するgetSensorValue()は以下の通り。

const GoogleSpreadsheetAsPromised = require('google-spreadsheet-as-promised')
const CREDS = require('./credentials.json')
const sheetId = process.env.SHEET_ID // id from sheet URL

async function getSensorValue () {
  const sheet = new GoogleSpreadsheetAsPromised()
  await sheet.load(sheetId, CREDS)
  const worksheet = await sheet.getWorksheetByName('シート1')
  const cell = (await worksheet.getCells('A1:A1')).getAllValues()

  return cell[0].split(',')
}


最終的にechoman()は以下のようになりました。

async function echoman (ev) {
  // const pro = await client.getProfile(ev.source.userId)
  let msg = ''
  if (ev.message.text.includes('おやすみ')) {
    goodNight()
  }
  if (ev.message.text.includes('掃除') | ev.message.text.includes('片付け')) {
    tidyMyRoom()
  }
  if (ev.message.text.includes('何度') | ev.message.text.includes('温度')) {
    const sensorValues = await getSensorValue()
    msg = await `${sensorValues[0]} ${sensorValues[1]}計測\n 温度: ${sensorValues[2]}\n 湿度: ${sensorValues[3]}%\n 照度: ${sensorValues[4]} lx\nです。`
  }

  if (msg === '') {
    msg = await conversation(ev.message.text)
  }
  console.log(`[in]echoman(): msg = ${msg}`)

  return client.replyMessage(ev.replyToken, {
    type: 'text',
    text: msg
  })
}

我が家のエアコンのリモコンはBluetoohのためRS-WFIREX3から操作できないのが残念だが部屋を擬人化したbotとしてだいたいやりたいことはできた。


試してると愛着が湧いてきて引越しするのが辛くなるなと思って試しにメッセージ送ってみたら

f:id:tak95:20190531201506p:plain

速攻で新しい家人探し始めた。。。orz