【C#/LINQ】LINQの学習 その(4) 9×9表を一行で出力する

投稿者: | 2012年2月9日

あまり実用性の無いプログラムだが、下のような9×9表をLINQを使って一行のプログラムで出力してみよう。

1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
・・・

一行で、という制限があるため、少し頭を使う問題となっている。
プログラムは以下のようになる。

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

namespace LinqLesson
{
    class Program
    {
        static void Main(string[] args)
        {
            Enumerable.Range(1, 9)
                .SelectMany(x => Enumerable.Range(1, 9).Select( y => Tuple.Create(x,y) ) )
                .ToList()
                .ForEach(t=> Console.Write( String.Format("{0,3}", t.Item1 * t.Item2 ) + (t.Item2 == 9 ? "\n" : "") ) );
       }
    }
}

一行、と言いつつ改行をしているが、見やすさのためにそうしている。
Main中でセミコロンは一つしか使っていない。
実行すると以下のように表示される。

プログラムの各要素について見ておこう。
まず、Range()メソッドで1~9までのシーケンスを生成する。

// 1~9までのシーケンス
// 1,2,3,4,5,6,7,8,9
Enumerable.Range(1, 9);

次に、シーケンスの各要素をさらに1~9のシーケンスに変換する。
このとき、Select()メソッドを使うと1~9まで列挙するIEnumerable<int>型のシーケンスが9つできてしまう。

// IEnumerable<int>型の要素を9個分もつ一連のシーケンス
// IEnumerable<int>,IEnumerable<int>,・・・
Enumerable.Range(1, 9).Select(x=>Enumerable.Range(1, 9));

そこで、SelectMany()メソッドを使うことにする。
すると、int型の要素を9×9個分もつ一連のシーケンスが作られる。

// int型の要素を9×9個分もつ一連のシーケンス
// 1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,・・・
Enumerable.Range(1, 9).SelectMany(x=>Enumerable.Range(1, 9));

さて、このままではただのintのシーケンスなので掛け合わせる数の組み合わせ情報としたい。
そこで右側のRangeで生成したシーケンスをSelect()メソッドで掛け算の組み合わせのタプルに変換する。

// 掛け算の組み合わせタプルにする
// (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9)・・・
Enumerable.Range(1, 9).SelectMany(x => Enumerable.Range(1, 9).Select( y => Tuple.Create(x,y) ) );

ここまでできたら、後はリスト化して列挙するだけである。

Enumerable.Range(1, 9)
	.SelectMany(x => Enumerable.Range(1, 9).Select( y => Tuple.Create(x,y) ) )
	// リスト化
	.ToList()
	// 列挙
	.ForEach(t=> /* 表示処理 */ );

見た目を整えるため、表示処理を少し工夫している。

// 列挙して表示
ForEach(t=> Console.Write( String.Format("{0,3}", t.Item1 * t.Item2 ) + (t.Item2 == 9 ? "\n" : "") ) );

列挙する要素はここではタプルである。ここで表示する段階で初めて掛け算の値を求める。
さらに、9番目まで列挙したら改行を加える処理を行っている。

// 9×9表を出力する
Enumerable.Range(1, 9)
	.SelectMany(x => Enumerable.Range(1, 9).Select( y => Tuple.Create(x,y) ) )
	.ToList()
	.ForEach(t=> Console.Write( String.Format("{0,3}", t.Item1 * t.Item2 ) + (t.Item2 == 9 ? "\n" : "") ) );

以上で、9×9表を出力するプログラムが完成した。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です