C Preprocessorを侵略するゲソ!

この記事は Functional Ikamusume Advent Calendar jp 2010 http://partake.in/events/5784afd8-d43b-4cbe-9256-430d5ababa2b のために書かれたでゲソ!

今日はおまえたちにC Preprocessorを使ったプログラミングを紹介するでゲソ!
私はC Preprocessorは初心者なので、簡単な機能だけしか使えないでゲソ!

手始めにフィボナッチ数を実装してみようじゃなイカ!
イカOCamlでの実装を示すでゲソ。

let rec fib_iter a b c = 
  if c <= 0
  then
    a
  else
    fib_iter b (a+b) (c-1)
in
let fib d = 
  fib_iter 1 1 d
in
let rec iter e f =
  if e <= f
  then begin
    print_int (fib e);
    print_newline ();
    iter (e+1) f
  end else
    ()
in
iter 0 10

実行結果はこんな感じになるでゲソ。

1
1
2
3
5
8
13
21
34
55
89
- : unit = ()

実装しなイカ?

これをC Preprocessorで実装するでゲソ。

ただ、直打ちだとすごく面倒になるので、メタプログラミングするでゲソ。
もっと早く思いついていればメタプログラミングの会で話せたんじゃなイカ?
サンプルコードは http://xhl.kitsunemimi.org/ika1219.zip にあるでゲソ。

1つの関数は1つのファイルで定義するでゲソ。ファイル名は 関数名.ika にするでゲソ。
まず、fib_iter の実装を示すでゲソ。

/* file: fib_iter.ika */
#include "ika.h"

ARGS(A,B,C)

IF( C <= 0 )
THEN
  RETURN( A )
ELSE
  CALL(Z1, fib_iter, B, A+B, C-1)
  RETURN( Z1 )
ENDIF

順番に解説していくでゲソ!

/* file: fib_iter.ika */
#include "ika.h"

ika.h はメタプログラミング用のヘッダでゲソ。詳細は後で話すでゲソ。

ARGS(A,B,C)

ファイルの頭で、関数の引数宣言を行うでゲソ。
この場合は、3つの引数 A, B, C を取るという宣言でゲソ。
今の所全ての変数・引数などの型は整数でゲソ。

IF( C <= 0 )
THEN
  RETURN( A )
ELSE
  CALL(Z1, fib_iter, B, A+B, C-1)
  RETURN( Z1 )
ENDIF

IF, THEN, ELSE, ENDIF を使って条件分岐ができるでゲソ。
返す値の指定はRETURNを使うでゲソ。

  CALL(Z1, fib_iter, B, A+B, C-1)

関数呼び出しでゲソ。
fib_iter が関数名、それ以降が引数、Z1が返値を格納する変数でゲソ。

OCamlソースコードと対応しているじゃなイカ!

この調子で fib と iter も実装するでゲソ。

/* file: fib.ika */
#include "ika.h"

ARGS(D)
CALL(Z2,fib_iter,1,1,D)
RETURN(Z2)
/* file: iter.ika */
#include "ika.h"

ARGS(E,F)

IF(E <= F)
THEN
  CALL(Z3,fib,E)
  printf( "%d\n", Z3 );
  CALL(Z4,iter,E+1,F)
ENDIF

トップレベルはとりあえずmain関数を定義しておくでゲソ。

/* file: main.ika */
#include "ika.h"

INCLUDE <stdio.h>

int main()
{
  CALL(Z4,iter,0,10)
  return 0;
}

これで実装完了でゲソ!

注意点としては、自力でα変換する必要があるでゲソ。
つまり、各ファイルで変数名がかぶらないようにする必要があるでゲソ。
もう一段メタプログラミングすれば解消できると思うでゲソが、そこまではやらなかったでゲソ。

あと、再帰は末尾再帰しかできないでゲソ。

コンパイルしなイカ?

実装ができたら cpp (C Preprocessor)で処理するでゲソ。
hoge.ika を cpp に通して hoge.ika.c に変換するでゲソ。

$ for file in *.ika; do cpp -P $file > $file.c; done
  • P は行番号情報を出力しない gcc cpp のオプションでゲソ。なくても動くでゲソ。

hoge.ika.c が、メタプログラミングをしない場合の hoge の C Preprocessor での実装でゲソ。

トップレベルの関数の.ika.cをもう一度gccコンパイルすると実行できるようになるでゲソ。

