2012-08-17 47 views
0

我昨天开始做的一个'我该死的'项目是一个Befunge口译员。除了边缘情况外,我大部分都在工作。将锯齿字符[] []转换为字符[,]?

我偷懒,并决定在befunge程序与此阅读:

char[][] program = File.ReadAllLines(args[0]).Select(x => x.ToCharArray()).ToArray(); 

我知道我是为自己以后创造更多的工作,但我希望去其他地方,并留在这一点。现在它晚了,我需要修复program不是矩形的事实。比方说,我有这个befunge程序:

v v < 
    @ 
>  ^

第1和第3行9个字符长,但2号线仅5中,我有我befunge解释设置方式,我会得到一个IndexOutOfBoundsException前该程序终止,因为在将^解释为方向改变之后,我将尝试访问program[1][8]并且program[1]仅为5长。我怎样才能用program创建一个char[,]并用空格填充多余的字符?

我知道我可以确定最长行的长度,行数,用这些字符创建char [,]并复制它们,但我希望稍微简单一些,更优雅。如果一种新方法更好,我完全可以抛出上面的线。

+1

我觉得你的回答你的问题在那里:“只需确定最长行的长度,行数,创建char [,]并将它们复制到” – Almo 2012-08-17 17:59:00

+0

“哦,以及制作Befunge解释器的道具。这是一个很酷的esolang。我做了一个类似于那么多年前的冲击波游戏,在那里编写了像Carnage Heart这样的机器人。 – Almo 2012-08-17 17:59:50

+0

只有一个解决方案并不能使其成为最佳解决方案。如果有人能够以不同的方式指向我,我可以学习更多关于C#的知识。 – 2012-08-17 18:00:24

回答

2

而不是重新创建整个参差不齐的数组(假设它可能相当大),你可以为它创建一个包装。该包装将能够进行边界检查并返回一些默认值,如果它超出界限而不是错误。

public class Matrix<T> 
{ 
    public T[][] UnderlyingCollection {get;set;} //should probably be readonly and set in the constructor 

    public T DefaultValue {get;set;} 

    public T this[int i, int j] 
    { 
    get 
    { 
     if(UnderlyingCollection.Length > i && UnderlyingCollection[i].Length > j) 
     return UnderlyingCollection[i][j]; 
     else 
     return DefaultValue; 
    } 
    set 
    { /*TODO implement*/ } 

    } 
} 
+0

因为这是一个翻译,速度是一个巨大的要求(也许我应该提到它)。您的实施必须在每次发出请求时验证i和j。 +1 tho,它仍然有效。 – 2012-08-17 18:39:22

+0

@CoreyOgburn呃,如果'i'由于短路而无效,它不必验证'i'和'j',但通常会验证它们是。实际上,验证这两个是非常快速的检查。你需要做数万亿次和数万亿次的提取才能真正看到与这些检查有显着的时间差异。 – Servy 2012-08-17 18:41:45

+0

在您的解决方案中,如果两个值都正确,则需要一定的时间,否则需要更少的时间。如果变量是正确的,我宁愿保存时间的情况,如果不正确(最有可能终止程序),则使用额外的时间。通过做一点时间设置来创建一个矩形阵列,合适的情况不会被检查放慢,而是完成。我知道这是我谈论的很短的时间,有时完全是不可估量的,但我觉得这是一个更好的习惯。 – 2012-08-17 19:46:43

0

男人,我不知道如果这是你在找什么,但检查了这一点:

public static class CharArrayExtension 
{ 
    public static char[,] FormatMatrix(this char[][] matrix) 
    { 
     int TotalColumns = matrix.Length; 
     int TotalLines = 0; 

     //Get the longest line of the current matrix 
     for (int column = 0; column < TotalColumns; column++) 
     { 
      int line = matrix[column].Length; 

      if (line > TotalLines) 
       TotalLines = line; 
     } 

     //Instantiate the resulting matrix 
     char[,] Return = new char[TotalColumns, TotalLines]; 

     Return.Initialize(); 

     //Retrieve values from the current matrix 
     for (int CurrentColumn = 0; CurrentColumn < TotalColumns; CurrentColumn++) 
     { 
      int MaxLines = matrix[CurrentColumn].Length; 

      for (int CurrentLine = 0; CurrentLine < MaxLines; CurrentLine++) 
      { 
       Return[CurrentColumn, CurrentLine] = matrix[CurrentColumn][CurrentLine]; 
      } 
     } 

     return Return; 
    } 
} 

