-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBestShuffle.cs
60 lines (52 loc) · 2.17 KB
/
BestShuffle.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System.Collections.Generic;
using System.Linq;
namespace CyberDojo.BestShuffle
{
public sealed record LetterCount(char Letter, int Count, int LastIndex = -1);
public sealed record FindBestModel(
char LetterInQuestion,
IEnumerable<char> UsedLetters,
IEnumerable<LetterCount> SelectionPool);
public class BestShuffle
{
public string Shuffle(string s)
{
var pool = GetLetterCounts(s);
var shuffled = new char[s.Length];
for (var index = 0; index < s.Length; index++)
{
var bestReplacement = GetNextBest(new FindBestModel(s[index], shuffled, pool));
shuffled[index] = bestReplacement ?? s[index];
}
return string.Join("", shuffled);
}
public static List<LetterCount> GetLetterCounts(string input)
{
var chars = input.ToCharArray().ToList();
return chars.GroupBy(x => x)
.Select(x => new LetterCount(x.Key, x.Count(), x.Count() == 1 ? chars.LastIndexOf(x.Key) : -1))
.OrderByDescending(x => x.Count).ThenByDescending(x => x.LastIndex).ToList();
}
public char? GetNextBest(FindBestModel model)
{
var poolWithoutLetterInQuestion =
model.SelectionPool.Where(x => x.Letter != model.LetterInQuestion);
var poolWithRemaining = RemoveUsedUpLetter(poolWithoutLetterInQuestion, model.UsedLetters);
return poolWithRemaining.FirstOrDefault()?.Letter;
}
private IEnumerable<LetterCount> RemoveUsedUpLetter(
IEnumerable<LetterCount> poolWithoutLetterInQuestion,
IEnumerable<char> modelUsedLetters)
{
return poolWithoutLetterInQuestion.Select(x =>
new LetterCount(x.Letter, x.Count - modelUsedLetters.Count(c => c == x.Letter)
)).Where(x => x.Count > 0).ToList();
}
public string Print(string original)
{
var shuffled = Shuffle(original);
var score = original.Where((t, i) => t == shuffled[i]).Count();
return $@"{original}, {shuffled}, {score}";
}
}
}