schemeの可変長引き数メモ

SICPこの辺を読んでたら、

(define (make-serializer)
  (let ((mutex (make-mutex)))
    (lambda (p)
      (define (serialized-p . args)
        (mutex 'acquire)
        (let ((val (apply p args)))
          (mutex 'release)
          val))
      serialized-p)))

のという関数定義があって、これの(define (serialized-p . args)が見慣れない形だと思ったのでメモ。

  • lispでは、関数呼び出しは先頭要素が関数であるようなリスト。
  • lispのリストとは、要素をcons, i.e. ( . ) で繋げたもの。
    • (item1 . (item2 . (item3 . ... . (itemN . ())...)
  • (serialized-p . args) を上の形に当てはめると、
    • serialized-p -> 先頭要素
    • args -> リスト(serialized-p . args)から先頭要素を除いたリスト
  • と理解出来る。
  • つまり、argsは、実際に serialized-pが呼ばれた時の引き数全部。
  • こういう形を許せば、可変長の引き数にも自然に対応出来ている。なるほど。

ちなみに、(apply p args) を (p args)と書くのはだめ。(p args)だと、一引数関数pを一つのリストargsに適用するという意味になってしまうから。

priority_queueの順番

メモ

/*! if g++ -g 2012-07-06_005542.cpp -o 2012-07-06_005542.out; then ./2012-07-06_005542.out; fi
 */

#include <queue>
#include <iostream>


using namespace std;


int main(int argc, char *argv[]){
  priority_queue<int, vector<int>, less<int> > p;
  priority_queue<int, vector<int>, greater<int> > q;
  if(less<int>()(1,2)){
    cout << "1 is less than 2" << endl;
  }
  size_t n = 10;
  for(size_t i = 0; i < n; ++i){
    p.push(i);
    q.push(i);
  }
  while(p.size()){
    /* pは大きい順、qは小さい順に出てくる */
    cout << p.top() << "," << q.top() << endl;
    p.pop(); q.pop();
  }
  return 0;
}

evernote api のメモ

概要

自分のPCの中に、これまでに読んだ/これから読みたい論文が一つのディレクトリにまとめて沢山ある。これらを、Evernoteに全部アップロードしてしまおうと思いたち、PythonからEvernote APIをいじってみたので、メモと作りかけスクリプトを置いておく。
Evernoteの中に論文が入っていると、

  • 論文ファイルと論文に関するメモをまとめて保管出来る
  • メモの有無で未読/既読が判定出来る
  • タグを付けれる
  • 検索が利く

ので、結構便利だと思う。

メモ

以下、evernote apiを使った時のメモ

  • sandbox
    • 本番と同じ機能だけど本番とは別の場所に隔離されているテスト用環境
  • OAuth
    • サードパーティ製アプリがユーザのパスワードを知ること無くユーザの資産に対して許可されたアクションを起こすために必要な認証
  • Developers token
    • 自分一人用のちっちゃなスクリプトなら、OAuthを実装しなくても、EvernoteにDevelopers tokenを発行してもらえば良い。
    • sandobx用と本番用がある
  • UserStore, NoteStoreの2つの大きなサービス
    • UserStore
      • アカウント情報
      • これを通じてNoteStore等のデータを取得
    • NoteStore
      • 実際のデータ
      • こっちのAPIをいじって、ノートの中身を取得したり、新規ノートを作ったり。
  • ノートブックはGUID(globally unique id)を指定して取得
  • ノートは、検索語・ノートブックのGUID・タグのGUID等を指定してリストの形で取得

作りかけのスクリプト

evernote-dirsync

  • 指定したディレクトリ下の指定した拡張子のファイルを全部アップロードする
  • アップロード済みのファイルはアップロードしない
    • アップロード済みか否かの判定は、ノートのタイトル == ファイル名
  • アップロード制限容量のチェックはしてない(TODO)

ネットワーク用語メモ

概要

自宅のmac book proをいじっている時にimacのHDをマウントしたい、と思い、無線LAN内のローカルIPアドレスを固定にするために調べたネットワーク用語の自分用メモ。間違っている所も多々あるだろうけど、晒しage。

本文

  • サブネットマスク
    • IPアドレスは、32bit 2進数
    • このアドレスは、サブネットに分割される
    • 32bit の内、何桁がサブネットを識別する番号かを知らせるのがサブネットマスク
  • サブネットの意義
    • 送信側端末は、自分が属するサブネットのルータにパケットを送る
    • 送信側ルータは、宛先IPアドレスサブネットマスクから宛先サブネットを判別し、宛先サブネットのルータにパケットを送る
    • それより細かいアドレスへの送信は、受信側ルータの担当
    • 手紙を郵便局に預けて、送信側郵便局が受信側郵便局に送り、さらに受信側郵便局が宛先に届けるイメージ
    • 郵便局は、郵便局の位置と自分担当の住所の位置だけを知っていればよく、他の郵便局担当の住所は知らなくて良い
    • 例えば、32bit の内、「最初の8bitがサブネット用」と固定すると、255個のサブネットしか存在出来無い
    • また、各サブネットが担当出来るアドレスの数も、2^24個と固定される
    • サブネットには大きいものも小さいものも居るので、サブネットマスクで、サブネット用アドレスを可変長にするのが便利
  • NAPT変換
    • ルータは、「LAN側」「WAN側」の出入口を持つ
    • LANからWANに向けて通信が始まる場合
      • パケットの中に、「自分のWAN側アドレス」「自分のポート番号」を含める。WAN側の端末は、このアドレスとポートに向かってパケットを送信してくる
      • この時、ポート番号を、LAN内の各端末毎に変えておけば、外部から送られてきたパケットがLAN内のどの端末向けか分かる
      • この「端末とポート番号の対応」は固定ではなく、通信の度に変わる
  • ポートフォワーディング
    • しかし、WANからLANに向けて通信が始まる場合には、パケットの宛先に書かれているポート番号に対応する端末が無いという状態になり、このままではWAN側から始まる通信が実現出来無い。
    • LAN側にサーバーがある場合には、WAN側のクライアントから通信が始まるので、こういう時に困る
    • だので、特定のポートには特定のLAN内端末を予め割り当てておく
  • デフォルトゲートウェイ
    • サブネットとサブネットをつなぐルータ(それ以外のルータって何なんだろう?)
    • 端末からパケットを送る際には、自分/宛先のIPアドレスサブネットマスクを比較
    • 自分のサブネットなら、直接送信
    • 別のサブネットなら自分の中に定義されているデフォルトゲートウェイに向けて送信
  • DHCP【Dynamic Host Configuration Protocol】サーバ
  • ネットワーク設定を勝手にやってくれるサーバ

コマンド

digestとfilehashで適当に永続化

概要

d:id:hotoku:20120328 で、S4オブジェクトの中にキャッシュを持つ方法を考えたが、先のコードのままでは、オブジェクト自身以外の引数がある場合には上手くいかない。また、当たり前だけど、メモリにキャッシュがあるのでRを終了したらキャッシュも消える。だので、関数の引数を直列化してkey value storeでディスクに置く事を考えた。digestfilehashというライブラリを使った実装をメモ。

digestライブラリ

Rオブジェクトを直列化した後、色んな関数でハッシュ値を計算して文字列で返してくれるライブラリ。

> library(digest)
> digest(1:10)
[1] "c08951d2c283a799ab013bf845ed822e"

こんな感じ。

filehashライブラリ

お手軽key value storeライブラリ。

> library(filehash)
> db.file <- "filehash_test"
> dbCreate(db.file) # カレントディレクトリに"filehash_test"というファイルが出来る
[1] TRUE
> db <- dbInit(db.file)   # dbオブジェクト作成
> dbInsert(db, "a", 1:10) # 値の挿入
> dbFetch(db, "a")        # 値の取得
 [1]  1  2  3  4  5  6  7  8  9 10
> db$a #こういうアクセスも用意されている
 [1]  1  2  3  4  5  6  7  8  9 10
> db[["a"]] #こういうアクセスも用意されている その2
 [1]  1  2  3  4  5  6  7  8  9 10

コード例

library(filehash)
library(digest)




setClass("someClass", representation(db="filehash",
                                     pow="numeric"))
setMethod("initialize", "someClass",
          function(.Object, pow){
            .Object@db <- dbInit("filehash_test")
            .Object@pow <- pow
            .Object
          })

setGeneric("veryHeavyCalculation", function(obj, arg)standardGeneric("veryHeavyCalculation"))
setMethod("veryHeavyCalculation",
          signature(obj="someClass", arg="numeric"),
          function(obj, arg){
            key <- digest(list(pow=obj@pow, arg=arg))
            if(dbExists(obj@db, key)) return(dbFetch(obj@db, key))
            cat("executing very heavy calculation\n")
            val <- sum(arg^obj@pow)
            dbInsert(obj@db, key, val)
            val
          })


obj <- new("someClass", 3)
veryHeavyCalculation(obj, 1:10) # 真面目に計算
veryHeavyCalculation(obj, 1:10) # key value storeから取得

Croc Champ 2012 ? Round 1 : A Rock-Paper-Scissors

方針

  • n が大きいので単純に数える事はしない
  • 多くとも m*k ラウンドやれば後は周期的なので、m*k までシミュレーション
/*! if g++ -g a.cpp; then ./a.out < a.test; fi
 */

#include <cmath>

#include <iostream>
#include <string>
#include <vector>

using namespace std;

typedef unsigned long long ull;

enum wins {A, B, D};

wins match(char a, char b){
  if((a=='R' && b=='S') ||
     (a=='S' && b=='P') ||
     (a=='P' && b=='R')) return A;
  if((b=='R' && a=='S') ||
     (b=='S' && a=='P') ||
     (b=='P' && a=='R')) return B;
  else return D;
}


int main(int argc, char *argv[]){
  ull n;
  cin >> n;
  string a, b;
  cin >> a >> b;

  ull lcm = a.size() * b.size();

  ull temp_a=0, temp_b=0;
  ull ret_a=0, ret_b=0;
  ull res = n % lcm;
  for(ull i = 0; i < min(n, lcm); i++){
    switch(match(a[i % a.size()], b[i % b.size()])){
    case A:{
      ret_b++;
      break;
    }
    case B:{
      ret_a++;
      break;
    }
    case D:{
      break;
    }
    }
    if((i+1)==res){
      temp_a = ret_a;
      temp_b = ret_b;
    }
  }

  ull x = n / lcm;
  cout << x * ret_a + temp_a << " "
       << x * ret_b + temp_b << endl;
  return 0;
}

S4クラス用のgeneric関数でキャッシュを実現する方法を考える

概要

Rが常に値渡しであるために関数の返り値のキャッシュをオブジェクトの中に素直に持てなくて困ったので解決法を考えた。

背景

ある特定のオブジェクトを引数として、もの凄く重たい関数が何回も呼ばれるとする。毎回真面目に計算するのはしんどいので、初回呼び出し時だけはちゃんと計算してその計算結果をオブジェクトの中にキャッシュとして残しておいて、2回目以降はキャッシュを返すだけにしたい。

上手く行かない例

setClass("NotCachedClass", representation(is.cached="logical",
                                          cached.value="POSIXct"))

setMethod("initialize", "NotCachedClass",
          function(.Object, ...){
            .Object@is.cached <- FALSE
            .Object
          })

setGeneric("veryHeavyCalculation",
           function(obj)standardGeneric("veryHeavyCalculation"))
setMethod("veryHeavyCalculation", signature=(obj="NotCachedClass"),
          function(obj){ # <- 呼び出し元の引数のコピーが実引数となる
            if(obj@is.cached){
              cat("using cached value\n")
              obj@cached.value
            }
            else{
              cat("calculating\n")
              ret <- Sys.time()
              obj@is.cached <- TRUE
              obj@cached.value <- ret
              ret
            }
          })

object.a <- new("NotCachedClass")
veryHeavyCalculation(object.a) # 真面目に計算
veryHeavyCalculation(object.a) # 2回目の計算だけど、真面目に計算

素直に考えるとこんな感じで上手く行って欲しいんだけど、これは上手く行かない。何故なら、veryHeavyCalculationの仮引数objの実引数は、グローバル環境に存在しているobject.aそのものではなくて、そのコピーだからだ。つまり、上のプログラムだと、グローバル環境の中のobject.aではなくて、関数呼び出し時に作成されたそのコピーの中にキャッシュが作成される。だから、2回object.aを引数としてveryHeavyCalculationを呼び出しても、object.aの中にはキャッシュが無いので真面目に計算されてしまう。

上手く行く例

オブジェクトの中にクロージャーを持って、その中にキャッシュを持てば良い。

setClass("CachedClass", representation(is.cached="function",
                             get.cache="function",
                             set.cache="function"))
setMethod("initialize", "CachedClass",
          function(.Object, ...){
            cache <- local({
              cached       <- FALSE
              cached.value <- NULL
              is.cached <- function(){
                cached
              }
              get.cache <- function(){
                cached.value
              }
              set.cache <- function(v){
                cached       <<- TRUE
                cached.value <<- v
              }
              function(method){
                if(method=="cached") return(is.cached)
                if(method=="get") return(get.cache)
                if(method=="set") return(set.cache)
              }
            })
            arg = list(...)
            .Object@is.cached <- cache("cached")
            .Object@get.cache <- cache("get")
            .Object@set.cache <- cache("set")
            .Object
          })
setGeneric("veryHeavyCalculation", function(obj)standardGeneric("veryHeavyCalculation"))
setMethod("veryHeavyCalculation",
          signature(obj="CachedClass"),
          function(obj){
            if(obj@is.cached()){
              cat("using cached value\n")
              obj@get.cache()
            }
            else{
              cat("calculating\n")
              ret <- Sys.time()
              obj@set.cache(ret)
              ret
            }
          })

object.a <- new("CachedClass")
veryHeavyCalculation(object.a)
veryHeavyCalculation(object.a)
b <- new("CachedClass")
veryHeavyCalculation(b)