パズル:nまでの整数を二つの組に分けて合計した結果が同じだった2番目と3番目を出力する

問題:1からnまでの整数を二つの組に分けて合計した結果が同じだった2番目と3番目を出力する。

public void nまでの整数を二つの組に分けて合計した結果が同じだった2番目と3番目()
{
//Enumerable.Select().Sum()は使わない方向で
Func<int, int, int> xからyまでの計 = (int x, int y) => ((x + y) * ((y - x + 1) / 2)) + (((y + x) / 2) * ((y - x + 1) % 2));
Func<int, bool> nまでの数字を二つの組に分けて合計した結果が同じ = (int n) => Enumerable.Range(n / 2, n - (n / 2))
.Where(分ける数字 => xからyまでの計(1, 分ける数字) ==
xからyまでの計(分ける数字 + 1, n))
.Select(x => x).Count() > 0;
int[] 該当するnのリスト = Enumerable.Range(2, int.MaxValue - 2).Where(n => nまでの数字を二つの組に分けて合計した結果が同じ(n))
.Select(n => n)
.Take(3).ToArray();
Console.WriteLine("no2:{0},no3:{1}", 該当するnのリスト[1], 該当するnのリスト[2]);
}
Share

パズルが面白そうだったのでVBとC#で書いてみた

数学パズル

3桁の数値とその数値を2乗した値の各数字が1から9までの数字で構成されるような3桁の数値をすべて求めるプログラムを作成せよ。

例えば 763*763=582169 となるが、これは、1,2,3,5,6,7,8,9 からなり、4が抜けているからダメ。

窓際プログラマーの独り言 -C#の話題を中心に:[Haskell

C#

var list = from x in Enumerable.Range(100,900)
where
(
from z in ((x * x).ToString() + x.ToString()).ToCharArray().Distinct() where z != '0'  select z
).Distinct().Count() == 9
select x;

VB

Dim list = From x In Enumerable.Range(100, 900) _
Where _
( _
From z In ((x * x).ToString() & x.ToString()).ToCharArray().Distinct() Where z <> "0"c Select z _
).Count = 9 _
Select x

最終的に生成される文字列が0を含んでいなくて、重複していなくて、9桁なら、問題の条件を満たすというロジックです。

追記:NyaRuRuさんに教えてもらったので、toCharArrayをなくすついでにいろいろといじったバージョン(C#のみ)

var list = from x in Enumerable.Range(100, 900)
where (x*1000000+x*x).ToString().Distinct().Where(s => s != '0').Count() == 9
select x;
Share

またまた、パズルが面白そうだったのでC#で書いてみた

問題

4桁の数値を順序を逆転させた数値(例えば、5432の場合は2345が逆転させた数値)で割ったときに、割り切れる4桁の数を求めよ。

(つまり、5432 / 2345 が割り切れればよい)

ただし、商が1のものや、割る数が4桁でないものは除外する。

窓際プログラマーの独り言 -C#の話題を中心に:[Haskell

var list = from x in Enumerable.Range(1000, 9000)
let y = Convert.ToInt32(new string(x.ToString().ToCharArray().Reverse().ToArray()))
where y >= 1000 && (x % y) == 0 && (x / y) != 1
select x;
Share

型付データセットを使うことで複雑なSQLはコードの外に追い出す

私のシステム設計の指針は複雑度の分散です。

だからコードの中に複雑なクエリは書きません。

問い合わせのクエリは、何らかの目的があって発行するものなので、JOIN等複数のテーブルが絡む複雑なクエリは、すべてRDBMS側にViewとして持つようにしています。

追記:2009年あたりから、ストアドも対象とするようにしました。

そのためのツールとして型付データセットを利用しています。

そうすることで、コードの中では常に一つのオブジェクト(テーブルであれVIEWであれ)に対して操作をするだけで済むので複雑なクエリが発行される事はありません。

それを実現するために、SQLを直接書かないでクエリを発行するためのフレームワークを作成してあります。

詳しくは書きませんが、型付データセット内で定義されているテーブル単位にラップしているクラスがあり、それに条件を積み上げたオブジェクトをアタッチする事で、様々なクエリを発行するようになっています。

ラップしているクラス自体の定義は前もって用意してあるテーブルにアクセスするための機能を持った抽象クラスを継承してテーブルを指定しているだけなので、数行で済むため作成やメンテナンスの労力はほぼありません。

SQLServerやOracleといった製品毎の差異もフレームワーク側で吸収(.NET Framework2.0にはその機能が実装されていて、そっちに移行しようか悩みました。)し、その中でクエリを自動生成するようにしているため、システムをコーディングするときは、仕様にあうように条件オブジェクトをブロックのように積み上げて、ラップしているクラスにアタッチするだけで良いです。

また、内部でパラメタライズドクエリ(+必要なエスケープ)を作成するためSQLInjectionといった問題も発生しません。

また、ラップするクラス名はテーブルやビューと同じ名前にしてある事と、ビューは目的に応じた名称にしている事から、何が目的でデータにアクセスしているのかが一目瞭然になっています。

この取り組みはもう4年以上続けていますが、

  • 複雑なクエリは外(RDBMS側)に目的に応じたVIEWとして持っている
  • クエリがコードの中に点在しない
  • コード内でデータにアクセスしている部分へのアクセスやコントロールがしやすい

などから昔のシステムでも保守にかける時間が少なくて済んでいます。

また、開発時にコードが複雑になりすぎないため、それ以前に比較すると不具合が少なかったり、不具合が発生してもそれにかける作業時間が少なく済んでいます。

コードの中に複雑なクエリを書いてしまって、修正が大変だとか嘆いている、そこのあなた。

コードにとっての保守フェーズはコードは書いた瞬間から始まっています。

とりあえず複雑なクエリはRDBMSに持ってもらう事でコードの見通しを良くしてみてはいかがでしょうか。

Share

接続詞を甘く見るな(日本語コーディング)

日本語コーディングでメソッド名を決めるとき

動詞

または

名詞+動詞

となるパターンが多いが、後者の「名詞+動詞」のパターンの場合、高い確率で接続詞を省略する傾向にある。

大抵の場合、文脈から接続詞の部分がなんなのか判断する事が可能だが、そうではない場合もあるし、中にはミスリードする人もいるだろう。

だから、できるだけ接続詞を省略して欲しくないのだ。

○○(名詞)△△(動詞)

というメソッド名よりも、

○○を△△する

○○が△△する

○○に△△する

としたい。

Share

コードの10戒

長いコーディング標準は、読むのも守るのもメンテするのも大変です。

なので、短いけど守ってほしい事と理由を犬の10戒の真似をしてまとめてみました。

1.名前は分かりやすいものにしてください。

わたしをよく知ってもらいたいのです。

だから名前は分かりやすいものにしてください。

メソッド等の名前が文章になってもかまいません。何をしようとしているのかを明示してください。

変数の名前も、その存在理由が分かるような名前にしてください。

2.わたしは、共通やcommonという名前が自分に含まれることを嫌います。

変数もメソッドも定数もクラスも役割を持ったあるべき場所に配置してください。

3.わたしが動作するための条件を指定してください。

わたしは動作するための条件を知ってもらいたいのです。

わたしが動作するための条件を前段階であらかじめ記述してください。

4.スコープは最小にしてください。

わたしは嫌われたくありません。

複数の問題が同時に存在していると人は混乱しやすくなり、わたしを嫌います。

変数のスコープも処理のスコープも最小になるように心がけてください。

5.わたしは太ると不健康になります。

不必要なコードを「将来のために」と作らないでください。

6.わたしは、できるだけ理解されやすいままでいたいと願っています。

だからチューニングをする前に非機能要求を定めて、計測してください。

そして、本当に必要なときだけチューニングしてください。

7.わたしをテストしてください。

わたしはあなたの作ったとおりにしか動きません。

あなた自身が正しく作ったかどうかをテストしてください。

8.思い通りに動かないとわたしを罵る前にわたしがそうなる原因が何かないか、あなた自身に問いかけてください。

繰り返しますがわたしはあなたが作ったとおりにしか動作できないのです。

9.保守で修正する前にわたしの事を理解してください。

理解したうえで修正するようにしてください。

わたしは秩序を乱されることが苦手なのです。

10.コーディング標準を守ってください。

わたしはとてもデリケートな存在です。

コーディング標準が守られていないと、存在意義がなくなってしまいます。

だから自分ルールでの無秩序なコーディングはやめてください。

Share

明日から仕事なので世界のナベアツ問題の応用編もコードをLINQで書いてみた

勝手に世界のナベアツ問題と名付けてみました。

ルール

1から40まで数字を読み上げる。

3の倍数と3のついた数字の時だけアホになる。

応用編として、

上のルール+8の倍数の時だけ気持ちよくなる。

FizzBuzz問題の変わりに世界のナベアツ問題をコーディングしたらおもしろいだろうか – NAL-6295の舌先三寸

結果的に、よりいっそう脱力感に・・・。

var 読み上げるリスト = from 今の数字 in Enumerable.Range(1, 40)
let 今の数字が3の倍数だった = (今の数字 % 3 == 0)
let 今の数字に3がついていた = (今の数字.ToString().IndexOf("3") >= 0)
let 今アホになる = 今の数字が3の倍数だった || 今の数字に3がついていた
let 今気持ちよくなる = (今の数字 % 8 == 0)
select (今アホになる ? "アホ" : "") +
(今気持ちよくなる ? "アハン" : "") +
(!今アホになる && !今気持ちよくなる ? 今の数字.ToString() : "");
foreach (var value in 読み上げるリスト)
{
Console.WriteLine(value);
}
Console.ReadKey();

Share

FizzBuzz問題の変わりに世界のナベアツ問題をコーディングしたらおもしろいだろうか

元は、世界のナベアツの「3の倍数と3のつく数だけアホになる男」というネタです。

勝手に世界のナベアツ問題と名付けてみました。

ルール

1から40まで数字を読み上げる。

3の倍数と3のついた数字の時だけアホになる。

応用編として、

上のルール+8の倍数の時だけ気持ちよくなる。

1 2 アホ 4 5 アホ 7 8 アホ 10 11 アホ アホ 14・・・

といった感じだろうか。

我ながらくだらない。

追記:

LINQで書くとこんな感じ

var result = from x in Enumerable.Range(1,40)
let s = x.ToString()
select x % 3 == 0 ? "アホ": s.IndexOf("3") >= 0 ? "アホ": s;
foreach (var value in result)
{
Console.WriteLine(value);
}

Share

コードを読むという事と、型という情報と型推論

暗黙的型付け(その3)

http://blogs.wankuma.com/rti/archive/2007/12/27/114850.aspx

乗り遅れてしまったので、ブログでこっそり自分のスタンスを、「コードを読むときにどうしてたか」思い出しながら・・・

コードを読むときは、そのコードが何を実現しているかが重要なので、何が存在して、それが何をしているのかを気にする。

そのときに、変数がどんな存在なのかは気にするが、どんな型なのかは必要だと思うまで気にしない。

どんな型なのかよりも、変数名で決定づけられている、「それがどんな存在なのか」の方が重要で、型は後で知りたければ必要に応じて開発環境が教えてくれるので、型推論を利用する事に違和感は特にないし脳内VMが必要だとも思わない。(5年くらい前は、「開発環境がある前提で考えるなんてどうなんだそれ。」と思っていた。)

型推論を利用したところで、結局、コンパイル時には型が決定されるわけなのだから(これがあるから、型は後で知れば良いと思える。)、普通に型を書いた場合とあまり違いがあるようには見えない。むしろ、型の情報が隠れることで変数そのものが、どんな存在なのかがクローズアップされる。

結果的に、文脈を追っている過程で型情報が目に入らないので、いちいち思考停止しないですむようにも思える。

とはいえ、別に普段から知りたいときに後で知ればよいと思って読んでいるので、気のせいかもしれないけれど。

もちろん、型推論で決定された型が利用したい型ではない場合は、型を明示的に宣言すればよい。

まぁ、でも、今のところ型推論を利用する時は、過去のエントリにあるような匿名型を利用するときくらいかなぁ。

関連する過去のエントリ

読みやすいコードを書くために匿名型を利用する。

http://d.hatena.ne.jp/NAL-6295/20070915/p1

読みやすいコードのためにLINQを利用する。

http://d.hatena.ne.jp/NAL-6295/20070920/p1

Share