2009年02月27日

『双方向データバインドによる単体入力エラーチェック』

   このエントリーをはてなブックマークに追加 Clip to Evernote
マイクロソフト社のコンサルタントnakamaさんが、Windows フォームの双方向データバインドを使った単体入力エラーチェックの実装方法の記事をブログ「とあるコンサルタントのつぶやき」で公開しています。

双方向データバインドによる単体入力エラーチェック

Windows フォームの開発をしている方は必読だと思います。
  

Posted by gushwell at 21:46Comments(0)TrackBack(0)

2009年02月25日

[パズル]ステインハウスの三角形

   このエントリーをはてなブックマークに追加 Clip to Evernote
ステインハウスの三角形とは、以下の3つの条件を見たいています。
1.この三角形は以下のように0と1からんばっている。
2. n行目はn-1行目の隣同士の数字の排他的論理和となっている。
3. 0 の数と1の数が同じ。


ステインハウスの三角形


問題1
三角形の辺の長さ n を与えられた時、nの値ごとに、何個のステインハウスの三角形があるかを調べるプログラムを書け。
ただし、左右対象となる鏡像は同一の三角形とみなすこと。

-----

すべてのパターンに対して、1と0の数が同じになる三角形の数を数えるという、もっともオーソドックスな方法を採用することにします。
それしか、思いつかない(笑)

n個からなる0と1からなるすべてのパターンを求める方法の一つとして、
0から2^n-1までの整数をビットパターンに変換すれ方法があります。
これだと、nの上限に制限ができてしまうけど、そこまで大きな三角形は必要ないだろいと、勝手に対象外ということにしました。

つまり、

int maxcount = (int)Math.Pow(2, n);
for (int i = 0; i < maxcount; i++) {
...
}

というループで、すべてのパターンを処理できることになります。
実際のコードは、LINQを使って

Enumerable.Range(0, maxcount).Aggregate(...);

というコードにしています。

この iから、ビットパターンを生成して、逆三角形の上辺のパターンとし、排他的論理和を行い、三角形を作ります。この三角形の、0と1の数が等しければ、ステインハウスの三角形ということで、カウントアップしていけば、答えが求まることになります。

なお、0と1の和が偶数でないと、条件3を満たさないので、辺の長さを nとすれば、

n * (n + 1) / 2

が偶数のときだけ、計算すればよいことになります。
上記計算式は、三角形の面積(1と0の総数)を示しています。
また、鏡像を2重にカウントしないようにするために工夫していますが、それは実際にコードを見てください。

これをC#で書いたのが以下のコードです。
今回は、今まで以上にLINQを使っています。LINQ面白いですね。
特に、ToInt()メソッドやNeedCount()メソッド内のコードは感動的です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XorTriangle {
class Program {
static void Main(string[] args) {
int n = 20;
for (int i = 1; i <= n; i++) {
if (i * (i + 1) / 2 % 2 == 0) {
Solver sol = new Solver(i);
Console.WriteLine("{0} : {1}", i, sol.Execute());
}
}
}
}

class Solver {
private int width;
private bool[] buffer;
public Solver(int n) {
this.width = n;
buffer = new bool[n];
}

public int Execute() {
int maxcount = (int)Math.Pow(2, width);
return Enumerable.Range(0, maxcount).Aggregate(0, (acc, n) =>
acc + (IsSteinhausTriangle(n, width) ? 1 : 0)
);
}

// ステインハウスの三角形かどうかを調べる
private bool IsSteinhausTriangle(int baseline, int width) {
// int型のまま処理するのは、面倒なので、bool[]に変換して処理をする。
bool[] line = ToArray(baseline, width);
if (!NeedCount(line)) // 鏡像を考慮する。
return false;
int tcount = 0; // 1の数
int fcount = 0; // 0の数
while (line.Length >= 1) {
tcount += line.Where(b => b == true).Count();
fcount += line.Where(b => b == false).Count();
line = NextLine(line);
}
return tcount == fcount;
}

// 鏡像をカウントしないようにするための判定メソッド
private bool NeedCount(bool[] line) {
if (IsRound(line))
// 左右対称ならば、他に鏡像となるパターンはないので、これは調べる必要がある。
return true;
// 左右対称でないならば、鏡像のパターンが他にもうひとつあるので、
// 片方だけを調べるようにする。
return ToInt(line.Reverse().ToArray()) > ToInt(line);
}

// ビットパターンが左右対称かどうかを調べる
private bool IsRound(bool[] line) {
int j = line.Length - 1;
int i = 0;
while ( i < j ) {
if (line[i++] != line[j--]) {
return false;
}
}
return true;
}

// bool[]をビットパターンとみなし、intに変換する
private int ToInt(bool[] line) {
return line.Aggregate(0, (r, b) => r * 2 + (b ? 1 : 0));
}

// 整数nを width個からなるbool配列に変換する
public bool[] ToArray(int n, int width) {
bool[] array = new bool[width];
int mask = 1;
width.Times(i => {
array[i] = (n & mask) != 0;
mask <<= 1;
});
return array;
}

// 1段下のラインを排他的論理和を使い求める
public bool[] NextLine(bool[] line) {
bool[] next = new bool[line.Length - 1];
int i = 0;
// ここで、Aggregateを使うのは邪道かな?
line.Aggregate((a, b) => {
next[i++] = a ^ b;
return b;
});
return next;
}

// デバッグ用 
public void PrintLine(bool[] line) {
line.ForEach(b => Console.Write(b ? 1 : 0));
Console.WriteLine();
}
}


static class EnumerableExtentions {
// 要素の数だけ、actionを呼び出す
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
foreach (var x in source) {
action(x);
}
}

// n回、actionを呼び出す
public static void Times(this int count, Action<int> action) {
for (int i = 0; i < count; i++)
action(i);
}
}
}





