我正在用C#做一些练习,我刚刚完成了我自己的atbash密码实现,下面是代码:
public class AtbashCipher
{
private string _plain = "abcdefghijklmnopqrstuvwxyz";
private string _cipher = "zyxwvutsrqponmlkjihgfedcba";
private readonly string _input;
private readonly List<int> _indices = new List<int>();
public AtbashCipher(string input)
{
_input = input;
}
public string Encode()
{
Splitter(_input).ForEach(x => _indices.Add(_plain.IndexOf(x)));
return _indices.Aggregate("", (current, index) => current + _cipher[index]);
}
public string Decode()
{
Splitter(_input).ForEach(x => _indices.Add(_cipher.IndexOf(x)));
return _indices.Aggregate("", (current, index) => current + _plain[index]);
}
private List<char> Splitter(string input)
{
return input.ToCharArray().ToList();
}
}有时感觉有点重复,我班上所有的变量看起来都很混乱。有什么更优雅的方法吗?
发布于 2017-06-28 03:59:10
好吧,如果你真的不想重复,你可以这样做
public static class AtbashCipher
{
private static string Rotate(string input, bool direction)
{
char min = direction ? 'z' : 'a';
char max = direction ? 'a' : 'z';
return input.ToList().Aggregate("", (current, character) => current + (char)(min - (character - max)));
}
public static string Encode(string plaintext)
{
return Rotate(plaintext, true);
}
public static string Decode(string cyphertext)
{
return Rotate(cyphertext, false);
}
}如果您期望获得很大的输入,那么使用StringBuilder和foreach循环可能更有性能,而不是使用聚合()调用。
发布于 2017-06-28 18:32:52
因为AtBash密码是一个简单的反向,所以您不需要_plain和_cipher。_indices没有理由处于类级别;相反,它应该在Encode和Decode中本地定义。
您甚至可以考虑取消拥有类实例,而使类及其方法成为静态的。如果将Decode保持为类实例,则可以简化为简单地返回_input!
您应该确保将输入字符串设置为小写,以防有人输入"Hello“。类似于:
_input = input.ToLowerInvariant();除了你应该尽量避免土耳其的“将”问题,代孕对被视为单一字符。避免的方法是使用大写。
另外,拆分器应该只使用char[],而不是转换ToList()。再说一次,你不需要真正的拆分器。
这些都是要考虑的事情。以下是我的看法:
public static class AtbashCipher
{
private const string DefaultAlphabet = "abcdefghijklmnopqrstuvwxyz";
public static string Encode(string input, string alphabet = DefaultAlphabet)
{
var plain = alphabet.ToUpperInvariant();
var letters = new List<char>(input.Length);
foreach (var c in input.ToUpperInvariant())
{
if (char.IsLetter(c))
{
// Get index of plain alphabet, but subtract from end
var index = plain.Length - plain.IndexOf(c) - 1;
letters.Add(plain[index]);
}
}
return new string(letters.ToArray());
}
public static string Decode(string input, string alphabet = DefaultAlphabet)
{
// reverse alphabet to get cipher
string cipher = new string(alphabet.ToUpperInvariant().Reverse().ToArray());
var letters = new List<char>(input.Length);
foreach (var c in input.ToUpperInvariant())
{
if (char.IsLetter(c))
{
var index = cipher.Length - cipher.IndexOf(c) - 1;
letters.Add(cipher[index]);
}
}
return new string(letters.ToArray());
}
}您可能会注意到,编码和解码看起来非常相似,除了选择普通或密码。以DRY的名义(不要重复),这可以简化为:
public static class AtbashCipher
{
private const string DefaultAlphabet = "abcdefghijklmnopqrstuvwxyz";
public static string Encode(string input, string alphabet = DefaultAlphabet)
{
var plain = alphabet.ToUpperInvariant();
return Transform(input, plain);
}
public static string Decode(string input, string alphabet = DefaultAlphabet)
{
var cipher = new string(alphabet.ToUpperInvariant().Reverse().ToArray());
return Transform(input, cipher);
}
private static string Transform(string input, string code)
{
var letters = new List<char>(input.Length);
foreach (var c in input.ToUpperInvariant())
{
if (char.IsLetter(c))
{
var index = code.Length - code.IndexOf(c) - 1;
letters.Add(code[index]);
}
}
return new string(letters.ToArray());
}
}发布于 2017-06-29 15:37:19
Atbash是它自己的逆方法,因此不需要单独的Encode()和Decode()方法:例如,Atbash(b) = y;Atbash(y) =b。只需一个Transform()方法即可。
您也不需要_plain和_cipher数组,您可以使用内置的字符排序。字符c是字母表中“a”前面的(c - 'a')位置,因此它的Atbash编码与“z”:('z' - (c - 'a'))之前的位置相同。这可以通过收集常量部分:(('z' + 'a') - c)来简化。
我的C#非常生疏,过时了,所以这是伪代码:
constant zANDa <- ascVal('z') + ascVal('a')
method Transform(inText) returns String
inText <- toLowercase(inText)
outText <- ""
foreach character c in inText
if (IsAlphabetic(c))
outText.append(char(zANDa - ascVal(c)))
else
// Non-alphabetic characters.
outText.append(c)
end if
end foreach
return outText
end Transform对于大写字母,请使用constant ZandA <- ascVal('Z') + ascVal('A')。
https://codereview.stackexchange.com/questions/166822
复制相似问题