R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

何で必要になったのか?

http://blogs.wankuma.com/rti/archive/2008/07/18/149606.aspx?Pending=true
順列生成メソッド

の続きです。

何故このようなメソッドを作ったのか

というと、ちゃんと理由がある訳です。

最近レイトン教授なるゲームにはまっている会社の後輩が僕に以下の出題をしてきました。


○○○○○-○○○○=33333
丸の中に1~9の数字を全て使用して式を完成させて下さい


基本的に僕はひねくれているので、素直に自分で解かずに、解を得るソフトウェアを作ろうと思った訳です。
んで、リンク先のメソッドを使って解いてみました。

こんな感じです。


static class Program
{
  [STAThread]
  static void Main()
  {
     foreach(var x in (new HogeHoge()).Answers()) Console.WriteLine(x);
  }
}

public class HogeHoge {
  public int[] Answers() {
    var q = Mathematics.GetPermutation("123456789")
      .Where(p => {
        var a = Convert.ToInt32(p.Substring(0, 5));
        var b = Convert.ToInt32(p.Substring(5, 4));
        return (a - b) == 33333; })
      .Select(p => Convert.ToInt32(p));
    return q.ToArray();
  }
}


これを実行すると 412687935,412867953 という数字が得られます。
ということで、41268 - 7935 = 33333 あるいは 41286 - 7953 = 33333 が答えです。

投稿日時 : 2008年7月22日 13:35

Feedback

# re: 何で必要になったのか? 2008/07/22 14:01 melt

GetAanswer……IDE の進化の弊害でしょうか。

# re: 何で必要になったのか? 2008/07/22 14:27 オムライス禁止!

AnAnswerだよねぇ
とか、Aだから答えが一個しか返ってきたらダメだよねぇ。
とか、本筋とまったく関係ないところに突っ込んでみる。
#いまだにRefactoringと聞くたびに「24時間戦えますか~♪」の曲が頭にうごめくっす。「リ」しかあってないのに^^;
Refactoringが re+foactor(ing形)とすると、まったく意味は関係ないんですが^^;

# re: 何で必要になったのか? 2008/07/22 14:39 R・田中一郎

melt さん

>GetAanswer……IDE の進化の弊害でしょうか。

わっ、びっくりした!
修正しておきました^^;

-------------------------------------------
オムライス禁止! さん

誰やねんw

>AnAnswerだよねぇ
>とか、Aだから答えが一個しか返ってきたらダメだよね

う~ん、この辺は作る時ちょっとひっかかったんですよね。

answers にしておきます。

# re: 何で必要になったのか? 2008/07/22 14:52 ghost_shell

> 基本的に僕はひねくれているので、素直に自分で解かずに、解を得るソフトウェアを作ろうと思った訳です。

むしろ真っ当だと思います。

実際は、自力できちんと解いてみてから答え合わせのために
組み立てたんですよねー?
(違う?)

> 何故このようなメソッドを作ったのか

真実は、真っ先にVS2008を立ち上げて全ての解を求めてくれることを知っていた後輩くんがRさんを利用した
っていうことですよねー?
(違うw?)
#> 何故このようなメソッドを作るはめになったのかw

# re: 何で必要になったのか? 2008/07/22 15:02 NyaRuRu

とりあえず答えが知りたいだけなら一応これで.

var answers =
from a in Enumerable.Range(1, 9)
from b in Enumerable.Range(1, 9).Except(new[] { a })
from c in Enumerable.Range(1, 9).Except(new[] { a, b })
from d in Enumerable.Range(1, 9).Except(new[] { a, b, c })
from e in Enumerable.Range(1, 9).Except(new[] { a, b, c, d })
from f in Enumerable.Range(1, 9).Except(new[] { a, b, c, d, e })
from g in Enumerable.Range(1, 9).Except(new[] { a, b, c, d, e, f })
from h in Enumerable.Range(1, 9).Except(new[] { a, b, c, d, e, f, g })
from i in Enumerable.Range(1, 9).Except(new[] { a, b, c, d, e, f, g, h })
let x = a * 10000 + b * 1000 + c * 100 + d * 10 + e
let y = f * 1000 + g * 100 + h * 10 + i
where (x - y) == 33333
select new { X = x, Y = y };

問題としてはこれと同種という気がします.
http://d.hatena.ne.jp/NyaRuRu/20080303/p2

# re: 何で必要になったのか? 2008/07/23 13:38 R・田中一郎

