18 Star 133 Fork 63

编程语言算法集 / C-Sharp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
BitArray.cs 23.62 KB
一键复制 编辑 原始数据 按行查看 历史
Gerson Jr 提交于 2024-01-08 14:18 . Switch to file-scoped namespaces (#434)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
// Original Author: Christian Bender
// Class: BitArray
//
// implements IComparable, ICloneable, IEnumerator, IEnumerable
//
// This class implements a bit-array and provides some
// useful functions/operations to deal with this type of
// data structure. You see a overview about the functionality, below.
//
//
// Overview
//
// Constructor (N : int)
// The constructor receives a length (N) of the to create bit-field.
//
// Constructor (sequence : string)
// setups the array with the input sequence.
// assumes: the sequence may only be allowed contains onese or zeros.
//
// Constructor (bits : bool[] )
// setups the bit-field with the input array.
//
// Compile(sequence : string)
// compiles a string sequence of 0's and 1's in the inner structure.
// assumes: the sequence may only be allowed contains onese or zeros.
//
// Compile (number : int)
// compiles a positive integer number in the inner data structure.
//
// Compile (number : long)
// compiles a positive long integer number in the inner data structure.
//
// ToString ()
// returns a string representation of the inner structure.
// The returned string is a sequence of 0's and 1's.
//
// Length : int
// Is a property that returns the length of the bit-field.
//
// Indexer : bool
// indexer for selecting the individual bits of the bit array.
//
// NumberOfOneBits() : int
// returns the number of One-bits.
//
// NumberOfZeroBits() : int
// returns the number of Zero-Bits.
//
// EvenParity() : bool
// returns true if parity is even, otherwise false.
//
// OddParity() : bool
// returns true if parity is odd, otherwise false.
//
// ToInt64() : long
// returns a long integer representation of the bit-array.
// assumes: the bit-array length must been smaller or equal to 64 bit.
//
// ToInt32() : int
// returns a integer representation of the bit-array.
// assumes: the bit-array length must been smaller or equal to 32 bit.
//
// ResetField() : void
// sets all bits on false.
//
// SetAll(flag : bool) : void
// sets all bits on the value of the flag.
//
// GetHashCode() : int
// returns hash-code (ToInt32())
//
// Equals (other : Object) : bool
// returns true if there inputs are equal otherwise false.
// assumes: the input bit-arrays must have same length.
//
// CompareTo (other : Object) : int (interface IComparable)
// output: 0 - if the bit-arrays a equal.
// -1 - if this bit-array is smaller.
// 1 - if this bit-array is greater.
// assumes: bit-array lentgh must been smaller or equal to 64 bit
//
// Clone () : object
// returns a copy of this bit-array
//
// Current : object
// returns the current selected bit.
//
// MoveNext() : bool
// purpose: increases the position of the enumerator
// returns true if 'position' successful increased otherwise false.
//
// Reset() : void
// resets the position of the enumerator.
//
// GetEnumerator() : IEnumerator
// returns a enumerator for this BitArray-object.
//
// Operations:
//
// & bitwise AND
// | bitwise OR
// ~ bitwise NOT
// >> bitwise shift right
// >> bitwise shift left
// ^ bitwise XOR
//
// Each operation (above) returns a new BitArray-object.
//
// == equal operator. : bool
// returns true if there inputs are equal otherwise false.
// assumes: the input bit-arrays must have same length.
//
// != not-equal operator : bool
// returns true if there inputs aren't equal otherwise false.
// assumes: the input bit-arrays must have same length.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataStructures;
/// <summary>
/// This class implements a bit-array and provides some
/// useful functions/operations to deal with this type of
/// data structure.
/// </summary>
public sealed class BitArray : ICloneable, IEnumerator<bool>, IEnumerable<bool>
{
private readonly bool[] field; // the actual bit-field
private int position = -1; // position for enumerator
/// <summary>
/// Initializes a new instance of the <see cref="BitArray" /> class.
/// setups the array with false-values.
/// </summary>
/// <param name="n">length of the array.</param>
public BitArray(int n)
{
if (n < 1)
{
field = new bool[0];
}
field = new bool[n];
}
/// <summary>
/// Initializes a new instance of the <see cref="BitArray" /> class.
/// Setups the array with the input sequence.
/// purpose: Setups the array with the input sequence.
/// assumes: sequence must been greater or equal to 1.
/// the sequence may only contain ones or zeros.
/// </summary>
/// <param name="sequence">A string sequence of 0's and 1's.</param>
public BitArray(string sequence)
{
// precondition I
if (sequence.Length <= 0)
{
throw new ArgumentException("Sequence must been greater than or equal to 1");
}
// precondition II
ThrowIfSequenceIsInvalid(sequence);
field = new bool[sequence.Length];
Compile(sequence);
}
/// <summary>
/// Initializes a new instance of the <see cref="BitArray" /> class.
/// Setups the bit-array with the input array.
/// </summary>
/// <param name="bits">A boolean array of bits.</param>
public BitArray(bool[] bits) => field = bits;
/// <summary>
/// Gets the length of the current bit array.
/// </summary>
private int Length => field.Length;
/// <summary>
/// Gets element given an offset.
/// </summary>
/// <param name="offset">Position.</param>
/// <returns>Element on array.</returns>
public bool this[int offset]
{
get => field[offset];
private set => field[offset] = value;
}
/// <summary>
/// Returns a copy of the current bit-array.
/// </summary>
/// <returns>Bit-array clone.</returns>
public object Clone()
{
var theClone = new BitArray(Length);
for (var i = 0; i < Length; i++)
{
theClone[i] = field[i];
}
return theClone;
}
/// <summary>
/// Gets a enumerator for this BitArray-Object.
/// </summary>
/// <returns>Returns a enumerator for this BitArray-Object.</returns>
public IEnumerator<bool> GetEnumerator() => this;
/// <summary>
/// Gets a enumerator for this BitArray-Object.
/// </summary>
/// <returns>Returns a enumerator for this BitArray-Object.</returns>
IEnumerator IEnumerable.GetEnumerator() => this;
/// <summary>
/// Gets a value indicating whether the current bit of the array is set.
/// </summary>
public bool Current => field[position];
/// <summary>
/// Gets a value indicating whether the current bit of the array is set.
/// </summary>
object IEnumerator.Current => field[position];
/// <summary>
/// MoveNext (for interface IEnumerator).
/// </summary>
/// <returns>Returns True if 'position' successful increased; False otherwise.</returns>
public bool MoveNext()
{
if (position + 1 >= field.Length)
{
return false;
}
position++;
return true;
}
/// <summary>
/// Resets the position of the enumerator.
/// Reset (for interface IEnumerator).
/// </summary>
public void Reset() => position = -1;
/// <summary>
/// Disposes object, nothing to dispose here though.
/// </summary>
public void Dispose()
{
// Done
}
/// <summary>
/// Returns a bit-array that represents the bit by bit AND (&amp;).
/// Assumes arrays have the same length.
/// </summary>
/// <param name="one">First bit-array.</param>
/// <param name="two">Second bit-array.</param>
/// <returns>bit-array.</returns>
public static BitArray operator &(BitArray one, BitArray two)
{
var sequence1 = one.ToString();
var sequence2 = two.ToString();
var result = new StringBuilder();
var tmp = new StringBuilder();
// for scaling of same length.
if (one.Length != two.Length)
{
int difference;
if (one.Length > two.Length)
{
// one is greater
difference = one.Length - two.Length;
// fills up with 0's
for (var i = 0; i < difference; i++)
{
tmp.Append('0');
}
tmp.Append(two);
sequence2 = tmp.ToString();
}
else
{
// two is greater
difference = two.Length - one.Length;
// fills up with 0's
for (var i = 0; i < difference; i++)
{
tmp.Append('0');
}
tmp.Append(one);
sequence1 = tmp.ToString();
}
} // end scaling
var len = one.Length > two.Length ? one.Length : two.Length;
var ans = new BitArray(len);
for (var i = 0; i < one.Length; i++)
{
result.Append(sequence1[i].Equals('1') && sequence2[i].Equals('1') ? '1' : '0');
}
ans.Compile(result.ToString().Trim());
return ans;
}
/// <summary>
/// Returns a bit-array that represents the bit by bit OR.
/// Assumes arrays have the same length.
/// </summary>
/// <param name="one">First bit-array.</param>
/// <param name="two">Second bit-array.</param>
/// <returns>bit-array that represents the bit by bit OR.</returns>
public static BitArray operator |(BitArray one, BitArray two)
{
var sequence1 = one.ToString();
var sequence2 = two.ToString();
var result = string.Empty;
var tmp = string.Empty;
// for scaling of same length.
if (one.Length != two.Length)
{
int difference;
if (one.Length > two.Length)
{
// one is greater
difference = one.Length - two.Length;
// fills up with 0's
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += two.ToString();
sequence2 = tmp;
}
else
{
// two is greater
difference = two.Length - one.Length;
// fills up with 0's
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += one.ToString();
sequence1 = tmp;
}
} // end scaling
var len = one.Length > two.Length ? one.Length : two.Length;
var ans = new BitArray(len);
for (var i = 0; i < len; i++)
{
result += sequence1[i].Equals('0') && sequence2[i].Equals('0') ? '0' : '1';
}
result = result.Trim();
ans.Compile(result);
return ans;
}
/// <summary>
/// Returns a bit-array that represents the operator ~ (NOT).
/// Assumes arrays have the same length.
/// </summary>
/// <param name="one">Bit-array.</param>
/// <returns>bitwise not.</returns>
public static BitArray operator ~(BitArray one)
{
var ans = new BitArray(one.Length);
var sequence = one.ToString();
var result = string.Empty;
foreach (var ch in sequence)
{
if (ch == '1')
{
result += '0';
}
else
{
result += '1';
}
}
result = result.Trim();
ans.Compile(result);
return ans;
}
/// <summary>
/// Returns a bit-array that represents bitwise shift left (&gt;&gt;).
/// Assumes arrays have the same length.
/// </summary>
/// <param name="other">Bit-array.</param>
/// <param name="n">Number of bits.</param>
/// <returns>Bitwise shifted BitArray.</returns>
public static BitArray operator <<(BitArray other, int n)
{
var ans = new BitArray(other.Length + n);
// actual shifting process
for (var i = 0; i < other.Length; i++)
{
ans[i] = other[i];
}
return ans;
}
/// <summary>
/// Returns a bit-array that represents the bit by bit XOR.
/// Assumes arrays have the same length.
/// </summary>
/// <param name="one">First bit-array.</param>
/// <param name="two">Second bit-array.</param>
/// <returns>bit-array.</returns>
public static BitArray operator ^(BitArray one, BitArray two)
{
var sequence1 = one.ToString();
var sequence2 = two.ToString();
var tmp = string.Empty;
// for scaling of same length.
if (one.Length != two.Length)
{
int difference;
if (one.Length > two.Length)
{
// one is greater
difference = one.Length - two.Length;
// fills up with 0's
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += two.ToString();
sequence2 = tmp;
}
else
{
// two is greater
difference = two.Length - one.Length;
// fills up with 0's
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += one.ToString();
sequence1 = tmp;
}
} // end scaling
var len = one.Length > two.Length ? one.Length : two.Length;
var ans = new BitArray(len);
var sb = new StringBuilder();
for (var i = 0; i < len; i++)
{
_ = sb.Append(sequence1[i] == sequence2[i] ? '0' : '1');
}
var result = sb.ToString().Trim();
ans.Compile(result);
return ans;
}
/// <summary>
/// Returns a bit-array that represents bitwise shift right (>>).
/// Assumes arrays have the same length.
/// </summary>
/// <param name="other">Bit-array.</param>
/// <param name="n">Number of bits.</param>
/// <returns>Bitwise shifted BitArray.</returns>
public static BitArray operator >>(BitArray other, int n)
{
var ans = new BitArray(other.Length - n);
// actual shifting process.
for (var i = 0; i < other.Length - n; i++)
{
ans[i] = other[i];
}
return ans;
}
/// <summary>
/// Checks if both arrays are == (equal).
/// The input assumes arrays have the same length.
/// </summary>
/// <param name="one">First bit-array.</param>
/// <param name="two">Second bit-array.</param>
/// <returns>Returns True if there inputs are equal; False otherwise.</returns>
public static bool operator ==(BitArray one, BitArray two)
{
if (ReferenceEquals(one, two))
{
return true;
}
if (one.Length != two.Length)
{
return false;
}
var status = true;
for (var i = 0; i < one.Length; i++)
{
if (one[i] != two[i])
{
status = false;
break;
}
}
return status;
}
/// <summary>
/// Checks if both arrays are != (not-equal).
/// The input assumes arrays have the same length.
/// </summary>
/// <param name="one">First bit-array.</param>
/// <param name="two">Second bit-array.</param>
/// <returns>Returns True if there inputs aren't equal; False otherwise.</returns>
public static bool operator !=(BitArray one, BitArray two) => !(one == two);
/// <summary>
/// Compiles the binary sequence into the inner data structure.
/// The sequence must have the same length, as the bit-array.
/// The sequence may only be allowed contains ones or zeros.
/// </summary>
/// <param name="sequence">A string sequence of 0's and 1's.</param>
public void Compile(string sequence)
{
// precondition I
if (sequence.Length > field.Length)
{
throw new ArgumentException($"{nameof(sequence)} must be not longer than the bit array length");
}
// precondition II
ThrowIfSequenceIsInvalid(sequence);
// for appropriate scaling
var tmp = string.Empty;
if (sequence.Length < field.Length)
{
var difference = field.Length - sequence.Length;
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += sequence;
sequence = tmp;
}
// actual compile procedure.
for (var i = 0; i < sequence.Length; i++)
{
field[i] = sequence[i] == '1';
}
}
/// <summary>
/// Compiles integer number into the inner data structure.
/// Assumes: the number must have the same bit length.
/// </summary>
/// <param name="number">A positive integer number.</param>
public void Compile(int number)
{
var tmp = string.Empty;
// precondition I
if (number <= 0)
{
throw new ArgumentException($"{nameof(number)} must be positive");
}
// converts to binary representation
var binaryNumber = Convert.ToString(number, 2);
// precondition II
if (binaryNumber.Length > field.Length)
{
throw new ArgumentException("Provided number is too big");
}
// for appropriate scaling
if (binaryNumber.Length < field.Length)
{
var difference = field.Length - binaryNumber.Length;
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += binaryNumber;
binaryNumber = tmp;
}
// actual compile procedure.
for (var i = 0; i < binaryNumber.Length; i++)
{
field[i] = binaryNumber[i] == '1';
}
}
/// <summary>
/// Compiles integer number into the inner data structure.
/// The number must have the same bit length.
/// </summary>
/// <param name="number">A positive long integer number.</param>
public void Compile(long number)
{
var tmp = string.Empty;
// precondition I
if (number <= 0)
{
throw new ArgumentException($"{nameof(number)} must be positive");
}
// converts to binary representation
var binaryNumber = Convert.ToString(number, 2);
// precondition II
if (binaryNumber.Length > field.Length)
{
throw new ArgumentException("Provided number is too big");
}
// for appropriate scaling
if (binaryNumber.Length < field.Length)
{
var difference = field.Length - binaryNumber.Length;
for (var i = 0; i < difference; i++)
{
tmp += '0';
}
tmp += binaryNumber;
binaryNumber = tmp;
}
// actual compile procedure.
for (var i = 0; i < binaryNumber.Length; i++)
{
field[i] = binaryNumber[i] == '1';
}
}
/// <summary>
/// Is the opposit of the Compile(...) method.
/// </summary>
/// <returns>Returns a string representation of the inner data structure.</returns>
public override string ToString()
{
// creates return-string
return field.Aggregate(string.Empty, (current, t) => current + (t ? "1" : "0"));
}
/// <summary>
/// Gets the number of one-bits in the field.
/// </summary>
/// <returns>quantity of bits in current bit-array.</returns>
public int NumberOfOneBits()
{
// counting one-bits.
return field.Count(bit => bit);
}
/// <summary>
/// Gets the number of zero-bits in the field.
/// </summary>
/// <returns>quantity of bits.</returns>
public int NumberOfZeroBits()
{
// counting zero-bits
return field.Count(bit => !bit);
}
/// <summary>
/// To check for even parity.
/// </summary>
/// <returns>Returns True if parity is even; False otherwise.</returns>
public bool EvenParity() => NumberOfOneBits() % 2 == 0;
/// <summary>
/// To check for odd parity.
/// </summary>
/// <returns>Returns True if parity is odd; False otherwise.</returns>
public bool OddParity() => NumberOfOneBits() % 2 != 0;
/// <summary>
/// Returns a long integer representation of the bit-array.
/// Assumes the bit-array length must been smaller or equal to 64 bit.
/// </summary>
/// <returns>Long integer array.</returns>
public long ToInt64()
{
// Precondition
if (field.Length > 64)
{
throw new InvalidOperationException("Value is too big to fit into Int64");
}
var sequence = ToString();
return Convert.ToInt64(sequence, 2);
}
/// <summary>
/// Returns a long integer representation of the bit-array.
/// Assumes the bit-array length must been smaller or equal to 32 bit.
/// </summary>
/// <returns>integer array.</returns>
public int ToInt32()
{
// Precondition
if (field.Length > 32)
{
throw new InvalidOperationException("Value is too big to fit into Int32");
}
var sequence = ToString();
return Convert.ToInt32(sequence, 2);
}
/// <summary>
/// Sets all bits on false.
/// </summary>
public void ResetField()
{
for (var i = 0; i < field.Length; i++)
{
field[i] = false;
}
}
/// <summary>
/// Sets all bits on the value of the flag.
/// </summary>
/// <param name="flag">Bollean flag (false-true).</param>
public void SetAll(bool flag)
{
for (var i = 0; i < field.Length; i++)
{
field[i] = flag;
}
}
/// <summary>
/// Checks if bit-array are equal.
/// Assumes the input bit-arrays must have same length.
/// </summary>
/// <param name="obj">Bit-array object.</param>
/// <returns>Returns true if there inputs are equal otherwise false.</returns>
public override bool Equals(object? obj)
{
if (obj is null)
{
return false;
}
var otherBitArray = (BitArray)obj;
if (Length != otherBitArray.Length)
{
return false;
}
for (var i = 0; i < Length; i++)
{
if (field[i] != otherBitArray[i])
{
return false;
}
}
return true;
}
/// <summary>
/// Gets has-code of bit-array.
/// Assumes bit-array length must been smaller or equal to 32.
/// </summary>
/// <returns>hash-code for this BitArray instance.</returns>
public override int GetHashCode() => ToInt32();
private static void ThrowIfSequenceIsInvalid(string sequence)
{
if (!Match(sequence))
{
throw new ArgumentException("The sequence may only contain ones or zeros");
}
}
/// <summary>
/// Utility method foir checking a given sequence contains only zeros and ones.
/// This method will used in Constructor (sequence : string) and Compile(sequence : string).
/// </summary>
/// <param name="sequence">String sequence.</param>
/// <returns>returns True if sequence contains only zeros and ones; False otherwise.</returns>
private static bool Match(string sequence) => sequence.All(ch => ch == '0' || ch == '1');
}
C#
1
https://gitee.com/TheAlgorithms/C-Sharp.git
git@gitee.com:TheAlgorithms/C-Sharp.git
TheAlgorithms
C-Sharp
C-Sharp
master

搜索帮助