結果は、以下のとおりです。

3 : 3
4 : 3
7 : 7
8 : 22
11 : 87
12 : 205
15 : 956
16 : 2595
19 : 16402
20 : 29992


※当記事に掲載したコードは、『ナノピコ教室・プログラミング問題集』(駒木悠二+有澤誠 編 共立出版株式会社)に掲載されている問題をGushwellがC#で解いたものです。

  
Posted by gushwell at 23:01Comments(1)TrackBack(0)

2009年02月23日

WindowsFormsのカーソルが、WaitCursorから変更できない

   このエントリーをはてなブックマークに追加 Clip to Evernote
Visual Studio 2008のデザイナー画面で、FormクラスのCursorプロパティが、WaitCursorから他の値に変更できなくなってしまいました。

「コントロールのロック」をしたわけでもないのに、何で?

と思って、Form1.Designer.csのソースを見てみたら、

this.UseWaitCursor = true;

というコードがありました。
あれ、こんなプロパティ設定したつもりはないんだけど。。。
プロパティウィンドウの操作ミスで、falseからTrueに変更されてしまったみたいです。
このプロパティを falseにしたら、変更できるようになりました。

UseWaitCursorプロパティなんて、いままで気にしたことがなかったので、しばらく悩みました。

※ UseWaitCursorプロパティをTrueに設定すると、現在のコントロールおよびすべての子コントロールに待機カーソルを使用するようになります。  
Posted by gushwell at 23:19Comments(2)TrackBack(0)

2009年02月22日

「C#プログラミングレッスン」 リフレクション編

   このエントリーをはてなブックマークに追加 Clip to Evernote
Gushwell's C# Programing Page --「窓際プログラマーの独り言」別館で、メールマガジン『C#プログラミングレッスン』のバックナンバー「リフレクション編」をダウンロードできるようにしました。

現在は、LINQ to XML編を連載中です。
  
Posted by gushwell at 12:31Comments(0)TrackBack(0)

2009年02月19日

[パズル]覆銭問題

   このエントリーをはてなブックマークに追加 Clip to Evernote

英語では、Penny Flipping Problem というらしい。

覆銭問題とは
1. n枚のコインを全部表にして積み上げる
2. 最初に、上の1枚を裏返す。次に上から2枚目をまとめてひっくり返す。
次に3枚、4枚とひっくり返す。
n枚全体をひっくり返したら、また1枚に戻る。
3. この手順を繰り返し、初期状態に戻るには、何回ひっくり返したらよいか。


『ナノピコ教室』の解答には、数学的な考察がなされており、どうやったら、高速なプログラムになるか(つまり計算式を導き出す方法)が書いてありますが、僕には難しすぎて理解できないので、素直に解いてみました。

初期設定のコードを省略するために、コインの表を false, 裏を trueで表しています。
これで配列にセットしたコイン(bool型)を実際にひっくり返していって、元の状態(すべてがfalse)に戻るまで、処理を繰り返しています。