$ gcc -o main main.ika.c
$ ./main
1
1
2
3
5
8
13
21
34
55
89

できたじゃなイカ!

ちなみに、C Preprocessorを通すとこんな感じの出力が出るでゲソ。
stdio.h に対応する部分と大量に出る空行、pragmaは省略したでゲソ。

$ cpp main.ika.c
int main()
{
  printf( "%d\n", ( (1<<0)+ 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( 0 + (1<<1)+ 0 + 0 + 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ (1<<1)+ 0 + 0 + 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ 0 + (1<<2)+ 0 + 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( 0 + 0 + 0 + (1<<3)+ 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ 0 + (1<<2)+ (1<<3)+ 0 + 0 + 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ 0 + (1<<2)+ 0 + (1<<4)+ 0 + 0 + 0 + 0) );
  printf( "%d\n", ( 0 + (1<<1)+ 0 + 0 + 0 + (1<<5)+ 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ (1<<1)+ (1<<2)+ 0 + (1<<4)+ (1<<5)+ 0 + 0 + 0) );
  printf( "%d\n", ( (1<<0)+ 0 + 0 + (1<<3)+ (1<<4)+ 0 + (1<<6)+ 0 + 0) );
  return 0;
}

CPP時に値が計算されていることが分かるんじゃなイカ?

解説しなイカ?

要するに、条件分岐を #if / #else / #endif で、変数束縛を #define で、関数呼び出しを #include で実装しているでゲソ。
つまり、こんな感じじゃなイカ?

/* file: fib_iter.ika.c */
                          /*  let rec fib_iter a b c =   */
#if A <= 0                /*    if c <= 0 then           */
#define RETURN_VALUE A    /*      a                      */
#else                     /*    else                     */
#define A B               /*      (* set 1st argument *) */
#define B A+B             /*      (* set 2nd argument *) */
#define C C-1             /*      (* set 3rd argument *) */
#include "fib_iter.ika.c" /*      fib_iter b (a+b) (c-1) */
#endif                  

ただ、このままでは動かないでゲソ。
これが動かないのは当然でゲソ。
#define A した時点で古いAが上書きされてしまうからでゲソ。
たとえば、

#define B 1
#define A B
#define B A+B
B

と書いても、B → A+B → B+B と置換されるだけで終わってしまうでゲソ。
#defineの右辺の式は#define時点では評価されず、実際に展開された時にはじめて評価されるでゲソ。

ここで、各変数が8ビット変数であると仮定すると、イカのようなコードで expr のその時点での値に X を束縛できるでゲソ。

#if (expr) & 1
#define X0 1
#else
#define X0 0
#endif
#if (expr) & 2
#define X1 2
#else
#define X1 0
#endif
#if (expr) & 4
#define X2 4
#else
#define X2 0
#endif
#if (expr) & 8
#define X3 8
#else
#define X3 0
#endif
#if (expr) & 16
#define X4 16
#else
#define X4 0
#endif
#if (expr) & 32
#define X5 32
#else
#define X5 0
#endif
#if (expr) & 64
#define X6 64
#else
#define X6 0
#endif
#if (expr) & 128
#define X7 128
#else
#define X7 0
#endif
#undef X
#define X (X0+X1+X2+X3+X4+X5+X6+X7)

こうすれば、exprの中で使われた変数が#undefされたりされても、X0〜X7が生きていればXの値は有効でゲソ!
X0〜X7の変数名は必要に応じてα変換すればいいでゲソ。
これを X <=: expr と表現することにするでゲソ。
関数の頭とかで適当な別変数に引数の値をセットして、それ以外の場合は #define でできるでゲソ。

/* file: fib_iter.ika.c */
a <=: A
b <=: B
c <=: C
                          /*  let rec fib_iter a b c =   */
#if a <= 0                /*    if c <= 0 then           */
#define RETURN_VALUE a    /*      a                      */
#else                     /*    else                     */
#define A b               /*      (* set 1st argument *) */
#define B a+b             /*      (* set 2nd argument *) */
#define C c-1             /*      (* set 3rd argument *) */
#include "fib_iter.ika.c" /*      fib_iter b (a+b) (c-1) */
#endif                  

但し、これだけではまだ不十分でゲソ。
#includeを展開するとこんな風になるでゲソ。

/* file: fib_iter.ika.c */
a <=: A
b <=: B
c <=: C
                          /*  let rec fib_iter a b c =   */
#if a <= 0                /*    if c <= 0 then           */
#define RETURN_VALUE a    /*      a                      */
#else                     /*    else                     */
#define A b               /*      (* set 1st argument *) */
#define B a+b             /*      (* set 2nd argument *) */
#define C c-1             /*      (* set 3rd argument *) */
// #include "fib_iter.ika.c" /*      fib_iter b (a+b) (c-1) */
/* file: fib_iter.ika.c */
a <=: A
b <=: B
c <=: C

#define を展開すると

/* file: fib_iter.ika.c */
a <=: A
b <=: B
c <=: C
                          /*  let rec fib_iter a b c =   */
#if a <= 0                /*    if c <= 0 then           */
#define RETURN_VALUE a    /*      a                      */
#else                     /*    else                     */
#define A b               /*      (* set 1st argument *) */
#define B a+b             /*      (* set 2nd argument *) */
#define C c-1             /*      (* set 3rd argument *) */
// #include "fib_iter.ika.c" /*      fib_iter b (a+b) (c-1) */
/* file: fib_iter.ika.c */
a <=: b
b <=: a+b
c <=: c-1

c <=: c-1 が問題でゲソ。
これを展開すると

#if (c0+c1+c2+c3+c4+c5+c6+c7-1) & 1
#define c0 1
#else
#define c0 0
#endif
#if (c0+c1+c2+c3+c4+c5+c6+c7-1) & 2 /* まちがい! c0は既に新しい値で更新されてしまっている! */
#define c1 2
#else
#define c1 0
#endif
...

となるでゲソ。

/* file: fib_iter.ika.c */
a1 <=: A
b1 <=: B
c1 <=: C
a  <=: a1
b  <=: b1
c  <=: c1
                          /*  let rec fib_iter a b c =   */
#if a <= 0                /*    if c <= 0 then           */
#define RETURN_VALUE a    /*      a                      */
#else                     /*    else                     */
#define A b               /*      (* set 1st argument *) */
#define B a+b             /*      (* set 2nd argument *) */
#define C c-1             /*      (* set 3rd argument *) */
#include "fib_iter.ika.c" /*      fib_iter b (a+b) (c-1) */
#endif                  

こんな感じに二重にすると、問題なくなるでゲソ。

ただ、これはすごく面倒なので、メタプログラミングしたでゲソ。
ついでだからC Preprocessorでメタプログラミングしたでゲソ!

UTPC 2010

5位でした。
http://www.utpc.jp/2010/standings.html

感想をだらだらと。

A: 唯 k t k r ! これが全ての流れを決定付けた。 typedef unsigned int ui; とか書いた。問題自体は即答。9分

B, C: 書くだけ。9分

D: 書くだけ。DFSでうにょうにょ。しかしエンバグと、非連結の場合の条件読み間違えて 2WA。

E: キョンうぜぇwww

ある2行2列取ってきた時に、

ox
xo

のようになっていたら、ox入れ替えても大丈夫なので、No。

よって、任意の2行取ると、

oooooooxxxxxxxxx
oooooooooooooxxx

のようになっているはず(列順は入れ替えがあるかもしれない)。

つまり、各行で左から全部のONを詰めて矛盾なければいいんじゃね。

でちゃんと証明せず出したら通った。

F: 地道にDPで書いた。しかしエンバグした、つーかSample通ってねぇよw

H: 迷い猫と聞いてG飛ばしてHへ。O(1000*1000)くらいのDPで、最大猫数以下で抑えられるかどうかが判定できるので、あとはその上限値に関して2分探索。

G: 座標変換、以上。死にそうだった(ぉ

I: 原理的には(物理位置,禁止シーケンスのそれぞれの何文字目にいるか)でダイクストラした。幅優先でよかったね。後半は最長のものだけでおk。経路がどれくらい延びるかの上限は証明抜きで出したけど無事通った。

J: ワカラネ。適当にサンプル作った範囲では0,1,2しかでなさそうだが...むむ。とりあえず記念submitだけしておいた。

K: ワカラネ。結構時間かけて考えて、解けるような気はしたけどだめだった。

L: 捨て捨てwww

JKLの難しめの問題と、それまでの道中、という感じでした。難問ひとつも解けずorz

コードはこちら。証明書期限切れてますサーセンwwworz https://makoto.kitsunemimi.org/tmp/UTPC2010/
今回はコードがひどいです。A問題で唯ktkr! と思ってしまったがために、H問題はこんな感じに。普通に書いた後に置換したわけじゃないよ!(ぉ

// きょうも のぞみ の手助けをする戦いが はじまる

/*
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
_______________________________
        __    _        /フ´ ⌒ヾ\          [l{≫=≪}!
      [>´  「:ンr<ム      t:く.〈〈! リNソハ_rァ         刃'⌒ `゙マ
     /巛Nル|-イ爪ビ      \>|!|゚ο゚|iK/       (ム/ iハルlrァ
    └|N!゚- ゚ム|†|ハ†〉_     ,八げ丞!け )ヽ       _,リiW゚ -゚リウ
      (\レ<⌒゙∨ lレ' て_     (( ノく∩_,」>レソ    ーz '/,/にエィ「、
     `ljサΖ厂>、  _))       []┤        '乏_<ム_,>リノ)
         ヒl ̄`<ユ         └'          ∠>'  Z〉
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::このコードは洋菓子専門店「ストレイキャッツ」の提供でお送りしております:::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

#include <string>
#include <string.h>
#include <sstream>
#include <vector>
#include <algorithm>
#include <list>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <map>
#include <queue>
using namespace std;

typedef unsigned int ui;
typedef string azusa;
typedef long long yui;
#define mofumofu vector
typedef int kikimora;
typedef void witch;
#define nanoha 708
#define azunyan string
#define azunyaan string
#define azunyaaan string
#define azunyaaaan string
#define azunyaaaaan string
#define azunyaaaaaan string
#define azunyaaaaaaan string
#define azunyaaaaaaaan string
#define suwako map
#define couple pair
// ZUN QUALITY
#define chen  const
#define cheen  const
#define cheeen  const
#define cheeeen  const

kikimora DP[1005][1005];

kikimora solve( kikimora M, cheen mofumofu< couple<kikimora, kikimora> > &XC, chen mofumofu<kikimora> &E, int pos, int bef, int q0, int j )
{
	kikimora n = E.size();
	if( pos == n - 1 )
		return 1;

	if( DP[pos][bef] >= 0 )
		return DP[pos][bef];
	int q = 0, q1 = 0;
	for( kikimora i = pos + 1, j2 = j; i < n; i ++ ){
		while( j < XC.size() && XC[j].first <= E[i] ){
			q += XC[j++].second;
		}
		while( j2 < XC.size() && XC[j2].first * 2 <= E[pos] + E[i] ){
			q1 += XC[j2++].second;
		}
		int myq = q0 + q1;
		if( myq > M )
			break;
		if( solve( M, XC, E, i, pos, q - q1, j ) )
			return DP[pos][bef] = 1;
	}
	return DP[pos][bef] = 0;
}

kikimora test( kikimora M, cheeeen mofumofu< couple<kikimora, kikimora> > &XC, chen mofumofu<kikimora> &E )
{
	kikimora n = E.size();
	kikimora q = 0;
	for( kikimora i = 1, j = 0; i < n-1; i ++ ){
		while( j < XC.size() && XC[j].first <= E[i] )
			q += XC[j++].second;
		if( solve( M, XC, E, i, 0, q, j ) )
			return 1;
	}
	return 0;
}

kikimora main()
{
	kikimora n, m;
	cin >> n >> m;
	mofumofu< couple<kikimora, kikimora> > XC(n);
	mofumofu< kikimora >Esa(m);
	kikimora totalCats = 0;
	for( kikimora i = 0; i < n; i ++ ){
		ui t;
		couple<kikimora, kikimora> xc;
		cin >> xc.first >> t >> xc.second;
		XC[i] = xc;
		totalCats += xc.second;
	}
	sort( XC.begin(), XC.end() );
	
	Esa.push_back( -1000000 );
	Esa.push_back( +1000000 );
	for( kikimora i = 0; i < m; i ++ ){
		cin >> Esa[i];
	}
	sort( Esa.begin(), Esa.end() );

	kikimora L = 0, R = totalCats;
	while( L + 1 < R ){
		kikimora M = (L + R) / 2;
		memset( DP, 0xff, sizeof(DP) );
		if( test( M, XC, Esa ) )
			R = M;
		else
			L = M;
	}
	cout << R << endl;
	return 0;
}

makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002.html

の解答。354バイト。短くする所に特に力入れた。
gccコンパイル、stdinから入力、stdoutに出力。

所要時間: 最初のコード:30分、短くするの:今日の移動時間のほとんど(烏山→川崎)。

なんというか、ある意味すごく自分らしいコードなので、充実感があります...

#define Q ,C^=1,M>++V||F(V,v,f-C,i,L+sprintf(S+L,"(%d%d%d)\0[%d%d]\0  (%d%d)\0  [%d]"+C*9,i,i
#define P M,v,f,i,L,V,C)long long v;
char S[99];F(P{if(!((f|(v-=0LL+V<<i*5)?:puts(S))&0x842108421084210LL))for(i=V=10;v*--i;C=0 Q),2)Q+1,i+2),1057)Q+1),33)Q,i),3)Q+2),1025));}main(P{for(v=L=0,i=13;i--;v+=1LL<<getchar()*5-240);for(i=10;--i;V=f=C=3 Q),2)Q),1));}

適当に改行入れたver:

#define Q ,C^=1,M>++V||F(V,v,f-C,i,L+sprintf(S+L,\
"(%d%d%d)\0[%d%d]\0  (%d%d)\0  [%d]"+C*9,i,i
#define P M,v,f,i,L,V,C)long long v;
char S[99];F(P{if(!((f|(v-=0LL+V<<i*5)?:puts(S))&0x842108421084210LL))
for(i=V=10;v*--i;C=0 Q),2)Q+1,i+2),1057)Q+1),33)Q,i),3)Q+2),1025));}
main(P{for(v=L=0,i=13;i--;v+=1LL<<getchar()*5-240);
for(i=10;--i;V=f=C=3 Q),2)Q),1));}

七対子は非対応ですw

輪行+諏訪大社行ってきた。

観光等

半分くらいTwitterの発言をコピペして作る日記。

18きっぷが余っていることに端を発した旅行。前日に輪行に行こうという声がしたので急遽装備を整え出発。出発時点では甲府方面ということしか決まっていなかった(ホリデー快速河口湖が運行されていたのが理由)。
最初は甲府盆地でワイナリーでもめぐるかみたいな漠然とした感じだったのだが、ぐぐっているうちに、甲府諏訪湖のサイクリング日記がひっかかって、行ってみようかなと思う→勾配見てやる気なくす→諏訪湖とかサイクリングいいんじゃね→諏訪湖の周りに何かあるっけ→諏訪大社があるらしい→じゃあそれで、ということで諏訪大社へ。時間切れにより上社のみ。諏訪子見てませんwww

着いてから、そういえば諏訪子様の聖地ですかね、ということに気づく。

まずは上社前宮へ。途中ちょっと道に迷う。私は乗り換える駅の名前は覚えられても曲がる交差点の名前は覚えられないぜ!!! 自主経路教習やりつつ、ああ、俺経路選択無理だわ、と思ったことを思い出した。

前宮でちょっとぶらぶらしてから、本宮へ。

途中に守矢家。資料館だったらしいが「神長官 守矢」という表札出てるしどうみても一般民家にしか見えなかったので入らなかった。むぅ。 http://www.5884atease.com/kanko/moriyasiryou/moriyasiryou.htm

で、本宮。いい感じの入り口。
ついたら10〜20分待ちの行列ができてました。普通に諏訪大社信仰集めてますね。

で、何気なく絵馬コーナーのぞいたら諏訪子様絵入りの絵馬が大量にあってふいた。諏訪子様信仰集めすぎですwww
(一番前に掛かっていた絵馬約100枚中: 諏訪子7、神奈子4、早苗2、その他3(きめぇ丸、霊夢、小町)、但し絵入りのみカウント。文字のみも散見された)

厄除お守りを買う。諏訪子様の守護お願いします!

すわっすわっ。ケロちゃんってあんなにかわいかったっけ。\しんこう/
今年4-5月には諏訪大社御柱祭。行こうかな。 http://ja.wikipedia.org/wiki/%E5%BE%A1%E6%9F%B1%E7%A5%AD

帰りは論文読んだり寝てたりしてた。

自転車

今回は初輪行である。

輪行袋は「オーストリッチ 超速FIVE輪行袋」なるものを買った。
後輪外すのめんどかったので手抜き。

車内では立てて、ホリデー快速河口湖の最後尾席の後ろにおいたり、ドア際の席に座りながら脇においたりしていた。
中央本線は基本的に空いていたので問題なし。
自転車の組み立て・解体は収納とか諸々込みで10分あれば余裕。
帰りの茅野駅では5分で解体収納乗車するというひどい事態になりましたがwww

大月からの自転車は上り坂だったので結構時間がかかった。道と勾配くらいは調べるべきだと思った。

帰りの稲田堤から家まで自転車で35分かかった。やっぱこのあたり自転車には激しく不向きだよww(特に帰路)。再度会社に自転車移動させるかな。

行程

矢野口0800→JR→0820立川0844→JR快速ホリデー快速河口湖1号→0934大月→自転車→初狩1047→JR→1137甲府1149→JR→1250茅野→自転車→諏訪大社上社前宮→諏訪大社上社本宮→ハルピンラーメン→茅野1522→JR→1822高尾1833→JR→1850立川1857→JR→1919稲田堤。
交通費2300+食費850+おまもり500。

あずさに乗ってしまえば一時間早く茅野についたらしい。そうしとけばよかった。
乗り継ぎが悪い時にちょっとだけ特急チートをするのも手か。計算量跳ね上がるけど。
前回北陸でやろうとした時は3000円分くらい使わないとダメだったんだけど、今回は800円くらい(大月→山梨市)だった。

ほうれん草のトルティーヤ

トルティー

  1. 強力粉170g、ほうれん草一束(ゆでてミキサーで粉砕する)、オリーブオイル大さじ1、塩少々、水適量をまぜてこねて生地を作る。全部で300gくらいになった。
  2. 一時間ほど寝かす。
  3. うすく延ばしフライパンで軽く焼く。生地50gにつきうちの小さめのフライパンくらい(謎)のおおきさ。
  4. 具を巻いて食べる。

巻く具

  1. ウィンナー(1袋)、ベーコン(3枚)、ハム(2枚)、トマト(1/2個)あたりを適当に切って炒めて卵(2個)でとじる。
  2. 好みで塩コショウなどを振る。
  3. ちょっっと少なかったかもしれん。

参考にしたもの: http://cookpad.com/recipe/184164

DFWで食べた Rollóg を再現すべくやってみた。
色々違った(たぶん再現はかなり難しい)けど方向性の近いおいしいものができて満足である。

菓子色々

かるかん粉が富沢商店で半額だったことに端を発した料理大会。

  1. かるかん作るお!
  2. でもその前に寒天が食いたい → とりあえず寒天を鍋で煮立たせる → 一部はそのまま寒天に
  3. 少し甘いものが食いたい → 砂糖を投入して錦玉(皿・左)にする
  4. 粉とか彼岸のおはぎに使った餡とか余っていたので投入 → 羊羹(皿・上)、上南羹(皿・下)、かるかん粉羹(? 皿・右)など
  5. よしかるかん作るお! (左上:試作1号、上:試作2号) まだ大和芋の味がしたりするけど食感自体は少し近づけた気はする。ただ正直市販物との間には越えられない壁が感じられる。
  6. メレンゲ余った! → 梨の蒸しケーキに
  7. 梨余った! → 寒天とアイスと一緒に(左下)

レシピメモ。

寒天系は以前と同様。ただ今回粉系を多く入れすぎて、寒天的ゼリー的なものというよりは粉主体のもちもちした感じになってしまった。

かるかん:

  1. かるかん粉25gを水20gで溶き、砂糖30g、大和芋11gとまぜ、泡だて器で空気を入れるようにして混ぜる(ここまでで試作1号)。
  2. さらに卵白を泡立てメレンゲを作り(卵1/6個分くらい?)、1で作ったものに加えて泡だて器で混ぜる。(試作2号)
  3. 強火で蒸す。今回20分蒸したが、小さかったためか少し蒸しすぎた。10分くらいがよかったかも。蒸しすぎるともちもちしてきてかるかんのさくっとした感じがなくなる感じがした。

蒸しケーキ:

  1. 小麦粉40gをふるい、卵黄(1個分)、角切りの梨(1/8切れ弱?)、余ったメレンゲ(卵1個分弱)をまぜる。
  2. 蒸す。
  3. ベーキングパウダー入れ忘れたとか、卵黄が思いっきりダマになったとかあったけど、まぁ自分で食うにはそれなりのものはできた。