翼度科技»论坛 编程开发 .net 查看内容

【算法】用c#实现自定义字符串编码及围栏解码方法

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
编写一个函数/方法,它接受2个参数、一个字符串和轨道数,并返回ENCODED字符串。
编写第二个函数/方法,它接受2个参数、一个编码字符串和轨道数,并返回DECODED字符串。
然后使用围栏密码对其进行解码。
这种密码用于通过将每个字符沿着一组“竖状轨道”依次放在对角线上来对字符串进行编码。首先开始对角向下移动。当你到达底部时,反转方向,对角向上移动,直到你到达顶部轨道。继续,直到到达字符串的末尾。然后从左到右读取每个“尾号”以导出编码字符串。
例如,字符串“WEAREDISCOVEREDFLEATONCE”可以在三轨系统中表示如下:
W E C R L T E
E R D S O E E F E A O C
A I V D E N
编码的字符串将是:
WECRLTEERDSOEEFEAOCAIVDEN
对于编码和解码,假设尾号的数量>=2,并且传递空字符串将返回空字符串。
请注意,为了简单起见,上面的示例排除了标点符号和空格。然而,也有一些测试包括标点符号。不要过滤掉标点符号,因为它们是字符串的一部分。
算法实现:
  1. 1 using System;
  2. 2 using System.Linq;
  3. 3
  4. 4 public class RailFenceCipher
  5. 5 {
  6. 6    public static string Encode(string s, int n)
  7. 7    {
  8. 8        var mod = (n - 1) * 2;
  9. 9        return string.Concat(s.Select((c, i) => new { c, i })
  10. 10           .OrderBy(a => Math.Min(a.i % mod, mod - a.i % mod))
  11. 11           .Select(a => a.c));
  12. 12    }
  13. 13
  14. 14    public static string Decode(string s, int n)
  15. 15    {
  16. 16        var mod = (n - 1) * 2;
  17. 17        var pattern = Enumerable.Range(0, s.Length)
  18. 18           .OrderBy(i => Math.Min(i % mod, mod - i % mod));
  19. 19        return string.Concat(s.Zip(pattern, (c, i) => new { c, i })
  20. 20           .OrderBy(a => a.i).Select(a => a.c));
  21. 21    }
  22. 22 }