以下にC#のコードを示します。
毎度のことながら、一部でLINQを使って書いています。

using System;
using System.Collections.Generic;
using System.Linq;

namespace fukusen {
class Program {
static void Main(string[] args) {
for (int i = 1; i < 20; i++) {
Solver sol = new Solver(i);
int n = sol.Execute();
Console.WriteLine("f({0}) = {1}", i, n);
}
}
}

class Solver {
private int number;
private bool[] disks;
public Solver(int n) {
number = n;
disks = new bool[n]; // 初期状態はすべて false
}

// 1,2,3,...n,1,2,3,...n,1,2,3,...nを永遠に繰り返す
IEnumerable<int> Repeat(int number) {
IEnumerable<int> nums = Enumerable.Range(1, number);
while (true) {
foreach (var n in nums)
yield return n;
}
}

public int Execute() {
int count = 0;
foreach (var n in Repeat(number)) {
Turn(n);
count++;
if (IsFin())
break;
}
return count;
}

// N枚のコインをひっくり返す。
public void Turn(int n) {
int i = 0;
int j = n - 1;
while (i <= j) {
bool temp = disks[i];
disks[i++] = !disks[j];
disks[j--] = !temp;
}
}

public bool IsFin() {
return disks.All(d => d == false);
}
}
}

>


※当記事に掲載したコードは、『ナノピコ教室・プログラミング問題集』(駒木悠二+有澤誠 編 共立出版株式会社)に掲載されている問題をGushwellがC#で解いたものです。
  
Posted by gushwell at 06:25Comments(0)TrackBack(0)

2009年02月16日

SlickEdit Gadgets v1.0

   このエントリーをはてなブックマークに追加 Clip to Evernote

SlickEdit Gadgets v1.0
http://www.slickedit.com/content/view/441

このツールには、Visual Studio 2008のコードエディタで、カーソルのある行を色付けしてくれる機能があります。
最近、このツールの存在を知り、インストールしてみました。

色は自分でカスタマイズできるので、邪魔にならない程度の淡い色を指定しています。
[ツール]-[オプション]画面の SlickEditタブページで設定できます。

その他、Command Spy, File Explorer、Data Object Anakyzer, SLOC Report などの機能があります。


  
Posted by gushwell at 21:48Comments(0)TrackBack(0)

2009年02月15日

[パズル]梅花碁(2)

   このエントリーをはてなブックマークに追加 Clip to Evernote
梅花碁(1)の続きです。
問2は、「黒ー白ー黒と打って、黒が必ず勝ちになる手を探す」というものです。

前回作成した Board クラスと SolverクラスのGetWinPositionメソッドはそのまま利用しています。

今までのナノピコ教室の問題と同様、バックトラックをする再帰処理を書けばできるはず、ということでC#で書いてみましたが、ビジネスアプリ開発を専門とする僕は、思考型のゲームプログラムの作成にはほとんど縁がないので、ちょっと手こずりました。

拡張すれば、対戦型のプログラムができるようプログラムを設計してあります。
探索コードの中の

List koho

