using System.Threading.Tasks.Dataflow;
using System.Collections.Generic;
public static void Main()
Console.WriteLine("Fetching The Iliad of Homer to find reversed words");
var downloadString = new TransformBlock<string, string>(uri =>
Console.WriteLine($"{DateTime.Now}: Downloading '{0}'...", uri);
var data = new HttpClient().GetStringAsync(uri).ConfigureAwait(false).GetAwaiter().GetResult();
Console.WriteLine($"{DateTime.Now}: Downloaded '{0}'...", uri);
var createWordList = new TransformBlock<string, string[]>(text =>
Console.WriteLine("Creating word list...");
char[] tokens = text.Select(c => char.IsLetter(c) ? c : ' ').ToArray();
text = new string(tokens);
return text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var filterWordList = new TransformBlock<string[], string[]>(words =>
Console.WriteLine("Filtering word list...");
.Where(word => word.Length > 3)
var findReversedWords = new TransformManyBlock<string[], string>(words =>
Console.WriteLine("Finding reversed words...");
var wordsSet = new HashSet<string>(words);
return from word in words.AsParallel()
let reverse = new string(word.Reverse().ToArray())
where word != reverse && wordsSet.Contains(reverse)
var printReversedWords = new ActionBlock<string>(reversedWord =>
Console.WriteLine("Found reversed words {0}/{1}",
reversedWord, new string(reversedWord.Reverse().ToArray()));
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
downloadString.LinkTo(createWordList, linkOptions);
createWordList.LinkTo(filterWordList, linkOptions);
filterWordList.LinkTo(findReversedWords, linkOptions);
findReversedWords.LinkTo(printReversedWords, linkOptions);
downloadString.Post("http://www.gutenberg.org/files/6130/6130-0.txt");
downloadString.Complete();
printReversedWords.Completion.Wait();