いろいろがんばりたいブログ

情報科学科の人がいろいろ書きます。

2014年度ミニコンに向けて1

予定は未定です

2014年こそ、ミニコンに出る予定である。 とはいえ、ただ普通に作っただけではおもしろくない。 ちなみに一昨年は、Juliusを使って音声認識でロボットを操縦しようとした。

使いたい技術

フルのLinuxが走るボードを使用する。Haskellを走らせるためである。 古くからこの分野にはFunctional Reactive Programmingと呼ばれる分野が存在する。 これは関数型プログラミングの上にReactiveなパラダイムを構築しようというものである。 詳しくは以下を参照されたし。

なお、現在までに同様の試みはいくつか存在する。 例えば以下である。

しかしながら小型のロボットに搭載した例はあまりないようだ。 RasberryPiをはじめとした小型Linuxボードの登場によって、小さいロボットの作成が可能だろうと思われる。

そもそも

そもそもなぜ、FRPをロボットに使用しようと考えたか。 ある日、ロボットがモナドではないかと考えたからである。

追伸メモ

センサー類はi2cをつかうと良いようだ。もしかしたら加速度センサーのみあれば、積分によって座標が求まるのではと考えていたが、ノイズ等の誤差が蓄積するため難しいようだ。

Firefoxのvimperatorから英語でグーグル検索する

色々とやってられなかったので。

  • まず、ここから Google (No country redirect) とかかれたところをクリックして、なんかインストールする。
  • 一時的にNavigation Toolbarをオンにして、検索窓の左のとこからManage Search Engineする。
  • いらないのを消したりして、google USのkeywordをeとかにしておく。

あとは:open eとかすればOK.

.vimperatorrc に以下のように書くと便利である。

nnoremap e o e
nnoremap E t e

雷ちゃんはかわいい

かわいいのでどこでも声を聞きたいので適当にでっちあげた。
あまりやりすぎないようにね。 swftoolsバグってるっぽくて透明なのがとりだせない……。

#!/bin/sh
VOICE_URL="http://203.104.105.167"
NUMBER_OF_VOICE=53
VOICE_DIR=voice
PIC_DIR=pic
WAIT_TIME=1

# make directory.
init ()
{
    mkdir -p $VOICE_DIR
    mkdir -p $PIC_DIR
}

# wget --referer="http://203.104.105.167/" http://203.104.105.167/kcs/sound/kc236/3.mp3
voice_download ()
{
    KN="$1"
    DOWNLOAD_DIR=$VOICE_DIR/$KN
    mkdir -p $DOWNLOAD_DIR
    echo "voice: $1 download start to $DOWNLOAD_DIR"
    for vi in `seq 1 $NUMBER_OF_VOICE`
    do
        wget --referer="$VOICE_URL/" $VOICE_URL/kcs/sound/kc$KN/$vi.mp3 -P $DOWNLOAD_DIR > /dev/null 2>&1
        sleep $WAIT_TIME
    done
}

pic_download ()
{
    KN="$1"
    DOWNLOAD_DIR=$PIC_DIR/$KN
    mkdir -p $DOWNLOAD_DIR
    echo "$pic: 1 download start to $DOWNLOAD_DIR"
    wget http://125.6.184.15/kcs/ships/$KN.swf -P $DOWNLOAD_DIR > /dev/null 2>&1

    for i in `swfextract $DOWNLOAD_DIR/$KN.swf | grep JPEGs | sed "s/.*ID(s)//" | sed "s/,//g"`
    do
        swfextract $DOWNLOAD_DIR/$KN.swf -j $i -o $DOWNLOAD_DIR/$i.jpeg
    done
}

init
voice_download 236
pic_download 236

POJ 1637 Sightseeing tour

オイラー閉路にtwo-wayなエッジを追加した問題. 最大流で解けます。考え方は以下の通り

  • まずtwo-wayなエッジであろうと入力そのまま有向なエッジとしてグラフに追加していく。
  • 出るエッジについて-1,入るエッジについて+1を各ノードで計算しておく。通常のオイラー閉路ならば、各ノードで0ならOK?
  • 今回はtwo-wayなものをそのままグラフに追加したので、0にはならないが、必ず2の倍数になる。なぜなら、正解のグラフの向きにしたときには各ノードで0であり、正解と逆向きにすると入るところが+2,出るところが-2となるからである。
  • inoutをすべて/2する。これは流量を丁度1とするためである。(実際には2を流したいが、1だけ流してしまうのを防ぐ)
  • 流れないならば、決め打ちしたエッジはそのままで良く、流れるのならば、丁度-1+2=1となって逆向きのエッジを張ることに相当する
  • 最初にtwo-wayなエッジで決め打ちしたのと逆方向に流量1のエッジをつける
  • inoutがプラスとなっているところにsuper sourceからプラス分流し、マイナスとなっているところにsuper sinkからマイナス分流す
  • プラスの総量分がsuper sourceからsuper sinkから流れたらOK.
#include <vector>
#include <iostream>
#include <queue>

using namespace std;

// ----- lib start
struct Edge{
    int to,cap,rev;
    Edge(int _to,int _cap,int _rev) : to(_to),cap(_cap),rev(_rev) {};
};

void add_edge(vector<vector<Edge> >& E,int from,int to,int cap){
    E[from].push_back(Edge(to,cap,E[to].size()));
    E[to].push_back(Edge(from,0,E[from].size()-1));
}

vector<int> levels(vector<vector<Edge> > &E,int s){
    vector<int> level(E.size(),-1);
    level[s] = 0;
    queue<int> Q;
    Q.push(s);
    while(!Q.empty()){
        int v = Q.front();
        Q.pop();
        for(size_t i=0;i<E[v].size();i++){
            Edge &e = E[v][i];
            if(e.cap > 0 and level[e.to] == -1){
                level[e.to] = level[v]+1;
                Q.push(e.to);
            }
        }
    }
    return level;
}