は、そのための用意した変数ですが、このプログラムではほとんど意味をなしていません。
このままだと、あまりにも探索する手が多すぎるので、本格的にやろうとすれば、もっと工夫が必要になってくると思われます。
また、それぞれの手にポイントを付けて、どれが最善手かを調べるようにしないといけませんし、良い手か悪い手かの判断アルゴリズムを考え出さなくてはいけません。
それと、深さ優先の探索を採用していますが、幅優先の探索に変更する必要もあると思われます。って、幅優先のプログラムって今まで書いたことがありません(^^;

また、SearchBlack, SearchWhiteというほとんど瓜二つのメソッドがあるので、これも一つにしたいところです。


using System;
using System.Collections.Generic;
using System.Linq;

namespace Umehana {
class Program {
static void Main(string[] args) {
Solver sol = new Solver();
string[] data = new string[] {
" ",
" O # ",
" O O ",
" # ",
" ",
" # # ",
" O ",
" ",
" ",
" ", };
sol.ReadData(data);
sol.Print();
var r = sol.SearchBlack(0);
if (r.Win == Board.Black)
Console.WriteLine("({0},{1})に打てば2手目で黒の勝ちです。",
r.Position.X, r.Position.Y);
else
Console.WriteLine("黒が2手目で勝ちになる手はありません。");
}
}

class Value {
public char Win { get; set; }
public Position Position { get; set; }
}

class Solver {
public Board board;
private Random rnd = new Random();
public Solver () {
board = new Board(10);
}

public void Print() {
board.Print();
}

private char Opponent(char piece) {
return piece == Board.Black ? Board.White : Board.Black;
}

public Value SearchBlack(int depth) {
if (depth >= 3)
return new Value { Win = Board.Empty, Position = null };
Position winpos = GetWinPosition(Board.Black);
if ( winpos != null )
return new Value { Win = Board.Black, Position = winpos };

// すぐに勝ちになる手はない。先読みする。
List<Value> koho = new List<Value>();
foreach (var pos in board.Vacants()) {
board.Put(pos, Board.Black);
try {
Value val = SearchWhite(depth + 1);
if (val.Win == Board.Black)
return new Value { Win = Board.Black, Position = pos };
else if (val.Win != Board.White)
koho.Add(new Value { Win = Board.Empty, Position = pos });
} finally {
board[pos] = Board.Empty;
}
}
int count = koho.Count();
if (count == 0)
// どこに打っても白の勝ち
return new Value { Win = Board.White, Position = board.Vacants().First()};
else
return koho.Skip(rnd.Next(0, count - 1)).First();
}

public Value SearchWhite(int depth) {
if (depth >= 3)
return new Value { Win = Board.Empty, Position = null };
Position winpos = GetWinPosition(Board.White);
if ( winpos != null )
return new Value { Win = Board.White, Position = winpos };

// すぐに勝ちになる手はない。先読みする。
List<Value> koho = new List<Value>();
foreach (var pos in board.Vacants()) {
board.Put(pos, Board.White);
try {
if (board.IsWin(Board.White)) {
return new Value { Win = Board.White, Position = pos };
}

Value val = SearchBlack(depth + 1);
if (val.Win == Board.White)
return new Value { Win = Board.White, Position = pos };
else if (val.Win != Board.Black)
koho.Add(new Value { Win = Board.Empty, Position = pos });
} finally {
board[pos] = Board.Empty;
}
}
int count = koho.Count();
if (count == 0)
// どこに打っても黒の勝ち
return new Value { Win = Board.Black, Position = board.Vacants().First() };
else
return koho.Skip(rnd.Next(0, count - 1)).First();
}

public Position GetWinPosition(char piece) {
foreach (var pos in board.Vacants()) {
board.Put(pos, piece);
try {
if (board.IsWin(piece))
return pos;
} finally {
board[pos] = Board.Empty;
}
}
return null;
}

public void ReadData(string[] lines) {
int y = 0;
foreach (var line in lines) {
int x = 0;
foreach (var c in line) {
if (c == Board.Black || c == Board.White)
board.Put(x, y, c);
x++;
}
y++;
}
}
}

class Position {
public int X { get; set; }
public int Y { get; set; }
}

class Board {
static public char Empty = ' ';
static public char Black = '#';
static public char White = 'O';
private char[,] cells;
private int width;
public Board(int width) {
cells = new char[width, width];
this.width = width;
foreach (var pos in AllCells())
this[pos] = Empty;
}
private char this[int x, int y] {
get { return cells[x, y]; }
set { cells[x, y] = value; }
}
public char this[Position pos] {
get { return cells[pos.X, pos.Y]; }
set { cells[pos.X, pos.Y] = value; }
}
public void Put(int x, int y, char piece) {
cells[x, y] = piece;
}
public void Put(Position pos, char piece) {
cells[pos.X, pos.Y] = piece;
}
public IEnumerable<Position> Vacants() {
foreach (var pos in AllCells()) {
if (this[pos] == Empty)
yield return pos;
}
}
public IEnumerable<Position> AllCells() {
for (int x = 0; x < width; x++)
for (int y = 0; y < width; y++)
yield return new Position { X = x, Y = y };
}
public bool IsWin(char piece) {
foreach (var pos in AllCells())
if (IsWinPattern(pos,piece))
return true;
return false;
}
public bool IsWinPattern(Position pos, char piece) {
if (this[pos] != piece)
return false;
for (int size = 1; size < (width - 1) / 2; size++) {
if (!((size <= pos.X && pos.X < width - size) &&
(size <= pos.Y && pos.Y < width - size)))
continue;
// パターン1
if (this[pos.X - size, pos.Y] == piece &&
this[pos.X + size, pos.Y] == piece &&
this[pos.X, pos.Y - size] == piece &&
this[pos.X, pos.Y + size] == piece)
return true;
// パターン2
if (this[pos.X - size, pos.Y - size] == piece &&
this[pos.X - size, pos.Y + size] == piece &&
this[pos.X + size, pos.Y - size] == piece &&
this[pos.X + size, pos.Y + size] == piece)
return true;
}
return false;
}
public void Print() {
Console.WriteLine(" 0123456789");
for (int y = 0; y < width; y++) {
Console.Write(y);
for (int x = 0; x < width; x++)
Console.Write(cells[x, y]);
Console.WriteLine();
}
}
}
}






※当記事に掲載したコードは、『ナノピコ教室・プログラミング問題集』(駒木悠二+有澤誠 編 共立出版株式会社)に掲載されている問題をGushwellがC#で解いたものです。  
Posted by gushwell at 22:43Comments(0)TrackBack(0)

2009年02月11日

『ナノピコ教室』:8クイーンゲーム(3)

   このエントリーをはてなブックマークに追加 Clip to Evernote
1月31日の記事の続きです。

8Queenゲームですが、あまりにも遅いので早くしてみました。

変更点
・Chessboardのデータ構造の変更
・クィーンの置ける場所の判定方法の変更
の2点。

Chessboardのデータ構造は、チェスボードの周囲もデータに含め、利き筋を調べる際に「ボードから出たら」という判断を簡単にできるようにしました。
斜めの利き筋を調べるコードは行数は増えましたが、格段に理解しやすくなりました。
また、クィーンが置けるかどうかの判定は、クィーンを置く際に、他のクィーンの利き筋かどうかを調べて、置けるかどうかを判定するのではなく、クィーンを置いた時に、利き筋にマークをつけ、マークがある場所には置くことができないという判断に変更しました。
また、この変更にともない、一手先を調べる際にChessboardのクローンを作成し、そのクローンを使うようにしました。

実際に10×10のボードの場合どれくらいの時間でできるかを調べてみると、
僕のノートPCでは、1分5秒で終わりました。前のプログラムが2時間くらいかかっていたわけですから、100倍以上の速度アップとなりました。

ちなみに、『ナノピコ教室」の解答をい見ると、当時(1974年ごろ)の汎用機 HITAC8410で、100分で解けたとありました。
HITAC8410がどれくらいの速度なのかがわかりませんが、今のPCは、当時のコンピュータよりは、たぶん数万倍は早いと思う(勝手な想像です)ので、まだまだ速度改善はできるのかも知れませんが、その方法を思いつかないので、この辺でやめておきます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

namespace _8QFight {
class Program {
static void Main(string[] args) {
Stopwatch sw = new Stopwatch();
sw.Start();

Solver solver = new Solver(8);
char r = solver.Solve();
sw.Stop();
solver.Print();

if (r == Chessboard.Black)
Console.WriteLine("先手必勝です");
else
Console.WriteLine("後手必勝です");
Console.WriteLine(sw.Elapsed);
}
}

class Record {
public Record Root;
public int PlaceX { get; set; }
public int PlaceY { get; set; }
public char Piece { get; set; }
public List<Record> Children { get; private set; }

public Record() {
Children = new List<Record>();
}

public void Add(Record rec) {
Children.Add(rec);
rec.Root = this.Root;
}

public void Clear() {
Children.Clear();
}

public void Print(int indent) {
if (Piece != 0)
Console.WriteLine("{0} {1} ({2},{3})", new string(' ',indent), Piece, PlaceX, PlaceY);
foreach (var x in Children)
x.Print(indent+1);
}

public override string ToString() {
return string.Format("{0} {1}", Piece, PlaceX);
}
}

class Solver {
public Record record;
private int Width;
public Solver(int width) {
record = new Record();
record.Root = record;
Width = width;
}

public char Solve() {
Chessboard board;
board = new Chessboard(Width);

int half = Width / 2 + Width % 2;
char win;
for (int y = 1; y <= half; y++) {
for (int x = y; x <= half; x++) {
int p = y * (Width+2) + x;
board = new Chessboard(Width);
record = new Record();
record.Root = record;

Record nr = Put(board,p, Chessboard.Black,record);

win = Evaluate(board,Chessboard.White, nr);
if (win == Chessboard.Black) {
board.Print();
return win;
}
}
}
return Chessboard.White;
}

public void Print() {
record.Print(0);
}

public char Evaluate(Chessboard board, char piece, Record rec) {
foreach (var place in board.CanPutPlaces()) {
Chessboard temp = board.Clone();
Record nr = Put(temp, place, piece, rec);
char win = Evaluate(temp, Opponent(piece), nr);
if (win == piece) {
rec.Clear();
rec.Add(nr);
return piece;
}
}
return Opponent(piece); // 候補が無い場合もここに来る。
}

private Record Put(Chessboard board,int place, char piece, Record rec) {
board.Put(place, piece);
Record nr = new Record { PlaceX = place%(Width+2), PlaceY=place/(Width+2), Piece = piece };
rec.Add(nr);
return nr;
}

private char Opponent(char piece) {
return piece == Chessboard.Black ? Chessboard.White : Chessboard.Black;
}
}

class Chessboard {
public const char Empty = '.';
public const char White = 'O';
public const char Black = '#';
public const char Edge = ' ';
public const char Not = '-';
private const char Finished = '/';

private int maxsize;
private char[] cells;
private int startIndex;
private int endIndex;
private int OuterWidth { get; set; }
public int Width { get; private set; }

private Chessboard() {
}

public Chessboard(int width) {
this.Width = width;
OuterWidth = width + 2;
startIndex = OuterWidth + 1;
endIndex = OuterWidth * (OuterWidth - 1) - 2;
this.maxsize = (OuterWidth) * (OuterWidth);
cells = Enumerable.Repeat(Edge, maxsize).ToArray();
for (int x = 1; x <= width; x++)
for (int y = 1; y <= width; y++)
cells[y * (OuterWidth) + x] = Empty;
}

public Chessboard Clone() {
Chessboard nb = new Chessboard();
nb.Width = this.Width;
nb.OuterWidth = this.OuterWidth;
nb.startIndex = this.startIndex;
nb.endIndex = this.endIndex;
nb.maxsize = this.maxsize;
nb.cells = (char[])this.cells.Clone();
return nb;
}


public int X(int now) {
return now % (OuterWidth);
}

public int Y(int now) {
return now / (OuterWidth);
}

public void Put(int place, char piece) {
foreach (var i in Courses(place))
if (cells[i] == Empty)
cells[i] = Not;
cells[place] = piece;
}

public void UnPut(int place) {
cells[place] = Empty;
}

public void Clear(int place) {
cells[place] = Empty;
}

public bool CanPut(int place) {
return (cells[place] == Empty);
}

public IEnumerable<int> CanPutPlaces() {
for (int i = startIndex; i <= endIndex; i++ )
if (CanPut(i)) {
yield return i;
}
}

public IEnumerable<int> Courses(int now) {
return Virtical(now)
.Concat(Horizontal(now))
.Concat(SlantL(now))
.Concat(SlantR(now)).Distinct();
}

public IEnumerable<int> Virtical(int now) {
int m = now % OuterWidth;
return Enumerable.Range(1, Width).Select(i => i * OuterWidth + m);
}

public IEnumerable<int> Horizontal(int now) {
return Enumerable.Range((now / OuterWidth) * OuterWidth+1, Width);
}

// 右上がり
public IEnumerable<int> SlantR(int now) {
int w1 = OuterWidth - 1;
int i = now - w1;
while (cells[i] != Edge) {
yield return i;
i -= w1;
}
i = now + w1;
while (cells[i] != Edge) {
yield return i;
i += w1;
}
}

public IEnumerable<int> SlantL(int now) {
int w1 = OuterWidth + 1;
int i = now - w1;
while (cells[i] != Edge) {
yield return i;
i -= w1;
}
i = now + w1;
while (cells[i] != Edge) {
yield return i;
i += w1;
}
}

public void Print() {
int i = 0;
foreach (var c in cells) {
Console.Write(c);
if (++i == OuterWidth) {
Console.WriteLine();
i = 0;
}
}
}
}
}




※当記事に掲載したコードは、『ナノピコ教室・プログラミング問題集』(駒木悠二+有澤誠 編 共立出版株式会社)に掲載されている問題をGushwellがC#で解いたものです。
  
Posted by gushwell at 22:38Comments(0)TrackBack(0)