165 lines
No EOL
5 KiB
Text
165 lines
No EOL
5 KiB
Text
[](https://classroom.github.com/a/XKnXJRYx)
|
|
:sectnums:
|
|
:nofooter:
|
|
:toc: left
|
|
:icons: font
|
|
:data-uri:
|
|
:source-highlighter: highlightjs
|
|
:stem: latexmath
|
|
|
|
= Int.05 -- Numbers
|
|
|
|
This is a simple training exercise without any interesting background story 😉
|
|
|
|
== `NumberString`
|
|
|
|
Given a string consisting of numbers and digits in any order and combination, the goal is to extract all numbers while preserving order.
|
|
This extraction is supposed to happen by means of enumeration.
|
|
|
|
[plantuml]
|
|
----
|
|
@startuml
|
|
hide empty methods
|
|
hide empty fields
|
|
|
|
class DigitEnumerator <<sealed>> {
|
|
-string _text [readonly]
|
|
-int _index
|
|
+DigitEnumerator(string)
|
|
}
|
|
interface IEnumerator<int> {}
|
|
class NumberString <<sealed>> {
|
|
-string _text [readonly]
|
|
-int? _numericValue
|
|
+int NumericValue [readonly]
|
|
+int this[int] [readonly]
|
|
+NumberString(string)
|
|
}
|
|
interface IEnumerable<int> {}
|
|
interface IComparable<NumberString> {}
|
|
|
|
IEnumerator <|.. DigitEnumerator
|
|
IEnumerable <|.. NumberString
|
|
IComparable <|.. NumberString
|
|
|
|
@enduml
|
|
----
|
|
|
|
=== `DigitEnumerator`
|
|
|
|
* Enumerates digits in a `NumberString`
|
|
** Example: `a3bc1jki45u` => `3`, `1`, `4`, `5`
|
|
* Ignores all non-digit characters (letters)
|
|
* Implements the enumerator pattern
|
|
|
|
=== `NumberString`
|
|
|
|
* A string containing both letters and digits
|
|
* Can be enumerated
|
|
** Using a `DigitEnumerator`
|
|
* Can be compared
|
|
** By directly implementing `IComparable` -- no comparer required
|
|
** Comparison is based on the `NumericValue`
|
|
* Has a `NumericValue` property which represents the number encoded in the string
|
|
** Example: `a3bc1jki45u` => `3145`
|
|
** This property is _cached_ => only calculate at first call!
|
|
* It additionally has an _indexer_
|
|
** Accesses only the _digits_
|
|
*** Utilizing the enumerator
|
|
** Example: `a1bc3jki45u`, assessing index 2 => `3`
|
|
* Make sure to implement all _equality_ members including operators & hash code
|
|
|
|
== `NumberFactory`
|
|
|
|
A kind of digital factory which is able to give us a _something_ (a `INumbers` instance) which provides numbers which comply to a certain condition and are within the specified range.
|
|
|
|
[plantuml]
|
|
----
|
|
@startuml
|
|
hide empty methods
|
|
hide empty fields
|
|
|
|
class EvenNumbers <<sealed>> {}
|
|
class OddNumbers <<sealed>> {}
|
|
class PrimeNumbers <<sealed>> {}
|
|
class SquareNumbers <<sealed>> {}
|
|
abstract class AbstractNumbers {
|
|
-List<long> _list;
|
|
#AbstractNumbers(long, long)
|
|
{abstract} #bool PickupNumber(long)
|
|
-void GenerateNumbers()
|
|
}
|
|
interface INumbers {
|
|
+long this[int] [readonly]
|
|
+long LowerBound [readonly]
|
|
+long UpperBound [readonly]
|
|
+int Length [readonly]
|
|
}
|
|
interface IEnumerable<long> {}
|
|
interface IEnumerator<long> {}
|
|
enum NumberType {
|
|
Even
|
|
Odd
|
|
Square
|
|
Prime
|
|
}
|
|
static class Factory {
|
|
{static} +INumbers Create(NumberType, long, long)
|
|
}
|
|
class NumbersEnumerator <<sealed>> {
|
|
-int Index
|
|
-List<long> List [readonly]
|
|
+NumbersEnumerator(List<long>)
|
|
}
|
|
|
|
AbstractNumbers <|-- EvenNumbers
|
|
AbstractNumbers <|-- OddNumbers
|
|
AbstractNumbers <|-- PrimeNumbers
|
|
AbstractNumbers <|-- SquareNumbers
|
|
INumbers <|.. AbstractNumbers
|
|
IEnumerable <|.. INumbers
|
|
IEnumerator <|.. NumbersEnumerator
|
|
|
|
@enduml
|
|
----
|
|
|
|
=== `NumbersEnumerator`
|
|
|
|
* A very straight forward implementation of an `IEnumerator` for (`long`) numbers
|
|
* `Current` should return `-1` if the position is invalid
|
|
|
|
=== `INumbers`
|
|
|
|
* Defines the lower and upper bound of the range the numbers are picked from
|
|
* Ensures that implementations will provide an indexer for accessing the n-th number fulfilling the specific condition in the range
|
|
* Allows to get the total amount of number which fulfill the requirements
|
|
* Implements `IEnumerable<long>`
|
|
** We are using `long` instead of `int` to allow for very big numbers as well 😉
|
|
|
|
=== `AbstractNumbers`
|
|
|
|
* A base class for all number generators providing some common, shared implementations
|
|
* The indexer should return `-1` for invalid index values
|
|
* Make use of the `NumbersEnumerator`
|
|
* `GenerateNumbers` internally calls `PickNumber` which will be implemented by subclasses to decide which numbers to pick -- this check will be done for each number in the specified range
|
|
** Picked numbers should be stored in the list
|
|
* Hint: The constructor should call `GenerateNumbers`
|
|
|
|
=== Generator Implementations
|
|
|
|
* `EvenNumbers`: selects even numbers in the given range
|
|
* `OddNumbers`: selects odd numbers in the given range
|
|
* `PrimeNumbers`: selects prime numbers in the given range
|
|
** A simple loop-based implementation (just as we have implemented in first grade) is sufficient, but don't be overly wasteful with system resources
|
|
* `SquareNumbers`: selects square numbers in the given range
|
|
** https://en.wikipedia.org/wiki/Square_number[What is a square number]
|
|
|
|
=== `Factory`
|
|
|
|
* A static factory class which is able to create instances of `INumbers` implementations
|
|
* If an unknown `NumberType` is specified, return `null`
|
|
** Hint: to do that you'll need the `!` operator which is fine in this one case 😉
|
|
|
|
== Sample Run
|
|
|
|
image::pics/sample_run.png[Sample Run] |