I have managed to match the groups as follows using the expression,
\([^\)]*\)
Example strings are,
s11(h 1 1 c)(h 1 1 c) x="" y="" z="" phi="" theta=""
e(45,10,h 1 1 c,1,cross,max) x="" y="" z="" phi="" theta=""
With the above expression I can match (h 1 1 c)(h 1 1 c) and (45,10,h 1 1 c,1,cross,max)
But I want to capture the starting string s11 and e along with (h 1 1 c)(h 1 1 c) and (45,10,h 1 1 c,1,cross,max)
Asking for length until first occurence is the same as asking of index of first occurence.
No need for regular expressions here, as stated in comments, method returning index of first occurence will suffice:
var lengthOfSubstring = "rxx(a 0 0 b)(a 0 0 b)".IndexOf(')'); // returns 11
if( lengthOfSubstring < 0 )
{
// character not found within the string, so the substring doesn't exist
}
Related
I’m having an issue with an algorithm I’m trying to implement in C# (the language doesn't matter much I guess).
Let’s say I have a list that could be of any length..for example:
var maxNumbers = new List<int>{5,3,2}();
The numbers in the list represent the maximum value of each entry. For example, the first entry means that it can be any number between 1 and 5 (5 is included).
Now, I want to print all combinations of every possible value for each entry in the list.
To explain:
The first number in the list is 5, so the possible values are 1,2,3,4,5
The second number in the list is 3, so the possible values
are 1,2,3
The last number in the list is 2, so the possible values
are 1,2
My algorithm should print something like:
1-1-1
1-1-2
1-2-1
1-2-2
1-3-1
1-3-2
1-2-1
etc.
I tried to implement this using recursion but wasn't able to get it. Here is my code:
void Iterate(List<int> numbers)
{
if (numbers.Count == 0)
{
Console.WriteLine("");
return;
}
int number = numbers[0];
for (int i = 1; i <= number; i++)
{
Console.WriteLine($"{i} ");
Iterate(numbers.Where((v, index) => index != 0).ToList());
}
}
Can anyone provide insights?
A non recursive approach;
We use Select(Enumerable.Range) to turn your list of maxes into a list of list of ints representing all the numbers..
Then we repeatedly use SelectMany to add another level to the list. SelectMany expects to be fed an enumerable. In the first instance there is only one item in combos, which gets crossed with 5 items from the first entry in ints, so SelectMany produces 5 items.
Second time round SelectMany effectively thinks it's expanding a "5 lists of 3 items" into a "list of 15 items". Third time round SelectMany thinks it's expanding a "15 lists of 2 items" into a "list of 30 items"...
public static string[] Combine(IEnumerable<int> maxes)
{
var ints = maxes.Select(max => Enumerable.Range(1, max));
IEnumerable<string> combos = new[] { "" };
foreach (var i in ints)
{
combos = combos.SelectMany(r => i.Select(x => r + (r == "" ? "" : "-") + x));
}
return combos.ToArray();
}
This answer fixes your code, the crucial problem with which, for me, was that the solution didn't carry any memory of where it had got to so far with making the output, so there isn't any way for iterate to repeat the earlier loop outputs
Here's the fixed code:
static void Iterate(List<int> numbers, string sofar)
{
if (numbers.Count == 0)
{
Console.WriteLine(sofar);
return;
}
for (int i = 1; i <= numbers[0]; i++)
{
Iterate(numbers.Skip(1).ToList(), sofar + i + " ");
}
}
Your code in the question hs a bit of a typo in that it does a WriteLine in the for loop which really messed up the output. Removing that to just Write you get:
1 1 1
2
2 1
2
3 1
2
2 1 1
2
2 1
2
3 1
2
3 1 1
2
2 1
2
3 1
2
4 1 1
2
2 1
2
3 1
2
5 1 1
2
2 1
2
3 1
2
If I add some spaces to change the alignment:
1 1 1
2 --> it's 1 1 2
2 1 --> it's 1 2 1
2 --> it's 1 2 2 etc
3 1
2
2 1 1
2
2 1
2
3 1
2
3 1 1
2
2 1
2
3 1
2
...
You can see it's nearly there, in that it's printing the number that changes each time, it's just lost any memory of what to print in terms of the numbers that haven't changed. The altered code passes the "string we generated so far" and devolves responsibility for printing it to just the if. Each time the loop calls Iterate it passes the string built so far so it keeps that memory of where it got up to
I have an "infinite" 2D grid and I want to detect closed/complete "structures" - areas of any shape which are enclosed on all sides. However, I need to identify each individual closed circuit - including the larger shape, if any.
In researching this, I've discovered the cycle detection algorithm, but I don't see a clean/efficient way to separate the larger circuit from the smaller ones.
For example given the following two "complete" structures:
0 1 1 1 0
0 1 0 1 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 1 1
0 1 0 1 0 1
0 1 1 1 1 1
The first is a single cell enclosed by 8 "walls". The cycle detection makes it trivial to detect this.
The second example consists of two copies of example one but they share a wall. There are three separate circuits I care about - the left room, the right room, and the overall structure.
Multiple passes of a cycle algorithm might work, but I'd have to be sure I'm not retracing an already-found shape.
I've also looked at the flood fill algorithm, but it seems like it makes the assumption you already know a point inside the bounded area. With an infinite 2D grid I'd need a size limit to force it to give up if it's not in a valid structure.
Are there solutions I'm missing or have I missed something with my thinking?
I will only do this "check" when a boundary value is added. Using the example above, if I change any 0 -> 1, a new cycle has potentially been created and I'll run the logic. I do not care about identifying separate structures and will always have an origin coordinate.
I've been studying the solutions posted here but they're all based on already knowing which nodes are connected to other nodes. I've already toyed with logic that identifies each individual "line" and I can keep going from there, but it feels redundant.
I would do this like this:
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 0 1 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
fill the background with 2
to determine if you are in background just cast a ray and count consequent zeores. Once you find location where the ray length is bigger then circuit size limit you got your start point.
[0]0-0-0-0-0-0
0 1 1 1 1 1 0
0 1 0 1 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1 0 1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
Do not use unbound recursive flood fills for this !!! because for "infinite" area you will stack overflow. You can limit the recursion level and if reached instead of recursion add point to some que for further processing latter. This usually speeds thing up a lot and limits the stack usage...
find first 0
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1[0]1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
flood fill it with 3
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1 3 1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
select all 1 near 3
this is your circuit. If you remember the bbox while filling #3 then you need to scan only area enlarged by one cell on each side... Selected cells are your circuit.
2 2 2 2 2 2 2
2 * * * 1 1 2
2 * 3 * 0 1 2
2 * * * 1 1 2
2 2 2 2 2 2 2
flood fill 3 with 2
this will avoid of usage already processed circuits
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1 2 1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
loop #2 while any 0 found
change all 2 back to 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 0 1 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
It is a contours finding problem.
One of possible algorithms is described by Satoshi Suzuki and Keiichi Abe in their paper called Topological Structural Analysis of Digitized Binary Images by Border Following in 1985. And it is not trivial. But you can use OpenCV, it's cv2.findContours() function implements this algorithm.
If you choose to use OpenCV, the solution is easy. You extract contours alongside it's hierarchy. Contours that has at least one child (hole) and their child contours are objects that you are looking for. Example using managed OpenCV wrapper called OpenCvSharp:
byte[,] a = new byte[7, 6]
{
{ 0, 1, 1, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 1 },
{ 0, 1, 0, 1, 0, 1 },
{ 0, 1, 1, 1, 1, 1 }
};
// Clone the matrix if you want to keep original array unmodified.
using (var mat = new MatOfByte(a.GetLength(0), a.GetLength(1), a))
{
// Turn 1 pixel values into 255.
Cv2.Threshold(mat, mat, thresh: 0, maxval: 255, type: ThresholdTypes.Binary);
// Note that in OpenCV Point.X is a matrix column index and Point.Y is a row index.
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(mat, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxNone);
for (var i = 0; i < contours.Length; ++i)
{
var hasHole = hierarchy[i].Child > -1;
if (hasHole)
{
var externalContour = contours[i];
// Process external contour.
var holeIndex = hierarchy[i].Child;
do
{
var hole = contours[holeIndex];
// Process hole.
holeIndex = hierarchy[holeIndex].Next;
}
while (holeIndex > -1);
}
}
}
You can try a list of points and verify the ones that are linked.
class PointList : List<Point>
{
/// <summary>
/// Adds the point to the list and checks for perimeters
/// </summary>
/// <param name="point"></param>
/// <returns>Returns true if it created at least one structure</returns>
public bool AddAndVerify(Point point)
{
this.Add(point);
bool result = LookForPerimeter(point, point, point);
Console.WriteLine(result);
return result;
}
private bool LookForPerimeter(Point point, Point last, Point original)
{
foreach (Point linked in this.Where(p =>
(p.X == point.X -1 && p.Y == point.Y)
|| (p.X == point.X + 1 && p.Y == point.Y)
|| (p.X == point.X && p.Y == point.Y - 1)
|| (p.X == point.X && p.Y == point.Y + 1)
))
{
if (!linked.Equals(last))
{
if (linked == original) return true;
bool subResult = LookForPerimeter(linked, point, original);
if (subResult) return true;
}
}
return false;
}
}
This code is intentended as a starting point, it probably has bugs and does not account for perimeters without 0 inside
Example of use:
class Program
{
static void Main(string[] args)
{
PointList list = new PointList();
list.AddAndVerify(new Point() { X = 0, Y = 0 }); //returns false
list.AddAndVerify(new Point() { X = 0, Y = 1 }); //returns false
list.AddAndVerify(new Point() { X = 0, Y = 2 }); //returns false
list.AddAndVerify(new Point() { X = 1, Y = 2 }); //returns false
list.AddAndVerify(new Point() { X = 2, Y = 2 }); //returns false
list.AddAndVerify(new Point() { X = 2, Y = 1 }); //returns false
list.AddAndVerify(new Point() { X = 2, Y = 0 }); //returns false
list.AddAndVerify(new Point() { X = 1, Y = 0 }); //returns True
}
}
Coming from a graph-theoretic view of the problem, you can interpret every 0 of your map as a node, neighboring 0s are connected with an edge. It sounds to me like what you want to do is compute the connected components of this graph (and maybe their connectivity by 1 values, to find 'neighboring rooms' of the same structure)
If you only want to compute this information once, a straightforward approach using a union-find data structure should suffice, where you apply union once per edge.
If you want to edit your map dynamically, the best approach based on the graph model would probably be some dynamic data structure that supports split or de-union operations, see for example here or here
I had a similar problem trying to find all circles inside a 2D street map graph (given as a SVG file). As you state I too could not find an algorithm for that.
I found the following solution though.
Assumptions
Grid Layout:
Each '1' in the grid is in one of the following states (or an homomorphism of that):
1. 0 2. 0 3. 0 4. 0 5. 0 6. 1
0 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1
0 0 1 0 1 1
But only example 3 to 6 make a sense for a connected wall, as in a connected wall each '1' has at least two '1's in its neighborhood.
Example 3 indicates a corner. This corner holds at most one structure.
Example 4 indicates a straight line. It can be the wall of zero, one or two structures.
Example 5 indicates a t-wall. It can be the wall of zero, one, two or three structures.
Example 6 indicates a cross-wall. It can be the corner of zero, one, two, three or four structures.
The Algorithm
The idea
Assuming the above, the algorithm works by finding a '1' and doing a depth first search, to mark all connected '1's. The traversed '1's are only marked, if the depth first search arrives at the starting position or at an already marked position.
The implementation
I will post an implementation the next few days for that one.
Re-posting my solution with an explanation and some code.
It took a few days before any answers were posted I tried to find a solution and believe I've found one that works very well for my needs.
Since I always have a starting point, I walk the edges from that point and fork the list of visited points each time the path "branches" off - allowing me to find multiple cycles.
Given a 2D grid with either a 1 or 0 in a cell:
0 1 1 1 1 1
0 1 0 1 0 1
0 1 1 1 1 1
Starting from a cell I already know is a 1, I begin my search:
For the current valid point:
add it to a "visited" list
look for any valid neighbors (except for last point I visited, to avoid infinite loops)
For each valid neighbor:
clone the list of points which is our "trail" to this new point
call step 1 with the neighbor point
Cloning allows each "branch" to become a unique cycle without mixing points.
I haven't run any performance profiling, but it works very well given the examples I've thrown at it.
It's possible to give me two copies of a cycle. For example, if I start in the NW corner, cells to the east and south both have valid paths to follow. They're both treated as new paths and followed, but they're just mirror images of the same cycle. For now, I just prune cycles like these - they have exactly the same points, as long as you ignore their order.
There's also a bit of filtering involved - like for problem #1 and trimming points if the end point matches a visited point that wasn't where we started. I think that's pretty much unavoidable and isn't a big deal but if there was a clean way to avoid that I would. I can't know what "begins" a new cycle until I've found it though, so you know, linear time flow strikes again.
public class CycleDetection {
// Cache found cycles
List<Cycle> cycles = new List<Cycle>();
// Provide public readonly access to our cycle list
public ReadOnlyCollection<Cycle> Cycles {
get { return new ReadOnlyCollection<Cycle>(cycles); }
}
// Steps/slopes that determine how we iterate grid points
public Point[] Steps = new Point[] {
new Point(1, 0),
new Point(0, 1),
new Point(-1, 0),
new Point(0, -1)
};
// Cache our starting position
Point origin;
// Cache the validation function
Func<Point, bool> validator;
public CycleDetection(Point origin, Func<Point, bool> validator) {
this.origin = origin;
this.validator = validator;
this.Scan();
}
// Activate a new scan.
public void Scan() {
cycles.Clear();
if (validator(origin)) {
Scan(new List<Point>(), origin);
}
}
// Add a cycle to our final list.
// This ensures the cycle doesn't already exist (compares points, ignoring order).
void AddCycle(Cycle cycle) {
// Cycles have reached some existing point in the trail, but not necessarily
// the exact starting point. To filter out "strands" we find the index of
// the actual starting point and skip points that came before it
var index = cycle.Points.IndexOf(cycle.Points[cycle.Points.Count - 1]);
// Make a new object with only the points forming the exact cycle
// If the end point is the actual starting point, this has no effect.
cycle = new Cycle(cycle.Points.Skip(index).ToList());
// Add unless duplicate
if (!cycles.Contains(cycle)) {
cycles.Add(cycle);
}
}
// Scan a new point and follow any valid new trails.
void Scan(List<Point> trail, Point start) {
// Cycle completed?
if (trail.Contains(start)) {
// Add this position as the end point
trail.Add(start);
// Add the finished cycle
AddCycle(new Cycle(trail));
return;
}
trail.Add(start);
// Look for neighbors
foreach (var step in Steps) {
var neighbor = start + step;
// Make sure the neighbor isn't the last point we were on... that'd be an infinite loop
if (trail.Count >= 2 && neighbor.Equals(trail[trail.Count - 2])) {
continue;
}
// If neighbor is new and matches
if (validator(neighbor)) {
// Continue the trail with the neighbor
Scan(new List<Point>(trail), neighbor);
}
}
}
}
I've posted the full source here: https://github.com/OutpostOmni/OmniGraph (includes some unrelated graph utils as well)
I have a list.
1 2 3 4 5 6 7
I wish to return a list of differences (deltas) between consecutive element.
1 1 1 1 1 1
How can I do this?
I am sure there must be a simple "collections" way of doing this - but I cannot find it.
You can use Enumerable.Skip and the overload of Enumerable.Select which projects the index:
List<int> deltaList = list.Skip(1) // skip first, irrelevant
.Select((num, index) => num - list[index]) // index 0 is second number in list
.ToList();
The trick is that Skip(1) does not only skip the first number (which is desired) but also changes the indices in Select. The first number's index will be 0 but it'll refer to the second number in the list (due to Skip(1)). Therefore num - list[index] subtracts the current with the previous number.
var result = list.Zip(list.Skip(1), (x, y) => y - x);
How do I find the longest increasing sub-sequence of integers from a list of integers in C#?
You just need to break in down into a smaller problem, that of finding the length of an increasing sequence given a starting point.
In pseudo-code, that's something like:
def getSeqLen (int array[], int pos):
for i = pos + 1 to array.last_element:
if array[i] <= array[i-1]:
return i - pos
return array.last_element + 1 - pos
Then step through the array, looking at these individual sequences. You know that the sequences have to be separated at specific points since otherwise the sequences would be longer. In other words, there is no overlap of these increasing sequences:
def getLongestSeqLen (int array[]):
pos = 0
longlen = 0
while pos <= array.last_element:
len = getSeqLen (array, pos)
if len > longlen:
longlen = len
pos = pos + len
return longlen
By way of graphical explanation, consider the following sequence:
element#: 0 1 2 3 4 5 6 7 8 9 10 11 12
value: 9 10 12 7 8 9 6 5 6 7 8 7 8
^ ^ ^ ^ ^
In this case, the ^ characters mark the unambiguous boundaries of a subsequence.
By starting at element 0, getSeqLen returns 3. Since this is greater than the current longest length of 0, we save it and add 3 to the current position (to get 3).
Then at element 3, getSeqLen returns 3. Since this is not greater than the current longest length of 3, we ignore it but we still add 3 to the current position (to get 6).
Then at element 6, getSeqLen returns 1. Since this is not greater than the current longest length of 3, we ignore it but we still add 1 to the current position (to get 7).
Then at element 7, getSeqLen returns 4. Since this is greater than the current longest length of 3, we save it and add 4 to the current position (to get 11).
Then at element 11, getSeqLen returns 2. Since this is not greater than the current longest length of 4, we ignore it but we still add 2 to the current position (to get 13).
Then, since element 13 is beyond the end, we simply return the longest length found (4).
You want what is known as patience sorting. It can compute the length, and find the sequence.
Here is my solution:
public static int[] FindLongestSequence(int[] seq)
{
int c_min = 0, c_len = 1;
int min = 1, len = 0;
for (int i = 0; i < seq.Length - 1; i++)
{
if(seq[i] < seq[i+1])
{
c_len++;
if (c_len > len)
{
len = c_len;
min = c_min;
}
} else
{
c_min = i+1;
c_len = 1;
}
}
return seq.Skip(min).Take(len).ToArray();
}
}
Create three variables: two integer lists and an integer. Set the integer initially to int.MinValue. As you iterate the list, if the current value is greater than your integer variable, append it to list 1. When this is not the case, clear list 1, but first copy list 1 to list 2 if it is longer than list 2. When you finish the sequence, return the longer list (and it's length).
As a performance tip too, if your current longest substring is longer than the remainder of the string, you can call it quits there!
I have solved this in O(n log n) time here:
http://www.olhovsky.com/2009/11/extract-longest-increasing-sequence-from-any-sequence/
An item in the final sequence, used to form a linked list.
class SeqItem():
val = 0 # This item's value.
prev = None # The value before this one.
def __init__(self, val, prev):
self.val = val
self.prev = prev
Extract longest non-decreasing subsequence from sequence seq.
def extract_sorted(seq):
subseqs = [SeqItem(seq[0], None)] # Track decreasing subsequences in seq.
result_list = [subseqs[0]]
for i in range(1, len(seq)):
result = search_insert(subseqs, seq[i], 0, len(subseqs))
# Build Python list from custom linked list:
final_list = []
result = subseqs[-1] # Longest nondecreasing subsequence is found by
# traversing the linked list backwards starting from
# the final smallest value in the last nonincreasing
# subsequence found.
while(result != None and result.val != None):
final_list.append(result.val)
result = result.prev # Walk backwards through longest sequence.
final_list.reverse()
return final_list
Seq tracks the smallest value of each nonincreasing subsequence constructed.
Find smallest item in seq that is greater than search_val.
If such a value does not exist, append search_val to seq, creating the
beginning of a new nonincreasing subsequence.
If such a value does exist, replace the value in seq at that position, and
search_val will be considered the new candidate for the longest subseq if
a value in the following nonincreasing subsequence is added.
Seq is guaranteed to be in increasing sorted order.
Returns the index of the element in seq that should be added to results.
def search_insert(seq, search_val, start, end):
median = (start + end)/2
if end - start < 2: # End of the search.
if seq[start].val > search_val:
if start > 0:
new_item = SeqItem(search_val, seq[start - 1])
else:
new_item = SeqItem(search_val, None)
seq[start] = new_item
return new_item
else: # seq[start].val <= search_val
if start + 1 < len(seq):
new_item = SeqItem(search_val, seq[start])
seq[start + 1] = new_item
return new_item
else:
new_item = SeqItem(search_val, seq[start])
seq.append(new_item)
return new_item
if search_val < seq[median].val: # Search left side
return search_insert(seq, search_val, start, median)
else: #search_val >= seq[median].val: # Search right side
return search_insert(seq, search_val, median, end)
Use the code like so:
import random
if __name__ == '__main__':
seq = []
for i in range(100000):
seq.append(int(random.random() * 1000))
print extract_sorted(seq)
One way to do it is with help from the Aggregate method:
var bestSubSequence = listOfInts.Skip(1).Aggregate(
Tuple.Create(int.MinValue, new List<int>(), new List<int>()),
(curr, next) =>
{
var bestList = curr.Item2.Count > curr.Item3.Count ? curr.Item2 : curr.Item3;
if (curr.Item1 > next)
return Tuple.Create(next, new List<int> {next}, bestList);
curr.Item2.Add(next);
return Tuple.Create(next, curr.Item2, bestList);
}).Item3;
It did not turn out as well as I had hoped when I started writing it and I think the other more direct ways to do it is better and easier to follow, but it might give a different perspective on how these kinds of tasks can be solved.
Friends, there is yet another scenario to solve. I am working it out without applying Linq.But I hope it is good opportunity for me to learn Linq if you share your code in Linq.
It is know as FLAMES
F - Friend
L - Lover
A - Admirer
M - Marry(Husband)
E - Enemy
S - Sister
Problem description:
Two names will be given (male, female).We have to strike out the common letters from both names. Then we have to count the number of remaining letters after striking out the common characters from both names. Finally we have to iterate the string FLAMES and striking out the letters in FLAMES until we will reach single character left. The remaining single character shows the relationship. I will explain the process more details in the following example.(Ignore cases and spaces).
Example :
Step 1
Male : Albert
Female : Hebarna
Letters “a”, “e” ,”b” are common in both names.
( Strike those letters from both string , even the name “Hebarna” contains two “a” you are allowed to strike single “a” from both string because The name “Albert” has only single “a”).
The resultant string is
Male : $ l $ $ r t
Female: H $ $ $ r n a
Step 2:
Count the remaining letters from both strings.
Count : 7
Step 3:
Using the count we have to iterate the string “FLAMES” in the following manner
F L A M E S
1 2 3 4 5 6
7
(Here the count 7 ends at F ,so strike F)
you will get
$ L A M E S
(Again start your count from immediate next letter (it should not already be hit out) if it is the last letter (“S”) then start from first letter “F” if ‘F” is not already hit out.
$ L A M E S
(igonre) 1 2 3 4 5
(ignore) 6 7
During counting never consider hit out letters.
$ L $ M E S
1 2 3
ignore 4 ignore 5 6 7
"s" will be hit out.
$ L $ M E $
ignore 1 ignore 2 3
4 ignore 5 6
7
"L" will be hit out
$ $ $ M E $
ignore 1 2 ignore
ignore ignore ignore 3 4 ignore
5 6
7
Finally "M" will be hit out. Then only remaining letter is "E" So albert is enemy to herbana.
Update :
Lettter "r" is also common in both names.I forgor to hit it out.Anyhow the process is same as explained.Thanks for pointing it out.
Step1 and Step2
var firstLookup = firstName.ToLookup(c => c.ToLower());
var secondLookup = secondName.ToLookup(c => c.ToLower());
var allChars = firstLookup.Keys.Union(secondLookup.Keys);
int count =
(
from c in allChars
let firstCount = firstLookup[c].Count()
let secondCount = secondLookup[c].Count()
select
firstCount < secondCount ? secondCount - firstCount :
firstCount - secondCount
).Sum()
Step3 (untested)
List<char> word = "FLAMES".ToList();
while (word.Count > 1)
{
int wordCount = word.Count;
int remove = (count-1) % wordCount;
word =
word.Select( (c, i) => new {c, i =
i == remove ? 0 :
i < remove ? i + wordCount + 1 :
i})
.OrderBy(x => x.i)
.Select(x => x.c)
.Skip(1)
.ToList();
}
char result = word.Single();
var count = male.Length + female.Length - male.Intersect( female ).Count();
while (flames.Length > 1)
{
flames = string.Join( '', flames.Where( (c,i) => i != (count % flames.Length) -1 ).ToArray() );
}
That last calculation part that iterates through the flames-letters and removing one after another can be precalculated.
public static Char GetChar(int diff) {
var idx = (diff - 1) % 60;
return "efefmeaelmaafmfaflefefeemsasamfmfallslslesmsasmmaelmlaslslfs"[idx];
}
Some things can be done without linq... unless I totally messed something up.