Skip to content

Instantly share code, notes, and snippets.

@aswhitehouse
Created July 14, 2018 05:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aswhitehouse/2276d811ca491dc3b0b96d372752a5fc to your computer and use it in GitHub Desktop.
Save aswhitehouse/2276d811ca491dc3b0b96d372752a5fc to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
//Using Maybe.cs
namespace ArrayStructure
{
[TestFixture]
public class Tests
{
[Test]
public void RepeatingNumber_EmptyArray_ReturnsNone()
{
Assert.False(FirstNonRepeatingNumber(new int[] {}).HasValue);
}
[Test]
public void RepeatingNumber_ArrayContainsOneValue_ReturnThatValue()
{
Assert.True(FirstNonRepeatingNumber(new[] {1}).Value == 1);
}
[Test]
public void RepeatingNumber_ArrayContains_Two_NonRepeatingNumbers_ReturnTheFirst()
{
Assert.True(FirstNonRepeatingNumber(new[] {1,2}).Value == 1);
}
[Test]
public void RepeatingNumber_ArrayContainsTwoReapeating_OneNon_ReturnNonRepeating()
{
Assert.True(FirstNonRepeatingNumber(new[] {1,1,2}).Value == 2);
}
[Test]
public void RepeatingNumber_ArrayContainsThreeRepeating_NoNon_ReturnNone()
{
Assert.False(FirstNonRepeatingNumber(new[] {1,1,2,2,3,3}).HasValue);
}
[Test]
public void RepeatingNumber_ArrayContainsManyMultipleRepeating_ReturnNon_Performs()
{
Assert.True(FirstNonRepeatingNumber(new[] {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1}).Value == 2);
}
[Test]
public void RepeatingNumber_ArrayContainsUnOrderedInvariants_ReturnTwo()
{
Assert.True(FirstNonRepeatingNumber(new[] {1,3,5,3,1,2,5}).Value == 2);
}
[Test]
public void RepeatingNumber_ArrayContainsANegativeNonRepeating_ReturnNegativeThree()
{
Assert.True(FirstNonRepeatingNumber(new[] {2,2,-3,6,6}).Value == -3);
}
private Maybe<int> FirstNonRepeatingNumber(IReadOnlyList<int> ints)
{
if (!ints.Any()) return Maybe<int>.None;
var duplicates = new List<int>();
for (var i = 0; i < ints.Count; i++)
{
for (var j = i+1; j < ints.Count; j++)
{
if (ints[i] == ints[j])
{
duplicates.Add(ints[i]);
}
}
}
var nonDuplicates = ints.ToList();
if (duplicates.Count == (double)nonDuplicates.Count / 2)
{
return Maybe<int>.None;
}
foreach (var item in duplicates)
{
nonDuplicates.RemoveAll(x => x == item);
}
return Maybe<int>.Some(nonDuplicates[0]);
}
}
}
@aswhitehouse
Copy link
Author

This is even better - but still.. Linq syntax isn't that readable.

    private Maybe<int> FirstNonRepeatingNumber(IReadOnlyList<int> ints)
    {            
        var duplicates = ints.GroupBy(x => x)
            .Where(g => g.Count() == 1)
            .Select(y => y.Key)
            .ToList();

        return duplicates.Count != 0 ? Maybe<int>.Some(duplicates[0]) : Maybe<int>.None;
    }

@jbrains
Copy link

jbrains commented Jul 25, 2018

I don't know the significance of Key here, but should it be Value? I'm literally just guessing based on the words and what I've seen in other libraries. I guess GroupBy().Where(Count == 1) creates a tuple of pairs that may 2 to the collection of 2s and 6 to the collection of 6s. Am I even close? In that case, Key makes sense. With my limited knowledge of LINQ, I'd leave a comment.

A nicer library would make the last line easier. In Haskell, for example, there is the function head which turns a list of Ts into Maybe a T, implemented exactly this way: return the first element of the list or Nothing if there isn't one. Maybe IReadOnlyList has such a beast? If not, then I'd extract that to a function and call it Head.

A question: how do you know that GroupBy() guarantees that the groupings appear in that List in the same sequence as the corresponding numbers in the original List? Do you just know it? Is it part of the actual contract of GroupBy()? or is it an accident of how GroupBy() is implemented right now? I came by this question merely by noting that I see no words in this implementation that appear to attempt to preserve this property. (It might just be common knowledge that GroupBy() works this way. I don't know.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment