悪い子のためのビットベクターによる定数倍最適化
※UTPC 2009 Problem F(天使の階段)ネタバレあり。
続きを読むネットで見かけた美人さん
この記事はきつねさんAdvent Calendarのために書かれました。
事前準備ゼロで速攻で書いたエントリが続くかと思いますが、とりあえずネットの海で今日検索した中で美人さんだと思った三次元きつねさんの紹介でもしようかと。
- Fort Worth Zooのスイフトギツネさん from http://www.ryanphotographic.com/canidae.htm
- コサックギツネさん http://en.wikipedia.org/wiki/File:Vulpes_corsac.jpg
- アカギツネさんその1 from http://czpohadka.blogspot.com/2011/03/o-lisce.html
- アカギツネさんその2 右の方が特に from http://www.fanpop.com/spots/foxes/images/8360467/title/foxes-wallpaper
- アカギツネさんその3
- 顔の傾げ方がヤバイアカギツネさんその4
たけるの通う小学校にDragon BookやSystemC等の専門書籍がてんこもりでヤバイでゲソ!
この記事は Functional Ikamusume Advent Calendar 2011 のために書かれたでゲソ!
時間がなくてまじめなネタが用意できなかったので、直前に見つけたネタっぽいネタになったでゲソ。まだ12/1の26時だからギリセーフでゲソ!
タケルの通う小学校の教室には、コンパイラ教科書の古典通称「Dragon Book(初版)」他色々なコンピュータ関連の書籍が置かれていて英才教育ぱないという話でゲソ!
イカ娘2期第2話「小学校に行かなイカ!?」の1シーンでゲソ。
さて、このすばらしき小学校の本棚ラインナップを紹介しようじゃなイカ!
- 一番左が明らかにDragon Bookの初版("Compilers: Principles, Techniques, and Tools")じゃなイカ! わたしも当然持っているでゲソ! まぁ個人的にはコンパイラの教科書としてはSteven Muchnick. Advanced Compiler Design and Implementationの方をお勧めしたいでゲソけどね。ちなみにDragon Book最新版はまだ買ってないでゲソ…(ぉ
- SystemC: from the ground up (左から5冊目)
- CとGNU開発ツールによる組み込みシステムプログラミング 第2版 (6冊目のオライリー本)
- SystemC Kernel Extensions for Heterogeneous System Modeling (7冊目の黄色い本)
- Performance Evaluation of Parallel Packet-Processing Architecture (8冊目の白と水色の本)
- ほとんど見切れてるけど、12冊目、たけるの髪の間から一番上だけが見えるのは小林芳直先生の定本 ASICの論理回路設計―高速・高信頼ディジタル・システムのための設計ノウハウでゲソ! これも持っているでゲソ!
やばい、この小学校ヤバイでゲソ! しかもなんかハードウェア設計とかコンパイラとか、コアなレイヤーの専門書が揃っているでゲソ! あの担任の先生に聞けばなんでも教えてくれて、そのまま1命令、1クロック、1ナノ秒を争う世界に連れて行かれてしまうのでゲソ!
しかし、関数型言語の本はないようでゲソね。しかしこれだけ下地があるのなら、侵略もしがいがあるじゃなイカ!
ネタばらしでゲソ:
Dragon Bookは漫然とアニメを見ていたら明らかに超見覚えのある本が映ったゲソので一発特定だったでゲソが、他の本まで詳細が分かるのは元ネタ画像を発見したからでゲソ。
- 元ネタ画像 http://homepage3.nifty.com/~Natsutan/img/books0.jpg 完 全 に 一 致
- 画像の出典/リンク元: なつたん 2007.08.11
- 別画像にThe Little Schemerとかあるので、これが出てくれば「イカ娘ちゃんはScheme大好きで、ここに映っている本はイカ娘が侵略のために持ってきたThe Little Schemerでゲソ!」っていうことになるでゲソが、今の所まだ見つかっていないでゲソ。
追記(2011/12/02)でゲソ:
どうやって元ネタ見つけたんでゲソか? という質問が多かったので追記。
- イカ娘見てたら「あっこれDragon Bookじゃね?」ってものを発見。
- 確認しようと思ったが、私の持ってる現物が手元になかった
- のでGoogleイメージ検索で「Compilers: Principles, Techniques, and Tools 背表紙」で検索したら、上の画像が1ページ目でひっかかった
- うんうん、やっぱりDragon Bookで確定ですね……ってちょっとマテ、右の本も全一致してるぞ!?
ということだったでゲソ!
C++でパターンマッチ欲しい
パターンマッチの良さとかに関する日記書いてるつもりが、いつの間にかC++の話がメインになっていたでござる。
パターンマッチについては http://togetter.com/li/6990 http://togetter.com/li/216989 あたりを参照のこと。
サンプルとして、整数と変数と足し算と掛け算から成る式を考え、その表示と分配法則による変換をします。
式 ::= 整数 | 変数 | 式+式 | 式*式
これの、OCaml(+パターンマッチ)とC++のそれぞれでの実装例を示し、
パターンマッチで解決したい問題や利点などをつらつらと。
ここに使われている例題のC++実装は、オブジェクト指向としては中途半端で微妙ではあります。
継承を使うなどの選択肢も考えましたが、本質的には問題は解決しない気がしています。
解決するような設計があれば教えてください、使いたいです(切実
複数のオブジェクトの内部構造に同時に関わる処理(distribute関数参照)を行う必要があるので、
継承やカプセル化を使って整理できるのは1つのオブジェクトに関する処理だけで、
その他のオブジェクトに関しては依然として今回の例のように外側からifなどで条件分岐するアクセスが必要になってくるのだと思います。
(継続スタイルでごにょごにょやればできることもあると思いますが、書きにくい…)
OCaml+パターンマッチによる実装例
type op = (* 演算子; とりあえず + と * のみ *) | Add (* + *) | Mul (* * *) let print_op o = match o with | Add -> print_string "+" | Mul -> print_string "*" type expr = (* 式 *) | BinOp of op * expr * expr (* 二項演算 *) | Var of string (* 変数 *) | Int of int (* 整数 *) (* 式の表示 *) let rec print_expr e = match e with | BinOp (o,e1,e2) -> print_string "("; print_expr e1; print_op o; print_expr e2; print_string ")" | Var v -> print_string v | Int i -> print_int i (* 式の分配法則による変換; 簡単のために、単純なケースのみ *) let rec distribute e = match e with | BinOp(Mul, BinOp(Add,a,b), c) (* (a+b)*c を (a*c)+(b*c)に変換する *) -> BinOp(Add, BinOp(Mul,a,c), BinOp(Mul,b,c)) | _ -> e ;; let e = BinOp(Mul, BinOp (Add, Int 1, Var "a"), Int 3) in (* (1+a)*3 *) print_expr e; print_newline (); print_expr (distribute e); print_newline ();
実行結果:
$ ocaml expr.ml ((1+a)*3) ((1*3)+(a*3))
C++による実装例
注: メモリリークしてます(Exprオブジェクトがdeleteされない)がそこは本質的ではないのでとりあえずスルーしてください。
#include <stdio.h> enum OP{ OP_ADD, // + OP_MUL, // * }; void print_op(enum OP o) { if( o == OP_ADD ){ printf( "+" ); } else if( o == OP_MUL ){ printf( "*" ); } } class Expr{ public: void print_expr() const{ if( isBinOp() ){ // 検査 printf( "(" ); getExpr1()->print_expr(); // アクセス print_op(getOp()); // アクセス getExpr2()->print_expr(); // アクセス printf( ")" ); } else if( isVar() ){ // 検査 printf( "%s", getVar() ); // アクセス } else if( isInt() ){ // 検査 printf( "%d", getInt() ); // アクセス } } const Expr *distribute() const{ // (a+b)*c を (a*c)+(b*c)に変換する if( isBinOp() && getOp() == OP_MUL && getExpr1()->isBinOp() && getExpr1()->getOp() == OP_ADD ){ Expr *a = getExpr1()->getExpr1(); Expr *b = getExpr1()->getExpr2(); Expr *c = getExpr2(); return createBinOp( OP_ADD, createBinOp(OP_MUL,a,c), createBinOp(OP_MUL,b,c) ); } else return this; } bool isBinOp() const { return typ == EXPR_BINOP; } enum OP getOp() const { return o; } Expr *getExpr1() const { return e1; } Expr *getExpr2() const { return e2; } bool isVar() const { return typ == EXPR_VAR; } const char *getVar() const { return var; } bool isInt() const { return typ == EXPR_INT; } int getInt() const { return i; } static Expr *createBinOp(enum OP o, Expr *e1, Expr *e2){ Expr *e = new Expr(); e->typ = EXPR_BINOP; e->o = o; e->e1 = e1; e->e2 = e2; return e; } static Expr *createInt(int i){ Expr *e = new Expr(); e->typ = EXPR_INT; e->i = i; return e; } static Expr *createVar(const char *var){ Expr *e = new Expr(); e->typ = EXPR_VAR; e->var = var; return e; } private: enum{ EXPR_BINOP, EXPR_VAR, EXPR_INT } typ; enum OP o; // 演算子; EXPR_BINOP用 Expr *e1, *e2; // EXPR_BINOP用 const char *var; // 変数; EXPR_VAR用 int i; // 整数; EXPR_INT用 }; int main() { Expr *e = // (1+a)*3 Expr::createBinOp( OP_MUL, Expr::createBinOp( OP_ADD, Expr::createInt(1), Expr::createVar("a") ), Expr::createInt(3) ); e->print_expr(); printf( "\n" ); e->distribute()->print_expr(); printf( "\n" ); return 0; }
実行結果:
$ g++ -o expr -Wall -Wextra expr.cpp $ ./expr ((1+a)*3) ((1*3)+(a*3))
検査とアクセスと変数スコープを一つに
まず、どうにかしたいのは、@kinabaさんの表現を借りると「検査とアクセス」の二つがC++版では分離していること。
一部抜粋すると、
void print_expr() const{ if( isBinOp() ){ // 検査 printf( "(" ); getExpr1()->print_expr(); // アクセス print_op(getOp()); // アクセス getExpr2()->print_expr(); // アクセス printf( ")" ); }
こんな感じで、isBinOp()で式が二項演算かどうか検査した後、その二項演算の各部分へのアクセスをgetExpr1()などで行っています。
問題としては、isBinOp()がfalseの場合でも(あるいは検査しなくても問答無用で)getExpr1()にアクセスできてしまうので、安全ではありません。
解決策の一つとして、検査とアクセスの両方を行う一つの関数を作ることがあります。
class Expr{ public: void print_expr() const{ Expr *e1, *e2; // 部分情報を格納するための変数宣言 enum OP o; const char *var; int i; if( isBinOp(&o,&e1,&e2) ){ // 検査+アクセス printf( "(" ); e1->print_expr(); print_op(o); e2->print_expr(); printf( ")" ); } else if( isVar(&var) ){ // 検査+アクセス printf( "%s", var ); } else if( isInt(&i) ){ // 検査+アクセス printf( "%d", i ); } } const Expr *distribute() const{ // (a+b)*c を (a*c)+(b*c)に変換する Expr *a, *b, *c, *e; enum OP o, o2; if( isBinOp(&o,&e,&c) && o == OP_MUL && e->isBinOp(&o2,&a,&b) && o2 == OP_ADD ){ return createBinOp( OP_ADD, createBinOp(OP_MUL,a,c), createBinOp(OP_MUL,b,c) ); } else return this; } bool isBinOp(enum OP *o, Expr **e1, Expr **e2) const { if( typ == EXPR_BINOP ){ *o = this->o; *e1 = this->e1; *e2 = this->e2; return true; } else return false; } bool isVar(const char **var) const { if( typ == EXPR_VAR ){ *var = this->var; return true; } else return false; } bool isInt(int *i) const { if( typ == EXPR_INT ){ *i = this->i; return true; } else return false; } // 後は同じ
isBinOpなどが成功した時には、渡したポインタ経由で各部分の情報も一緒に取ることができます。
これなら、不正なアクセスはできません。isBinOpが成功した時だけ、部分式の情報が得られます。
distributeのような、複数段/複数オブジェクトに渡る構造マッチングのコードも、少し見やすくなった気がします。
しかし、これでもまだ完全にきれいではありません。
- 「部分情報を格納するための変数宣言」と「検査+アクセス」が別。
- やはり、isBinOpなどを自分で書かないといけない
スコープの問題については、
void print_expr() const{ ... else if( const char *var = isVar() ){ // 検査+アクセス printf( "%s", var ); } ... } const char *isVar() const { if( typ == EXPR_VAR ) return this->var; else return NULL; }
みたいにすると回避できることもありますが、これは bool にすると false になる値を元のgetVar()が返さないことが前提です。
なので、このままではたとえば isInt() には適用できません。
何らかのwrapper classを返すことも考えられますが、以下に示すように1段分変換が必要であるような気がします。
class IntWrapper{ public: IntWrapper() : valid(false), i(0){} IntWrapper(int v) : valid(true), i(v){} operator bool() const { return valid; } int getValue() const { return i; } private: bool valid; int i; }; ... class Expr{ ... void print_expr() const{ ... else if( IntWrapper intWrapper = isInt() ){ printf( "%d", intWrapper.getValue() ); } ... } IntWrapper isInt() const { if( typ == EXPR_INT ) return IntWrapper(this->i); else return IntWrapper(); }
暗黙にIntWrapperを本来の値、この場合はintにキャストする演算子を定義することで変換を省く方法もあるかもですが、
その場合 bool へのキャスト演算子と衝突を起こすので使わない方がいいと思います。
(うっかり if( intWrapper.getValue() != 0 ) のつもりで if( intWrapper ) と書いてしまうと…)
OCamlのパターンマッチだと、
- 検査とアクセスを一つにすることによる安全性
- アクセスした結果の変数スコープが、検査結果の条件が成立するスコープと一致
- (わざわざ検査+アクセスメソッドとか書かなくてもOK)
ということが実現されます。
(* 式の表示 *) let rec print_expr e = match e with | BinOp (o,e1,e2) -> print_string "("; print_expr e1; print_op o; print_expr e2; print_string ")" | Var v -> print_string v | Int i -> print_int i
BinOp(o,e1,e2) の部分で、eがBinOpであるかの検査が行われ、成功したら部分構造がo,e1,e2の変数に入ります。
o,e1,e2の変数宣言も一緒にやっているようなもので、これらの変数はこの検査が成功した部分(同じ行の->右側部分)からのみアクセスできます。
分岐ケース記述漏れチェックが強力
OCamlのVariant型との組み合わせとかだと、全ての場合をカバーできているかの検査をコンパイラがやってくれます。
C++版で、isBinOpかisVarかisIntかのどれかがtrueになる、というのは設計意図としてはありますが、コンパイラはチェックしてくれません。
int foo() const{ if( isBinOp() ) return 0; else if( isVar() ) return 1; else if( isInt() ) return 2; // 設計上ではここに到達しないはずだけど、コンパイラにはそれが分からんのです // -> return必要だよ♪値返してね♪って言ってくる }
なので、こういう風に書くこともあるのではないでしょうか。しかし気持ち悪いです…
int foo() const{ if( isBinOp() ) return 0; else if( isVar() ) return 1; else if( isInt() ) return 2; assert(false); return -1; // 適当な値 }
あるいは
int foo() const{ if( isBinOp() ) return 0; else if( isVar() ) return 1; else /* if( isInt() ) */ return 2; }
また、例えば新しく1項演算式(例: ~1)を表すUnaryOpを追加して、isUnaryOp()の検査を追加する場合、追加し忘れてもコンパイラはあまり文句を言ってくれません。
(上のようにassert突っ込んでおけば実行時に落ちてはくれますが…)
OCamlだと、たとえば print_expr で Int に関するパターンマッチを抜かすと:
(* 式の表示 *) let rec print_expr e = match e with | BinOp (o,e1,e2) -> print_string "("; print_expr e1; print_op o; print_expr e2; print_string ")" | Var v -> print_string v (* Int i のパターンマッチを削除 *)
ちゃんとコンパイル時にWarningを上げてくれて、どのケースが抜けているかまで教えてくれます:
Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: Int _
これを利用すると、UnaryOp を追加 → コンパイル → Warningの列が出るので片っ端からUnaryOpに関するマッチを追加 → 設計変更完了!
ということができます。
(catch-allのマッチ書いてあるとひっかからないですが…)
C++だと、enumの値でswitchすると、case書き忘れはコンパイル時にwarning出してくれますが、
イカのように全部網羅しても warning: control reaches end of non-void function って出ますね…
int bar(enum OP o) { switch(o){ case OP_ADD: case OP_MUL: return 0; } }
その他パターンマッチの利点
強力な構造検査
複数段に渡る構造マッチングとか簡潔に書きたい。これは2段ですが、もっと深くなると更に強力に。
| BinOp(Mul, BinOp(Add,a,b), c) (* (a+b)*c を (a*c)+(b*c)に変換する *) -> BinOp(Add, BinOp(Mul,a,c), BinOp(Mul,b,c))
「値の構築とデータの取り出し」の構文が似ている
@kinabaさん哲学その2。
| BinOp (o,e1,e2) -> ... (* 検査+アクセス *) let e = BinOp(Mul, BinOp (Add, Int 1, Var "a"), Int 3) in (* 構築 *)
if( isBinOp(&o,&e1,&e2) ){ // 検査+アクセス Expr::createBinOp(OP_MUL, Expr::createBinOp(OP_ADD, Expr::createInt(1), Expr::createVar("a")),Expr::createInt(3)); // 構築
まぁこういうことです。
構文が似ていると、変換前(取り出し構文で記述)と変換後(構築構文で記述)の比較がしやすいです。
| BinOp(Mul, BinOp(Add,a,b), c) (* 変換前 *) -> BinOp(Add, BinOp(Mul,a,c), BinOp(Mul,b,c)) (* 変換後 *)
まとめ
- 安全
- 検査とアクセスを一度に行うことで、検査せずにアクセスすることを防ぐ
- アクセスした結果が格納される変数のスコープが、検査成功が成立するスコープと一致するので、検査が成功しなかった場合にはアクセス結果の変数が見えない
- 強力
- 複数段に渡る構造のマッチングとかできます
- 分岐ケース記述漏れチェックが強力です
- 読みやすい
- 構築とアクセスの構文が似ているのでプログラマが読み書きしやすいです
- 楽
- 言語built-inだとわざわざ検査+アクセスメソッドとか自分で書かなくてもOK
WindowsでのTeXの書き方メモ
最近色々と無駄に設定とかではまって時間無駄にしたので、次回は無駄にしないために日記として残します。
自分用のメモなので、「自分の場合はこういう設定にした」という箇所が多いです。再利用する人は適宜自分の好みで設定してください。何かより良い方法あればぷりーず。
主に英文論文を想定していますがそれ以外のTeX文書にも使える点はあるでしょう。
大まかな流れ
TeX, EPS →(latex)→ dvi →(dvips, dvipdfmx)→ ps, pdf。
TeX, PDF →(pdflatex)→ pdf というのも便利だけど、camera readyの段になって「PSファイルも送れ」と言われると悲しいので上記の方法にします。
$ latex paper.tex $ dvipdfmx -p letter -o paper.pdf -f dlbase14.map paper.dvi $ dvips -j0 -Pdl -t letter -o paper.ps paper.dvi $ gswin32c -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sPAPERSIZE=letter -sOutputFile=paper_ps.pdf paper.ps
本文の用意
適当に書けばいいと思います。
パッケージ紹介。Algorithm。かっこいい擬似コードが書けます。
\usepackage{algorithm} \usepackage{algorithmic} \renewcommand{\algorithmicrequire}{\textbf{Input:}} \renewcommand{\algorithmicensure}{\textbf{Output:}} \renewcommand{\algorithmiccomment}[1]{// #1}
グラフの用意
Excelでグラフ作って、EPSに変換します。
ここ http://kenkitagawa.cocolog-nifty.com/blog/2010/04/exceleps-eps-78.html を参考にしました。
- グラフを作ります。
- フォントは、Arial にしておきます。好きなフォントがある場合でもとりあえずArial。
- いくつかの定型サイズにしておくと、後でbounding boxの調整が楽です。
- 印刷ページサイズおよび余白の設定を各グラフごとにします(Excel 2002だと、各グラフごとに独立して設定が保存される模様)。
- グラフをクリック→印刷→PSプリンタを選択→印刷プレビュー→設定で、ページサイズ、余白、dpiなどが設定できます。
- 「ページ」A3横600dpi、「グラフ」印刷するグラフのサイズ:指定、「余白」上余白以外は全部0、ページ中央 水平・垂直にチェック。上余白も0でよかった気がする。
- 印刷するグラフのサイズを「指定」以外にすると、勝手に拡大縮小されるのだが、その際にレイアウトが崩れたりしたので使わない方向で。ページサイズが小さくても勝手に拡大縮小されるので無駄にでかいサイズを指定。
- グラフを選択し、印刷します
- PSプリンタ(Generic MS Publisher Color Printer)を選択
- TrueTypeフォント: 「デバイスフォントと代替」
- PostScript出力オプション:「EPS」
- TrueTypeフォント ダウンロードオプション: 「アウトライン」
- 出力先は、適当に。
- PSプリンタ(Generic MS Publisher Color Printer)を選択
- 出力されたEPSファイルのBounding boxを、ページいっぱいにグラフが出るように調整します。
ちなみに、こうするとフォントはEPSの時点では埋め込まれず、後でPDFにする時に埋め込まれる模様です。
フォントをArial以外の何かにして、TrueTypeフォント: 「ソフトフォントとしてダウンロード」とすると、EPSの時点で埋め込まれるような雰囲気がします。本当だろうか。これでもいい気がするけど私は上の方法にするぜ。
図の用意
OpenOffice Drawで図を作って、EPSにエクスポートします。
図1枚ごとに1ページのみからなる1ファイルにすると何かと便利なのでそうします。
hoge.odg をEPSにエクスポートする時にデフォルトで出力先が hoge.eps になります。
図のサイズに合わせてページ設定をします。縦幅とか横幅を揃えておくと縮尺の揃った論文になる気がします。
余白のサイズはどうやら除外されるようです。
フォントに関しては、どうやらEPSにはフォントというより単なる図形として吐かれている模様。PDFにした時のフォント一覧にも出ないし。
というか、今気づいたがそもそも図内の文字情報も落ちてるっぽい。検索できない。これはいいのか?
まぁ、そんな感じなので好きなフォントで図を作るといいと思います。
latexの実行
普通だと思います。
dvipdfmxによるPDF生成
フォントをちゃんと埋め込むために設定が必要。
- -f dlbase14.map オプションの指定: http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?PDF%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9#rdc781c9
- 設定ファイル書き換え: http://liosk.blog103.fc2.com/blog-entry-174.html 当該ファイルはgs8.71ではResource/Init/の下に移動していたが、それ以外は同じ。
という訳で、
$ dvipdfmx -p letter -o paper.pdf -f dlbase14.map paper.dvi
というコマンドラインができたとさ(-p letterは用紙サイズ指定)。
Adobe Readerで開いてファイル→文書のプロパティ→フォントを見るとちゃんと全て埋め込みサブセットになっていれば幸せ。
グラフ中のArialは「Helvetica(埋め込みサブセット)」に置換されています。
ArialじゃなくてHelvetica(少なくともそうっぽい)になってます。
gsが置換したのかな。実体はNimbusか何かかな。
dvipsでのPS生成(とGhostScriptでのPDF生成)
PSも出せとのお達しなのでdvipsでPSを吐きます。
ついでにPSからPDFを生成することもできます。
$ dvips -j0 -Pdl -t letter -o paper.ps paper.dvi $ gswin32c -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sPAPERSIZE=letter -sOutputFile=paper_ps.pdf paper.ps
dvipsのオプションについてはここ http://www.grassbook.org/neteler/highres_pdf.html を参考にしました。-j0 -Pdlを指定することで私の場合はフォントが全て埋め込まれた雰囲気がします。
xhl的・青春18切符で行く日帰り諏訪旅行プラン
諏訪は諏訪子様信者には超テンションの上がる聖地(※個人の感想であり実際の効能を保証するものではありません)なので一度行くといいと思うよ。
ということで、今日は青春18きっぷで行く日帰り諏訪旅行のご紹介を独断と偏見でお送りしよう、と思ったのだけれど、独断と偏見すぎて、なんか「私が割と軽めの日帰り諏訪旅行をする場合にどういう旅程にするか」というものになってしまったのでそのまま書きます。
世間標準からすると
- かなり鉄道偏重で、
- かつ鉄道乗車時間が長く、
- かつ観光時間が短く、
- かつ時速5〜6kmくらいで歩けることを想定していて、
- かつ飯の時間が組み込まれていません。
まぁ私の旅行では全ていつものことですが、全く万人におすすめできるプランではありませんのでご注意ください。
というかこの旅程を「軽め」と表現し、なおかつこういう旅行が好きな私の知り合いの人がいたら一緒に旅行に行こうじゃなイカ!
駅
とりあえず諏訪観光の拠点となる駅をまじめに紹介します。
新宿に近い順に三連続です:
往復の列車
中・央・本・線!
新宿から下諏訪まで4時間〜4時間半です。
1時間〜1時間半くらい列車の間隔があるので列車の時間は調べておきます。
上諏訪または茅野でしばらく停車する列車がありますのでうまく利用するといいことがあるかもしれません。
自転車がある場合のコース例
自転車があれば、適当に上記三駅のどこかで降りて、自転車で巡って、適当な駅から帰ればいいと思います。
諏訪湖一周もできるし、諏訪大社の各宮も回れます。
どこかでレンタサイクルを借りるか輪行袋に入れて持っていくかだと思います。
ただ冬季は路面の雪や凍結に注意かも。
自転車がない場合のコース例
使えそうなバスは日祝は運休のようだし、徒歩ですね!
※私は車には興味がないので徒歩です。
なお、駅名の左にあるのが着時刻、右にあるのが発時刻です。
- 新宿07:52->08:35高尾08:44->10:24甲府
- 【甲府乗継】甲府で30分あるので途中下車して何か軽く観光できますね。ちなみにこの乗り換えは甲府〜小淵沢間の好きな駅でできます。
- 甲府10:58->11:58茅野
- 【上社/茅野】茅野で降りて諏訪大社上社に参拝します(2時間33分)。徒歩片道40分*2と考えると、上社前宮、上社本宮あわせて1時間くらい時間があります。周辺にぽつぽつ関連の何かとかもあるのでそういうところに行くのもいいかも。
- 茅野1431->1436上諏訪
- 【諏訪湖/上諏訪】上諏訪駅から500〜800mくらい歩くと諏訪湖に出るので、諏訪湖畔ですわすわしましょう(38分)。
- 上諏訪1514->1519下諏訪
- 【下社/下諏訪】下諏訪駅から下社秋宮・春宮へ(1時間54分)。下諏訪駅-下社秋宮-下社春宮は徒歩各10分程度。こちらも移動時間を除いて1時間くらい時間があります。下諏訪は温泉がある(下社秋宮-下社春宮間)のでそういうところに行くのもいいかもしれない。
- 下諏訪1713->1947大月1952->2129新宿
- 【駅構内足湯/上諏訪】上諏訪-大月間の列車は上諏訪で12分停車する(1718上諏訪1730)ので、その間に列車から降りて上諏訪駅上りホームにある足湯に浸かりましょう。乗り遅れ注意。
ちなみに今日も諏訪行ってきました
はつもうで!
- 松本0809->0846下諏訪
- 【下社/下諏訪】(41分)
- 下社秋宮のみ。10分で徒歩した。人はまばら。巫女さんはたくさん。何か火の前で大幣と塩でお清めをしていた。
- 下諏訪0927->0937茅野
- 【上社/茅野】(2時間7分)
- 茅野1144->1420高尾1430->1508中野->秋葉原->帰宅