やったー!逆fizzbuzz書けたよー!\(^o^)/
逆fizzbuzz
逆FizzBuzz問題 (Inverse FizzBuzz) - 猫とC#について書くmatarilloの雑記
あるリストが与えられたときに、FizzBuzzを実行するとそのリストを出力するような最短の連続数列を求めよ。
魂のコード
package InverseFizzBuzz; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(inverseFizzBuzz); sub convert { my $word = shift; if ("fizz" eq $word) { 3; } elsif ("buzz" eq $word) { 5; } elsif ("fizzbuzz" eq $word) { 15; } else { undef; } } sub isMatchToAny { my $n = shift; return ((0 == $n % 3) | (0 == $n % 5) | (0 == $n % 15)); } sub isMatch { my ($n, $m) = @_; if (0 == $n % 15) { undef; } elsif (0 == $n % $m) { 1; } else { undef; } } sub matchList { my ($init, $words, $result) = @_; my @dewords = @{$words}; my @deresult = @{$result}; my $match = &convert(shift(@dewords)); for ($init..100) { push(@deresult, $_); if (&isMatch($_, $match)) { if (0 < scalar(@dewords)) { $match = &convert(shift(@dewords)); } else { return @deresult; } } elsif (&isMatchToAny($_)) { last; } } undef; } sub inverseFizzBuzz { my $match = &convert(shift); my @result; for (1..100) { if (&isMatch($_, $match)) { if (0 < scalar(@_)) { my @hiki = ($_); my @array = &matchList($_ + 1, \@_, \@hiki); if (!$array[0]) { next; } if (!$result[0] | (scalar(@array) < scalar(@result))) { @result = @array; } } else { push (@result, $_); last; } } } @result; }
テスト
#!/usr/bin/perl use strict; use warnings; use Test::Simple tests => 9; use InverseFizzBuzz; my @fizz = inverseFizzBuzz("fizz"); ok($fizz[0] == 3, 'fizz'); my @buzz = inverseFizzBuzz("buzz"); ok($buzz[0] == 5, "buzz"); my @fizzfizzbuzz = inverseFizzBuzz("fizz", "fizz", "buzz"); ok (join('.', @fizzfizzbuzz) eq "6.7.8.9.10", 'fizz fizz buzz'); my @fizzbuzz = inverseFizzBuzz("fizz", "buzz"); ok (join('.', @fizzbuzz) eq "9.10", 'fizz buzz'); my @buzzfizz = inverseFizzBuzz("buzz", "fizz"); ok (join('.', @buzzfizz) eq "5.6", 'buzz fizz'); my @fizzbuzzfizz = inverseFizzBuzz("fizz", "buzz", "fizz"); ok (join('.', @fizzbuzzfizz) eq "3.4.5.6", 'fizz buzz fizz'); my @fizzfizz = inverseFizzBuzz("fizz", "fizz"); ok (join('.', @fizzfizz) eq "6.7.8.9", 'fizz fizz'); my @buzzfizzbuzz = inverseFizzBuzz("buzz", "fizz", "buzz"); ok (!$buzzfizzbuzz[0], 'buzz fizz buzz #undef'); my @fizzbuzzbuzz = inverseFizzBuzz("fizz", "buzz", "buzz"); ok (!$fizzbuzzbuzz[0], 'fizz buzz buzz #undef');
$ perl InverseFizzBuzz.t 1..9 ok 1 - fizz ok 2 - buzz ok 3 - fizz fizz buzz ok 4 - fizz buzz ok 5 - buzz fizz ok 6 - fizz buzz fizz ok 7 - fizz fizz ok 8 - buzz fizz buzz \#undef ok 9 - fizz buzz buzz \#undef
総評
______
←樹海 |
. ̄.|| ̄ ┗(^o^ )┓三
|| ┏┗ 三
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
苦にならないコードレビュー
はじめに
今お世話になってる現場で新規プロジェクトが始まりそうなのだが、このままだと再びコードレビュー無しの開発が始まってしまう気がしてならない。ただ、スケジュール的にキツそうな案件なので、最小の手間である程度の成果を得られる形式はなんだろうと考えてみた。
前に失敗したパターン
偉そうに言ってみたけど、実はコードレビューを上手くできたことはあまり無い。原因として
- レビュアーがレビュー時に初めてコードを読む
- 時間が掛かりすぎる。見てほしいポイントを伝えても、そもそもレビューイが見てもらうポイントを勘違いしてたら終わり
- 細かく指摘しすぎる
- 一歩踏み込むと宗教論争にまで行きそうなところまで突っ込む、そういう話は楽しいんだけど掛かる時間の割に成果が少ない
- 量が多い
- コード量が多いと、いろいろと突っ込みが入っても直すのがだるい。じゃあ次から気をつけますとかなっちゃう。
- 基本はdis
- ノウハウの共有のはずなのにdisばかりが多くて"良い箇所"の共有ができてなかった。あんまり言われると萎えるしね。
考えてみた
上の失敗例を踏まえつつ、普通のプログラマのためのコードレビュー方式を考えてみた。
事前にコードリーディングしてもらう
印刷したの渡してもいいし、リポジトリのコード読んでもらうでもいいんだけど、先に見てもらい、指摘ポイントをメモっておいてもらうのがいいのかなと。レビューがスムーズになるのは当然として
- コードを読むスピードの差
- 書いた人を目の前にして急いで読まなきゃいけないストレス
を解決できるのは大きい。
モラリストになりすぎない
突っ込みはある程度汎用的なところで止めること。限定的なケースでの突っ込みも重要なんだけど、長くならないようにしたい。最悪なのはレビュアーが指摘しまくる自分に気持ちよくなってるケース。相手のことを尊重しつつ、チームの底力を上がるための指摘をしたい。細かい話は昼飯のネタにして盛り上がりましょう。
ある程度小さい部分をレビューしてもらう
ここが難しいんだけど
- あまりコード量が多くない
- そのプロジェクトでよく書かれるであろうコードのエッセンスが多く含まれている
ところを選んでレビューしたい。
通信部分の基底クラスとそれを呼び出している所だとか、プロジェクトを通してよく書く例が良い。まず時間が節約できるし、みんなが関係する部分の方がレビューしたいと思うので。
likeを探す
この書き方イイネ!とか言われたい(俺が)、この書き方良いから全体で取り入れよう!とかなれば相当の収穫だと思ってる。あとdisるにしてもコードをdisるわけであってレビューイは一切disられてないことを意識しましょう。
おわりに
書いた部分は必ずレビューしてもらうって方式が前提ではないので、どちらかというと勉強会的な感じでやれればいいかなと思ってます。レビュアーがライブでリファクタリングするのとか最高。バグに関しては単体テストの意識合わせとかやった方が時間対効果高いんじゃないでしょうか。
さらにメンバー内でコード書くときの観点とかある程度共有しておけばよりスムーズに進むような気がする、自分の場合は
かなぁ。リファクタリング本とかも重要だとは思うけど、個人的には汚いコードはホコリみたいに積もるもの、最初にホコリを残す人間にならないことというモラルが一番だと思ってるので、リファクタリング技術は二の次のような気がします。*1
「ノンデザイナーズ・デザインブック」読了
- 作者: Robin Williams,吉川典秀
- 出版社/メーカー: 毎日コミュニケーションズ
- 発売日: 2008/11/19
- メディア: 単行本(ソフトカバー)
- 購入: 58人 クリック: 1,019回
- この商品を含むブログ (105件) を見る
感想
作りたいWebアプリをスケッチすると必ずダサいものが出来るのですが、直し方がわからないので困っていました。で、twitterでたまに名前を見かけるこの本を読んでみたのですが、まさに
- 小綺麗なプロトタイプを作りたいだけ
- あまり勉強に時間をとられたくない
私のような人間にとっては(時間対効果的な意味で)ベストだったのかも知れません。
非常に読みやすい文調で、デザインの例となる絵が多く、本自体も薄いので思い出したくなったら会社を往復する電車内で復習できてしまうレベルです(一時間くらい)。マスターできるまで繰り返し読んでいこう。
リストと配列
基本
- リスト
- スカラーの集合に順序をつけて並べたもの
- 配列
- リストを格納する変数
配列へのアクセス
qwショートカット
リスト代入
配列全体を表す@
配列の先頭or末尾の要素を操作
- 末尾の要素を取り除く
- $fred = pop(@array);
- 末尾に要素を追加
- push(@array, 0);
- 先頭の要素を取り除く
- $m = shift @array;
- 先頭に要素を追加
- unshift(@array, 5);
配列を文字列に展開
- スカラー変数と同じくダブルクォーテーション内で展開できる
- "@array"
- 文字列として@arrayを入れたい
- "\@array"
- '@array'
foreach
# 制御変数を明示的に指定 foreach $word (qw/ hoge fuga piyo /) { print "$word\n"; } # デフォルト制御変数を使用 foreach (qw/ hoge fuga piyo /) { print "$_\n"; } # 制御変数は値コピーではないので # ループ中に対象のリストの中身を操作できる @words = qw/ hoge fuga piyo /; foreach (@words) { $_ .= "\n"; }
並び替え
# 逆順を取得 print reverse(1..10)."\n"; # デフォルトのソート(ASCIIコード順) # ソート条件は他にも指定できる @words = sort(qw/hoge fuga piyo/); print "@words\n";
スカラーコンテキストとリストコンテキスト
- 式が置かれている位置によって意味が変わる
- コンテキスト == 式が置かれている場所を示す概念
- Perlが式を解析する場合はスカラー値かリスト値のどちらかを期待する
- 例外もある
- コンテキストによって評価が変わる例
# リストの個数を返す $n = @array; 3 + @array; # 文字列を逆順にして返す reverse($hoge);
- スカラーコンテキストを強制するscalar関数
- リストコンテキスト強制関数は無い、必要ないとのこと
@array = qw/ a b c /; # 配列の中身を表示する print "string :", @array, "\n"; # 配列の要素数を表示する print "number :", scalar @array, "\n";
リストコンテキストで
# 次の1行 $line = <STDIN>; # 全ての行 @lines = <STDIN>; # 全ての行を読み込み # 各要素から改行を取り除く chomp(@lines = <STDIN>);
interfaceのネスト
はじめに
サンドイッチメソッドを取り除こうとした時に、interfaceを使用するクラスにネストして書けるのか気になった。使用範囲的に別ファイルにするのも変な話だし
書けます
書けたのだが、他にもいろいろ書けるらしい。具体的には
- interface内にネスト
- interface内にネストしたクラスにネスト
とのこと。そもそもinterface内にクラスをネストできることを知らなかったので、ぜひ使っていきたいなと。
注意すべきところとしては、ネストしたinterfaceは修飾子があろうがなかろうがstaticになるというところ。アクセス制御は相応のものを指定すればOK。
public class My { private interface Foo { public void foo(Hoge hoge); } private void do (Foo f) { foreach (Hoge hoge : Hoges) { f.foo(hoge); } } private static void main(String[] args) { do(new Foo() { @Override public void foo(Hoge hoge) { // それぞれの処理 } }); } }
さいごに
そもそもJava的にこの書き方はありなんだろうか。無名関数のようにインタフェースをポンポン作っていいのか不安。
@Overrideアノテーションでエラー
はじめに
既存のプロジェクトをインポートしたら@Overrideを使用している箇所でもの凄い怒られた。「型 ○○ のメソッド ×× はスーパークラスのメソッドをオーバーライドする必要があります」って...してるじゃないかと
jdkのバージョンによって@Overrideアノテーションの仕様が違うらしい
調べてみたらこれがわかったので、プロジェクト設定からJavaコンパイラの項目を調べてみると、コンパイラー準拠レベルが1.5になっていました...これを1.6に変更、エラーが消えてくれました。Eclipseの設定としては1.6になってたので私は問題なかったですが、こちらも確認しておくとよいかなと
ちなみに
中には@Overrideを消すとかいうなんともいえない対応方法もネットに転がってたので気をつけたほうがいいですね
数値と文字列
浮動小数点
整数
- アンスコで繋げて読みやすく
- 61_298_040_283_768
数値演算子
- 剰余できます
- 10 % 3 = 1
- べき乗もできます
- 2**3 = 8
文字列
- シングルクォート文字列リテラル
- シングルクォートと逆スラ(続けて置いた場合)以外のすべてを文字として認識する
- 文字中にシングルクォートを入れたい場合は逆スラでエスケープ
- 改行文字を入れたい場合は連結させるとか
- ダブルクォート文字列リテラル
- "hello world\n"
- "coke\tsprite"
- 変数展開が可能
- スカラーかリストかで展開が変わったり
$hoge = "hoge"; print "string: $hoge\n"; @hogefuga = qw/hoge fuga/; print "array1: @hogefuga\n"; print "array2: ".@hogefuga."\n";
perl test.pl string: hoge array1: hoge fuga array2: 2
- 演算子
- 連結
- 'hello world'."\n"
- 繰り返し
- 連結
$s1 = "hoge" x 3; print "repeat1: $s1\n"; $s2 = 5 x 4; print "repeat2: $s2\n";
$ perl test.pl repeat1: hogehogehoge repeat2: 5555