using System.Collections; namespace Numbers.NumberString; /// /// Represents a string consisting of digits and letters intermixed /// /// /// public sealed class NumberString : IEnumerable, IComparable { private readonly string _text; private int? _numericValue; /// /// Creates a new instance of based on the given text. /// As a simplification, the text is assumed to be a valid number string. /// /// A string containing digits and letters public NumberString(string text) { _text = text; string digitsOnly = new string(text.Where(char.IsDigit).ToArray()); _numericValue = digitsOnly.Length > 0 ? int.Parse(digitsOnly) : 0; } /// /// Gets the numeric value contained in the number string /// public int NumericValue => _numericValue ?? 0; /// /// Gets the digit at the given index. /// If the index is out of range, -1 is returned. /// /// Digit index public int this[int index] { get { string numberString = _numericValue.HasValue ? _numericValue.Value.ToString() : string.Empty; if (index < 0 || index >= numberString.Length || numberString == string.Empty) { return -1; } return GetDigit(numberString[index]); static int GetDigit(char c) => c - '0'; } } public int CompareTo(NumberString? other) { if (ReferenceEquals(this, other)) { return 1; } return NumericValue.CompareTo(other?.NumericValue); } public IEnumerator GetEnumerator() => new DigitEnumerator(_text); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public override bool Equals(object? obj) { if (obj is not NumberString numberString) { return false; } return numberString._numericValue == _numericValue; } public override int GetHashCode() => _numericValue?.GetHashCode() ?? 0; public static bool operator >(NumberString a, NumberString b) => a.CompareTo(b) > 0; public static bool operator <(NumberString a, NumberString b) => a.CompareTo(b) < 0; public static bool operator ==(NumberString a, NumberString b) => a?.Equals(b) ?? ReferenceEquals(b, null); public static bool operator !=(NumberString a, NumberString b) => !(a == b); }