复制代码
测试用例:
  1.   1 using NUnit.Framework;
  2.   2 using System;
  3.   3 using System.Collections.Generic;
  4.   4 using System.Linq;
  5.   5 public class SolutionTest
  6.   6 {
  7.   7     [Test]
  8.   8     public void BasicTests()
  9.   9     {
  10. 10         string[][] config =
  11. 11         {
  12. 12             new[] { "Hello, World!", "Hoo!el,Wrdl l" },               // encode
  13. 13             new[] { "Hello, World!", "Hlo ol!el,Wrd" },               // encode
  14. 14             new[] { "Hello, World!", "H !e,Wdloollr" },               // encode
  15. 15             new[] { "H !e,Wdloollr", "Hello, World!" },               //  decode
  16. 16             new[] { "", "" },                            // encode
  17. 17             new[] { "", "" },                            //  decode
  18. 18             new[] { "WEAREDISCOVEREDFLEEATONCE", "WECRLTEERDSOEEFEAOCAIVDEN" },   // encode
  19. 19             new[] { "WECRLTEERDSOEEFEAOCAIVDEN", "WEAREDISCOVEREDFLEEATONCE" },   //  decode
  20. 20             new[] { "WEAREDISCOVEREDFLEEATONCE", "WIREEEDSEEEACAECVDLTNROFO" },   // encode
  21. 21             new[] { "WIREEEDSEEEACAECVDLTNROFO", "WEAREDISCOVEREDFLEEATONCE" },   //  decode
  22. 22             new[] { "WEAREDISCOVEREDFLEEATONCE", "WCLEESOFECAIVDENRDEEAOERT" },   // encode
  23. 23             new[] { "WECRLTEERDSOEEFEAOCAIVDEN", "WLSADOOTEEECEAEECRFINVEDR" }    //  decode
  24. 24         };
  25. 25         int[] rails = { 3, 2, 4, 4, 3, 3, 3, 3, 4, 4, 5, 5 };
  26. 26         for (int i = 0; i < config.Length; i++)
  27. 27         {
  28. 28             var actual = i % 2 == 0 || i == 1
  29. 29                 ? RailFenceCipher.Encode(config[i][0], rails[i])
  30. 30                 : RailFenceCipher.Decode(config[i][0], rails[i]);
  31. 31
  32. 32             Assert.AreEqual(config[i][1], actual);
  33. 33         }
  34. 34     }
  35. 35
  36. 36     /* *****************
  37. 37      *   RANDOM TESTS
  38. 38      * *****************/
  39. 39
  40. 40     private class Sol
  41. 41     {
  42. 42         private static IEnumerable<T> Fencer<T>(int n, IEnumerable<T> str)
  43. 43         {
  44. 44             var rails = Enumerable.Range(0, n).Select(r => new List<T>()).ToList();
  45. 45             int[] data = { 0, 1 };
  46. 46             int x = 0, dx = 1;
  47. 47             foreach (var t in str)
  48. 48             {
  49. 49                 rails[data[x]].Add(t);
  50. 50                 if (data[x] == n - 1 && data[dx] > 0 || data[x] == 0 && data[dx] < 0)
  51. 51                     data[dx] *= -1;
  52. 52                 data[x] += data[dx];
  53. 53             }
  54. 54             return rails.SelectMany(lst => lst);
  55. 55         }
  56. 56
  57. 57         public static string Encode(string s, int n) => new string(Fencer(n, s).ToArray());
  58. 58
  59. 59         public static string Decode(string s, int n)
  60. 60         {
  61. 61             char[] arr = new char[s.Length];
  62. 62             int[] j = { 0 };
  63. 63             Fencer(n, Enumerable.Range(0, s.Length)).ToList().ForEach(i => arr[i] = s[j[0]++]);
  64. 64             return new string(arr);
  65. 65         }
  66. 66     }
  67. 67
  68. 68     private Random rnd = new Random();
  69. 69
  70. 70     private int Rand(int start, int end) { return start + rnd.Next(end - start); }
  71. 71
  72. 72     [Test]
  73. 73     public void FixedStringVariousRails()
  74. 74     {
  75. 75         var msg = "WEAREDISCOVEREDFLEEATONCE";
  76. 76         Console.WriteLine($"Input for these tests:\n{msg}");
  77. 77
  78. 78         for (int r = 0; r < 10; r++)
  79. 79         {
  80. 80             var rails = Rand(2, 11);
  81. 81             var exp = Sol.Encode(msg, rails);
  82. 82             Assert.AreEqual(exp, RailFenceCipher.Encode(msg, rails));
  83. 83
  84. 84             rails = Rand(2, 11);
  85. 85             exp = Sol.Decode(msg, rails);
  86. 86             Assert.AreEqual(exp, RailFenceCipher.Decode(msg, rails));
  87. 87         }
  88. 88     }
  89. 89
  90. 90     private static string lorem = "Amet non facere minima iure unde, provident, "
  91. 91                                   + "veritatis officiis asperiores ipsa eveniet sit! Deserunt "
  92. 92                                   + "autem excepturi quibusdam iure unde! Porro alias distinctio "
  93. 93                                   + "ipsam iure exercitationem molestiae. Voluptate fugiat quasi maiores!jk";
  94. 94     private static List<string> lorarr = lorem.Split(' ').ToList();
  95. 95
  96. 96     [Test]
  97. 97     public void RandomTests()
  98. 98     {
  99. 99         Console.WriteLine($"Base string for these tests (or a shuffled version):\n{lorem}");
  100. 100
  101. 101         for (int r = 0; r < 50; r++)
  102. 102         {
  103. 103             var msg = Shuffle();
  104. 104             int rails = Rand(2, 51);
  105. 105             var exp = Sol.Encode(msg, rails);
  106. 106             Assert.AreEqual(exp, RailFenceCipher.Encode(msg, rails));
  107. 107
  108. 108             msg = Shuffle();
  109. 109             rails = Rand(2, 51);
  110. 110             exp = Sol.Decode(msg, rails);
  111. 111             Assert.AreEqual(exp, RailFenceCipher.Decode(msg, rails));
  112. 112         }
  113. 113     }
  114. 114
  115. 115     private string Shuffle()
  116. 116     {
  117. 117         Shuffle(lorarr);
  118. 118         return string.Join(" ", lorarr);
  119. 119     }
  120. 120
  121. 121     public static void Shuffle<T>(List<T> deck)
  122. 122     {
  123. 123         var rnd = new Random();
  124. 124         for (int n = deck.Count - 1; n > 0; --n)
  125. 125         {
  126. 126             int k = rnd.Next(n + 1);
  127. 127             T temp = deck[n];
  128. 128             deck[n] = deck[k];
  129. 129             deck[k] = temp;
  130. 130         }
  131. 131     }
  132. 132 }
复制代码
 

来源:https://www.cnblogs.com/lan80/archive/2023/08/21/17645151.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具