Created
July 1, 2016 11:30
-
-
Save amoerie/8990c4543b5a8e214ff3066ca4bd7bf6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
namespace Wordlist { | |
public class Program { | |
public static void Main(string[] args) { | |
IList<IWord> words = ReadWords().ToList(); | |
var stopwatch = new Stopwatch(); | |
stopwatch.Start(); | |
const int requestedLength = 6; | |
// index all words by their length | |
ILookup<int, IWord> wordsByLength = words.ToLookup(w => w.Length); | |
// create a set of all words of the desired total length. This makes "Contains" checks blazing fast | |
var wordEqualityComparer = new WordEqualityComparer(); | |
ISet<IWord> wordsOfRequestedLength = new HashSet<IWord>(wordsByLength[requestedLength], wordEqualityComparer); | |
var combinations = Enumerable.Range(1, requestedLength - 1) | |
// start with all words of length "i" | |
.SelectMany(i => wordsByLength[i] | |
// create a combination with all other words of length "total - i" | |
.SelectMany(word => wordsByLength[requestedLength - i].Select(otherWord => new WordCombination(word, otherWord))) | |
// verify that combination is in the list | |
.Where(combination => wordsOfRequestedLength.Contains(combination) ) | |
) | |
// materialize the results | |
.ToList(); | |
stopwatch.Stop(); | |
Console.WriteLine("Combinations: " + combinations.Count); | |
Console.WriteLine("Time taken: " + stopwatch.ElapsedMilliseconds + "ms"); | |
Console.WriteLine("Press [enter] to see all combinations"); | |
Console.ReadLine(); | |
Console.WriteLine(string.Join(Environment.NewLine, combinations)); | |
Console.ReadLine(); | |
} | |
private static IEnumerable<IWord> ReadWords() { | |
var assembly = Assembly.GetExecutingAssembly(); | |
var resourceName = "Wordlist.wordlist.txt"; | |
using (var stream = assembly.GetManifestResourceStream(resourceName)) { | |
using (var reader = new StreamReader(stream, Encoding.UTF8)) { | |
string line; | |
while ((line = reader.ReadLine()) != null) { | |
yield return new Word(line); | |
} | |
} | |
} | |
} | |
} | |
} | |
namespace Wordlist { | |
public interface IWord { | |
string Content { get; } | |
int Length { get; } | |
} | |
} | |
namespace Wordlist { | |
public class Word : IWord { | |
public string Content { get; } | |
public int Length { get; } | |
public Word(string content) { | |
Content = content; | |
Length = content.Length; | |
} | |
} | |
} | |
namespace Wordlist { | |
public class WordCombination : IWord { | |
private IWord Left { get; } | |
private IWord Right { get; } | |
public int Length { get; } | |
public string Content { get; } | |
public WordCombination(IWord left, IWord right) { | |
Left = left; | |
Right = right; | |
Content = left.Content + right.Content; | |
Length = Content.Length; | |
} | |
public override string ToString() { | |
return $"{Left.Content} + {Right.Content} = {Content}"; | |
} | |
} | |
} | |
using System; | |
using System.Collections.Generic; | |
namespace Wordlist { | |
public class WordEqualityComparer : IEqualityComparer<IWord> { | |
public bool Equals(IWord x, IWord y) { | |
return x.Length == y.Length && string.Equals(x.Content, y.Content, StringComparison.OrdinalIgnoreCase); | |
} | |
public int GetHashCode(IWord word) { | |
return word.Content.GetHashCode(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment