I am trying to develop an algorithm in C# that can take an array list of URL's and output them in an outline numbered list.
As you can imagine I need some help. Does anyone have any suggestions on the logic to use to generate this list?
Example Output:
1 - http://www.example.com/aboutus
1.2 - http://www.example.com/aboutus/page1
1.3 - http://www.example.com/aboutus/page2
1.3.1 - http://www.example.com/aboutus/page2/page3
1.3.1.1 - http://www.example.com/aboutus/page2/page3/page4
1.3.2 - http://www.example.com/aboutus/page5/page6
1.3.2.1 - http://www.example.com/aboutus/page5/page7/page9
1.3.2.2 - http://www.example.com/aboutus/page5/page8/page10
1.4 - http://www.example.com/aboutus/page10
1.4.1 - http://www.example.com/aboutus/page10/page11
1.4.2 - http://www.example.com/aboutus/page10/page12
1.1.5 - http://www.example.com/aboutus/page13
1.1.6 - http://www.example.com/aboutus/page14
1.1.6.1 - http://www.example.com/aboutus/page14/page15
1.1.6.2 - http://www.example.com/aboutus/page14/page16
1.1.6.3 - http://www.example.com/aboutus/page14/page17
... and so on
Take a look at the System.URI class. It should have some methods and properites that should be usefull, like the segments property that splilts the uri into its segmented parts (split by slash bascially). You could create a list of the segment arrays, sort the list, then simply iterate the list adjusting the numbers depending on wether the current list index segments match the previous list index segments.
You'll probably have to strip protocol and query string parameters, so +1 to the advise to use System.URI class to handle that.
As for the printing it in tree-shape - a direct approach is to use a Dictionary<string, string> to keep association of child (key) to a parent (value).
Another way is to take advantage of List<T>.Sort, e.g. like this:
public static void Print(List<string> list)
{
var path = new Stack<string>();
var count = new Stack<int>();
path.Push("");
count.Push(0);
list.Sort(new Comparison<string>(UrlComparison));
foreach (var x in list)
{
while (!x.StartsWith(path.Peek())) { path.Pop(); count.Pop(); }
count.Push(count.Pop() + 1);
foreach(var n in count.Reverse()) Console.Write("{0}.", n);
Console.WriteLine(" {0}", x);
path.Push(x);
count.Push(0);
}
}
Unfortunately, p.campbell is right, a custom comparison is actually required here, which makes this implementation still pretty performant, but more bulky (?:-abuse warning):
public static int UrlComparison(string x, string y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
for(int n = 0; n < Math.Min(x.Length, y.Length); n++)
{
char cx = x[n], cy = y[n];
if(cx == cy) continue;
return
(cx == '/' || cx == '.' || cx == '?') ? -1 :
(cy == '/' || cy == '.' || cy == '?') ? 1 :
(cx > cy) ? 1 : -1;
}
return (x.Length == y.Length) ? 0 : (x.Length > y.Length) ? 1 : -1;
}
PS: Just to put a disclaimer, I feel that Stacks logic is consize, but a bit more complex to understand. In a long-term project, I'd stick with a child-parent dictionary.
May be this Generic Tree Collection will be helpful.
There are few Tree Collections on the Code Project: one, two.
I think you need to implement some sort of tree collection to handle the order. Because if you added a new link called http://www.example.com, that would become 1 instead of http://www.example.com/aboutus.
Then you can print the in-order traversal of the tree and it will be exceedingly simple.
Related
foreach (Point p in Snake.Body)
if (p.X == Food.Point.X && p.Y == Food.Point.Y)
{
Points++;
Food = new FoodSpawn();
Snake.Grow(Points + 4);
}
The error when I use it is = "Collection was modified; enumeration operation may not execute"
I assume that you want to find if the Snake.Body collection of Points contains the Food.Point, change your properties and then stop the loop. (Otherwise you could have serious problem in correctly traversing your collection and incrementing its size)
So, assumming that Body is an array of Point
for(int x = 0; x < Snake.Body.Length; x++)
{
Point p = Snake.Body[x];
if (p.X == Food.Point.X && p.Y == Food.Point.Y)
{
Points++;
Food = new FoodSpawn();
Snake.Grow(Points + 4);
break;
}
}
If Snake.Body is a List<Point> then we need to change the for loop to
for(int x = 0; x < Snake.Body.Count(); x++)
Or using LINQ
int cnt = Snake.Body.Count(x => x.X == Food.Point.X && p.Y == Food.Point.Y);
if(cnt != 0)
{
Points++;
Food = new FoodSpawn();
Snake.Grow(Points + 4);
}
The simplest way would be
foreach (Point p in Snake.Body.ToArray())
The problem in your case is that you're trying to work on the total number of points in the body of the snake,
foreach (Point p in Snake.Body)
but at the end of this loop (or in the middle) the points alter. They increase or decrease. Once they do, they cause this error in the enumeration. In your code, this point
Points++;
It is increasing the points, and thus triggering the error. And after this line of code,
Snake.Grow(Points + 4);
It is making the Snake object grow, to the points provided. This is the very place, where the error is. Actually not the error, but instead this is the place which in invoking the error to trigger at the next loop.
So, what you can do would be to create a simple int variable to and then work on it.
First, as mentioned, you're trying to alter your collection (making your snake grow) during an enumeration - which is not allowed, because it leaves the enumerator not knowing where to continue from or (worse) missing something that would have been added earlier in the iteration.
A better way to approach this particular case might be to perform a check, and then execute your growth logic after that check, or perform logic based in the .Any function of Linq
if(Snake.Body.Any(p => p.X == Food.Point.X && p.Y == Food.Point.Y))
{
Points++;
Food = new FoodSpawn();
Snake.Grow(Points + 4);
}
or, if you want feed to occur multiple times in the same loop (multiple foods available) use the .Where function
foreach(var p in Snake.Body
.Where(p => p.X == Food.Point.X && p.Y == Food.Point.Y)
.ToArray()) // This caches the result and avoids those pesky errors
{ ... }
This will prevent modification until enumeration
The task is to keep an array of objects untouched if input is null and, otherwise, remove the elements that are on positions specified by the input. I've got it working but I'm vastly dissatisfied with the code quality.
List<Stuff> stuff = new List<Stuff>{ new Stuff(1), new Stuff(2), new Stuff(3) };
String input = "5";
if(input == null)
return stuff;
int mask = Int32.Parse(input);
for (int i = stuff.Count - 1; i >= 0; i--)
if ((mask & (int)Math.Pow(2, i)) == 0)
stuff.RemoveAt(i);
return stuff;
The actual obtaining input and the fact that e.g. String.Empty will cause problems need not to be regarded. Let's assume that those are handled.
How can I make the code more efficient?
How can I make the syntax more compact and graspable?
Instead of the backwards running loop, you could use Linq with the following statement.
stuff = stuff.Where( (iStuff, idx) => (mask & (int)Math.Pow(2, idx)) != 0 );
Or even cooler using bitwise shit.
stuff = stuff.Where((_, index) => (mask >> index & 1) == 1);
It uses an overload of Where which can access the position in the sequence, as documented here. For a similar task, there is also an overload of Select which gives access to the index, as documented here.
Untested, but you could make an extension method that iterates the collection and filters, returning matching elements as it goes. Repeatedly bit-shifting the mask and checking the 0th bit seems the easiest to follow - for me at least.
static IEnumerable<T> TakeMaskedItemsByIndex(this IEnumerable<T> collection, ulong mask)
{
foreach (T item in collection)
{
if((mask & 1) == 1)
yield return item;
mask = mask >> 1;
}
}
I have a spinning text : {T1{M1|{A1|B1}|M2}F1|{X1|X2}}
My question is : How can i find all permutations in C# ?
T1M1F1
T1M2F1
T1A1F1
T1B1F1
X1
X2
Any suggestions ?
Edit :
Thank you for your help but M1,A1, .. are examples
With words that could give :
{my name is james vick and i am a {member|user|visitor} on this {forum|website|site} and i am loving it | i am admin and i am a {supervisor|admin|moderator} on this {forum|website|site} and i am loving it}.
my name is james vick and i am a {member|user|visitor} on this {forum|website|site} and i am loving it => 3 * 3 => 9 permutations
i am admin and i am a {supervisor|admin|moderator} on this {forum|website|site} and i am loving it => 3 * 3 => 9 permutations
Result : 18 permutations
Method to generate all permuatuons of spinnable strings
I've implemented a simple method to solve this problem.
It takes an ArrayList argument containing spinnable text string(s).
I use it to generate all the permutations of multiple spinnable strings.
It comes with extra functionality of support of optional blocks, surronded by "[ ]" brackets.
Eq.:
If you have a single string object in the ArrayList with content of:
{A | {B1 | B2 } [B optional] }
It populates the array list with all the permutations, "extracted"
Contents after invocation of method:
A
B1
B1 B optional
B2
B2 B optional
You can also pass multiple strings as argument to generate permutations for all of them:
Eg.:
Input:
ArraList with two string
{A1 | A2}
{B1 | B2}
Contents after invocation:
A1
A2
B1
B2
This implementation works by always finding the inner most bracket pair in the first spinnable section, then extract it. I do this until all the special {}, [] characters are removed.
private void ExtractVersions(ArrayList list)
{
ArrayList IndicesToRemove = new ArrayList();
for (int i = 0; i < list.Count; i++)
{
string s = list[i].ToString();
int firstIndexOfCurlyClosing = s.IndexOf('}');
int firstIndexOfBracketClosing = s.IndexOf(']');
if ((firstIndexOfCurlyClosing > -1) || (firstIndexOfBracketClosing > -1))
{
char type = ' ';
int endi = -1;
int starti = -1;
if ((firstIndexOfBracketClosing == -1) && (firstIndexOfCurlyClosing > -1))
{ // Only Curly
endi = firstIndexOfCurlyClosing;
type = '{';
}
else
{
if ((firstIndexOfBracketClosing > -1) && (firstIndexOfCurlyClosing == -1))
{ // Only bracket
endi = firstIndexOfBracketClosing;
type = '[';
}
else
{
// Both
endi = Math.Min(firstIndexOfBracketClosing, firstIndexOfCurlyClosing);
type = s[endi];
if (type == ']')
{
type = '[';
}
else
{
type = '{';
}
}
}
starti = s.Substring(0, endi).LastIndexOf(type);
if (starti == -1)
{
throw new Exception("Brackets are not valid.");
}
// start index, end index and type found. -> make changes
if (type == '[')
{
// Add two new lines, one with the optional part, one without it
list.Add(s.Remove(starti, endi - starti+1));
list.Add(s.Remove(starti, 1).Remove(endi-1, 1));
IndicesToRemove.Add(i);
}
else
if (type == '{')
{
// Add as many new lines as many alternatives there are. This must be an in most bracket.
string alternatives = s.Substring(starti + 1, endi - starti - 1);
foreach(string alt in alternatives.Split('|'))
{
list.Add(s.Remove(starti,endi-starti+1).Insert(starti,alt));
}
IndicesToRemove.Add(i);
}
} // End of if( >-1 && >-1)
} // End of for loop
for (int i = IndicesToRemove.Count-1; i >= 0; i--)
{
list.RemoveAt((int)IndicesToRemove[i]);
}
}
I hope I've helped.
Maybe it is not the simplest and best implementation, but it works well for me. Please feedback, and vote!
In my opinion, you should proceed like this:
All nested choice lists i.e. between { } should be "flattened" to a single choice list. Like in your example:
{M1|{A1|B1}|M2} -> {M1|A1|B1|M2}
Use recursion to generate all possible combinations. For example, starting from an empty array, first place T1 since it is the only option. Then from the nested list {M1|A1|B1|M2} choose each element in turn an place it on the next position and then finally F1. Repeat until all possibilities are exhausted.
This is just a rough hint, you need to fill in the rest of the details.
So I have a list of items. Each item on the list has a property called notional. Now, the list is already sorted. What I need to do is, develop a function that sets the type of list to one of the following:
Bullet - notional is the same for every item
Amortizing - notional decreases over the course of the schedule (might stay the same from element to element but it should never go up, and should end lower)
Accreting - notional increases over the course of the schedule (might stay the same from element to element but it should never go down, and should end higher)
Rollercoaster - notional goes up and down (could end the same, higher, or lower, but shouldn't be the same for each element and shouldn't be classfied as the other types)
What would this method look like and what would be the most efficient way to go through the list and figure this out?
Thanks!
This would be a straightforward way to do it:
bool hasGoneUp = false;
bool hasGoneDown = false;
T previous = null; // T is the type of objects in the list; assuming ref type
foreach(var item in list)
{
if (previous == null) {
previous = item;
continue;
}
hasGoneUp = hasGoneUp || item.notional > previous.notional;
hasGoneDown = hasGoneDown || item.notional < previous.notional;
if(hasGoneUp && hasGoneDown) {
return Trend.Rollercoaster;
}
previous = item;
}
if (!hasGoneUp && !hasGoneDown) {
return Trend.Bullet;
}
// Exactly one of hasGoneUp and hasGoneDown is true by this point
return hasGoneUp ? Trend.Accreting : Trend.Amortizing;
Let trendOut = Bullet
Loop from First Item to Last item
2.1. If previous notional < next notional
2.1.a. If trendOut = Amortizing return RollerCoaster
2.1.b. Else set trendOut = Accreting
2.2. if Previous Notional > next notional
2.2.a. If trendOut = Accreting return RollerCoaster
2.2.b. Else set trendOut = Amortizing
return trendOut.
You could probably do something as simple as this
var changeList = new List<Integer>
for(i = 0; i < yourList.Count() - 1; i++)
{
changeList.Add(yourList.Item(i + 1) - yourList.Item(i));
}
//Determine if the nature of the list
var positiveChangeCount = changeList.Where(x => x < 0);
var negativeChangeCount = changeList.Where(x => X > 0);
if (positiveChangeCount = yourList.Count)
{
Accreting;
}
elseif (negativeChangeCount = yourList.Count)
{
Amortizing;
}
elseif (negativeChangeCount + PositiveChangeCount = 0)
{
Bullet;
}
else
{
Rollercoaster;
}
I usually start of by optimizing for simplicity first and then performance. Hence, I would start by making a second list of N-1 elements, whose {elements} are differences between the {notionals} of the first list.
Hence, for the second list, I would expect the following for the list of your needs
Bullet - ALL elements are 0
Amortising - ALL elements stay 0 or negative
Accreting - ALL elements stay 0 or positive
Rollercoaster - Elements oscillate between negative & positive
You can probably optimize it an do it in one pass. Basically, this is a discrete differentiation over your data.
bool OnlyGreaterOrEqual=true;
bool OnlyLessOrEqual=true;
foreach(int i=1;i<itemList.Count;i++){
if(itemList[i].notional>itemList[i-1].notional){
OnlyLessOrEqual=false;
}else if(itemList[i].notional<itemList[i-1].notional){
OnlyGreaterOrEqual=false;
}
}
if(OnlyGreaterOrEqual && OnlyLessOrEqual){
return "Bullet";
}else if(OnlyGreaterOrEqual){
return "Accreting":
}else if(OnlyLessOrEqual){
return "Amortizing";
}else{
return "RollerCoast";
}
This is basically a Linq implementation of Danish's answer. It'll require (worst case) 3 passes through the list, but because they are so small it won't really matter from a performance point of view. (I wrote it to work on a list of ints so you'll have to modify it easily to work with your types).
var tmp = values
.Skip(1)
.Zip( values, (first, second) => first - second )
.ToList();
var up = tmp.Any( t => t > 0 );
var down = tmp.Any( t => t < 0 );
if( up && down )
// Rollercoaster
else if( up )
// Accreting
else if( down )
// Amortizing
else
// Bullet
You could also (ab)use the Aggregate operator and Tuple to do it as one query. However, this will fail if the collection is empty and is a bit weird to use in production code.
var result = values.Skip(1).Aggregate(
Tuple.Create<int, bool, bool>( values.First(), false, false ),
( last, current ) => {
return Tuple.Create(
current,
last.Item2 || (current - last.Item1) > 0,
last.Item3 || (current - last.Item1) < 0 );
});
result will be a tuple that contains:
the last element of the collection (which is of no use)
Item2 will contain a boolean indicating whether any element was bigger than the previous element
Item3 will contain a boolean indicating whether any element was smaller than the previous element
The same switch statement as above can be used to decide which pattern your data follows.
Sorry for such a basic question regarding lists, but do we have this feature in C#?
e.g. imagine this Python List:
a = ['a','b,'c']
print a[0:1]
>>>>['a','b']
Is there something like this in C#? I currently have the necessity to test some object properties in pairs. edit: pairs are always of two :P
Imagine a larger (python) list:
a = ['a','a','b','c','d','d']
I need to test for example if a[0] = a[1], and if a[1] = a[2] etc.
How this can be done in C#?
Oh, and a last question: what is the tag (here) i can use to mark some parts of my post as code?
You can use LINQ to create a lazily-evaluated copy of a segment of a list. What you can't do without extra code (as far as I'm aware) is take a "view" on an arbitrary IList<T>. There's no particular reason why this shouldn't be feasible, however. You'd probably want it to be a fixed size (i.e. prohibit changes via Add/Remove) and you could also make it optionally read-only - basically you'd just proxy various calls on to the original list.
Sounds like it might be quite useful, and pretty easy to code... let me know if you'd like me to do this.
Out of interest, does a Python slice genuinely represent a view, or does it take a copy? If you change the contents of the original list later, does that change the contents of the slice? If you really want a copy, the the LINQ solutions using Skip/Take/ToList are absolutely fine. I do like the idea of a cheap view onto a collection though...
I've been looking for something like Python-Slicing in C# with no luck.
I finally wrote the following string extensions to mimic the python slicing:
static class StringExtensions
{
public static string Slice(this string input, string option)
{
var opts = option.Trim().Split(':').Select(s => s.Length > 0 ? (int?)int.Parse(s) : null).ToArray();
if (opts.Length == 1)
return input[opts[0].Value].ToString(); // only one index
if (opts.Length == 2)
return Slice(input, opts[0], opts[1], 1); // start and end
if (opts.Length == 3)
return Slice(input, opts[0], opts[1], opts[2]); // start, end and step
throw new NotImplementedException();
}
public static string Slice(this string input, int? start, int? end, int? step)
{
int len = input.Length;
if (!step.HasValue)
step = 1;
if (!start.HasValue)
start = (step.Value > 0) ? 0 : len-1;
else if (start < 0)
start += len;
if (!end.HasValue)
end = (step.Value > 0) ? len : -1;
else if (end < 0)
end += len;
string s = "";
if (step < 0)
for (int i = start.Value; i > end.Value && i >= 0; i+=step.Value)
s += input[i];
else
for (int i = start.Value; i < end.Value && i < len; i+=step.Value)
s += input[i];
return s;
}
}
Examples of how to use it:
"Hello".Slice("::-1"); // returns "olleH"
"Hello".Slice("2:-1"); // returns "ll"