2012-08-17 87 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