C#练习题答案: 简单加密#3 - 转动比特【难度:3级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战

简单加密#3 - 转动比特【难度:3级】:

答案1:

public class Kata {
  const string alph = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
  const string encr = "KqLrIoJpa6b7Y4Z5CiDjAgBhSyTzQwRxOuPvMsNte f.c8d9GmHnEkFlW2X3U0V1";

  public static string Crypt(string text,string input,string output) {
      string res = string.Empty;
      if(string.IsNullOrEmpty(text)) return(text);
      int q = input.IndexOf(text[0]);
      if(q<0) throw new System.Exception();
      for(int i=1;i<text.Length;i++) {
          int p = input.IndexOf(text[i]);
          if(p<0) throw new System.Exception();
          int s = (p/32)%2-(q/2)%2;
          res += output[q+2*s];
          q = p-32*s;
      }
      res += output[q];
      return res;
  }
    
  public static string Encrypt(string text) {
      return(Crypt(text,alph,encr));
  }
  
  public static string Decrypt(string encryptedText) {
      return(Crypt(encryptedText,encr,alph));
  }      
}​

答案2:

using System;

public class Kata
{
  const string chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
  public static string Encrypt(string text)
  {
    if (String.IsNullOrEmpty(text)) return text;
    string r="",c;
    char [] b;
    char [][] t=new char[text.Length][];
    int p;
    for (int i=0;i<text.Length;i++) if ((p=chars.IndexOf(c=text[i]+""))<0) throw new Exception("Hy Steffen!"); else t[i]=numberToBits(p);
    for (int i=0;i<text.Length;i++) {
       b=t[i];
       if (i<text.Length-1) {char b1=getBit(b,5), b2=getBit(t[i+1],1); setBit(b,5,b2); setBit(t[i+1],1,b1);}//1
       b=xorBit(b,2); b=xorBit(b,4); //2
       b=swapBits(b,1,4); b=swapBits(b,2,5); b=swapBits(b,3,6); //3
       b=swapBits(b,1,2); b=swapBits(b,3,4); b=swapBits(b,5,6); //4
       b=reverseBits(b);  b=swapBits(b,1,3); //5+6
       r+=chars[bitsToNumber(b)];
    }
    return r;
  }
  
  public static string Decrypt(string eText)
  {
    if (String.IsNullOrEmpty(eText)) return eText;
    string r="",c;
    char [] b, b1=new char[eText.Length], b5=new char[eText.Length];
    char [][] t=new char[eText.Length][];
    int p;
    for (int i=0;i<eText.Length;i++) if ((p=chars.IndexOf(c=eText[i]+""))<0) throw new Exception("Hy Steffen!"); else t[i]=numberToBits(p);
    for (int i=eText.Length-1;i>=0;i--) {
       b=t[i];
       b=swapBits(b,1,3); b=reverseBits(b); //6+5
       b=swapBits(b,1,2); b=swapBits(b,3,4); b=swapBits(b,5,6); //4
       b=swapBits(b,1,4); b=swapBits(b,2,5); b=swapBits(b,3,6); //3
       b=xorBit(b,2); b=xorBit(b,4); //2
       b1[i]=getBit(b,1); b5[i]=getBit(b,5); //later on for rule 1
       t[i]=b;
    }
    for (int i=eText.Length-2;i>=0;i--) {t[i]=setBit(t[i],5,b1[i+1]); t[i+1]=setBit(t[i+1],1,b5[i]);}
    for (int i=0;i<eText.Length;i++) r+=chars[bitsToNumber(t[i])];
    return r;
  }
  
  public static char[] numberToBits(int num) {char[] r=new char[6]; for (int i=5; i>=0; i--) r[5-i]=((1<<i)&amp;num)>0?'1':'0'; return r;}
  public static int bitsToNumber(char[] bits) {int r=0; for (int i=0; i<=5; i++) r+=bits[i]=='1'?1<<(5-i):0; return r;}
  public static char[] swapBits(char[] num, int bit1, int bit2) {char t=num[bit1-1]; num[bit1-1]=num[bit2-1]; num[bit2-1]=t; return num;}
  public static char[] xorBit(char[] num, int bit) {num[bit-1]=num[bit-1]=='1'?'0':'1'; return num;}
  public static char[] reverseBits(char[] bits) {char[] r=new char[6]; for (int i=5; i>=0; i--) r[5-i]=bits[i]; return r;}
  public static char getBit(char[] bits, int bit) {return bits[bit-1];}
  public static char[] setBit(char[] bits, int bit, char value) {bits[bit-1]=value; return bits;}
}​

答案3:

using System;//for using Func<>
using System.Linq;//for using x.Contains()
public class Kata
{
  public static string Encrypt(string text)
  {
    if (text == null || text == "")//return the string if it is null or empty
      return text;  
    char[] key = new char[] {'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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '.'};   
    string encryptedText = "";//the above array is used to convert each char into a number. The string encryptedText will be returned with the encoded message
    Func<char, string> CharToBin = new Func<char, string> (x => Convert.ToString(Array.IndexOf(key, x), 2));//returns the binary representation of the position in key of a given char
    for (int i = 0; i < text.Length; i++)//for every char in the input string
    {
      if (!key.Contains(text[i]))//if the char is not in the array of acceptable characters, throw an exception
        throw new System.Exception();          
      char previousBit = i > 0 ? ("00000" + CharToBin(text[i - 1]))[("00000" + CharToBin(text[i - 1])).Length - 2] : ' ', nextBit = i < text.Length - 1 ? ("00000" + CharToBin(text[i + 1]))[("00000" + CharToBin(text[i + 1])).Length - 6] : ' ';//previousBit is the bit at position 4 (5th) of the last character, or 0 if there is no previous char. nextBit is the bit at position 0 (1st) of the next char. Leading 0's are appended to ensure the string is at least 6 bits long.
      string encryptedBin = EncryptNextChar("00000" + CharToBin(text[i]), previousBit, nextBit);//returns the encrypted result of a given 6 bit binary string     
      Func<string, char> BinToChar = new Func<string, char> (x => key[Convert.ToInt32(x, 2)]);//returns the char that is represented by the binary string given
      encryptedText += BinToChar(encryptedBin);//converts the encrypted binary back to a char, and appends it to the end of encryptedText to be returned
    } 
    return encryptedText;//returns the encrypted string
  }
  
  public static string EncryptNextChar(string bits, char previousBit, char nextBit)
  {    
    Func<char, char> Inverse = new Func<char, char> (x => x == '0' ? '1' : '0');//returns the inverse of a given bit
    char a = bits[bits.Length - 6], b = bits[bits.Length - 5], c = bits[bits.Length - 4], d = bits[bits.Length - 3], e = bits[bits.Length - 2], f = bits[bits.Length - 1];//a b c d e f are the bits at position 0 1 2 3 4 5 respectively of the string bits
    if (previousBit == ' ' &amp;&amp; nextBit == ' ')//if no char before or after
      return f.ToString() + c.ToString() + Inverse(b).ToString() + a.ToString() + Inverse(d).ToString() + e.ToString();//this is the how the bits end up after the encryption shuffles them
    else if (previousBit == ' ')//if no char before
      return f.ToString() + c.ToString() + Inverse(b).ToString() + a.ToString() + Inverse(d).ToString() + nextBit.ToString();//this is the how the bits end up after the encryption shuffles them
    else if (nextBit == ' ')//if no char after
      return f.ToString() + c.ToString() + Inverse(b).ToString() + previousBit.ToString() + Inverse(d).ToString() + e.ToString();//this is the how the bits end up after the encryption shuffles them
    else//if a char in the middle of a string
      return f.ToString() + c.ToString() + Inverse(b).ToString() + previousBit.ToString() + Inverse(d).ToString() + nextBit.ToString();//this is the how the bits end up after the encryption shuffles them
  }
  
  public static string Decrypt(string encryptedText)
  {
    if (encryptedText == null || encryptedText == "")//return the string if it is null or empty
      return encryptedText;  
    char[] key = new char[] {'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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '.'};   
    string text = "";//the above array is used to convert each char into a number. The string text will be returned with the decoded message
    Func<char, string> CharToBin = new Func<char, string> (x => Convert.ToString(Array.IndexOf(key, x), 2));//returns the binary representation of the position in key of a given char
    for (int i = 0; i < encryptedText.Length; i++)//for every char in the input string
    {
      if (!key.Contains(encryptedText[i]))//if the char is not in the array of acceptable characters, throw an exception
        throw new System.Exception();  
      char previousBit = i > 0 ? ("00000" + CharToBin(encryptedText[i - 1]))[("00000" + CharToBin(encryptedText[i - 1])).Length - 1] : ' ', nextBit = i < encryptedText.Length - 1 ? ("00000" + CharToBin(encryptedText[i + 1]))[("00000" + CharToBin(encryptedText[i + 1])).Length - 3] : ' ';//previousBit is the bit at position 5 (6th) of the last character, or 0 if there is no previous char. nextBit is the bit at position 3 (4th) of the next char. Leading 0's are appended to ensure the string is at least 6 bits long. These positions are different to encryption due to how the encryption process shuffles the bits.
      string decryptedBin = DecryptNextChar("00000" + CharToBin(encryptedText[i]), previousBit, nextBit);//returns the decrypted result of a given 6 bit binary string         
      Func<string, char> BinToChar = new Func<string, char> (x => key[Convert.ToInt32(x, 2)]);//returns the char that is represented by the binary string given 
      text += BinToChar(decryptedBin); //converts the decrypted binary back to a char, and appends it to the end of text to be returned
    }
    return text;//returns the decrypted string
  }
  
  public static string DecryptNextChar(string bits, char previousBit, char nextBit)
  {
    Func<char, char> Inverse = new Func<char, char> (x => x == '0' ? '1' : '0');//returns the inverse of a given bit
    char a = bits[bits.Length - 6], b = bits[bits.Length - 5], c = bits[bits.Length - 4], d = bits[bits.Length - 3], e = bits[bits.Length - 2], f = bits[bits.Length - 1];//a b c d e f are the bits at position 0 1 2 3 4 5 respectively of the string bits    
    if (previousBit == ' ' &amp;&amp; nextBit == ' ')//if no char before or after
      return d.ToString() + Inverse(c).ToString() + b.ToString() + Inverse(e).ToString() + f.ToString() + a.ToString();//this is how to rearrange the bits to unshuffle them
    else if (previousBit == ' ')//if no char before
      return d.ToString() + Inverse(c).ToString() + b.ToString() + Inverse(e).ToString() + nextBit.ToString() + a.ToString();//this is how to rearrange the bits to unshuffle them
    else if (nextBit == ' ')//if no char after
      return previousBit.ToString() + Inverse(c).ToString() + b.ToString() + Inverse(e).ToString() + f.ToString() + a.ToString();//this is how to rearrange the bits to unshuffle them
    else//if a char in the middle of a string
      return previousBit.ToString() + Inverse(c).ToString() + b.ToString() + Inverse(e).ToString() + nextBit.ToString() + a.ToString();//this is how to rearrange the bits to unshuffle them
  }
}​

答案4:

using System;
using System.Linq;
using System.Text;

public class Kata
{
    private static readonly string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
    private static byte GetIndexByte(char c) => Convert.ToByte(Alphabet.IndexOf(c));
    private static char GetIndexChar(byte b) => Alphabet[Convert.ToInt32(b)];
    private static bool GetBitValue(byte b, int i) => (b &amp; (1 << 6 - i)) != 0;
    private static byte SetBitValue(byte b, int i, bool value) => Convert.ToByte(value ? (b | (1 << 6 - i)) : (b &amp; ~(1 << 6 - i)));

    public static string Encrypt(string text)
    {
        // Throw out invalid input
        if (string.IsNullOrEmpty(text)) return text;
        if (text.Any(c => !Alphabet.Contains(c))) throw new Exception("Illegal character detected");

        // Cycle through each character in the string and perform bit-wise operations to encrypt them
        var builder = new StringBuilder();
        var enc = text.ToCharArray();
        for (int i = 0; i < enc.Length; i++)
        {
            var currentByte = GetIndexByte(enc[i]);

            // Swap Byte1/Bit5 with Byte2/Bit1 (if there is a Byte2)
            if (i < enc.Length - 1)
            {
                var nextByte = GetIndexByte(enc[i + 1]);
                var value = GetBitValue(nextByte, 1);
                nextByte = SetBitValue(nextByte, 1, GetBitValue(currentByte, 5));
                currentByte = SetBitValue(currentByte, 5, value);
                enc[i + 1] = GetIndexChar(nextByte);
            }

            // Read all bits, operate on them, and set them based on the encryption rules
            var b1 = GetBitValue(currentByte, 1);
            var b2 = GetBitValue(currentByte, 2);
            var b3 = GetBitValue(currentByte, 3);
            var b4 = GetBitValue(currentByte, 4);
            var b5 = GetBitValue(currentByte, 5);
            var b6 = GetBitValue(currentByte, 6);
            currentByte = SetBitValue(currentByte, 1, b6);
            currentByte = SetBitValue(currentByte, 2, b3);
            currentByte = SetBitValue(currentByte, 3, !b2);
            currentByte = SetBitValue(currentByte, 4, b1);
            currentByte = SetBitValue(currentByte, 5, !b4);
            currentByte = SetBitValue(currentByte, 6, b5);

            builder.Append(GetIndexChar(currentByte));
        }

        return builder.ToString();
    }

    public static string Decrypt(string encryptedText)
    {
        // Throw out invalid input
        if (string.IsNullOrEmpty(encryptedText)) return encryptedText;
        if (encryptedText.Any(c => !Alphabet.Contains(c))) throw new Exception("Illegal character detected");

        // Cycle through each character in the string (in reverse order) and perform bit-wise operations to decrypt them
        var builder = new StringBuilder();
        var dec = encryptedText.ToCharArray();
        byte nextByte = byte.MaxValue;
        for (int i = dec.Length - 1; i >= 0; i--)
        {
            var currentByte = GetIndexByte(dec[i]);

            // Read all bits, operate on them, and set them based on the decryption rules
            var b1 = GetBitValue(currentByte, 1);
            var b2 = GetBitValue(currentByte, 2);
            var b3 = GetBitValue(currentByte, 3);
            var b4 = GetBitValue(currentByte, 4);
            var b5 = GetBitValue(currentByte, 5);
            var b6 = GetBitValue(currentByte, 6);
            currentByte = SetBitValue(currentByte, 1, b4);
            currentByte = SetBitValue(currentByte, 2, !b3);
            currentByte = SetBitValue(currentByte, 3, b2);
            currentByte = SetBitValue(currentByte, 4, !b5);
            currentByte = SetBitValue(currentByte, 5, b6);
            currentByte = SetBitValue(currentByte, 6, b1);

            // Swap Byte1/Bit5 with Byte2/Bit1 (if there is a Byte2)
            if (i < dec.Length - 1)
            {
                var value = GetBitValue(nextByte, 1);
                nextByte = SetBitValue(nextByte, 1, GetBitValue(currentByte, 5));
                currentByte = SetBitValue(currentByte, 5, value);
                dec[i + 1] = GetIndexChar(nextByte);
            }

            if (nextByte < byte.MaxValue)  builder.Append(GetIndexChar(nextByte));
            nextByte = currentByte;
        }

        builder.Append(GetIndexChar(nextByte));
        return new string(builder.ToString().Reverse().ToArray());
    }
}​

答案5:

using System;
public class Kata
    {
        public static string Encrypt(string text)
        {
            if (text == null) return null;
            if (text == "") return "";
            string region = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
            string first = "";
              if (region.IndexOf(text[0])==-1) throw new Exception();
            string second = Convert.ToString(region.IndexOf(text[0]), 2);
            while (second.Length < 6)
                second = "0" + second;

            for (int i = 0; i < text.Length; i++)
            {
                first = second;
                if (i + 1 < text.Length)
                {
                    if (region.IndexOf(text[i+1])==-1) throw new Exception();
                    second = Convert.ToString(region.IndexOf(text[i + 1]), 2);
                    while (second.Length < 6)
                        second = "0" + second;
                    string temp = first.Substring(4, 1);
                    first = first.Remove(4, 1).Insert(4, second[0].ToString());
                    second = temp + second.Substring(1);
                }
                // 2
                if (first[1] == '1') first = first.Remove(1, 1).Insert(1, "0");
                else first = first.Remove(1, 1).Insert(1, "1");
                if (first[3] == '1') first = first.Remove(3, 1).Insert(3, "0");
                else first = first.Remove(3, 1).Insert(3, "1");
                // 3
                first = first.Substring(3, 3) + first.Substring(0, 3);
                // 4
                for (int j = 0; j < 6; j += 2)
                {
                    first = first.Remove(j + 1, 1).Insert(j, first[j + 1].ToString());
                }
                //5
                string s = "";
                for (int j = first.Length - 1; j >= 0; j--)
                {
                    s += first[j];
                }
                first = s;
                //6
                first = first[2] + (first.Substring(1)).Remove(1, 1).Insert(1, first[0].ToString());
                int index = Convert.ToInt32(first, 2);
                text = text.Remove(i, 1).Insert(i, region[index].ToString());
            }

            return text;
        }

        public static string Decrypt(string encryptedText)
        {
            if (encryptedText == null) return null;
            if (encryptedText == "") return "";
            string region = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
              if (region.IndexOf(encryptedText[encryptedText.Length-1])==-1) throw new Exception();
            string first = "";
            string second = Convert.ToString(region.IndexOf(encryptedText[encryptedText.Length-1]), 2);

            while (second.Length < 6)
                second = "0" + second;
            second = Decoding(second);

            for (int i = encryptedText.Length-1; i >= 0; i--)
            {
                first = second;                  
                if (i - 1 >= 0)
                {
                    if (region.IndexOf(encryptedText[i-1])==-1) throw new Exception();
                    second = Convert.ToString(region.IndexOf(encryptedText[i - 1]), 2);
                    while (second.Length < 6)
                        second = "0" + second;
                    second = Decoding(second);

                    string temp = second.Substring(4, 1);
                    second = second.Remove(4, 1).Insert(4, first[0].ToString());
                    first = temp + first.Substring(1);
                 }

                int index = Convert.ToInt32(first, 2);
                    encryptedText = encryptedText.Remove(i, 1).Insert(i, region[index].ToString());
                }
                    return encryptedText;
        }

        public static string Decoding(string first)
        {
            //6
            first = first[2] + (first.Substring(1)).Remove(1, 1).Insert(1, first[0].ToString());
            //5
            string s = "";
            for (int j = first.Length - 1; j >= 0; j--)
            {
                s += first[j];
            }
            first = s;
            // 4
            for (int j = 0; j < 6; j += 2)
            {
                first = first.Remove(j + 1, 1).Insert(j, first[j + 1].ToString());
            }
            // 3
            first = first.Substring(3, 3) + first.Substring(0, 3);
            // 2
            if (first[1] == '1') first = first.Remove(1, 1).Insert(1, "0");
            else first = first.Remove(1, 1).Insert(1, "1");
            if (first[3] == '1') first = first.Remove(3, 1).Insert(3, "0");
            else first = first.Remove(3, 1).Insert(3, "1");

            return first;
        }
    }

    
   

​

答案6:

using System;

public class Kata
{
    private static readonly char[] chars = { '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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '.' };

    private static void Swap(char[] firstArray, char[] secondArray, int first, int second)
    {
        char tmp = firstArray[first];
        firstArray[first] = secondArray[second];
        secondArray[second] = tmp;
    }

    private static void changeBitsEncypt(char[] array)
    {
        array[1] = array[1] == '0' ? '1' : '0'; // Step 2
        array[3] = array[3] == '0' ? '1' : '0';
        Swap(array, array, 3, 0); // Step 3
        Swap(array, array, 4, 1);
        Swap(array, array, 5, 2);
        Swap(array, array, 1, 0); // Step 4
        Swap(array, array, 2, 3);
        Swap(array, array, 4, 5);
        Array.Reverse(array); // Step 5
        Swap(array, array, 2, 0); // Step 6
    }

    private static void changeBitsDecrypt(char[] array)
    {
        Swap(array, array, 2, 0); // Step 6
        Array.Reverse(array); // Step 5
        Swap(array, array, 4, 5);
        Swap(array, array, 2, 3);
        Swap(array, array, 1, 0); // Step 4
        Swap(array, array, 5, 2);
        Swap(array, array, 4, 1);
        Swap(array, array, 3, 0); // Step 3
        array[3] = array[3] == '0' ? '1' : '0';
        array[1] = array[1] == '0' ? '1' : '0'; // Step 2
    }

    private static char[] getIndexBits(char[] result, char c)
    {
        int index = Array.IndexOf(chars, c);
        if (index < 0)
        {
            throw new Exception();
        }
        return Convert.ToString(index, 2).PadLeft(6, '0').ToCharArray();
    }

    public static string Encrypt(string text)
    {
        if (text == null || text.Length == 0)
        {
            return text;
        }
        char[] result = (char[])text.ToCharArray().Clone();
        for (int i = 0; i < text.Length; i++)
        {
            char[] firstBits = getIndexBits(result, result[i]);
            if (i < text.Length - 1) // Step 1
            {
                char[] secondBits = getIndexBits(result, result[i + 1]);
                Swap(firstBits, secondBits, 4, 0);
                result[i + 1] = chars[Convert.ToInt32(new String(secondBits), 2)];
            }
            changeBitsEncypt(firstBits); // Step 2 - 6
            result[i] = chars[Convert.ToInt32(new String(firstBits), 2)];
        }
        return new string(result);
    }

    public static string Decrypt(string encryptedText)
    {
        if (encryptedText == null || encryptedText.Length == 0)
        {
            return encryptedText;
        }
        char[] result = (char[])encryptedText.ToCharArray().Clone();      
        for (int i = encryptedText.Length - 1; i >= 0; i--)
        {
            char[] firstBits = getIndexBits(result, result[i]);
            changeBitsDecrypt(firstBits); // Step 2 - 6
            if (i < encryptedText.Length - 1) // Step 1
            {
                char[] secondBits = getIndexBits(result, result[i + 1]);
                Swap(firstBits, secondBits, 4, 0);
                result[i + 1] = chars[Convert.ToInt32(new String(secondBits), 2)];
            }
            result[i] = chars[Convert.ToInt32(new String(firstBits), 2)];
        }
        return new string(result);
    }
}​

答案7:

using System;
using System.Collections.Generic;
using System.Linq;

public class Kata {
  private const string CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";

  public static string Encrypt(string text) {
    return EncryptOrDecrypt(text, true);
  }
  
  public static string Decrypt(string encryptedText) {
    return EncryptOrDecrypt(encryptedText, false);
  }
  
  private static string EncryptOrDecrypt(string text, bool encrypt) {
    if (string.IsNullOrEmpty(text)) return text;
    var indices = text.Select(c => CHARS.IndexOf(c));
    if (indices.Any(i => i < 0)) throw new Exception("Invalid character");
    var bytes = indices.Select(i => Convert.ToString(i, 2).PadLeft(6, '0').ToCharArray());
    if (encrypt) {
      bytes = Step1(bytes).Select(Step2).Select(Step3).Select(Step4).Select(Step5).Select(Step6);
    } else {
      bytes = Step1(bytes.Select(Step6).Select(Step5).Select(Step4).Select(Step3).Select(Step2));
    }
    return string.Concat(bytes.Select(b => CHARS[Convert.ToInt32(new string(b), 2)]));
  }
  
  private static IEnumerable<char[]> Step1(IEnumerable<char[]> bytes) {
    var byteList = bytes.ToList();
    for (var i = 0; i < byteList.Count - 1; i++) {
      var temp = byteList[i][4];
      byteList[i][4] = byteList[i+1][0];
      byteList[i+1][0] = temp;
    }
    return byteList;
  }
  
  private static char[] Step2(char[] bits) {
    bits[1] = (char)('0' + '1' - bits[1]);
    bits[3] = (char)('0' + '1' - bits[3]);
    return bits;
  }
  
  private static char[] Step3(char[] bits) {
    return new char[] { bits[3], bits[4], bits[5], bits[0], bits[1], bits[2] };
  }
  
  private static char[] Step4(char[] bits) {
    return new char[] { bits[1], bits[0], bits[3], bits[2], bits[5], bits[4] };
  }
  
  private static char[] Step5(char[] bits) {
    Array.Reverse(bits);
    return bits;
  }
  
  private static char[] Step6(char[] bits) {
    var temp = bits[0];
    bits[0] = bits[2];
    bits[2] = temp;
    return bits;
  }
}​

答案8:

using System;
using System.Linq;

public class Kata
{
  private static readonly string VALID = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
  public static string Encrypt(string plainText)
  {
    #region Validate
    if (string.IsNullOrEmpty(plainText))
      return plainText;

    if (plainText.Any((c) => VALID.IndexOf(c) == -1))
      throw new Exception("Invalid characters in input string");

    #endregion

    Func<int, int, int, int, Tuple<int, int>> swapBits = (x, bitx, y, bity) =>
    {
      var tmp = ((x &amp; bitx) == bitx ? y | bity : y &amp; ~bity);
      x = ((y &amp; bity) == bity ? x | bitx : x &amp; ~bitx);
      y = tmp;
      return Tuple.Create(x, y);
    };
    Func<int, int, int, int> swapBitsInX = (x, firstBit, secondBit) =>
    {
      var firstBitSet = (x &amp; firstBit) == firstBit;
      var secondBitSet = (x &amp; secondBit) == secondBit;
      x = firstBitSet ? x | secondBit : x &amp; ~secondBit;
      x = secondBitSet ? x | firstBit : x &amp; ~firstBit;
      return x;
    };
    Func<int, int[], int> toggleBits = (target, bits) => target ^ (bits.Aggregate(0, (acc, b) => acc | b));

    int bit1 = 32, bit2 = 16, bit3 = 8, bit4 = 4, bit5 = 2, bit6 = 1;

    var xs = plainText.Select((c) => VALID.IndexOf(c)).ToArray();
    for (int i = 0; i < xs.Length; i++)
    {
      if (i != xs.Length - 1)
      {
        // 1. Swap indexes[i].bit5 with indexes[i+1].bit1 (if this is not the last index)
        var swapped = swapBits(xs[i], bit5, xs[i + 1], bit1);
        xs[i] = swapped.Item1;
        xs[i + 1] = swapped.Item2;
      }
      // 2. Flip bits 2 and 4 (xs[i].bit2 = !xs[i].bit2, xs[i].bit4 = !xs[i].bit4)
      xs[i] = toggleBits(xs[i], new int[] { bit2, bit4 });
      // 3. Swap bit1 with bit4, bit2 with bit5, and bit3 with bit6
      xs[i] = swapBitsInX(xs[i], bit1, bit4);
      xs[i] = swapBitsInX(xs[i], bit2, bit5);
      xs[i] = swapBitsInX(xs[i], bit3, bit6);
      // 4. Swap bit1 with bit2, bit3 with bit4, and bit5 with bit6
      xs[i] = swapBitsInX(xs[i], bit1, bit2);
      xs[i] = swapBitsInX(xs[i], bit3, bit4);
      xs[i] = swapBitsInX(xs[i], bit5, bit6);
      // 5. Reverse the bits
      xs[i] = swapBitsInX(xs[i], bit1, bit6);
      xs[i] = swapBitsInX(xs[i], bit2, bit5);
      xs[i] = swapBitsInX(xs[i], bit3, bit4);
      // 6. Swap bit1 with bit3
      xs[i] = swapBitsInX(xs[i], bit1, bit3);
    }
    return string.Concat(xs.Select((idx) => VALID[idx]));
  }
  public static string Decrypt(string cipherText)
  {
    #region Validate
    if (string.IsNullOrEmpty(cipherText))
      return cipherText;

    if (cipherText.Any((c) => VALID.IndexOf(c) == -1))
      throw new Exception("Invalid characters in input string");

    #endregion

    Func<int, int, int, int, Tuple<int, int>> swapBits = (x, bitx, y, bity) =>
    {
      var tmp = ((x &amp; bitx) == bitx ? y | bity : y &amp; ~bity);
      x = ((y &amp; bity) == bity ? x | bitx : x &amp; ~bitx);
      y = tmp;
      return Tuple.Create(x, y);
    };
    Func<int, int, int, int> swapBitsInX = (x, firstBit, secondBit) =>
    {
      var firstBitSet = (x &amp; firstBit) == firstBit;
      var secondBitSet = (x &amp; secondBit) == secondBit;
      x = firstBitSet ? x | secondBit : x &amp; ~secondBit;
      x = secondBitSet ? x | firstBit : x &amp; ~firstBit;
      return x;
    };
    Func<int, int[], int> toggleBits = (target, bits) => target ^ (bits.Aggregate(0, (acc, b) => acc | b));

    int bit1 = 32, bit2 = 16, bit3 = 8, bit4 = 4, bit5 = 2, bit6 = 1;

    var xs = cipherText.Select((c) => VALID.IndexOf(c)).ToArray();
    for (int i = xs.Length - 1; i >= 0; i--)
    {
      // 6. Swap bit1 with bit3
      xs[i] = swapBitsInX(xs[i], bit1, bit3);
      // 5. Reverse the bits
      xs[i] = swapBitsInX(xs[i], bit1, bit6);
      xs[i] = swapBitsInX(xs[i], bit2, bit5);
      xs[i] = swapBitsInX(xs[i], bit3, bit4);
      // 4. Swap bit1 with bit2, bit3 with bit4, and bit5 with bit6
      xs[i] = swapBitsInX(xs[i], bit1, bit2);
      xs[i] = swapBitsInX(xs[i], bit3, bit4);
      xs[i] = swapBitsInX(xs[i], bit5, bit6);
      // 3. Swap bit1 with bit4, bit2 with bit5, and bit3 with bit6
      xs[i] = swapBitsInX(xs[i], bit1, bit4);
      xs[i] = swapBitsInX(xs[i], bit2, bit5);
      xs[i] = swapBitsInX(xs[i], bit3, bit6);
      // 2. Flip bits 2 and 4 (xs[i].bit2 = !xs[i].bit2, xs[i].bit4 = !xs[i].bit4)
      xs[i] = toggleBits(xs[i], new int[] { bit2, bit4 });
      if (i != xs.Length - 1)
      {
        // 1. Swap indexes[i].bit5 with indexes[i+1].bit1 (if this is not the last index)
        var swapped = swapBits(xs[i], bit5, xs[i + 1], bit1);
        xs[i] = swapped.Item1;
        xs[i + 1] = swapped.Item2;
      }
    }
    return string.Concat(xs.Select((idx) => VALID[idx]));
  }
}​

答案9:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

public class Kata
{
        public static string Encrypt(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }
            if (!IsLegal(text))
            {
                throw new Exception("Illegal characters in string");
            }
            char[] region = CreateRegion();
            char[] encText = text.ToCharArray();
            for (int i = 0; i < encText.Length; i++)
            {
                bool tmp;
                int ix1 = Array.IndexOf(region, encText[i]);
                bool[] binary1 = Convert.ToString(ix1, 2).PadLeft(6, '0').Select(c => c == '1').ToArray();
                //Step 1
                if (i < encText.Length - 1) 
                {
                    int ix2 = Array.IndexOf(region, encText[i + 1]);
                    bool[] binary2 = Convert.ToString(ix2, 2).PadLeft(6, '0').Select(c => c == '1').ToArray();
                    tmp = binary2[0];
                    binary2[0] = binary1[4];
                    binary1[4] = tmp;
                    encText[i + 1] = BoolsToChar(binary2, region);
                }
                // Step 2
                binary1[1] = !binary1[1];
                binary1[3] = !binary1[3];
                // Step 3
                int len = binary1.Length / 2;
                for (int j = 0; j < len; j++)
                {
                    tmp = binary1[j];
                    binary1[j] = binary1[j + len];
                    binary1[len + j] = tmp;
                }
                // Step 4
                for (int j = 0; j < binary1.Length; j+=2)
                {
                    tmp = binary1[j];
                    binary1[j] = binary1[j + 1];
                    binary1[j + 1] = tmp;
                }
                // Step 5
                Array.Reverse(binary1);
                // Step 6
                tmp = binary1[0];
                binary1[0] = binary1[2];
                binary1[2] = tmp;
                encText[i] = BoolsToChar(binary1, region);
            }
            return new string(encText);
        }

        public static string Decrypt(string encryptedText)
        {
            if (string.IsNullOrEmpty(encryptedText))
            {
                return encryptedText;
            }
            if (!IsLegal(encryptedText))
            {
                throw new Exception("Illegal characters in string");
            }
            char[] region = CreateRegion();
            char[] decText = encryptedText.ToCharArray();
            for (int i = decText.Length - 1; i >= 0; i--)
            {
                bool tmp;
                int ix1 = Array.IndexOf(region, decText[i]);
                bool[] binary1 = Convert.ToString(ix1, 2).PadLeft(6, '0').Select(c => c == '1').ToArray();
                // Step 6
                tmp = binary1[0];
                binary1[0] = binary1[2];
                binary1[2] = tmp;
                // Step 5
                Array.Reverse(binary1);
                // Step 4
                for (int j = 0; j < binary1.Length; j += 2)
                {
                    tmp = binary1[j];
                    binary1[j] = binary1[j + 1];
                    binary1[j + 1] = tmp;
                }
                // Step 3
                int len = binary1.Length / 2;
                for (int j = 0; j < len; j++)
                {
                    tmp = binary1[j];
                    binary1[j] = binary1[j + len];
                    binary1[len + j] = tmp;
                }
                // Step 2
                binary1[1] = !binary1[1];
                binary1[3] = !binary1[3];
                //Step 1
                if (i < decText.Length - 1)
                {
                    int ix2 = Array.IndexOf(region, decText[i + 1]);
                    bool[] binary2 = Convert.ToString(ix2, 2).PadLeft(6, '0').Select(c => c == '1').ToArray();
                    tmp = binary2[0];
                    binary2[0] = binary1[4];
                    binary1[4] = tmp;
                    decText[i + 1] = BoolsToChar(binary2, region);

                }
                decText[i] = BoolsToChar(binary1, region);
            }
            return new string(decText);
        }

        private static char BoolsToChar(bool[] arr, char[] region)
        {
            //Change endian
            Array.Reverse(arr);
            BitArray ba = new BitArray(arr);
            byte[] bytes = new byte[1];
            ba.CopyTo(bytes, 0);
            int index = Convert.ToInt32(bytes[0]);
            return region[index];
        }
        
        private static bool IsLegal(string str)
        {
            Regex r = new Regex("^[\\s\\da-zA-Z0-9 .]*$");
            return r.IsMatch(str);
        }
        
        private static char[] CreateRegion()
        {
            List<char> region = new List<char>();
            string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            region.AddRange(alphabet.ToCharArray());
            region.AddRange(alphabet.ToLower().ToCharArray());
            region.AddRange("0123456789".ToCharArray());
            region.AddRange(" .".ToCharArray());
            return region.ToArray();
        }
}​

答案10:

using System;
using System.Collections.Generic;
using System.Linq;

public class Kata
{
    private const string Region = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .";
    public static string Encrypt(string text)
    {
        if (string.IsNullOrEmpty(text))
        {
            return text;
        }

        if (text.Any(x => !Region.Contains(x)))
        {
            throw new Exception();
        }

        var enc = "";
        var allBits = new List<char[]>();
        foreach (var letter in text)
        {
           allBits.Add(Convert.ToString(Region.IndexOf(letter), 2).PadLeft(6, '0').ToCharArray());
        }
        for (var i = 0; i < allBits.Count; i++)
        {
            var bits = allBits[i];
            //Step 1
            var holder = bits[4];
            if (i + 1 < allBits.Count)
            {
                bits[4] = allBits[i+1][0];
                allBits[i + 1][0] = holder;
            }

            //step 2
            bits[1] = FlipBit(bits[1]);
            bits[3] = FlipBit(bits[3]);
            //step 3
            bits = SwapBits(bits, 0, 3);
            bits = SwapBits(bits, 1, 4);
            bits = SwapBits(bits, 2, 5);

            //step 4
            for (var j = 0; j < bits.Length; j = j + 2)
            {
                bits = SwapBits(bits, j, j + 1);
            }
            //step 5
            bits = bits.Reverse().ToArray();

            //step 6
            bits = SwapBits(bits, 0, 2);
            enc += Region[Convert.ToInt32(new string(bits), 2)];
        }

        return enc;
    }

    private static char FlipBit(char bit)
    {
        return bit == '0' ? '1' : '0';
    }

    private static char[] SwapBits(char[] bits, int idx1, int idx2)
    {
        var ret = bits;
        var holder = bits[idx1];
        ret[idx1] = bits[idx2];
        ret[idx2] = holder;
        return ret;
    }

    public static string Decrypt(string encryptedText)
    {
        if (string.IsNullOrEmpty(encryptedText))
        {
            return encryptedText;
        }

        if (encryptedText.Any(x => !Region.Contains(x)))
        {
            throw new Exception();
        }

        var dec = "";
        var allBits = new List<char[]>();
        foreach (var letter in encryptedText)
        {
            allBits.Add(Convert.ToString(Region.IndexOf(letter), 2).PadLeft(6, '0').ToCharArray());
        }

        for (var i = allBits.Count-1; i >= 0; i--)
        {
            var bits = allBits[i];
            //step 6
            bits = SwapBits(bits, 0, 2);

            //step 5
            bits = bits.Reverse().ToArray();

            //step 4
            for (var j = 0; j < bits.Length; j = j + 2)
            {
                bits = SwapBits(bits, j, j + 1);
            }

            //step 3
            bits = SwapBits(bits, 0, 3);
            bits = SwapBits(bits, 1, 4);
            bits = SwapBits(bits, 2, 5);

            //step 2
            bits[1] = FlipBit(bits[1]);
            bits[3] = FlipBit(bits[3]);

            allBits[i] = bits;
        }

        //Step 1
        for (var i = 0; i < allBits.Count; i++)
        {
            var bits = allBits[i];
            var holder = bits[4];
            if (i + 1 < allBits.Count)
            {
                bits[4] = allBits[i + 1][0];
                allBits[i + 1][0] = holder;
            }
            dec += Region[Convert.ToInt32(new string(bits), 2)];
        }

        return dec;
    }
}​

上一篇:SAP XS Engine


下一篇:如何一本正经的写出别人无法维护的代码