int good_path(vector<vector<Edge> > &E,
        vector<int> &iter,
        vector<int> &level,
        int v,int t,int f){
    if(v == t) return f;
    for(int &i=iter[v];i<(int)E[v].size();i++){
        Edge &e = E[v][i];
        if(e.cap > 0 and level[v] < level[e.to]){
            int d = good_path(E,iter,level,e.to,t,min(f,e.cap));
            if(d > 0){
                e.cap -= d;
                E[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(vector<vector<Edge> > E,int s,int t){
    int flow = 0;
    const int INF = 1 << 30;
    while(true){
        vector<int> level = levels(E,s);
        if(level[t] < 0) return flow;
        vector<int> iter(E.size());
        int f;
        while((f=good_path(E,iter,level,s,t,INF)) > 0){
            flow += f;
        }
    }
}
// ----- lib end.

struct Street {
    int x,y,di;
    Street() {}
    Street(int _x,int _y,int _di) : x(_x),y(_y),di(_di) {}
};


bool solve(const vector<Street> &s,int m){
    vector<int> inout(m);
    // m is super source.
    // m+1 is super sink
    int source = m;
    int sink = m+1;
    vector<vector<Edge> > E(m+2);
    for(size_t i=0;i<s.size();i++){
        inout[s[i].x]--;
        inout[s[i].y]++;
        // two-way
        if(s[i].di == 0){
            add_edge(E,s[i].y,s[i].x,1);
        }
    }
    for(int i=0;i<m;i++){
        if(inout[i] % 2 == 1) return false;
        inout[i] /= 2;
    }
    int send=0;
    for(int i=0;i<m;i++){
        if(0 < inout[i]){
            add_edge(E,source,i,inout[i]);
            send += inout[i];
        }else if(inout[i] < 0){
            add_edge(E,i,sink,-inout[i]);
        }
    }
    return max_flow(E,source,sink) == send;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n;
    cin >> n;
    for(int test=0;test<n;test++){
        int m,s;
        cin >> m >> s;
        vector<Street> st(s);
        for(int i=0;i<s;i++){
            cin >> st[i].x >> st[i].y >> st[i].di;
            st[i].x--;
            st[i].y--;
        }
        if(solve(st,m)){
            cout << "possible" << endl;
        }else{
            cout << "impossible" << endl;
        }
    }
    return 0;
}

EmacsでシンタックスハイライトしたテキストをHTML化する方法

Emacs24以上で。

  • package.elとかでhtmlizeをインストールする。
  • disable-themeでテーマを一時的に無効化(黒背景とかだとヤバい?)
  • M-x htmlize-file でファイルを指定する。
  • HTMLができる

参考

StateMonadをOCamlで書いた。

というお話。コンパイラを書く時に必要になるっぽいので。

(*simple monad*)
module type MONAD =
  sig
    (* Type for state.It's Covariant*)
    type +'a t
    (* lift up normal value to monaded value.*)
    val return : 'a -> 'a t
    (* bind is the function to apply function
         that take normal value and return monaded value to monaded value*)
    val bind : 'a t -> ('a -> 'b t) -> 'b t
  end

(*extended monad.*)
module type EMONAD =
  sig
    include MONAD
    (* let (>>=) = bind *)
    val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
    (*lift up function to monad.
        let lift f t = bind t (fun x -> return @@ f x)
     *)
    val lift : ('a -> 'b) -> 'a t -> 'b t
  end

(*for STATE_MONAD*)
module type STATE =
  sig
    type t
  end

module type STATE_MONAD =
  functor(State : STATE) ->
         sig
           include EMONAD
           (* receive monad and initial state*)
           val run : 'a t -> State.t -> ('a * State.t)
           (* set state to arg*)
           val put : State.t -> unit t
           (* get state.*)
           val get : State.t t
         end

module StateMonad : STATE_MONAD =
  functor(State : STATE) ->
         struct
             type state = State.t
             (* monad type*)
             type 'a t = state -> ('a * state)
             (* make pair of value and state*)
             let return a = fun s -> (a,s)
             (* return state -> ('a * state)
                at first,apply m(1st arg) to s ,
                apply f to returned value*)
             let bind m f =
               (* get new state and value ,*)
               fun s ->
               match m s with
               | (x,s') -> f x s'
             let (>>=) = bind
             let lift f t = bind t (fun x -> return @@ f x)
             let run m a = m a
             let put s =
               fun _ -> ((),s)
             let get =
               fun s -> (s,s)
           end

(* sample usage *)
module IntStateMonad = StateMonad(
                           struct
                             type t = int
                           end
                         )

type 'a cons_list = Nil | Cons of 'a * 'a cons_list

let cons a lst =
  IntStateMonad.(get >>=
                   fun i ->
                   put (succ i)
                 >>= (fun x
                      -> return (Cons (a ,lst))))
(* it is equal to cons*)
(* let cons0 a lst = *)
(*   IntStateMonad.(bind (bind get (fun x -> put @@ succ x)) (fun x -> return (Cons (a,lst)))) *)


(* (\* リストに一個追加したら、カウンターが1になる *\) *)
(* assert (Cons ("a", Nils), 1) = *)
(*     (IntStateMonad.(run (cons "a" Nils >>= fun s -> return s) 0)) *)

(* (\* リストに2個追加したら、カウンターが2になる *\) *)
(* assert (Cons ("b", Cons ("a", Nil)), 2) = *)
(*     (IntStateMonad.(run (cons "a" Nil >>= cons "b" >>= fun s -> return s) 0)) *)

参考