Comment detail

ソートするコードの生成 (Nested Flatten)

stringでだらだら書くのは.NETらしくないので、CodeDOMで書いてみた。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
using System;
using System.CodeDom;
using System.Collections.Generic;

using CSC = System.CodeDom.CodeStatementCollection;
using CVD = System.CodeDom.CodeVariableDeclarationStatement;
using CC  = System.CodeDom.CodeConditionStatement;
using CTR = System.CodeDom.CodeTypeReferenceExpression;
using CMR = System.CodeDom.CodeMethodReferenceExpression;
using CMI = System.CodeDom.CodeMethodInvokeExpression;
using CVR = System.CodeDom.CodeVariableReferenceExpression;
using CP  = System.CodeDom.CodePrimitiveExpression;
using CBO = System.CodeDom.CodeBinaryOperatorExpression;

class Program
{
  static void Main(string[] args)
  {
    GenSort(5, Console.Out);
    Console.ReadKey();
  }

  static void GenSort(int n, System.IO.TextWriter writer)
  {
    string[] vName = "a b c d e f g h i j k l m n o p q r s t u v w x y z".Split(' ');

    CodeCompileUnit compileUnit = new CodeCompileUnit();
    CodeNamespace name = new CodeNamespace();
    compileUnit.Namespaces.Add(name);

    name.Imports.Add(new CodeNamespaceImport("System"));

    CodeTypeDeclaration type = new CodeTypeDeclaration("Sort");
    name.Types.Add(type);

    CodeMemberMethod main = new CodeEntryPointMethod();
    type.Members.Add(main);

    CMI readLine = new CMI(new CMR(new CTR("Console"), "ReadLine"));
    CMI intParse = new CMI(new CMR(new CTR("System.Int32"), "Parse"), readLine);
    for (int i = 0; i < n; i++)
      main.Statements.Add(new CVD(typeof(int), vName[i], intParse));

    CMR writeLine = new CMR(new CTR("Console"), "WriteLine");

    string[] p = new string[n];
    for (int i = 0; i < n; i++)
      p[i] = string.Format("{{{0}}}", i);
    CP format = new CP(string.Join(" ", p));

    CVR[] vars = new CVR[n];
    for (int i = 0; i < n; i++)
      vars[i] = new CVR(vName[i]);

    IList<int> orderd = new List<int>(n);
    IList<int> notyet = new List<int>(n);
    for (int i = 0; i < n; i++)
      notyet.Add(i);

    GenIf(main.Statements, orderd, notyet, writeLine, format, vars);

    (new Microsoft.CSharp.CSharpCodeProvider()).GenerateCodeFromCompileUnit
      (compileUnit, writer, (new System.CodeDom.Compiler.CodeGeneratorOptions()));
  }

  static void GenIf(CSC statements, IList<int> compared, IList<int> notyet,
    CMR writeLine, CP format, CVR[] vars)
  {
    if (notyet.Count == 0)
    {
      CMI method = new CMI(writeLine);
      method.Parameters.Add(format);
      foreach (int index in compared)
        method.Parameters.Add(vars[index]);
      statements.Add(method);
      return;
    }
    int current = notyet[0];
    notyet.RemoveAt(0);
    if (compared.Count == 0)
    {
      compared.Add(current);
      GenIf(statements, compared, notyet, writeLine, format, vars);
      return;
    }
    for (int i = 0; i < compared.Count; i++)
    {
      CC ifStatement = new CC();
      statements.Add(ifStatement);
      ifStatement.Condition = new CodeBinaryOperatorExpression
        (vars[current], CodeBinaryOperatorType.LessThan, vars[compared[i]]);
      compared.Insert(i, current);
      GenIf(ifStatement.TrueStatements, compared, notyet, writeLine, format, vars);
      compared.RemoveAt(i);
      statements = ifStatement.FalseStatements;
    }
    compared.Add(current);
    GenIf(statements, compared, notyet, writeLine, format, vars);
  }
}

Index

Feed

Other

Link

Pathtraq

loading...