用法:

 char[] Length5 = new char[]{ 'a', 'b', 'c', 'd', 'e'}; 
     char[] Length10 = new char[10]; 

     char[][] Matrix = new char[2][]; 
     Matrix[0] = Length5; 
     Matrix[1] = Length10; 

     char[,] FormattedMatrix = Matrix.FormatMatrix(); 

任何反馈将不胜感激。


UPDATE

尼古拉斯指出的性能问题。我很好奇,所以我做了如下的微弱的标杆:

 char[] Length5 = new char[]{ 'a', 'b', 'c', 'd', 'e'}; 
     char[] Length10 = new char[10]; 

     char[][] Matrix = new char[2][]; 
     Matrix[0] = Length5; 
     Matrix[1] = Length10; 

     Stopwatch stopWatch = new Stopwatch(); 

     stopWatch.Start(); 

     for (int i = 0; i < 5000; i++) 
     { 
      char[,] FormattedMatrix = Matrix.FormatMatrix(); 
     } 

     stopWatch.Stop(); 

     Console.WriteLine(string.Format("Andre Calil: {0} ms", stopWatch.ElapsedMilliseconds)); 

     stopWatch.Reset(); 

     stopWatch.Start(); 

     for (int i = 0; i < 5000; i++) 
     { 
      char[,] FormattedMatrix = RectArrayFromJagged<char>(Matrix); 
     } 

     stopWatch.Stop(); 

     Console.WriteLine(string.Format("Nicholas Carey: {0} ms", stopWatch.ElapsedMilliseconds)); 

     Console.ReadLine(); 

我已经多次运行它,平均结果是:

Andre Calil: 3 ms 
Nicholas Carey: 5 ms 

我知道那这不是一个适当的基准测试,但像我的解决方案一样,在性能方面并没有那么糟糕。

+0

你的回答正是我说我不想在我的问题的最后部分做的。 – 2012-08-18 16:57:13

+0

@CoreyOgburn你不说你*不想要*你说*你更喜欢*更优雅和简单的东西。意思完全不同,我认为你的downvote是不合适的。你遇到了一个问题,我为它提出了一个解决方案。 – 2012-08-18 19:07:49

2

基于@ AndreCalil之前的回答,这可能会更高效,特别是对于大型原始类型的数组。原始类型的数组可以被视为字节的缓冲区平,可在这样的工作是有用的(如果你有使用汇编或C经验):

static void Main(string[] args) 
{ 
    string[][] jagged = new string[][] { new string[] { "alpha" ,            } , 
              new string[] { "bravo" , "charlie" ,         } , 
              new string[] { "delta" , "echo" , "foxtrot" ,      } , 
              new string[] { "golf" , "hotel" , "india" , "juliet" ,   } , 
              new string[] { "kilo" , "lima" , "mike" , "nancy" , "oscar" , } , 
             } ; 
    string[,] rectangular = RectArrayFromJagged<string>(jagged) ; 

    return; 
} 

public static T[,] RectArrayFromJagged<T>(T[][] a) 
{ 
    int rows = a.Length; 
    int cols = a.Max(x => x.Length); 
    T[,] value = new T[ rows , cols ] ; 

    value.Initialize() ; 

    if (typeof(T).IsPrimitive) 
    { 
     int elementSizeInOctets = Buffer.ByteLength(value)/value.Length ; 
     for (int i = 0 ; i < rows ; ++i) 
     { 
      int rowOffsetInOctets = i * cols * elementSizeInOctets ; 
      int rowLengthInOctets = a[i].Length * elementSizeInOctets ; 
      Buffer.BlockCopy(a[i] , 0 , value , rowOffsetInOctets , rowLengthInOctets) ; 
     } 
    } 
    else 
    { 
     for (int i = 0 ; i < rows ; ++i) 
     { 
      int rowLength = a[i].Length ; 
      for (int j = 0 ; j < rowLength ; ++j) 
      { 
       value[i,j] = a[i][j] ; 
      } 
     } 
    } 
    return value ; 
} 
+0

+1了解。会不错,从你投票,至少对于这个想法=) – 2012-08-17 22:46:27

+0

对不起!你走了。 – 2012-08-17 22:52:07

+0

没有。多谢,伙计。我将用我们的解决方案进行微观基准测试 – 2012-08-17 22:54:27