私は 2 進数を扱っており、配列内の 1 つの違いの間にある 2 つの文字列を見つけようとしています。例えば
string[]binary = {"{0000}","{0001}","{0111}"};
最初の要素と 2 番目の要素で 4 番目の文字だけが異なるので、それを表示する必要があります。C#で効率的な方法はありますか? ありがとう..
私は 2 進数を扱っており、配列内の 1 つの違いの間にある 2 つの文字列を見つけようとしています。例えば
string[]binary = {"{0000}","{0001}","{0111}"};
最初の要素と 2 番目の要素で 4 番目の文字だけが異なるので、それを表示する必要があります。C#で効率的な方法はありますか? ありがとう..
これは役立つかもしれません:
public static int StringDistance(string first, string second)
{
int result = 0;
for (int i = 0; i < first.Length; i++)
{
if (!first[i].Equals(second[i]))
{
result++;
}
}
return result;
}
そして、次のように使用できます。
string[] binary = { "{0000}", "{0001}", "{0111}" };
var result = binary.Where(input => binary.Any(i => StringDistance(i, input) == 1)).ToArray();
//output: {"0000", "0001"}
これはどうでしょうか。これは、1 つの異なるビットを持つ 2 進数のすべてのペアを見つけます。
class Program {
static void Main( string[ ] args ) {
string[] binary = { "{0000}", "{0001}", "{0111}" };
var differentNumbers = DifferentNumbers( binary );
foreach ( Tuple<string, string, int> tuple in differentNumbers )
Console.WriteLine( string.Format( "{0} ; {1} - index {2}", tuple.Item1, tuple.Item2, tuple.Item3 ) );
}
public static List<Tuple<string, string, int>> DifferentNumbers( string[ ] array ) {
var differentNumbers = new List<Tuple<string, string, int>>( );
for ( int i = 0; i < array.Length; i++ ) {
for ( int j = i + 1; j < array.Length; j++ ) {
int count = 0, index = 0;
for ( int c = 1; c < array[ i ].Length - 1; c++ ) {
if ( array[ i ][ c ] != array[ j ][ c ] ) {
index = c;
if ( count++ > 1 )
break;
}
}
if ( count == 1 )
differentNumbers.Add( new Tuple<string, string, int>( array[ i ], array[ j ], index ) );
}
}
return differentNumbers;
}
}
結果:
{0000} ; {0001} - インデックス 4
各文字列を 1 回反復して UInt64 に変換し、相互にテストするために非常に効率的に複数回使用できます。
static private void TestCheckFor1BitDiff()
{
string[] values = new string[]
{
"0000",
"0001",
"0111",
"1000",
"1111"
};
UInt64[] intValues = values.Select(v => ConvertBinaryToUInt64(v)).ToArray();
bool comp01 = CheckFor1BitDiff(intValues[0], intValues[1]); // true
bool comp02 = CheckFor1BitDiff(intValues[0], intValues[2]); // false
bool comp12 = CheckFor1BitDiff(intValues[1], intValues[2]); // false
bool comp03 = CheckFor1BitDiff(intValues[0], intValues[3]); // true
bool comp24 = CheckFor1BitDiff(intValues[2], intValues[4]); // true
}
private static UInt64 ConvertBinaryToUInt64(string value)
{
if (64 < value.Length)
{
throw new ArgumentException("exceeds 64 bits", "value");
}
UInt64 power = 1;
UInt64 retVal = 0;
foreach (char bit in value.ToArray().Reverse())
{
switch (bit)
{
case '1':
retVal += power;
break;
case '0':
break;
default:
throw new ArgumentException("contains characters other than 0 and 1", "value");
}
power *= 2;
}
return retVal;
}
static private bool CheckFor1BitDiff(string a, string b )
{
UInt64 a1 = ConvertBinaryToUInt64(a);
UInt64 b1 = ConvertBinaryToUInt64(b);
return CheckFor1BitDiff(a1, b1 );
}
static private bool CheckFor1BitDiff(UInt64 a, UInt64 b )
{
return IsPowerOfTwo( a ^ b );
}
static private bool IsPowerOfTwo(UInt64 value)
{
return (value & (value - 1)) == 0;
}