ghost_shell さん

>実際は、自力できちんと解いてみてから答え合わせのために
>組み立てたんですよねー?

いえ、単にネタとして作ってみただけですw

>真実は、真っ先にVS2008を立ち上げて全ての解を求めてくれることを知っていた後輩くんがRさんを利用した
>っていうことですよねー?

彼は、既に2パターン存在することまで解かっていたようです。

----------------------------------------------
NyaRuRu さん

>とりあえず答えが知りたいだけなら一応これで.

なるほど Exceptメソッドという手がありましたか。

>問題としてはこれと同種という気がします.

そうですね。
エントリーの記事は以前読んだものでしたが、言われてみて気付きました^^;

# re: 何で必要になったのか? 2008/07/24 11:58 nsharp

卑怯な後出しでw解いてみますた。

まずはpermutationの汎化から。

  static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> source) {
    return Permute(source, Enumerable.Empty<T>());
  }

  static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> left, IEnumerable<T> value) {
    if (!left.Any()) {
      yield return value;
    }

    foreach (var seq in left.SelectMany((x, i) => Permute(left.RemoveAt(i), value.Add(x)))) {
      yield return seq;
    }
  }

  static IEnumerable<T> RemoveAt<T>(this IEnumerable<T> source, int index) {
    return source.Where((x, i) => i != index);
  }

  static IEnumerable<T> Add<T>(this IEnumerable<T> source, T value) {
    return source.Concat(Enumerable.Repeat(value, 1));
  }

# re: 何で必要になったのか? 2008/07/24 11:59 nsharp

そして、問題の解へ。

  static string Join<T>(this IEnumerable<T> source, string separator) {
    return String.Join(separator, source.Select(x => x.ToString()).ToArray());
  }

  static void Main() {
    var q = from seq in Enumerable.Range(1, 9).Permute()
        let x = Convert.ToInt32(seq.Take(5).Join(""))
        let y = Convert.ToInt32(seq.Skip(5).Join(""))
        where x - y == 33333
        select new { x, y };

    foreach (var o in q) {
      Console.WriteLine("{0}, {1}", o.x, o.y);
    }
  }

2~3ヶ月C#から離れただけですっかり忘れてしまいますね・・・。

# re: 何で必要になったのか? 2008/07/24 12:48 nsharp

あ、空シーケンスのPermuteがバグってますた。(´・ω・`)
最初の関数を修正で。

  static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> source) {
    if (!source.Any()) {
      return Enumerable.Empty<IEnumerable<T>>();
    }
    return Permute(source, Enumerable.Empty<T>());
  }

長々とすみません・・・。

# re: 何で必要になったのか? 2008/07/24 15:25 R・田中一郎

みんなセンスあるなぁ^^;
僕も、作り直してみよう・・・

# re: 何で必要になったのか? 2008/07/24 17:37 NyaRuRu

>僕も、作り直してみよう・・・

作り直すとしたら,たとえば整数に特化したバージョンを一つ作るという方向性もありますね.
[0..n-1] の全並び替えが得られれば,あとは src[i] のインデックスアクセスが可能なので.

# re: 何で必要になったのか? 2008/07/24 17:58 NyaRuRu

うは.こんなページが microsoft.com にあった.
http://www.microsoft.com/japan/msdn/vs/vcsharp/mth_lexicograp.aspx

これですな.
http://reference.wolfram.com/mathematica/Combinatorica/ref/UnrankKSubset.ja.html

# re: 何で必要になったのか? 2008/07/25 1:38 NyaRuRu

あー,上のコメントで紹介した記事は,順列じゃなくて組み合わせの話です,念のため.

[1..n]の順列を辞書順に並べたk番目を求める話は,上の MSDN 記事からリンクされている以下の記事ですね.
http://msdn.microsoft.com/en-us/library/aa302371.aspx#permutat_topic3

# re: 何で必要になったのか? 2008/07/25 19:04 R・田中一郎

いろいろと情報をありがとうございました。
整数特化バージョンの方が汎用性は高そうですね。

# LqwyIRTpamCwVMaghBa 2011/12/13 20:39 http://www.drinkershealth.net/antabuse-disulfiram/

Yeah, it is clear now !... From the very beginning I did not understand where was the connection with the title !!...

# eHjgMLIzqu 2011/12/22 20:26 http://www.discreetpharmacist.com/

FuMmDV The topic is pretty complicated for a beginner!...

タイトル
名前
Url
コメント