From b26b2e5d788bf661cddf483f69439d581afc664f Mon Sep 17 00:00:00 2001 From: Mathias Soeken Date: Wed, 23 Sep 2020 12:49:43 +0200 Subject: [PATCH] Array function `Unique`. --- Standard/src/Arrays/Unique.qs | 59 ++++++++++++++++++++++++++++ Standard/tests/Arrays/UniqueTests.qs | 25 ++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 Standard/src/Arrays/Unique.qs create mode 100644 Standard/tests/Arrays/UniqueTests.qs diff --git a/Standard/src/Arrays/Unique.qs b/Standard/src/Arrays/Unique.qs new file mode 100644 index 00000000000..ea588a399eb --- /dev/null +++ b/Standard/src/Arrays/Unique.qs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Arrays { + /// # Summary + /// Returns a new array that has no equal adjacent elements. + /// + /// # Description + /// Given some array of elements and a function to test equality, this + /// function returns a new array in which the relative order of elements + /// is kept, but all adjacent elements which are equal are filtered to + /// just a single element. + /// + /// # Type Parameters + /// ## 'T + /// The type of each element of `array`. + /// + /// # Input + /// ## equal + /// A function that compares two elements such that `a` is considered to + /// be equal to `b` if `equal(a, b)` is `true`. + /// ## array + /// The array to be filtered for unique elements. + /// + /// # Output + /// Array with no equal adjacent elements. + /// + /// # Remarks + /// If there are multiple elements that are equal but not next to each other, + /// there will be multiple occurrences in the output array. Use this function + /// together with `Sorted` to get an array with overall unique elements. + /// + /// # Example + /// ```Q# + /// let unique1 = Unique(EqualI, [1, 1, 3, 3, 2, 5, 5, 5, 7]); + /// // same as [1, 3, 2, 5, 7] + /// let unique2 = Unique(EqualI, [2, 2, 1, 1, 2, 2, 1, 1]); + /// // same as [2, 1, 2, 1]; + /// let unique3 = Unique(EqualI, Sorted(LessThanOrEqualI, [2, 2, 1, 1, 2, 2, 1, 1])); + /// // same as [1, 2]; + /// ``` + function Unique<'T>(equal : (('T, 'T) -> Bool), array : 'T[]) : 'T[] { + if (Length(array) == 0) { + return new 'T[0]; + } + + mutable unique = ConstantArray(Length(array), Head(array)); + mutable count = 1; + + for (elem in Rest(array)) { + if (not equal(elem, unique[count - 1])) { + set unique w/= count <- elem; + set count += 1; + } + } + + return unique[0..count - 1]; + } +} diff --git a/Standard/tests/Arrays/UniqueTests.qs b/Standard/tests/Arrays/UniqueTests.qs new file mode 100644 index 00000000000..4309359bcf8 --- /dev/null +++ b/Standard/tests/Arrays/UniqueTests.qs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Arrays { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Logical; + + @Test("QuantumSimulator") + operation UniqueInts() : Unit { + AllEqualityFactI(Unique(EqualI, [0, 0, 1, 2, 2, 3, 4, 5, 5, 8, 42, 42, 39]), [0, 1, 2, 3, 4, 5, 8, 42, 39], "Data is not unique"); + AllEqualityFactI(Unique(EqualI, [0, 1, 1, 0, 0, 1, 1, 0]), [0, 1, 0, 1, 0], "Data is not unique"); + AllEqualityFactI(Unique(EqualI, Sorted(LessThanOrEqualI, [2, 2, 1, 1, 2, 2, 1, 1])), [1, 2], "Sorted data is not unique"); + } + + @Test("QuantumSimulator") + operation UniqueDoubles() : Unit { + let unique = Unique(EqualD, [1.1, 1.1, 2.2, 2.2, 2.2, 3.3, 0.5, 42.0]); + EqualityFactI(Length(unique), 5, "Unexpected length of unique data"); + Fact(unique[0] == 1.1, "Unexpected element in unique data"); + Fact(unique[1] == 2.2, "Unexpected element in unique data"); + Fact(unique[2] == 3.3, "Unexpected element in unique data"); + Fact(unique[3] == 0.5, "Unexpected element in unique data"); + Fact(unique[4] == 42.0, "Unexpected element in unique data"); + } +}