はてなキーワード: classとは
唐突にClass::Data::Inheritableのソースコードについて説明してやんよ。
使い方とかの説明はこの辺でも読んでから出直して来い、ごるぁ!
まぁとりあえずソース見てみろ、下記にはっつけてやっからよぉ!
1: package Class::Data::Inheritable; 2: 3: use strict qw(vars subs); 4: use vars qw($VERSION); 6: $VERSION = '0.06'; 7: 8: sub mk_classdata { 9: my ($declaredclass, $attribute, $data) = @_; 10: 11: if( ref $declaredclass ) { 12: require Carp; 13: Carp::croak("mk_classdata() is a class method, not an object method"); 14: } 15: 16: my $accessor = sub { 17: my $wantclass = ref($_[0]) || $_[0]; 18: 19: return $wantclass->mk_classdata($attribute)->(@_) 20: if @_>1 && $wantclass ne $declaredclass; 21: 22: $data = $_[1] if @_>1; 23: return $data; 24: }; 25: 26: my $alias = "_${attribute}_accessor"; 27: *{$declaredclass.'::'.$attribute} = $accessor; 28: *{$declaredclass.'::'.$alias} = $accessor; 29: } 30: 31: 1;
短いソースだなーこれ。でもな、なめんじゃねーぞ。短いけど色々な技術が盛り込まれてんだよコレはよぉ。
ハイ、まず3行目。
かるくstrictについて説明してやんよ。心して聞けよオマエラ。
strictっつーのはだな、つまりPerlにおける曖昧な部分をすこーしだけチェックしてくれるスグレモノなんだなコレが。
とりあえずざっくり言うと三つの機能があってだな、下記のよーに書くわけだ。
use strict 'vars'; use strict 'subs'; use strict 'refs';
varsってーのは簡単に言うとmyとかourとか宣言しろボケってやつですわ。
subsは裸体は許さんってやつですの、$とか%とかついていない裸の文字列をエラーにしてくれんだよ。
refsってのが一番やっかいな代物でな、これはムツカシイ言葉で言うとシンボリックリファレンスってんだが、要は変数名に変数を使うとエラーにしてくれるってこったよ。
で、これら全部ひっくるめてuse strict;なんだな。わかったか?オラ!
ちゅーことはだ、3行目を見ると意図的にrefsだけ外してるのがわかるよな。
つまりコレはこのコードのどこかで変数名に変数を使うってことを明示していることにもなるわけだ。けけけ。
あーもういいもういい、次だ、次。
4,5行目を見てみろよ。今時our使わずにuse vars使うなんてどんだけー。
ははは、まぁまてよ。
ourってのは明示的にグローバル変数を定義するもんなんだが、このourってやつが導入されたのがPerl5.6からなんだよ。
Perl5.5のころはourなんてなかったからグローバル変数定義すんのにこのuse varsを使っていたわけだ。
つまりこのモジュールはPerl5.5環境でも動くように配慮しているわけなんだな、ちゃんちゃん。ほほほ。
あーもう全然すすまねーよ。チクショウ、が、ま・・・・。
で、11-14行目。これはref関数使って$declaredclassがオブジェクトだったら死ぬって処理だ。
require CarpっつーのはCarpモジュールを動的にロードしてるっていうことだよぅ。
で、Carp::croak関数使ってエラー文はいて死ぬ、と。ちなみにこのCarp::croakってはまぁdie関数みたいなもんなんだ。
違いとしてはエラーの発生した原因を呼び出し元の奴のせいにして自分は悪くないんだよってアピールすることかな。まぁ実際使ってみりゃわかるよ。
さぁ、16行目。本編突入だ。長かった。長い道のりだったなお前ら。
sub {}ってのは無名サブルーチン(関数のリファレンス)ってやつだ。で、ここで注目すべき点はただひとつ!!!!!
19-23行目あたりをぼーっとみてると$declaredclass, $attribute, $dataっていう変数を使用していることがわかる。
これらの変数は9行目で受け取ったmk_classdataへの引数だ。
ここで問題が発生する。
myで宣言された変数の賞味期限はスコープの終端だ。それはわかるな?
つまり9行目で宣言された$declaredclass, $attribute, $dataといった変数どもは29行目のスコープの終端で消滅してしまうわけだ。
しかし!その消えてしまうはずの変数どもをsub {}という無名サブルーチンの中で使用してしまっている!!!
これが世間一般に語られているクロージャという仕組みなのだ!!!!!!うはははははははh!!!
本来生涯をまっとうするはずだった変数たちが別のサブルーチンの中にまぎれてしまうとその別のサブルーチンが消えてなくなるまでは死ぬことを許されなくなるのである!!!ざ・不☆老☆不☆死!
なんたる奇妙奇天烈なことであるが、この現実を受け入れることによってお前らの道が開けるんだ!!!すげーだろぉがよぉ!!
ボクはッ、キミがッ、クロージャを受け入れるまでッ、殴るのをやめないッ!
さて、肝心の16-24行目のアクセサ部分の処理の解説だけども、
引数が渡されてなければ特になんの処理もせずに$dataを返している。$dataってのは死ぬことを許されなくなったカワイソウな変数君だ。
つまり、Class::Data::Inheritableってやつはアクセサに渡された値をどこで保存してるのかというと、紛れも無いこの$data君に他ならない。
$data君がニート君になっちゃうとたちまちデータの読み書きができなくなるのであまり働かせ過ぎないように注意しよーね!
ハイ、次はアクセサに引数が渡された時の処理だけどな、20行目を見てみろ。$declaredclassに格納されてる値はmk_classdataメソッドを使用したときに格納された値になる。
package Hoge; use base qw/Class::Data::Inheritable/; Hoge->mk_classdata('hoge_accessor');
つまり上記の処理で例えると、$declaredclassには'Hoge'という文字列が入ってることになんだな。
で、この'Hoge'と$wantclassに入ってる値を比較しているわけだが、
package Hoge; use base qw/Class::Data::Inheritable/; Hoge->mk_classdata('hoge_accessor'); Hoge->hoge_accessor('aaa');
上記の処理で例えると$wantclassには$declaredclassと同じく'Hoge'が入ってくることになんだな。うっひょー。
んで、20行目のif文は$wantclassと$declaredclasが違う場合にだけ19行目の処理を実行しているわけだからこの場合はスルーするわけだぁ。ひょひょひょ。
じゃあだな、$wantclassと$declaredclasが違う場合ってどんな場合?ってことだが、下記に例を示すから目ん玉引ん剥いて網膜から直接見てみろよこのボケ野郎どもが。
package Hoge; use base qw/Class::Data::Inheritable/; Hoge->mk_classdata('hoge_accessor'); package Foo; use base qw/Hoge/; Foo->hoge_accessor('bbb');
HA!HA!HA!こういう場合だよ米ベー。$wantclass=Fooで$declaredclas=Hogeになるんで19行を実行し、Fooをベースにしてmk_classdataを呼ぶことでFooに同じ名前の新たなアクセサを提供し、元クラスHogeの値を壊さないようにするわけですなぁ。
考えた人すごいですなぁ。これがClass::Data::Inheritableが継承可能なクラス変数といわれる由縁でするまする。
で、最後の26-28行目はコレらの便利な処理をしてくれる$accessorさんをクラスに登録するというわけですよぉ。
27,28行目の*ってのは型グロブ変数ってという奴で、型グロブに対して無名サブルーチンを突っ込むと動的に関数を定義できるんだなぁコレが。
でここで、初めに俺が語った話を覚えてるか?へっ、オマエラなら覚えてないだろうなけっけ。use strictの話だよ。refsだよrefs。
ここでrefsを省いていたのが利いて来るんだ。refsって何だった?ホラ言ってミソ?
で良く見てみると型グロブ変数に対して「$declaredclass.'::'.$attribute」っていう変数を使おうとしているよね?これをしたかったからrefsだけ仲間外れにしてたわけですね。
はは。
あー、あー、あー。
これで終わりだよぅ。みんなわかったかな!?
コレ読んでもわからんやつはもう死ぬか、もしくはわからん用語について死ぬほど調べてもっかい読みなおしてみろこのド低のぅッ・・・ごふんごふん、このクサレ脳みそがぁ!!!!!!!!!!!!11
http://anond.hatelabo.jp/20071030034313 の二番煎じ
あまりのアホさに、作ってて気が狂いかけた
方針
using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.IO; using System.Reflection; using Microsoft.CSharp; delegate void ConvertTemplateDelegate(TextWriter tw, Dictionary<object, object> args); static class TemplateGenerator { public static ConvertTemplateDelegate Generate(string code) { CompilerParameters param = new CompilerParameters(); param.GenerateInMemory = true; param.ReferencedAssemblies.Add("System.Web.dll"); CompilerResults rs = new CSharpCodeProvider().CompileAssemblyFromSource(param, ParseTemplate(code)); if (0 < rs.Errors.Count) { StringWriter sw = new StringWriter(); sw.WriteLine("Compile Error..."); foreach (CompilerError err in rs.Errors) sw.WriteLine(err.ToString()); throw new Exception(sw.ToString()); } return (ConvertTemplateDelegate) Delegate.CreateDelegate(typeof(ConvertTemplateDelegate), rs.CompiledAssembly.GetType("Template", true).GetMethod("Convert")); } private static string ParseTemplate(string code) { using (StringWriter sw = new StringWriter()) { sw.WriteLine("using System; using System.Collections.Generic; using System.IO; using System.Web;"); sw.WriteLine("public static class Template {"); sw.WriteLine("public static void Convert(TextWriter tw, Dictionary<object, object> args) {"); int index = 0; while (0 <= index && index < code.Length) { int i = code.IndexOf("<%", index); sw.WriteLine("tw.Write(\"{0}\");", EscapeString(i < 0 ? code.Substring(index) : code.Substring(index, i - index))); if (0 <= i) { i += 2; int i2 = code.IndexOf("%>", i); if (0 <= i2) { string cc = code.Substring(i, i2 - i); if (cc.StartsWith("=")) sw.WriteLine("tw.Write(HttpUtility.HtmlEncode(\"\"+({0})));", cc.Substring(1)); else sw.WriteLine(cc); i = i2 + 2; } } index = i; } sw.WriteLine("}}"); return sw.ToString(); } } private static string EscapeString(string code) { return code.Replace("\\", "\\e").Replace("\"", "\\\"").Replace("\t", "\\t").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\\e", "\\\\"); } }
サンプル C# コード。ためしにテンプレートから Xml 生成して、標準出力してみる。
class Program { static void Main(string[] args) { ConvertTemplateDelegate func = TemplateGenerator.Generate(TemplateEngine.Resource1.template); using (StringWriter sw = new StringWriter()) { Dictionary<object, object> arg = new Dictionary<object, object>(); arg["title"] = "template sample"; arg["data"] = new string[] { "foo", "fooo", "<strong>foooooooooo!</strong>" }; func(sw, arg); Console.WriteLine(sw); } } }
サンプルテンプレート
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title><%= args["title"] %></title> </head> <body> <h1><%= args["title"] %></h1> <table> <% string[] data = (string[]) args["data"]; %> <% for(int i = 0; i < data.Length; i++) { %> <tr bgcolor="<%= i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>"> <td><%= i %></td> <td><%= data[i] %></td> </tr> <% } %> </table> </body> </html>
出力例
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>template sample</title> </head> <body> <h1>template sample</h1> <table> <tr bgcolor="#FFCCCC"> <td>0</td> <td>foo</td> </tr> <tr bgcolor="#CCCCFF"> <td>1</td> <td>fooo</td> </tr> <tr bgcolor="#FFCCCC"> <td>2</td> <td><strong>foooooooooo!</strong></td> </tr> </table> </body> </html>
CodeDom 使って動的コンパイル……って、このコードのままだとセキュリティ的に大問題な気がするな。
素直に ASP.NET 使ったほうが楽だと直感した。
あと EscapeString すっごく自信ない。たぶん修正が必要だと思うw
class BTree: def __init__(self, node_info=None): self.root = BNode(node_info) self.left = None self.right = None @classmethod def printNode(self, n): print "%s " % n.info, def walk(self, node = self.root, Execute=BTree.printNode): ... ...
walkメソッドは引数でエラーがでる。selfがわかんないみたい。name 'self' is not defined
そりゃそうか、実行時にselfが決まるんだから。でもname 'BTree' is not definedになるのは何故?
悲惨と表現するにはそれほど汚いソースでも無いよなぁ。(書き方ではなくて構造的に)
ただ、相変わらず開始タグと終了タグがちゃんと付けられて無い部分がちらほら。
テスト段階でチェックすればすぐにでも直せそうな箇所なんだし何でそのままになってるのかが気になるなぁ。
こういう確認も(吐かれる)ソースの汚さを改善する事で気付きやすくなるんだし色んな部分でメンテナンス性やら落としてそうだよなぁ。
あとやたらと多いspanは何なんだろう、cssはアレだから見る気にならないけどclassやidも無くて表示に大きく関わりそうな付けかたでもないっぽいしコレ削るだけでもそれなりにソース痩せると思うんだけど、なんだか色々と謎だわー。
前と比べればマシだけど、前の使い回しをしているmixiミュージックやレビューページの事もたまには思い出してあげてください。
はてブの人気エントリに「今回のmixiのリニューアルについて - 専門家に聞く」ってのがあるんだけど、そのページのにある寺田さんの発言がステキすぎて目が離せません。
文章構造、悪くないと思うけどね…。
とりたてて良くもないけど、そこそこいい感じじゃないすか?具体的にどう悲惨なんだろね。
今までの化石みたいなTableレイアウトのソースに比べれば、死ぬほどマトモでしょ。
個人的にはHTML要素のid・class指定にLowerCamelCaseを使うのは好きじゃないとか、onmouseover・onmouseoutみたいなDOMイベントをHTMLソース上に書かなくてもいいじゃんとかはあるけど。
但し、せっかくCSSにしたんだからHTMLソースを短くする努力をした方が良かった気がする。
PVが半端ないから、HTMLソースの量でも結構大きく響いてくるはず。
本当にそうですね…!やっぱり時代はPHPですよね(笑
今回のリニューアルは「テンプレートのリニューアル」であり、「システムも含めた全面的なリニューアル」ないんでそりゃ変わらないでしょ。
数千台のサーバで運営されており、実績のある現在のPerlベースのシステムを、PHPベースに変更することで何のメリットがあるんですかね?
「PHPだと、Perlと違い実行時にプロセスが立ち上がらないので高速です」とか言いそうな予感がプンプンしますが…。
「Javaベースにして、Oracleにしましょう」といった話であれば、はいはいSIer乙って気分になるんだけど、PHPが出てくるところがなんとも微笑ましいです。
どう考えても創業以来からの身内で開発をしているとしか思えません。技術や知識が古く、独自の思考をもった温室エンジニアたちが、権限ばかり与えられて新しく入ったデザイナーやコーダーと上手に連携できていない様子が目に浮かぶようです。
んー、1000万IDあるサイトを、運用する技術とかだけでも結構なもんだと思うけどね。
サイトのスケールアウトの難しさとか… 知ってるのかな?
どこまでいっても「なぜ上場したのか・・・」という問題に尽きます。
なんかあんまり触れられてないけど、今回のmixiのデザインリニューアルで一番強く思ったのは「mixiが持っていたキャッチーさが薄くなってしまった」ということ。
同時期に開始したGreeと、mixiの二つのSNSの内、mixiだけが圧倒的な勢いでユーザ数をのばしていった理由。
他のウェブサービスでは見ない原色系の色遣い。パッと見て親しみやすい感じ。オタクっぽくない感じ。
そこがmixiのアイデンティティだと思っていたので、普通になっちゃったことにビックリした。
初期のデザインコンセプトが「人と人をつなげる楽しいウェブサイト」だったとすると、
今回のリニューアルのデザインコンセプトは「ソーシャルプラットフォーム」みたいな感じで独自色を薄くした感じなのかねぇ…。
あと、非常に分かりづらいメニュー構成(操作メニューが2つあって、その意味づけがはっきりしていない)は、変わらないのが相変わらず駄目だと思った。
404 Blog Not Found:coders.each{|you| you.get(this) if you.langs[0] != 'ruby' } # - 書評 - 初めてのRuby
1章 ようこそ、Rubyのある生活へ
1.1 Rubyの特徴
1.1.1 オブジェクト指向言語
1.1.2 より良いPerl
ある研究によれば、生産性はそれぞれのプログラマでそれぞれ違う。
でも、あるプログラマに着目すれば、
そのプログラマが時間あたりに書けるコードの行数は、プログラミング言語によらず決まっている、
たとえば一年に50,000行なのだそうだ。
行数が決まっていたら、
どの言語で一番多くのことを達成できる?
そう、Rubyだよね。
例えば C のプログラムより 50 倍遅くなったとして、実行時間はどのくらい変わるだろうか?
もし C のプログラムが 0.01 秒で終わる としたら、
Ruby 版は 0.5 秒。あなたのプログラムは 0.49 秒速くす るために C で書く価値があるのか?
プログラムは開発の時間よりも保守の時間のほうがかかるというのはもはや常識だけども、
Ruby で書いてあれば例えば、
そういう点でも Ruby は非常にいい。
だいたい、スピードに対してごちゃごちゃ言うなら C じゃなくアセンブラで書けばいい。
それをなんで C で書いてるのかって言えば、
それはもちろん「コードがわかりやすい」とか、「早く書ける」って のが理由だろう。
そして、Ruby は C よりわかりやすいし速く書ける。
404 Blog Not Found:「PHPなめんな」と「(Perl|Python|Ruby)をなめんな」の違い
実行速度より実装速度(前編) - Object Station
配列に格納したものと一致しないものだけをピックアップしたかったのだが、
配列の中にその値があるかどうかの比較のしかたがわからずfor文でまわしました。
なんとなく感覚でequals()と==をつかいわけているが、もしかしたら違うかもしれない。
classのインスタンスというかイニシャライズに相当する書き方がわからず、
初期化が必要なクラスをつくることができず、ひとつのクラス内でダバダバ関数を書いている。
} catch(ArithmeticException e) {
System.err.println("エラー" + e.getMessage());
関数ごとにこんな風にいちいち書いてみたが、もっといいやり方があるきがする。
// デバック用出力関数
private void fDebug(String msg) {
if (!DEBUG_FLG){ return;}
System.out.println(msg);
}
挙句、こんな関数を作った。俺はバカかとおもった。
ログ出力用のヤツまでつくってしまった。いったいこれはどういうことだろう。
昔し、配列のsortを教えてもらった記憶があるのだが実はいまだにできない。
しかたが無いのでaddで任意の位置に足しているが、それをやるにもループ、配列.size()で分岐しながらなのでカッコワルイ。
勢いでつくった関数にオプショナルで引数を追加したくなったのだが、やりかたがわからなかったので諦めた。
Eclipseで一気に複数行をコメントアウトするような方法がわからない。
→わかった! ctrl+/だ! おー、便利。
気持ち悪いループとbreak文だらけになってしまいわかり難いのでラベルをつけた。
「label:」みたいにすればいいらしい。だが根本的に間違っている気がする。
Integerとintみたいなものを区別せずに使っている。実際何が違うのかわからないけど動くからいいやとかおもってしまっている。
@Overrideってなんだろう。
参照が深くなりすぎてしまって、ループの中でわざわざ変数を宣言しなおしている。
DDDDD masuda = AAAA.BBBB().CCCC(ohdeyansu);
ookamiotokoto = masuda.funga() + masuda.hajimeruzamasu();
どうなんだろうか。
何か計算結果がおかしいなとおもったら int * (int/int) で、分母が計算途中で丸められてた。
int * (float)(int/int) こんな回避の仕方をしてしまったのだがいいのだろうか。
たいしたことをしていないのだがやたらとコードが長くなる。
どうにかならんものか・・・。
@data=(a,b,c);print@data
#!/usr/bin/perl use strict; my @data = qw(a b c); my $cx = scalar @data; my $si = 0; my $ax; LOOP: $ax = $data[$si]; print $ax; $si++; not --$cx or goto LOOP;
#!/usr/bin/perl use strict; my @data = qw(a b c); package AtoH; use base qw(Tie::Handle); sub TIEHANDLE { my $class = shift; return bless {data => [@_]}, $class; } sub READLINE { return shift @{shift->{data}}; } package main; tie *ARGV, 'AtoH', @data; while (<>) { print; }
元増田の言いたいことは結構分かる。けど、それは実は「賢さ」の問題じゃなくて「階級(class)」及びそれに不随する文化の問題だと思う。想像するに、元増田はそこそこのレベルの私立中高一貫の男子高から東大とか行ったんじゃね? 公立中学に行ってれば多分こういう勘違いはしないと思うんだけどなあ……。
少なくとも元増田くらい賢ければ、異なる文化には異なる知のありようがあり得る、ってこと位は分かるだろう。自分の育った文化だけが文化ではないことも。そしたら、今の自分には見えていない「異なる知」の有り様も見えてくるかもしれないし、同時に自らと自らの周囲の「知」の有り様を問い直すこともできるはず。
とはいっても、学歴が一種の「指標」たりえることは必ずしも否定しない。上で書いたように、「学校」は、その人が育った「文化」を意味するからだ。「氏より育ち」なんて言葉が昔からあるから言うわけではないけれど、少なくともナントカ大出身の上司は、同じナントカ大出身の生徒のことは「何となく大体雰囲気が分かる」から「安心」して採用するんだよね、つまり。偏差値というのはむしろ後付なもののわけで、たとえば他の増田たちも、親兄弟のことは、隣の家の兄ちゃんよりは普通「信頼」できるだろう?それと同じ。再度言うけど、それは「賢さ」の問題ではなく「育った文化」の問題。日本は学歴社会だと思われてるけど、ホントのところ「(学歴)階級社会」という方が近い。たとえば二人の人間が同じ年齢、年収でも、その人が育った「階級文化」が異なればびっくりするくらい両者の生活は異なってたりする。たとえば同じように子供に1000円小遣いをやったとしても、そのあとでドンキに連れてくか本屋に連れてくか、コストは大して変わらなくても十年後の結果は全然違うだろう。そこで本屋に行った子供が(全員ではないにしろ)どっちかというと偏差値の高い学校に集まるのだとすれば、偏差値の高い学校ほど「そういう文化」の雰囲気が形成されていくことは想像に難くない。逆にそういう文化を身に付けないで、本当にただ「勉強ができる」だけで偏差値の高い学校に行くと、周囲との文化的ギャップにそれなりに苦労するみたいだ。
ちなみに最後に元増田が言ってる
というのは、非常に賛成。「形の見えないものにカネを出さない」というのはホント日本の悪習だよ。アイデアとかシステムとかココロガケとかを評価しない。チャレンジしトライしたココロガケを評価することができないから、「結果が全てだよフフン」とふんぞりかえるのが西洋的で合理的で近代的だと考えてる……ホントは評価能力がないだけなのに。そんで逆に形の無いものが現実に影響を与えたりすると過剰に怖れ、クレームとか世間とか空気とかを無意味に怖れたりする。で、そのうちバカみたいな新興宗教をあがめてたりする。始末に負えない。逆に、そんな国民に黙って奉仕してる知的エリートの人々はホントに偉いと思う。少なくとも、仕事で付き合いのある官僚の人たちは、真面目で有能で熱心で私生活でも感じの良い人たちばかりだ。昨今の公務員バッシングはホントにつくられたモノだと思う。それだけに、その手のニュースを見る度に辛い。
とりあえず元増田には、頭を柔軟にしつつ、その上で頑張って理想を持って生きて頂きたい、とお願いするよ。
長年日記じゃないけどそれっぽい機能
// ==UserScript== // @name AnonymousDiary for Pages // @namespace http://anond.hatelabo.jp/ // @description Like Naganen nikki (of hns and tDiary) function // @include http://anond.hatelabo.jp/ // ==/UserScript== GM_xmlhttpRequest({ method: "GET", url: "http://anond.hatelabo.jp/?page=2666", onload: function(result) { var src = result.responseText.match(/ <h3>(.|\s)*?\n<\/div>/g); var dst = document.evaluate("//div[@class='section']",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null); for (var i=0; i<dst.snapshotLength; i++) { if (src.length<=i) {break} dst.snapshotItem(i).innerHTML += '<\/div>\n<div class="section">\n'+src[i].replace(/<\/div>$/, ""); } } });
一つおきに過去のエントリを入れます。意図的に過去のエントリと特別分かるようにはしていません。時間をみれば分かりますけど。
// 仕組みとしては, tempalteでキャストする型が
// コンパイル時に決められた関数のポインタを突っ込むだけ.
// templateな関数でもその具体的な型はコンパイル前に一意に決めることが出来る.
#include <vector>
class asdf{virtual void f(){}};
class fdsa{virtual void f(){}};
//各関数はinline期待可能!?
class zxcv : asdf{
//関数ポインタを得る為, staticなメンバでなければならない.
template<typename T> static bool castor(zxcv *a){
return (bool)dynamic_cast<T*>(a);
}
typedef bool(*castorfunc_t)(zxcv*);
std::vector<castorfunc_t> castorFunc_Array;
public:
int get_typeLength(){
return (int)castorFunc_Array.size();
}
bool test(int i){
return (castorFunc_Array[i])(this);
}
template<typename T>void push_type(T){
castorFunc_Array.push_back(castor<T>);
}
};
int main(){
asdf a;
fdsa f;
zxcv z;
z.push_type(a);
z.push_type(f);
printf("asdf <- z %s\n", z.test(0) ? "true" : "false");
printf("fdsa <- z %s\n", z.test(1) ? "true" : "false");
return 0;
}
getter/setterを関数で書くと、後ろに()を付けないといけないから格好悪い!!
って人にオススメ?
template<typename T>struct _property{
virtual operator T() = 0;
typedef T _t;
};
class asdf{
int foo;
public:
struct __foo : _property<int>{
asdf &parent;
operator _t(){
printf("親クラス(?)のメンバへのアクセスが面倒...");
return parent.foo;
}
__foo(asdf &p) : parent(p){}
}y;
struct : _property<char*>{
operator _t(){
printf("ここに副作用付き処理を書ける!?\n");
printf("この関数が参照を返せばgetもどきも実装できる!?\n");
return "ふひひひ!やったね!!";
}
}x;
asdf(int v) : y(*this){ foo = v * v - v - v; }
};
void p(char*s){ printf("\n増田はこちらを振り返ると、\n悲しそうな顔をしてこう言った\n「%s」\n", s); }
int main(){
asdf a(127);
//生でprintfに渡すと型推論が行われない
//それ以外の関数だったら問題ないかも
p(a.x);
printf("\n");
//どうしてもと言うならキャストすべし
printf("\n%d\n", (int)a.y);
return 0;
}
VC8で動作確認してるよ!
はっきり言って普通にgetter/setter書くよりも手間多いね!
/* Ten */ if (typeof(Ten) == 'undefined') { Ten = {}; } Ten.NAME = 'Ten'; Ten.VERSION = 0.06; /* Ten.Class */ Ten.Class = function(klass, prototype) { if (klass && klass.initialize) { var c = klass.initialize; } else if(klass && klass.base) { var c = function() { return klass.base[0].apply(this, arguments) }; } else { var c = function() {}; } c.prototype = prototype || {}; c.prototype.constructor = c; Ten.Class.inherit(c, klass); if (klass && klass.base) { for (var i = 0; i < klass.base.length; i++) { var parent = klass.base[i]; if (i == 0) { c.SUPER = parent; c.prototype.SUPER = parent.prototype; } Ten.Class.inherit(c, parent); Ten.Class.inherit(c.prototype, parent.prototype); } } return c; } Ten.Class.inherit = function(child,parent) { for (var prop in parent) { if (typeof(child[prop]) != 'undefined' || prop == 'initialize') continue; child[prop] = parent[prop]; } } /* // Basic Ten Classes **/ /* Ten.JSONP */ Ten.JSONP = new Ten.Class({ initialize: function(uri,obj,method) { if (Ten.JSONP.Callbacks.length) { setTimeout(function() {new Ten.JSONP(uri,obj,method)}, 500); return; } var del = uri.match(/\?/) ? '&' : '?'; uri += del + 'callback=Ten.JSONP.callback'; if (!uri.match(/timestamp=/)) { uri += '&' + encodeURI(new Date()); } if (obj && method) Ten.JSONP.addCallback(obj,method); this.script = document.createElement('script'); this.script.src = uri; this.script.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(this.script); }, addCallback: function(obj,method) { Ten.JSONP.Callbacks.push({object: obj, method: method}); }, callback: function(args) { // alert('callback called'); var cbs = Ten.JSONP.Callbacks; for (var i = 0; i < cbs.length; i++) { var cb = cbs[i]; cb.object[cb.method].call(cb.object, args); } Ten.JSONP.Callbacks = []; }, MaxBytes: 8000, Callbacks: [] }); /* Ten.XHR */ Ten.XHR = new Ten.Class({ initialize: function(uri,opts,obj,method) { if (!uri) return; this.request = Ten.XHR.getXMLHttpRequest(); this.callback = {object: obj, method: method}; var xhr = this; var prc = this.processReqChange; this.request.onreadystatechange = function() { prc.apply(xhr, arguments); } var method = opts.method || 'GET'; this.request.open(method, uri, true); if (method == 'POST') { this.request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } var data = opts.data ? Ten.XHR.makePostData(opts.data) : null; this.request.send(data); }, getXMLHttpRequest: function() { var xhr; var tryThese = [ function () { return new XMLHttpRequest(); }, function () { return new ActiveXObject('Msxml2.XMLHTTP'); }, function () { return new ActiveXObject('Microsoft.XMLHTTP'); }, function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); }, ]; for (var i = 0; i < tryThese.length; i++) { var func = tryThese[i]; try { xhr = func; return func(); } catch (e) { //alert(e); } } return xhr; }, makePostData: function(data) { var pairs = []; var regexp = /%20/g; for (var k in data) { var v = data[k].toString(); var pair = encodeURIComponent(k).replace(regexp,'+') + '=' + encodeURIComponent(v).replace(regexp,'+'); pairs.push(pair); } return pairs.join('&'); } },{ processReqChange: function() { var req = this.request; if (req.readyState == 4) { if (req.status == 200) { var cb = this.callback; cb.object[cb.method].call(cb.object, req); } else { alert("There was a problem retrieving the XML data:\n" + req.statusText); } } } }); /* Ten.Observer */ Ten.Observer = new Ten.Class({ initialize: function(element,event,obj,method) { var func = obj; if (typeof(method) == 'string') { func = obj[method]; } this.element = element; this.event = event; this.listener = function(event) { return func.call(obj, new Ten.Event(event || window.event)); } if (this.element.addEventListener) { if (this.event.match(/^on(.+)$/)) { this.event = RegExp.$1; } this.element.addEventListener(this.event, this.listener, false); } else if (this.element.attachEvent) { this.element.attachEvent(this.event, this.listener); } } },{ stop: function() { if (this.element.removeEventListener) { this.element.removeEventListener(this.event,this.listener,false); } else if (this.element.detachEvent) { this.element.detachEvent(this.event,this.listener); } } }); /* Ten.Event */ Ten.Event = new Ten.Class({ initialize: function(event) { this.event = event; }, keyMap: { 8:"backspace", 9:"tab", 13:"enter", 19:"pause", 27:"escape", 32:"space", 33:"pageup", 34:"pagedown", 35:"end", 36:"home", 37:"left", 38:"up", 39:"right", 40:"down", 44:"printscreen", 45:"insert", 46:"delete", 112:"f1", 113:"f2", 114:"f3", 115:"f4", 116:"f5", 117:"f6", 118:"f7", 119:"f8", 120:"f9", 121:"f10", 122:"f11", 123:"f12", 144:"numlock", 145:"scrolllock" } },{ mousePosition: function() { if (!this.event.clientX) return; return Ten.Geometry.getMousePosition(this.event); }, isKey: function(name) { var ecode = this.event.keyCode; if (!ecode) return; var ename = Ten.Event.keyMap[ecode]; if (!ename) return; return (ename == name); }, targetIsFormElements: function() { var target = this.event.target; if (!target) return; var T = (target.tagName || '').toUpperCase(); return (T == 'INPUT' || T == 'SELECT' || T == 'OPTION' || T == 'BUTTON' || T == 'TEXTAREA'); }, stop: function() { var e = this.event; if (e.stopPropagation) { e.stopPropagation(); e.preventDefault(); } else { e.cancelBubble = true; e.returnValue = false; } } }); /* Ten.DOM */ Ten.DOM = new Ten.Class({ getElementsByTagAndClassName: function(tagName, className, parent) { if (typeof(parent) == 'undefined') { parent = document; } var children = parent.getElementsByTagName(tagName); if (className) { var elements = []; for (var i = 0; i < children.length; i++) { var child = children[i]; var cls = child.className; if (!cls) { continue; } var classNames = cls.split(' '); for (var j = 0; j < classNames.length; j++) { if (classNames[j] == className) { elements.push(child); break; } } } return elements; } else { return children; } }, removeEmptyTextNodes: function(element) { var nodes = element.childNodes; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) { node.parentNode.removeChild(node); } } }, nextElement: function(elem) { do { elem = elem.nextSibling; } while (elem && elem.nodeType != 1); return elem; }, prevElement: function(elem) { do { elem = elem.previousSibling; } while (elem && elem.nodeType != 1); return elem; }, scrapeText: function(node) { var rval = []; (function (node) { var cn = node.childNodes; if (cn) { for (var i = 0; i < cn.length; i++) { arguments.callee.call(this, cn[i]); } } var nodeValue = node.nodeValue; if (typeof(nodeValue) == 'string') { rval.push(nodeValue); } })(node); return rval.join(''); }, onLoadFunctions: [], loaded: false, timer: null, addEventListener: function(event,func) { if (event != 'load') return; Ten.DOM.onLoadFunctions.push(func); Ten.DOM.checkLoaded(); }, checkLoaded: function() { var c = Ten.DOM; if (c.loaded) return true; if (document && document.getElementsByTagName && document.getElementById && document.body) { if (c.timer) { clearInterval(c.timer); c.timer = null; } for (var i = 0; i < c.onLoadFunctions.length; i++) { c.onLoadFunctions[i](); } c.onLoadFunctions = []; c.loaded = true; } else { c.timer = setInterval(c.checkLoaded, 13); } } }); /* Ten.Style */ Ten.Style = new Ten.Class({ applyStyle: function(elem, style) { for (prop in style) { elem.style[prop] = style[prop]; } } }); /* Ten.Geometry */ Ten.Geometry = new Ten.Class({ initialize: function() { if (Ten.Geometry._initialized) return; var func = Ten.Geometry._functions; var de = document.documentElement; if (window.innerWidth) { func.getWindowWidth = function() { return window.innerWidth; } func.getWindowHeight = function() { return window.innerHeight; } func.getXScroll = function() { return window.pageXOffset; } func.getYScroll = function() { return window.pageYOffset; } } else if (de && de.clientWidth) { func.getWindowWidth = function() { return de.clientWidth; } func.getWindowHeight = function() { return de.clientHeight; } func.getXScroll = function() { return de.scrollLeft; } func.getYScroll = function() { return de.scrollTop; } } else if (document.body.clientWidth) { func.getWindowWidth = function() { return document.body.clientWidth; } func.getWindowHeight = function() { return document.body.clientHeight; } func.getXScroll = function() { return document.body.scrollLeft; } func.getYScroll = function() { return document.body.scrollTop; } } Ten.Geometry._initialized = true; }, _initialized: false, _functions: {}, getScroll: function() { if (!Ten.Geometry._initialized) new Ten.Geometry; return { x: Ten.Geometry._functions.getXScroll(), y: Ten.Geometry._functions.getYScroll() }; }, getMousePosition: function(pos) { // pos should have clientX, clientY same as mouse event if ((navigator.userAgent.indexOf('Safari') > -1) && (navigator.userAgent.indexOf('Version/') < 0)) { return { x: pos.clientX, y: pos.clientY }; } else { var scroll = Ten.Geometry.getScroll(); return { x: pos.clientX + scroll.x, y: pos.clientY + scroll.y }; } }, getElementPosition: function(e) { return { x: e.offsetLeft, y: e.offsetTop }; }, getWindowSize: function() { if (!Ten.Geometry._initialized) new Ten.Geometry; return { w: Ten.Geometry._functions.getWindowWidth(), h: Ten.Geometry._functions.getWindowHeight() }; } }); /* Ten.Position */ Ten.Position = new Ten.Class({ initialize: function(x,y) { this.x = x; this.y = y; }, subtract: function(a,b) { return new Ten.Position(a.x - b.x, a.y - b.y); } }); /* // require Ten.js **/ /* Ten.SubWindow */ Ten.SubWindow = new Ten.Class({ initialize: function() { var c = this.constructor; if (c.singleton && c._cache) { return c._cache; } var div = document.createElement('div'); Ten.Style.applyStyle(div, Ten.SubWindow._baseStyle); Ten.Style.applyStyle(div, c.style); this.window = div; this.addContainerAndCloseButton(); document.body.appendChild(div); if (c.draggable) { this._draggable = new Ten.Draggable(div, this.handle); } if (c.singleton) c._cache = this; return this; }, _baseStyle: { color: '#000', position: 'absolute', display: 'none', zIndex: 2, left: 0, top: 0, backgroundColor: '#fff', border: '1px solid #bbb' }, style: { padding: '2px', textAlign: 'center', borderRadius: '6px', MozBorderRadius: '6px', width: '100px', height: '100px' }, handleStyle: { position: 'absolute', top: '0px', left: '0px', backgroundColor: '#f3f3f3', borderBottom: '1px solid #bbb', width: '100%', height: '30px' }, containerStyle: { margin: '32px 0 0 0', padding: '0 10px' }, // closeButton: 'close.gif', closeButton: 'http://s.hatena.com/images/close.gif', closeButtonStyle: { position: 'absolute', top: '8px', right: '10px', cursor: 'pointer' }, _baseScreenStyle: { position: 'absolute', top: '0px', left: '0px', display: 'none', zIndex: 1, overflow: 'hidden', width: '100%', height: '100%' }, screenStyle: {}, showScreen: true, singleton: true, draggable: true, _cache: null },{ screen: null, windowObserver: null, visible: false, addContainerAndCloseButton: function() { var win = this.window; var c = this.constructor; var div = document.createElement('div'); win.appendChild(div); Ten.Style.applyStyle(div, c.containerStyle); this.container = div; if (c.handleStyle) { var handle = document.createElement('div'); Ten.Style.applyStyle(handle, c.handleStyle); win.appendChild(handle); this.handle = handle; } if (c.closeButton) { var btn = document.createElement('img'); btn.src = c.closeButton; btn.alt = 'close'; Ten.Style.applyStyle(btn, c.closeButtonStyle); win.appendChild(btn); new Ten.Observer(btn, 'onclick', this, 'hide'); this.closeButton = btn; } if (c.showScreen) { var screen = document.createElement('div'); Ten.Style.applyStyle(screen, Ten.SubWindow._baseScreenStyle); Ten.Style.applyStyle(screen, c.screenStyle); document.body.appendChild(screen); this.screen = screen; new Ten.Observer(screen, 'onclick', this, 'hide'); } }, show: function(pos) { pos = (pos.x && pos.y) ? pos : {x:0, y:0}; with (this.window.style) { display = 'block'; left = pos.x + 'px'; top = pos.y + 'px'; } if (this.screen) { with (this.screen.style) { display = 'block'; left = Ten.Geometry.getScroll().x + 'px'; top = Ten.Geometry.getScroll().y + 'px'; } } this.windowObserver = new Ten.Observer(document.body, 'onkeypress', this, 'handleEscape'); this.visible = true; }, handleEscape: function(e) { if (!e.isKey('escape')) return; this.hide(); }, hide: function() { if (this._draggable) this._draggable.endDrag(); this.window.style.display = 'none'; if (this.screen) this.screen.style.display = 'none'; if (this.windowObserver) this.windowObserver.stop(); this.visible = false; } }); /* Ten.Draggable */ Ten.Draggable = new Ten.Class({ initialize: function(element,handle) { this.element = element; this.handle = handle || element; this.startObserver = new Ten.Observer(this.handle, 'onmousedown', this, 'startDrag'); this.handlers = []; } },{ startDrag: function(e) { if (e.targetIsFormElements()) return; this.delta = Ten.Position.subtract( e.mousePosition(), Ten.Geometry.getElementPosition(this.element) ); this.handlers = [ new Ten.Observer(document, 'onmousemove', this, 'drag'), new Ten.Observer(document, 'onmouseup', this, 'endDrag'), new Ten.Observer(this.element, 'onlosecapture', this, 'endDrag') ]; e.stop(); }, drag: function(e) { var pos = Ten.Position.subtract(e.mousePosition(), this.delta); Ten.Style.applyStyle(this.element, { left: pos.x + 'px', top: pos.y + 'px' }); e.stop(); }, endDrag: function(e) { for (var i = 0; i < this.handlers.length; i++) { this.handlers[i].stop(); } if(e) e.stop(); } }); /* Hatena */ if (typeof(Hatena) == 'undefined') { Hatena = {}; } /* Hatena.User */ Hatena.User = new Ten.Class({ initialize: function(name) { this.name = name; }, getProfileIcon: function(name) { if (!name) name = 'user'; var pre = name.match(/^[\w-]{2}/)[0]; var img = document.createElement('img'); img.src = 'http://www.hatena.ne.jp/users/' + pre + '/' + name + '/profile_s.gif'; img.alt = name; img.setAttribute('class', 'profile-icon'); img.setAttribute('width','16px'); img.setAttribute('height','16px'); with (img.style) { margin = '0 3px'; border = 'none'; verticalAlign = 'middle'; } return img; } }, { profileIcon: function() { return Hatena.User.getProfileIcon(this.name); } }); /* Hatena.Star */ if (typeof(Hatena.Star) == 'undefined') { Hatena.Star = {}; } /* // Hatena.Star.* classes // **/ if (window.location && window.location.host.match(/hatena\.com/)) { Hatena.Star.BaseURL = 'http://s.hatena.com/'; } else { Hatena.Star.BaseURL = 'http://s.hatena.ne.jp/'; } Hatena.Star.Token = null; /* Hatena.Star.User */ Hatena.Star.User = new Ten.Class({ base: [Hatena.User], initialize: function(name) { if (Hatena.Star.User._cache[name]) { return Hatena.Star.User._cache[name]; } else { this.name = name; Hatena.Star.User._cache[name] = this; return this; } }, _cache: {} },{ userPage: function() { return Hatena.Star.BaseURL + this.name + '/'; } }); /* Hatena.Star.Entry */ Hatena.Star.Entry = new Ten.Class({ initialize: function(e) { this.entry = e; this.uri = e.uri; this.title = e.title; this.star_container = e.star_container; this.comment_container = e.comment_container; this.stars = []; this.comments = []; }, maxStarCount: 11 },{ flushStars: function() { this.stars = []; this.star_container.innerHTML = ''; }, bindStarEntry: function(se) { this.starEntry = se; for (var i = 0; i < se.stars.length; i++) { if (typeof(se.stars[i]) == 'number') { this.stars.push(new Hatena.Star.InnerCount(se.stars[i],this)); } else { this.stars.push(new Hatena.Star.Star(se.stars[i])); } } if (se.comments && !this.comments.length) { for (var i = 0; i < se.comments.length; i++) { this.comments.push(new Hatena.Star.Comment(se.comments[i])); } } this.can_comment = se.can_comment; }, setCanComment: function(v) { this.can_comment = v; }, showButtons: function() { this.addAddButton(); this.addCommentButton(); }, addAddButton: function() { if (this.star_container) { this.addButton = new Hatena.Star.AddButton(this); this.star_container.appendChild(this.addButton); } }, addCommentButton: function() { if (this.comment_container) { this.commentButton = new Hatena.Star.CommentButton(this); this.comment_container.appendChild(this.commentButton.img); } }, showStars: function() { var klass = this.constructor; // if (this.stars.length > klass.maxStarCount) { // var ic = new Hatena.Star.InnerCount(this.stars.slice(1,this.stars.length)); // this.star_container.appendChild(this.stars[0]); // this.star_container.appendChild(ic); // this.star_container.appendChild(this.stars[this.stars.length - 1]); // } else { for (var i = 0; i < this.stars.length; i++) { this.star_container.appendChild(this.stars[i]); } }, showCommentButton: function() { if (this.can_comment) { this.commentButton.show(); if (this.comments.length) this.commentButton.activate(); } else { // this.commentButton.hide(); } }, addStar: function(star) { this.stars.push(star); this.star_container.appendChild(star); }, addComment: function(com) { if (!this.comments) this.comments = []; if (this.comments.length == 0) { this.commentButton.activate(); } this.comments.push(com); }, showCommentCount: function() { this.comment_container.innerHTML += this.comments.length; } }); /* Hatena.Star.Button */ Hatena.Star.Button = new Ten.Class({ createButton: function(args) { var img = document.createElement('img'); img.src = args.src; img.alt = img.title = args.alt; with (img.style) { cursor = 'pointer'; margin = '0 3px'; padding = '0'; border = 'none'; verticalAlign = 'middle'; } return img; } }); /* Hatena.Star.AddButton */ Hatena.Star.AddButton = new Ten.Class({ base: ['Hatena.Star.Button'], initialize: function(entry) { this.entry = entry; this.lastPosition = null; var img = Hatena.Star.Button.createButton({ src: Hatena.Star.AddButton.ImgSrc, alt: 'Add Star' }); this.observer = new Ten.Observer(img,'onclick',this,'addStar'); this.img = img; return img; }, ImgSrc: Hatena.Star.BaseURL + 'images/add.gif' },{ addStar: function(e) { this.lastPosition = e.mousePosition(); var uri = Hatena.Star.BaseURL + 'star.add.json?uri=' + encodeURIComponent(this.entry.uri) + '&title=' + encodeURIComponent(this.entry.title); if (Hatena.Star.Token) { uri += '&token=' + Hatena.Star.Token; } new Ten.JSONP(uri, this, 'receiveResult'); }, receiveResult: function(args) { var name = args ? args.name : null; if (name) { this.entry.addStar(new Hatena.Star.Star({name: name})); //alert('Succeeded in Adding Star ' + args); } else if (args.errors) { var pos = this.lastPosition; pos.x -= 10; pos.y += 25; var scroll = Ten.Geometry.getScroll(); var scr = new Hatena.Star.AlertScreen(); var alert = args.errors[0]; scr.showAlert(alert, pos); } } }); /* Hatena.Star.CommentButton */ Hatena.Star.CommentButton = new Ten.Class({ base: ['Hatena.Star.Button'], initialize: function(entry) { this.entry = entry; this.lastPosition = null; var img = Hatena.Star.Button.createButton({ src: Hatena.Star.CommentButton.ImgSrc, alt: 'Comments' }); img.style.display = 'none'; this.observer = new Ten.Observer(img,'onclick',this,'showComments'); this.img = img; }, ImgSrc: Hatena.Star.BaseURL + 'images/comment.gif', ImgSrcActive: Hatena.Star.BaseURL + 'images/comment_active.gif' },{ showComments: function(e) { if (!this.screen) this.screen = new Hatena.Star.CommentScreen(); this.screen.bindEntry(this.entry); var pos = e.mousePosition(); pos.y += 25; this.screen.showComments(this.entry, pos); }, hide: function() { this.img.style.display = 'none'; }, show: function() { this.img.style.display = 'inline'; }, activate: function() { this.show(); this.img.src = Hatena.Star.CommentButton.ImgSrcActive; } }); /* Hatena.Star.Star */ Hatena.Star.Star = new Ten.Class({ initialize: function(args) { if (args.img) { this.img = args.img; this.name = this.img.getAttribute('alt'); } else { this.name = args.name; var img = document.createElement('img'); img.src = Hatena.Star.Star.ImgSrc; img.alt = this.name; with (img.style) { padding = '0'; border = 'none'; } this.img = img; } new Ten.Observer(this.img,'onmouseover',this,'showName'); new Ten.Observer(this.img,'onmouseout',this,'hideName'); if (this.name) { this.user = new Hatena.Star.User(this.name); this.img.style.cursor = 'pointer'; new Ten.Observer(this.img,'onclick',this,'goToUserPage'); } if (args.count && args.count > 1) { var c = document.createElement('span'); c.setAttribute('class', 'hatena-star-inner-count'); Ten.Style.applyStyle(c, Hatena.Star.InnerCount.style); c.innerHTML = args.count; var s = document.createElement('span'); s.appendChild(img); s.appendChild(c); return s; } else { return this.img; } }, ImgSrc: Hatena.Star.BaseURL + 'images/star.gif' },{ showName: function(e) { if (!this.screen) this.screen = new Hatena.Star.NameScreen(); var pos = e.mousePosition(); pos.x += 10; pos.y += 25; this.screen.showName(this.name, pos); }, hideName: function() { if (!this.screen) return; this.screen.hide(); }, goToUserPage: function() { window.location = this.user.userPage(); } }); /* Hatena.Star.InnerCount */ Hatena.Star.InnerCount = new Ten.Class({ initialize: function(count, e) { this.count = count; this.entry = e; var c = document.createElement('span'); c.setAttribute('class', 'hatena-star-inner-count'); Ten.Style.applyStyle(c, Hatena.Star.InnerCount.style); c.style.cursor = 'pointer'; c.innerHTML = count; new Ten.Observer(c,'onclick',this,'showInnerStars'); this.container = c; return c; }, style: { color: '#f4b128', fontWeight: 'bold', fontSize: '80%', fontFamily: '"arial", sans-serif', margin: '0 2px' } },{ showInnerStars: function() { var url = Hatena.Star.BaseURL + 'entry.json?uri=' + encodeURIComponent(this.entry.uri); new Ten.JSONP(url, this, 'receiveStarEntry'); }, receiveStarEntry: function(res) { var se = res.entries[0]; var e = this.entry; if (encodeURIComponent(se.uri) != encodeURIComponent(e.uri)) return; e.flushStars(); e.bindStarEntry(se); e.addAddButton(); e.showStars(); } }); /* Hatena.Star.Comment */ Hatena.Star.Comment = new Ten.Class({ initialize: function(args) { this.name = args.name; this.body = args.body; } },{ asElement: function() { var div = document.createElement('div'); with (div.style) { margin = '0px 0'; padding = '5px 0'; borderBottom = '1px solid #ddd'; } var ico = Hatena.User.getProfileIcon(this.name); div.appendChild(ico); var span = document.createElement('span'); with(span.style) { fontSize = '90%'; } span.innerHTML = this.body; div.appendChild(span); return div; } }); /* Hatena.Star.NameScreen */ Hatena.Star.NameScreen = new Ten.Class({ base: [Ten.SubWindow], style: { padding: '2px', textAlign: 'center' }, containerStyle: { margin: 0, padding: 0 }, handleStyle: null, showScreen: false, closeButton: null, draggable: false },{ showName: function(name, pos) { this.container.innerHTML = ''; this.container.appendChild(Hatena.User.getProfileIcon(name)); this.container.appendChild(document.createTextNode(name)); this.show(pos); } }); /* Hatena.Star.AlertScreen */ Hatena.Star.AlertScreen = new Ten.Class({ base: [Ten.SubWindow], style: { padding: '2px', textAlign: 'center', borderRadius: '6px', MozBorderRadius: '6px', width: '240px', height: '120px' }, handleStyle: { position: 'absolute', top: '0px', left: '0px', backgroundColor: '#f3f3f3', borderBottom: '1px solid #bbb', width: '100%', height: '30px', borderRadius: '6px 6px 0 0', MozBorderRadius: '6px 6px 0 0' } },{ showAlert: function(msg, pos) { this.container.innerHTML = msg; var win = Ten.Geometry.getWindowSize(); var scr = Ten.Geometry.getScroll(); var w = parseInt(this.constructor.style.width) + 20; if (pos.x + w > scr.x + win.w) pos.x = win.w + scr.x - w; this.show(pos); } }); /* Hatena.Star.CommentScreen */ Hatena.Star.CommentScreen = new Ten.Class({ base: [Ten.SubWindow], initialize: function() { var self = this.constructor.SUPER.call(this); if (!self.commentsContainer) self.addCommentsContainer(); return self; }, style: { width: '280px', height: '280px', overflowY: 'auto', padding: '2px', textAlign: 'center', borderRadius: '6px', MozBorderRadius: '6px' }, handleStyle: { position: 'absolute', top: '0px', left: '0px', backgroundColor: '#f3f3f3', borderBottom: '1px solid #bbb', width: '100%', height: '30px', borderRadius: '6px 6px 0 0', MozBorderRadius: '6px 6px 0 0' }, containerStyle: { margin: '32px 0 0 0', textAlign: 'left', padding: '0 10px' }, getLoadImage: function() { var img = document.createElement('img'); img.src = Hatena.Star.BaseURL + 'images/load.gif'; img.setAttribute('alt', 'Loading'); with (img.style) { verticalAlign = 'middle'; margin = '0 2px'; } return img; } },{ addCommentsContainer: function() { var div = document.createElement('div'); with (div.style) { marginTop = '-3px'; } this.container.appendChild(div); this.commentsContainer = div; }, showComments: function(e, pos) { var comments = e.comments; if (!comments) comments = []; this.commentsContainer.innerHTML = ''; for (var i=0; i<comments.length; i++) { this.commentsContainer.appendChild(comments[i].asElement()); } if (e.starEntry && !e.can_comment) { this.hideCommentForm(); } else { this.addCommentForm(); } var win = Ten.Geometry.getWindowSize(); var scr = Ten.Geometry.getScroll(); var w = parseInt(this.constructor.style.width) + 20; if (pos.x + w > scr.x + win.w) pos.x = win.w + scr.x - w; this.show(pos); }, bindEntry: function(e) { this.entry = e; }, sendComment: function(e) { if (!e.isKey('enter')) return; var body = this.commentInput.value; if (!body) return; this.commentInput.disabled = 'true'; this.showLoadImage(); var url = Hatena.Star.BaseURL + 'comment.add.json?body=' + encodeURIComponent(body) + '&uri=' + encodeURIComponent(this.entry.uri) + '&title=' + encodeURIComponent(this.entry.title); new Ten.JSONP(url, this, 'receiveResult'); }, receiveResult: function(args) { if (!args.name || !args.body) return; this.commentInput.value = ''; this.commentInput.disabled = ''; this.hideLoadImage(); var com = new Hatena.Star.Comment(args); this.entry.addComment(com); this.commentsContainer.appendChild(com.asElement()); }, showLoadImage: function() { if (!this.loadImage) return; this.loadImage.style.display = 'inline'; }, hideLoadImage: function() { if (!this.loadImage) return; this.loadImage.style.display = 'none'; }, hideCommentForm: function() { if (!this.commentForm) return; this.commentForm.style.display = 'none'; }, addCommentForm: function() { if (this.commentForm) { this.commentForm.style.display = 'block'; return; } var form = document.createElement('div'); this.container.appendChild(form); this.commentForm = form; with (form.style) { margin = '0px 0'; padding = '5px 0'; // borderTop = '1px solid #ddd'; } //if (Hatena.Visitor) { // form.appendChild(Hatena.Visitor.profileIcon()); //} else { // form.appendChild(Hatena.User.getProfileIcon()); //} var input = document.createElement('input'); input.type = 'text'; with (input.style) { width = '215px'; border = '1px solid #bbb'; padding = '3px'; } form.appendChild(input); this.commentInput = input; var img = this.constructor.getLoadImage(); this.loadImage = img; this.hideLoadImage(); form.appendChild(img); new Ten.Observer(input,'onkeypress',this,'sendComment'); } }); /* Hatena.Star.EntryLoader */ Hatena.Star.EntryLoader = new Ten.Class({ initialize: function() { var entries = Hatena.Star.EntryLoader.loadEntries(); this.entries = []; for (var i = 0; i < entries.length; i++) { var e = new Hatena.Star.Entry(entries[i]); e.showButtons(); this.entries.push(e); } this.getStarEntries(); }, createStarContainer: function() { var sc = document.createElement('span'); sc.setAttribute('class', 'hatena-star-star-container'); sc.style.marginLeft = '1px'; return sc; }, createCommentContainer: function() { var cc = document.createElement('span'); cc.setAttribute('class', 'hatena-star-comment-container'); cc.style.marginLeft = '1px'; return cc; }, scrapeTitle: function(node) { var rval = []; (function (node) { if (node.tagName == 'SPAN' && (node.className == 'sanchor' || node.className == 'timestamp')) { return; } else if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) { return; } var cn = node.childNodes; if (cn) { for (var i = 0; i < cn.length; i++) { arguments.callee.call(this, cn[i]); } } var nodeValue = node.nodeValue; if (typeof(nodeValue) == 'string') { rval.push(nodeValue); } })(node); return rval.join(''); }, headerTagAndClassName: ['h3',null], getHeaders: function() { var t = Hatena.Star.EntryLoader.headerTagAndClassName; return Ten.DOM.getElementsByTagAndClassName(t[0],t[1],document); }, loadEntries: function() { var entries = []; //var headers = document.getElementsByTagName('h3'); var c = Hatena.Star.EntryLoader; var headers = c.getHeaders(); for (var i = 0; i < headers.length; i++) { var header = headers[i]; var a = header.getElementsByTagName('a')[0]; if (!a) continue; var uri = a.href; var title = ''; // Ten.DOM.removeEmptyTextNodes(header); var cns = header.childNodes; title = c.scrapeTitle(header); var cc = c.createCommentContainer(); header.appendChild(cc); var sc = c.createStarContainer(); header.appendChild(sc); entries.push({ uri: uri, title: title, star_container: sc, comment_container: cc }); } return entries; } },{ getStarEntries: function() { var url = Hatena.Star.BaseURL + 'entries.json?'; for (var i = 0; i < this.entries.length; i++) { if (url.length > Ten.JSONP.MaxBytes) { new Ten.JSONP(url, this, 'receiveStarEntries'); url = Hatena.Star.BaseURL + 'entries.json?'; } url += 'uri=' + encodeURIComponent(this.entries[i].uri) + '&'; } new Ten.JSONP(url, this, 'receiveStarEntries'); }, receiveStarEntries: function(res) { var entries = res.entries; if (!entries) entries = []; for (var i = 0; i < this.entries.length; i++) { var e = this.entries[i]; for (var j = 0; j < entries.length; j++) { var se = entries[j]; if (!se.uri) continue; if (encodeURIComponent(se.uri) == encodeURIComponent(e.uri)) { e.bindStarEntry(se); entries.splice(j,1); break; } } if (typeof(e.can_comment) == 'undefined') { e.setCanComment(res.can_comment); } e.showStars(); e.showCommentButton(); } } }); /* Hatena.Star.WindowObserver */ Hatena.Star.WindowObserver = new Ten.Class({ initialize: funct
http://anond.hatelabo.jp/20070711013155 こちらの宿題を作ってみました。
http://anond.hatelabo.jp/20070711080519 で参加を宣言した者です。
#include "stdafx.h" #include <time.h> #include <conio.h> #include <list> using namespace std; enum MMError { MME_None = 0, MME_SizeError, MME_MemoryAllocError, MME_NotInitialized, }; enum MMKind { MMK_None = 0, MMK_Space, // 通路 MMK_Filled, // 埋まってるところ。掘れる。 MMK_Wall, // 壁。掘れないところ。 }; // // 迷路実体管理用クラス定義 // class CMazeMatrix { public: CMazeMatrix(); virtual ~CMazeMatrix(); public: virtual bool Initialize(int nXSize, int nYSize); // 初期化すると同時に、外壁まで作ってしまう。 virtual MMKind GetAt(int nXPos, int nYPos); virtual bool SetAt(int nXPos, int nYPos, MMKind kind); MMError GetLastError() {return m_lastError;} protected: inline int calcIndex(int nXPos, int nYPos) {return nYPos * m_nXSize + nXPos;} bool finalize(); protected: MMKind *m_pMaze; int m_nXSize; int m_nYSize; MMError m_lastError; }; // // 実体管理用クラス実体 // CMazeMatrix::CMazeMatrix() { m_pMaze = NULL; m_nXSize = 0; m_nYSize = 0; m_lastError = MME_None; } CMazeMatrix::~CMazeMatrix() { finalize(); } bool CMazeMatrix::Initialize(int nXSize, int nYSize) { finalize(); int nSize = nXSize * nYSize; if ((__int64)nSize != (__int64)nXSize * (__int64)nYSize) { m_lastError = MME_SizeError; return false; } m_pMaze = new MMKind[nSize]; if (m_pMaze == NULL) { m_lastError = MME_MemoryAllocError; return false; } m_nXSize = nXSize; m_nYSize = nYSize; int nCnt; for (nCnt = 0; nCnt < nSize; nCnt++) m_pMaze[nCnt] = MMK_Filled; for (nCnt = 0; nCnt < m_nXSize; nCnt++) { m_pMaze[calcIndex(nCnt, 0)] = MMK_Wall; m_pMaze[calcIndex(nCnt, m_nYSize - 1)] = MMK_Wall; } for (nCnt = 0; nCnt < m_nYSize; nCnt++) { m_pMaze[calcIndex(0, nCnt)] = MMK_Wall; m_pMaze[calcIndex(m_nXSize - 1, nCnt)] = MMK_Wall; } return true; } MMKind CMazeMatrix::GetAt(int nXPos, int nYPos) { #ifdef _DEBUG if (nXPos < 0 || nXPos >= m_nXSize || nYPos < 0 || nYPos >= m_nYSize) { m_lastError = MME_SizeError; return MMK_None; } #endif return m_pMaze[calcIndex(nXPos, nYPos)]; } bool CMazeMatrix::SetAt(int nXPos, int nYPos, MMKind kind) { #ifdef _DEBUG if (nXPos < 0 || nXPos >= m_nXSize || nYPos < 0 || nYPos >= m_nYSize) { m_lastError = MME_SizeError; return false; } #endif m_pMaze[calcIndex(nXPos, nYPos)] = kind; return true; } bool CMazeMatrix::finalize() { if (m_pMaze != NULL) { delete [] m_pMaze; m_pMaze = NULL; } return true; } // // 迷路作成用クラス定義 // class CMazeMaker { public: CMazeMaker(); virtual ~CMazeMaker(); public: bool Initialize(int nXSize, int nYSize); // 力業。ループで回す。メモリは食わない。 // 美しくない。 bool Generate1(); // 掘った箇所をスタックに積んで、掘れなくなったらスタックを戻す。 // 綺麗だけれど、迷路のサイズを増やすとスタックオーバーフローが起こる。 bool Generate2(); // Generate2をlistに置き換えたもの。 // stdを使ってしまったのが心残り。 bool Generate3(); MMError GetLastError() {return m_lastError;} protected: bool finalize(); bool checkPos(int nXPos, int nYPos, int nXAdd, int nYAdd); int process(int nXPos, int nYPos); void dig(int nXPos, int nYPos); bool makeStartGoal(); virtual CMazeMatrix* matrixAllocate(); protected: int m_nXSize; int m_nYSize; CMazeMatrix *m_pMatrix; MMError m_lastError; }; CMazeMaker::CMazeMaker() { m_nXSize = 0; m_nYSize = 0; m_pMatrix = NULL; m_lastError = MME_None; } CMazeMaker::~CMazeMaker() { finalize(); } bool CMazeMaker::Initialize(int nXSize, int nYSize) { finalize(); m_pMatrix = matrixAllocate(); if (m_pMatrix == NULL) { m_lastError = MME_MemoryAllocError; return false; } if (m_pMatrix->Initialize(nXSize, nYSize) == false) { m_lastError = m_pMatrix->GetLastError(); return false; } m_nXSize = nXSize; m_nYSize = nYSize; return true; } CMazeMatrix* CMazeMaker::matrixAllocate() { return new CMazeMatrix; } bool CMazeMaker::finalize() { if (m_pMatrix != NULL) { delete m_pMatrix; m_pMatrix = NULL; } return true; } // スタート位置と、ゴールの位置を作成。外壁部分に穴を開ける。 // 今回のアルゴリズムでは、外壁のすぐ内側が通路になっていないことがあるので // その場合には箇所を移動させる。 // どこをとっても通路が見あたらない場合には、エラーとする。 // (乱数の発生具合がとても意地悪な場合を考えると、可能性は少なくとも0ではない。) // bool CMazeMaker::makeStartGoal() { // スタート地点を左の壁の上の方に int nCnt = 0; for (nCnt = 1; nCnt < m_nYSize - 1; nCnt++) { if (m_pMatrix->GetAt(1, nCnt) == MMK_Space) { m_pMatrix->SetAt(0, nCnt, MMK_Space); break; } } if (nCnt == m_nXSize - 1) { return false; } // ゴール地点を右の壁の下の方に for (nCnt = m_nYSize; nCnt > 0; nCnt--) { if (m_pMatrix->GetAt(m_nXSize - 2, nCnt) == MMK_Space) { m_pMatrix->SetAt(m_nXSize - 1, nCnt, MMK_Space); break; } } if (nCnt == 0) { return false; } return true; } // 現在位置nXPos, nYPosからみて、nXAdd、nYAddを足した位置に移動できるかをチェック // 移動先が埋まっている状態で、さらに三方が通路以外に覆われているなら、OKとする bool CMazeMaker::checkPos(int nXPos, int nYPos, int nXAdd, int nYAdd) { if (m_pMatrix->GetAt(nXPos + nXAdd, nYPos + nYAdd) != MMK_Filled) return false; if (nXAdd == 0) { if (m_pMatrix->GetAt(nXPos - 1, nYPos + nYAdd * 2) != MMK_Space && m_pMatrix->GetAt(nXPos , nYPos + nYAdd * 2) != MMK_Space && m_pMatrix->GetAt(nXPos + 1, nYPos + nYAdd * 2) != MMK_Space && m_pMatrix->GetAt(nXPos - 1, nYPos + nYAdd ) != MMK_Space && m_pMatrix->GetAt(nXPos + 1, nYPos + nYAdd ) != MMK_Space) { return true; } } else { if (m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos - 1) != MMK_Space && m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos ) != MMK_Space && m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos + 1) != MMK_Space && m_pMatrix->GetAt(nXPos + nXAdd , nYPos - 1) != MMK_Space && m_pMatrix->GetAt(nXPos + nXAdd , nYPos + 1) != MMK_Space) { return true; } } return false; } static const int moveInfo[4][2] = { {-1, 0}, {0, -1}, {1, 0}, {0, 1}, }; int CMazeMaker::process(int nXPos, int nYPos) { int digCount=0; int aryMove[4] = {0}; if (m_pMatrix->GetAt(nXPos, nYPos) != MMK_Space) { return 0; } while (1) { int nMoveCount = 0; for (int nCnt = 0; nCnt < 4; nCnt++) { if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) { aryMove[nMoveCount] = nCnt; nMoveCount++; } } if (nMoveCount == 0) { break; } int nMove = ((rand() >> 1) % nMoveCount); nXPos = nXPos + moveInfo[aryMove[nMove]][0]; nYPos = nYPos + moveInfo[aryMove[nMove]][1]; m_pMatrix->SetAt(nXPos, nYPos, MMK_Space); digCount++; } return digCount; } bool CMazeMaker::Generate1() { // 開始点は1, 1から。(ループの先頭 m_pMatrix->SetAt(1, 1, MMK_Space); ::srand((unsigned int)time(NULL)); int nXCnt; int nYCnt; for (nXCnt = 1; nXCnt < m_nXSize - 1; nXCnt++) { for (nYCnt = 1; nYCnt < m_nYSize - 1; nYCnt++) { while (process(nXCnt, nYCnt) != 0) {} } } return makeStartGoal(); } void CMazeMaker::dig(int nXPos, int nYPos) { m_pMatrix->SetAt(nXPos, nYPos, MMK_Space); int aryMove[4] = {0}; while (1) { int nMoveCount = 0; for (int nCnt = 0; nCnt < 4; nCnt++) { if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) { aryMove[nMoveCount] = nCnt; nMoveCount++; } } if (nMoveCount == 0) { break; } int nMove = ((rand() >> 1) % nMoveCount); dig(nXPos + moveInfo[aryMove[nMove]][0], nYPos + moveInfo[aryMove[nMove]][1]); } } bool CMazeMaker::Generate2() { ::srand((unsigned int)time(NULL)); int nXStart = ((rand() >> 1) % (m_nXSize - 2)) + 1; int nYStart = ((rand() >> 1) % (m_nYSize - 2)) + 1; dig(nXStart, nYStart); return makeStartGoal(); } struct PosInfo { int xPos; int yPos; }; bool CMazeMaker::Generate3() { ::srand((unsigned int)time(NULL)); int nXStart = ((rand() >> 1) % (m_nXSize - 2)) + 1; int nYStart = ((rand() >> 1) % (m_nYSize - 2)) + 1; m_pMatrix->SetAt(nXStart, nYStart, MMK_Space); list<PosInfo> posList; PosInfo info = {nXStart, nYStart}; posList.push_back(info); while (posList.size() != 0) { int nXPos = (posList.rbegin())->xPos; int nYPos = (posList.rbegin())->yPos; int aryMove[4] = {0}; int nMoveCount = 0; for (int nCnt = 0; nCnt < 4; nCnt++) { if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) { aryMove[nMoveCount] = nCnt; nMoveCount++; } } if (nMoveCount == 0) { posList.pop_back(); continue; } int nMove = ((rand() >> 1) % nMoveCount); info.xPos = nXPos + moveInfo[aryMove[nMove]][0]; info.yPos = nYPos + moveInfo[aryMove[nMove]][1]; m_pMatrix->SetAt(info.xPos, info.yPos, MMK_Space); posList.push_back(info); } return makeStartGoal(); } // // コンソール出力用 class CMazeMakerConsole : public CMazeMaker { public: CMazeMakerConsole(){}; virtual ~CMazeMakerConsole(){}; public: void Output(); }; void CMazeMakerConsole::Output() { for (int nYCnt = 0; nYCnt < m_nYSize; nYCnt++) { for (int nXCnt = 0; nXCnt < m_nXSize; nXCnt++) { if (m_pMatrix->GetAt(nXCnt, nYCnt) == MMK_Space) { printf("."); } else { printf("#"); } } puts(""); } _getch(); } // // int _tmain(int argc, _TCHAR* argv[]) { CMazeMakerConsole maker; do { if (false == maker.Initialize(75, 50)) { puts("Initialize Error"); return 0; } } while (false == maker.Generate3()); //失敗するのは、スタート、ゴールが作れなかった場合。偶然そういうことになることもあるので、そうなったら作り直す。 maker.Output(); return 0; }
最初に昔の記憶を頼りにCMazeMaker::Generate1()を作ったけれど、美しくなかったのでGenerate2()を作成。迷路のサイズを増やすとスタックオーバーフローになるので、Generate3()を作成。一応、満足。
########################################################################### .....##...#.#.##.....##......#....#...#.#.#.........#.##.........##.#.....# #.#.##..#.#......###..###.##.#.##.#.###...#.#####.#....##.######....##.##.# #.#..##.#.#.##.###.##.....##...#....#...#.....##..#.##.#..##...####..#..#.# #.##..###.#..#..##..###.#..###.#.####.###.#####..####..#.##..#....##.##.#.# #..##.....##.##..##...#.##..#######...#.#.#...#.##....##.#..###.#..#.##.### #.####.#####.###.###.##..####.......###.###.#.###..##.#..#.##...##.#..#...# #....###......#..#.#....##....########..##..#..#..#####.######.##..##.##.## #.##..##.######.##...####..#####....#..##..###.#.##.##..#......#..###..#..# #..##.#...##....#..#.#..#.##.#...#.##.##..##.....#.....####.####.##.##.##.# ##..#...#..#.#######...##....#.#####..#..#########.##.##.#..##...##..#....# ###.########.##...##########.#...##..##.##.##...####..#....##..###..#####.# #.#..##...##..#.#.....##.....##.##..##..#...###.#.#..###.####.##...##.....# #.##.#..#..##.#.#####.#..#####..#..##..##.#.....#...##.#.#....####.#..##### #..#.#.###.#..#.....#...##.....##.##..##..##.##.#.###....####.#.#..#.###..# #.##.#.##....######.########.###..#..###.##..#....#.##.#...#..#...##...##.# #..#.#..###.##.#....#..#.....##..###..#...#.#######....#.#.#.##.#.####.##.# ##.#.##.##...#.#.#####...#####..##.##.##.##......#####.###.#.#..#..#.#..#.# ##....#..###...#....#..#.....#.##...#.#...#.#.##.....#..##.#...###...##...# #..#####...########.####.##.##....#...#######..#####.####..#####.########.# #.##.#.###..#.....#....###...###########...###..##...#....##.........##...# #..#....###...#.#.####..#..#.....#.#.....#..#..##..###.#.##..#######.#..### ##.####...#######...###.##.#.###.#...######.####..##...#.#..##...#...#.##.# #....####...#...###...#..#.#..####.#....#.....#..##..#.###.##..#.#.###.#..# ####...#..#.#.#..####.##.####......####.#####.##..#.##...#..####.#.#...#.## ##.###.#.##.#.##.#.#...#....##.######.#.##..#.###.######.##...#..#...###..# #..##..#.####.##.#...#.####..#........#..##....##...##....###...######...## #.##..##..##..#..##.####..##.#.######.##..####..#.#..##.###.#.#..#.##..#..# #.##.####.#..##.##..##...###.###...#...##.##.##.####.#..#...####.#..#.###.# #.#...#...#.###..##..#.#...#..#..#...#..#..#.##..##..#.##.#..##..##.#...### #...#...#.#...##..##...#.####.####.#######.#..##.#..##..#.##..##..#...#...# #.###########.###..#####....#...##.#..#....##..#...####.#..##..##.#######.# #....#....##..#.##....###.#####..#...##.######.#####.##.##.###....#.....#.# ###.##.#.##..##..####..#..#...##.###.##......#...##.....##..########.##.#.# #.#.#..#..#.####.#..##...##.#.#..#....######.#.#....#.#..##.#...##...#....# #...#.###...#......####.##..#...###.###...##.#.######.#.##..#.#..##.####.## #.#.#.#.#####.###.##....#..######.#.##..#..#.#..#.....#..##...##.#...#....# #.###.#...##...#..#..####.##.#.##.#.#..##.##.##.#.###.##..######.#.#.####.# #..##.#.#..#.#.####.###.#..#......#...#####..#..#...####.##..#.#.###.##...# ##..#...##.#.#.#........##.#.#.#.####..#....#######..##...##...#..#...###.# ###.######.#.#...####.#..#.#.###.#..##.#.####....###..###..##.###.###...#.# #...#...#..#####...##.####.#..#....##..#..#...##...##...##......#..####.#.# #.###.#...##...#####..##...##.#.##.#..###.#.######..##.###########.#....#.# #..#..##.##..#.#...#.##..######..###.##.#....###.##.##...#.......#.#.#.#### #.##.###..#.##...#.###..##....##........#.##..#...#..#.#.#.###.#.#.###....# #..#...##.#..#####..##.####.#.##.############...#.##.#.#.#...#.###..##.##.# ##.###..###.##...##.#..#....#..###....##....#######..#.###.###...##..###..# #...###..#...##.###.#.##.#####...#.##.#..##.#...#...##..#...###.####.#...## #.#...##...#......#......#.....#...#....##....#...#..##...#...#........#... ###########################################################################
ちなみに http://anond.hatelabo.jp/20070711194709 これを聞いたのは自分。
かなりたくさん書けることがわかりました。
http://anond.hatelabo.jp/20070711013155
人待ちの間暇だったから作ってみたよー。
さっくり作ったから無駄が多い気がするけど、とりあえず動いた。
全体が埋まったかどうかの判定をしないでひたすらまわしまくってるし、なんか綺麗な形じゃないけど、とりあえず投稿しちゃうよ!
これ綺麗な形にするの結構難しいんじゃないかな。面白いね。
class Maze class Box WALL = 0 LOAD = 1 def initialize(state = LOAD) @state = state end def is_wall? return true if @state == WALL false end def is_load? return true if @state == LOAD false end def set_wall @state = WALL end def set_load @state = LOAD end end TOP = 10 RIGHT = 11 BOTTOM = 12 LEFT = 13 def initialize(height = 100, width = 60) @height = height @width = width @data = Array.new self.fillbox @counter = 1000 @root = Array.new end def choose_random return rand(@width-3)+1, rand(@height-3)+1 end def choose_direct t = rand(4)+10 return t end def move(x, y, t) new_x = x new_y = y case t when TOP new_y -= 1 when RIGHT new_x += 1 when BOTTOM new_y += 1 when LEFT new_x -= 1 end return new_x, new_y end def make_load?(x, y) return false if x < 0 or y < 0 or x > @width-1 or y > @height-1 return false if @data[x][y].is_load? true end def dead_end?(x, y, t) case t when TOP if make_load?(x-1, y) and \ make_load?(x-1, y-1) and\ make_load?(x, y-1) and\ make_load?(x+1, y-1) and\ make_load?(x+1, y) then return false end when RIGHT if make_load?(x, y-1) and \ make_load?(x+1, y-1) and\ make_load?(x+1, y) and\ make_load?(x+1, y+1) and\ make_load?(x, y+1) then return false end when BOTTOM if make_load?(x-1, y) and \ make_load?(x-1, y+1) and\ make_load?(x, y+1) and\ make_load?(x+1, y+1) and\ make_load?(x+1, y) then return false end when LEFT if make_load?(x, y+1) and \ make_load?(x-1, y+1) and\ make_load?(x-1, y) and\ make_load?(x-1, y-1) and\ make_load?(x, y-1) then return false end end true end def check_all?(stack) for i in TOP..LEFT do return false if !stack.include?(i) end true end def extend(x, y) @data[x][y].set_load check_stack = Array.new loop do t = choose_direct check_stack << t new_x, new_y = move(x, y, t) if enable_new_point?(new_x, new_y) if !dead_end?(new_x, new_y, t) then @root << ["ex", new_x, new_y, t] extend(new_x, new_y) break end end break if check_all?(check_stack) end end def enable_new_point?(x, y) return false if x<=0 or y <= 0 or x > @width-1 or y > @height-1 return false if @data[x][y].is_load? true end def _make x = y = 0 loop do x, y = choose_random break if @data[x][y].is_load? end @root << [x,y] extend(x, y) end def make_goal x = @width - 2 y = @height - 1 for i in 1..@width-3 if @data[x-i][y-1].is_load? then @data[x-i][y].set_load break end end end def make_start for i in 1..@width-3 if @data[i][1].is_load? then @data[i][0].set_load break end end end def make self.fill_all x, y = choose_random @root << [x,y] @data[x][y].set_load extend(x,y) while(!is_fill?) do _make end make_goal make_start self end def is_fill? @counter -= 1 return true if @counter < 0 false end def fillbox for i in 0...@width do @data[i] = Array.new for j in 0...@height do @data[i][j] = Box.new end end end def fill_all for i in 0...@width do for j in 0...@height do @data[i][j].set_wall end end end def output for i in 0...@height do for j in 0...@width do if @data[j][i].is_wall? then print "#" else print " " end end print "\n" end end end Maze.new(30, 30).make.output ## output # ############################ # ## # # ## # # ## ## ## ## # ## ### # ### # ### # # #### ### # # # ## ## ## ### # # # ## ### # # # # #### ## # ### ## ## ## ## ### # ## # # # ### # # #### # ## ## ## # ## # #### # # ### # # # ### # #### # ## # # ## ## ## # # ### ###### ###### ### ####### ### # # ## ### # # # ## # # # ####### # # # # ### ### # # # # ## ## # ## # # ### # ######## ######## # # # ## ## # # ### # ### ## ## ## ## ##### # # ## # # # ### # # # ######## # ##### ## # # ## # ## # # ##### # # # ####### # ## # ## # ## ## # ## ### ### ## ####### # # ## ## ## ## ### ## # # #### ### # # ## # ## # # # ## ## # # ### ###### ## # # # # # # ## # ### # ## ## # # # # # ## ## # # ## ## # # ## # ## # ########################### ##
最近どうも増田が見にくいのは割とどうでもよさげなトラックバックがいっぱいあるからじゃないだろうか、と思って書いた。
トラックバックを見たい場合は元記事の右下のトラックバックをクリックする。
// ==UserScript== // @name kill masuda TB // @description kill masuda TB // @namespace http://anond.hatelabo.jp/ // @include http://anond.hatelabo.jp/ // @include http://anond.hatelabo.jp/?page=* // ==/UserScript== (function(){ divs = document.getElementsByTagName('div'); for(i = 0; i < divs.length; ++i){ if(divs[i].getAttribute('class') == 'section'){ if(divs[i].getElementsByTagName('h3')[0].innerHTML.match(/Re:/) || divs[i].innerHTML.match(/href=\"http:\/\/anond/) || divs[i].innerHTML.match(/anond:\d{14}/)){ divs[i].innerHTML = ''; } } } })();
割とどうでもよさげなトラックバック、きみが消えたらますだががらんとしちゃったよ……。
>1日のPVが50以下の場合
これくらいかも。
ネットショップで日に50って商売になるの?
>1.色々売ろうとする,いろいろやろうとする
アイテム数いま50ぐらい。同じ用途で50種類といった方がいいかもしれない。
ランチェスター戦略というのをはじめて聞いた。と、思ったけど、しらべてみたら読んだことがあったよ。
ターゲットの集中化はできてないかも。よし決めた。増田のようなディープ層だっ!
>2.HTMLが汚い。
言葉もございません。
いや、ショッピングモールに出店しているんだけど、すごいんだよ。ツールが。
全部fontタグで囲ってくるの。cssとか書いてもfontタグで囲ってあるの。
エリアごとに内容を入れようとすると全部tableタグで囲ってあるの。しかもclassもidも振ってないの。
なんかもう泣きそう。
ショッピングモールってやめた方がいいのかな?
なんか悲しくなってきた。
以前、オープンソースをいじくって作ってたころもあったのだけど、
せっかくモールに出店しているのに何か成果がだせていないのは悔しいので、
集中集約だーと自前の方は閉じてしまった。
そろそろ復活させようかな。
>3.本当にいい物を売る。
いいものを売ってるつもりなんだけど…。
伝え方もへたくそのようです。
>4.1,2,3ができたら、プログラマーを雇ってサイトの更新、管理の自動化する。
全然自動になってないや。
あー、もうへこむー。
お金かかるよー。
20070629230000改定
20070702125800バグ発見:スクリプト中にある「&&」が、「&&」になっている。増田の仕様らしい。
20070827224900改定
// ==UserScript== // @name anond pickup // @namespace http://anond.hatelabo.jp/20070608230645 // @description pickup trackback tree top section at Hatelabo::AnonymousDiary // @include http://anond.hatelabo.jp/* // ==/UserScript== (function() { var threshold_bm = 1; var threshold_tb = 1; var ignoreList = { "/20070801172335": 33, "/20070806163721": 10, }; var firstPager_l = document.evaluate("//div[@class='pager-l']",document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue; function Hide(){} Hide.prototype.setup = function() { this.style = document.createElement("style"); this.style.id = "hide"; this.style.type = "text/css"; document.getElementsByTagName("head")[0].appendChild(this.style); var self = this; this.a = new Object(); this.a.visible = document.createElement("a"); this.a.visible.id = "visible"; this.a.visible.href = "#"; this.a.visible.innerHTML = "visible hide section"; // this.a.visible.setAttribute("onclick","document.getElementById('hide').innerHTML = 'div.hide {display: block}';document.getElementById('visible').style.display = 'none';document.getElementById('unvisible').style.display = 'inline';"); this.a.visible.addEventListener("click", function(){self.visible()}, false); firstPager_l.parentNode.insertBefore(this.a.visible, firstPager_l); this.a.unvisible = document.createElement("a"); this.a.unvisible.id = "unvisible"; this.a.unvisible.href = "#"; this.a.unvisible.innerHTML = "unvisible hide section"; // this.a.visible.setAttribute("onclick","document.getElementById('hide').innerHTML = 'div.hide {display: none}';document.getElementById('visible').style.display = 'inline';document.getElementById('unvisible').style.display = 'none';"); this.a.unvisible.addEventListener("click", function(){self.unvisible()}, false); firstPager_l.parentNode.insertBefore(this.a.unvisible, firstPager_l); if (GM_getValue("visible", 0)) { this.visible(); } else { this.unvisible(); } } Hide.prototype.visible = function() { this.style.innerHTML = "div.hide {display: block}"; this.a.visible.style.display = "none"; this.a.unvisible.style.display = "inline"; GM_setValue("visible", 1); } Hide.prototype.unvisible = function() { this.style.innerHTML = "div.hide {display: none}"; this.a.visible.style.display = "inline"; this.a.unvisible.style.display = "none"; GM_setValue("visible", 0); } Hide.prototype.append = function(section) { if (section.className.match(/hide/)) { return; } section.className += " hide"; } Hide.prototype.clear = function(section) { section.className = section.className.replace(/ hide/g, ""); } Hide.prototype.is = function(section) { return section.className.match(/hide/); } var hide = new Hide(); hide.setup(); var target = document.evaluate( "//div[@class='section' and child::*[not(@class='sectionfooter') and descendant::a[starts-with(@href,'http://anond.hatelabo.jp/2') or starts-with(@href,'/2') and not(child::span[@class='sanchor'])]]]", document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); for (var i=0; i<target.snapshotLength; i++) { hide.append(target.snapshotItem(i)); } var tbs = document.evaluate( "//p[@class='sectionfooter']/a[2]", document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); for (var i=0; i<tbs.snapshotLength; i++) { var tb = tbs.snapshotItem(i); if (tb.innerHTML == "\u30c8\u30e9\u30c3\u30af\u30d0\u30c3\u30af(0)") { // hide.append(tb.parentNode.parentNode); bookmark(tb, 0); } else if (! hide.is(tb.parentNode.parentNode)) { trackback(tb, 1); } else { bookmark(tb, 1); } } function trackback(tb, callback) { GM_xmlhttpRequest({ method: "GET", url: "http://anond.hatelabo.jp/" + tb.pathname.match(/\d{14}/), onload: function(result) { var link = result.responseText.match(/<a name="tb">(.|\s)*/)[0].match(/<li>\s*<a href="http:\/\/anond.hatelabo.jp\/\d{14}"/g); var n = link.length; for (var l in link) { var m = "/" + link[l].match(/\d{14}/); if (m in ignoreList) { n -= ignoreList[m]; } } if (n < threshold_tb) { tb.innerHTML = tb.innerHTML.replace(/\)$/, "/"+n+")"); if (callback) { bookmark(tb); } } else { tb.innerHTML = tb.innerHTML.replace(/\)$/, '/<span style="color: red;">'+n+"</span>)"); } } }); } function bookmark(tb, callback){ GM_xmlhttpRequest({ method: "GET", url: "http://b.hatena.ne.jp/entry/rss/http://anond.hatelabo.jp/" + tb.pathname.match(/\d{14}/), onload: function(result) { var r = result.responseText.match(/<rdf:li rdf:resource=/g); if (r && r.length >= threshold_bm){ hide.clear(tb.parentNode.parentNode); if (callback) { trackback(tb); } } else { hide.append(tb.parentNode.parentNode); } } }); } })();
今はスッキリしているのは古いやつ
/// ==UserScript== // @name anond pickup // @namespace http://anond.hatelabo.jp/20070608230645 // @description pickup trackback tree top section at Hatelabo::AnonymousDiary // @include http://anond.hatelabo.jp/*?page=* // ==/UserScript== (function() { var target = document.evaluate( "//div[@class='section' and child::*[not(@class='sectionfooter') and descendant::a[starts-with(@href,'http://anond.hatelabo.jp/2') or starts-with(@href,'/2') and not(child::span[@class='sanchor'])]]]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for(var i=0; i<target.snapshotLength; i++) { target.snapshotItem(i).style.display = "none"; } var trackback = document.evaluate( "//p[@class='sectionfooter']/a[2]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for(var i=0; i<trackback.snapshotLength; i++) { if (trackback.snapshotItem(i).innerHTML == "\u30c8\u30e9\u30c3\u30af\u30d0\u30c3\u30af(0)") { trackback.snapshotItem(i).parentNode.parentNode.style.display = "none"; } else if (trackback.snapshotItem(i).parentNode.parentNode.style.display != "none") { count(trackback.snapshotItem(i)); } } function count(tb) { GM_xmlhttpRequest({ method: "GET", url: "http://anond.hatelabo.jp/" + tb.getAttribute("href").match(/[0-9]{14}/), onload: function(result) { var n = result.responseText.replace(/\n/g,"").match(/<a name="tb">.*/)[0].match(/<li>/g).length; if (n < 10) { tb.innerHTML = tb.innerHTML.replace(/\)$/,"/"+n+")"); } else { tb.innerHTML = tb.innerHTML.replace(/\)$/,'/<span style="color: red;">'+n+"</span>)"); } } }); } })();
っていうユーザースクリプト作ったよ。これ使うととってもすっきり。Re: 増田の読み方ってどうしてますか?と組み合わせればめちゃめちゃすっきり。
// ==UserScript== // @name anond unvisualizer with innerlink // @namespace http://anond.hatelabo.jp/ // @description unvisualize specific section at Hatelabo::AnonymousDiary // @include http://anond.hatelabo.jp/* // ==/UserScript== (function() { var target = document.evaluate( "//div[@class='section' and child::*[not(@class='sectionfooter') and descendant::a[starts-with(@href,'http://anond.hatelabo.jp/2') or starts-with(@href,'/2') and not(child::span[@class='sanchor'])]]]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for(var i=0; i<target.snapshotLength; i++) { target.snapshotItem(i).style.display = "none"; } })();
// ==UserScript== // @name anond unvisualizer // @namespace http://anond.hatelabo.jp/ // @description unvisualize specific section at Hatelabo::AnonymousDiary // @include http://anond.hatelabo.jp/* // ==/UserScript== (function() { var target = document.evaluate( "//p[@class='sectionfooter']/a[2]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for(var i=0; i<target.snapshotLength; i++) { if (target.snapshotItem(i).innerHTML == "\u30c8\u30e9\u30c3\u30af\u30d0\u30c3\u30af(0)") { target.snapshotItem(i).parentNode.parentNode.style.display = "none"; } } })();
// ==UserScript== // @name unvisualizer // @namespace http://anond.hatelabo.jp/ // @description unvisualize section including specific word at Hatelabo::AnonymousDiary // @include http://anond.hatelabo.jp/* // @exclude http://anond.hatelabo.jp/hatena/* // ==/UserScript== (function() { var target = document.evaluate( // "//div[@class='section' and contains(descendant::text(),'\u3042\u307c\u3093')]", "//div[@class='section' and descendant::*[contains(text(),'NG') or contains(text(),'2ch')]]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for(var i=0; i<target.snapshotLength; i++) { target.snapshotItem(i).style.display = "none"; } })();
キーワードべた書きだけど、とりあえずこんな感じで。
ただ、日本語がよくわからん。xpathって日本語だめ?'\u3042\u307c\u3093'って「あぼん」だよね?
コメントアウトしてあるやつもなんで駄目なのかわかんない。xpathよくわからん。
[追記]
念のため、excludeに自分のID以下のページを入れといた方が良いかもね。
その他、好きにして。
あ、なるほど。ありがとうございます。
ついでにもうひとつ聞いてみたいんですけど
パラメータってなんでもかんでもメンバ変数にしてしまうのがclassの設計作法としてあるんですかね?
このプログラムの場合、startとlastは外部から与えられそうな値ですが
fizzとbuzzはどっちかというとロジックの仕様として組み込まれている感じの値ですよね。
これが同じように並んでいることに、なんとなく気持ち悪い感じを受けるんですけど…(そもそもclassの設計が悪い?)。
割る数と割られる数と余りが0の時に返す文字列をプロパティに持って
割り切れるかどうかのチェックを行うメソッドと
割り切れないときには数字、割り切れる時には文字を返すメソッドをもつようなclassを作って
それに委譲するようにすればいいのかな?