Reputation: 535
I am trying to write an algorithm to delete a name from list of names at particular index. Initially i will read a file line by line. The file would be like this :
amelie barbon cat dog thomas | 3
raty pertw ituy |5
Now for example we see the first line where we have three(3) at last, so here we have to to read the number at last for each line , this number is blackNumber
, so called because after reading this number we have to delete the each string at this index one by one until we have 1 string left in the string array. And that only left string is our answer.
For example:
Cat
will be deleted in first iteration, and the list will become
amelie barbon dog thomas
Now dog
will be deleted and then thomas
,after these two similar deletion the list will be:
amelie barbon
Up to here my code is working fine, But now we have to delete at index 3 and the but there are 2 elements only in the list, so the next deletion counter has to start like this :
amelie(index:1)-> barbon(index:2)->amelie(index:3)
And the string amelie
must be deleted, which will remain barbon
in the list, and that's the answer is. (This last step when total number of list elements are less then blackNumber, then i am not able to get the logic that how to do).
What i have tried is below:(which will run infinitely when list count is smaller than blackNumber
)
class Program
{
static void Main(string[] args)
{
using (StreamReader reader = File.OpenText("C:\\Users\\Mohit\\Desktop\\PolmStudio Tasks\\anmeDelete\\anmeDelete\\file.txt"))
while (!reader.EndOfStream)
{
List<string> list = null;
string line = reader.ReadLine(); ;
if (null != line)
{
list = new List<string>();
string[] digits = line.Split(new char[] { ' ', '\n', '|' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < digits.Count() - 1; i++)
{
list.Add(digits[i]);
}
int blacknumber = Convert.ToInt32(digits[digits.Count() - 1]) - 1;
do
{
for (int i = 0; i < list.Count(); i++)
{
if (i == blacknumber)
{
list.RemoveAt(i);
}
}
} while (list.Count > 1);
}
foreach (string str in list)
{
Console.WriteLine(str);
}
Console.WriteLine("");
}
Console.ReadKey();
}
}
Upvotes: 1
Views: 3023
Reputation: 19149
Its a simple math. assume your list length is 3
. and you want to remove 5th
element.
5 % (3 - 1) = 1
. so you must remove item at index 1
i.e 2nd
element.
If the index of element that you are trying to remove is less than count of list then you just normally remove it.
List<string> list = new List<string>{"amelie", "barbon", "cat", "dog", "thomas"};
int blacknumber = 3;
blacknumber--; // because indexes are 0 based
do
{
list.RemoveAt(blacknumber < list.Count ? blacknumber : blacknumber % list.Count);
} while (list.Count > 1);
Console.WriteLine(list[0]); // prints barbon
Side note:
Do not use Count()
because it calls Enumerable.Count from linq. its not optimum. you can directly use the property of list. with list.Count
(without parenthesis.)
Upvotes: 1
Reputation: 535
Thanks for the given suggestion and solution your suggestion gave me idea that i cannot change the list items position which are to be deleted, but i can change the blackNumber using %
operator, so many friends gave me idea about how to do thanks to them but every one's algo is missing some condition. Below is the working solution which implements all necessary conditions :
string line = reader.ReadLine();
if (null != line)
{
list = new List<string>();
string[] digits = line.Split(new char[] { ' ', '\n', '|' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < digits.Count() - 1; i++)
{
list.Add(digits[i]);
}
int blacknumber = Convert.ToInt32(digits[digits.Count() - 1]);
int saveBlackNum = blacknumber;
do
{
for (int i = 0; i < list.Count(); i++)
{
if ((list.Count < (blacknumber)))
{
if(blacknumber % list.Count==0 )
{
blacknumber = list.Count();
}
else
{
blacknumber = ((blacknumber) % list.Count());
}
break;
}
if ((list.Count >= (blacknumber)))
{
if (i == blacknumber - 1)
{
list.RemoveAt(blacknumber - 1);
blacknumber = saveBlackNum;
break;
}
}
}
} while (list.Count > 1);
}
foreach (string str in list)
{
Console.WriteLine(str);
}
Console.WriteLine("");
May be helpful to some one else in future.
Upvotes: 1
Reputation: 44
Just change the inner loop to the following and you will get your required answer:
do
{
int i =0;
if (blacknumber >= list.Count()) i = blacknumber % list.Count();
else i = blacknumber;
list.RemoveAt(i);
} while (list.Count > 1);
Upvotes: 1
Reputation: 4268
I have a simpler solution. The only case I don't know based on your question is what happens if the blackNumber is 1. Will the answer be amelia or thomas?
Heres my code
var arr = new List<string>() { "amelie", "barbon", "cat", "dog", "thomas" };
var goal = blackline - 2;
if (goal > -1)
{
if (arr.Count > goal)
{
Console.WriteLine(arr[goal]);
}
else
{
Console.WriteLine(arr[arr.Count - 1]);
}
}
else
{
Console.WriteLine(arr[0]); //if blackline is 1 and answer is suppose to be amelia
//Console.WriteLine(arr[arr.Count - 1]); //If blackline is 1 and answer is suppose to be thomas
}
Upvotes: 1
Reputation: 363
I think, what you're looking for is using modulo %
of element n
by length
Since you're doing it with a List, you could do something:
int listIndex = i % list.Count;
I believe it shall do as you need. The modulo will return the remaining part of the division, hence the index you are looking for.
Upvotes: 2
Reputation: 138
I'm having trouble understanding what you want, is this what you want? To stop removing items if there are less items in that line than the blacknumber? 'if (i == blacknumber && list.Count >= blacknumber)'
Upvotes: -1