I want the console to writeLine false for each ally that does not have a peculiar item(afaerie_charm), and .25 for each ally that is true in the code:
public bool aFaerie_Charm()
{
var allylist = new List<Obj_AI_Hero>();
allylist.AddRange(HeroManager.Allies);
bool z = false;
for (int i = 0; i < allylist.Count; i++) //allylist.count = 4
{
z = Items.HasItem((int)ItemId.Faerie_Charm, allylist[i]);
}
return z;
}
In the above code, z is true if any of the allies in the list(4 allies) have 'faerie_charm' and false otherwise.
Now, in this part of the code: allylist[1] (ally 2) has the peculiar item, so bool returns true, then faerie = .25;, and a2mrs() returns .25, but here's the problem:
the code found that one of the allies has the item and .25, but i have no idea which ally has it, it's not returning 'ally 2 has item, and it's value is .25', that's the problem. Need advice or help please.
public double a2mrs()
{
double faerie = 0;
if (aFaerie_Charm() == true)
{
faerie = .25;
}
return faerie;
}
static void Main(String[] args)
{
Console.WriteLine(a2mrs())
}
output: .25
problem: from the output .25, i only know one of the allies has the item, i dont know which one has the item.
summary: how do i re-work the code so that it prints something like this:
'ally 1 = false'
'ally 2 = .25'
'ally 3 = false'
'ally 4 = false' ?
Your first method returns whether or not the last person in the party has a faerie charm, not whether anyone does. You'll probably need to refactor your methods so that they return the information for each ally. You could do this by changing your first method to
public List<bool> aFaerie_Charm()
{
var allylist = new List<Obj_AI_Hero>();
allylist.AddRange(HeroManager.Allies);
List<bool> z = new List<bool>();
for (int i = 0; i < allylist.Count; i++) //allylist.count = 4
{
z.Add(Items.HasItem((int)ItemId.Faerie_Charm, allylist[i]));
}
return z;
}
Then the print:
public void printHasFaerieCharm()
{
List<bool> charms = aFaerieCharm();
for (int i = 0; i < charms.Count; ++i)
{
Console.WriteLine("Ally " + (i + 1) + ": " + (charms[i] ? ".25" : "false"));
}
}
However, I would recommend you adjust the first method so it takes a parameter of the item you want to check for and uses that instead, that way you can reuse it when you want the same information for other items. You could do something similar with the second method to change what it prints when the item is found (and which item to find), or even add that information to the item's class (so it would be called as something like printWhoHasItem(ItemId.FaerieCharm) and look something like "ally i: " + ItemId.Message).
Well this code is wrong in every aspect. You do realize that result of aFaerie_Charm() is always the result of check for last ally from array?
First of all can't mix booleans with doubles on that stage of code. You need to decide on one of them (based on your use case) and interpret it when it's needed.
You need either return Dictionary from aFaerie_Charm() and in that dictionary you'll add KeyValuePair for each ally in your array, where Key is name of that ally and Boolean is either true or false. Or alternatively you can make aFaerie_Charm accept input parameter of ally and return boolean for that particular ally.
And at the end, you loop through that Dictionary and interpret that boolean anyway you want for display purpose.
In Linq you'll do something like that:
// Create dictionary, keys are names of allies, values says if that particular ally has "charm" or not
Dictionary<String, Boolean> allyData = (from x in HeroManager.Allies select new { Name = x.Name, HasCharm = Items.HasItem((int)ItemId.Faerie_Charm, x) }).ToDictionary(y => y.Name, z => z.HasCharm);
And now displaying:
// Loop through dictionary
foreach (KeyValuePair<String, Boolean> a in allyData)
{
// Display ally's name and if that ally has "charm" then print ".25" and print "false" otherwise
Console.WriteLine("%s = %s", a.Key, (a.Value ? ".25" : "false"));
}
You can add one more line to your method like this:
public bool aFaerie_Charm()
{
var allylist = new List<Obj_AI_Hero>();
allylist.AddRange(HeroManager.Allies);
bool z = false;
for (int i = 0; i < allylist.Count; i++) //allylist.count = 4
{
z = Items.HasItem((int)ItemId.Faerie_Charm, allylist[i]);
//You got 'z' now print a line
Console.WriteLine("Ally " + (i + 1) + ": " + z ? ".25" : "false");
}
return z;
}
Well, You can do this simple thing
In aFaerie_Charm method instead of bool return int
On that aFaerie_Charm method in the if block if HasItem returns true then you return index (i) value or else return -1.
Now in your a2mrs method check it is >0 or less than 0
So if > 0 then you have the index value so you can use that.
However in aFaerie_Charm method guess you need one break statement in for loop. Please check
Related
I have a fixed int value - 1050. I have around 50 dynamic values that I want to compare with the fixed value. So I compare it in a for loop. I have a public variable which I set as ok or notok depending on result. But my problem is that the value of the public variable is always the last value that I compared. Example, If I have the 20th dynamic value as 1000, it should return notok, but the value of the variable is always the last compared value. How do I set the variable to notok even if one/multiple of the values of dynamic variable doesnt match with fixed variable? I also display the total number of notok values in a listbox.
Here is what I have:
string result;
for(int i = 0; i < dynamicvalue.count; i++)
{
if(dynamicvalue[i] != setvalue)
{
result = "notok";
listBox1.Items.Add(result);
}
else
{
result = "ok";
}
}
To have "notok" if theres at least one not matching, one way to do it in plain code:
string result = "ok";
for(int i=0; i<dynamicvalue.count; ++i)
{
if(dynamicvalue[i] != setvalue)
{
result = "notok";
break;
}
}
You can use .Any() from Linq,
Determines whether any element of a sequence exists or satisfies a
condition.
string result = dynamicvalue.Any(x => x == setValue) ? "Ok" : "Not Ok";
If you want to use for loop without a break statement, you are just increasing the time complexity of your code.
I will never recommend it, but if you want you can try the below code
string result = "Ok";
bool flag = true;
//This for loop will iterate for n times.
for(int i = 0; i < dynamicvalue.Count; i++)
{
if(dynamicvalue[i] != setvalue && flag)
{
result = "Not Ok";
flag = false; //flag will help us to execute this block of code only once.
}
}
Perhaps the most performant way to answer this would be to keep your numbers in a HashSet instead (make dynamicvalue a HashSet<int>), then it's:
dynamicvalue.Contains(setvalue) ? "ok" : "notok"
A HashSet can much more quickly answer "do you contain this value?" than a list/array can
By the discussion going on in the comments I'm thinking that you want to go through all the elements in dynamicvalue and check all if any of them are ok or notok. If that is the case, you should turn result into an array. You get the last compared result because each time the cycle loops, the string gets assigned a new value all over again so the previous value gets discarded.
Is this what you want to do? I wrote it in c++
int setvalue = 1050;
int notok = 0;
int dynamicvalue[5] = {1, 2, 3, 1050, 4}; //for example
string result[5];
for (int i = 0; i < sizeof(dynamicvalue); i++){
if (dynamicvalue[i] != setvalue){
result[i] = "notok";
notok++; //to keep track of notok
}
else{
result[i] = "ok";
}
}
Afterwards if you cycle through the result array you will see that all the values were saved. I find it simpler to have an int variable to know how many times the result was notok
You forgot to get the actual value within dynamicvalue: your test should be if (dynamicvalue[i] != setvalue).
EDIT: And add a break; after the result="ok"; instruction to break the loop, too.
EDIT 2: An above answer gives the corrected code using a break.
I found a solution to this by reading #deminalla 's answer.
I added two more integers to work as counters and after the for loop I compare the values of these integers to get the final result.
Here's what I did:
string result;
int okcounter = 0;
int notokcounter = 0;
for(int i = 0; i < dynamicvalue.count; i++)
{
if(dynamicvalue[i] != setvalue)
{
notokcounter ++;
listBox1.Items.Add(notokcounter);
}
else
{
okcounter++;;
}
}
if(notokcounter >=1)
{
result = "notok";
}
else if(okcounter == dynamicvalue.count)
{
result = "ok";
}
I want to generally verify if a number/character exists within a specified index of an int value.
Here is pseudocode of what I want
if (octet[1].Exists){
return true;
} else {
return false;
}
// receiving int octet = 103 will return true.
// receiving int octet = 7 will return false.
Is there a function that already does this, or do you have to make one on your own?
Convert to a string then check the length?
var str = octet.ToString();
return str.Length >= 1;
I don't know a function like this, but you can write your own.
In instance:
var func = (int octet, int index) => (octet / (int)(Math.Pow(10, index)) != 0);
I would suggest using a System.Linq binding for this. Here is an example:
octet.ToString().Contains(n);
Where n is the digit you're looking for in string or char form. Hope this helps!
Just parse the int to a string and check if the number you are looking is equal to expected position.
var number = 12345;
if(number.ToString().IndexOf('2') == 1)//check if the value 2 is on the second position of the array
{
Console.WriteLine("yes");
}
I would like to change/set one of the values in the ConcurrentQueue. FixedSizedQueue is a ConcurrentQueue. I think the main issue I'm having to trying to get the ONE of the entries in this ConcurrentQueue. Any suggestions...
private void CalculateABC(FixedSizedQueue<Bar> q)
{
decimal sum = 0.0m;
foreach (var item in q.Queue)
{
sum = sum + item.close;
}
decimal ABCvalue = decimal.Round(sum / q.Limit, 5);
//I'm trying to set the value HERE.
//((Bar)(q.Queue)Items[19]).ABC = ABCvalue;
}
private void CalculateABC(FixedSizedQueue<Bar> q)
{
decimal sum = 0.0m;
Bar item19 = null;
int index = 0;
foreach (var item in q.Queue)
{
if (index++ == 19)
item19 = item;
sum = sum + item.close;
}
decimal ABCvalue = decimal.Round(sum / q.Limit, 5);
//I'm trying to set the value HERE.
if (item19 != null)
item19.ABC = ABCvalue;
}
It seems to me that you just need to do this:
private void CalculateABC(FixedSizedQueue<Bar> q)
{
q.Queue.Skip(19).First().ABC =
decimal.Round(q.Queue.Sum(x => x.close) / q.Limit, 5);
}
Obviously you must ensure that your queue has at least 20 elements for this to work.
While you may want to reevaluate using a queue instead of a list (or in this case a ConcurrentQueue instead of a ConcurrentBag) because it won't provide random access (and you'll need to enumerate all previous elements to get to the one you want) it still is an IEnumerable so you can use LINQ to index it, but the performance will be poor as indexing the 1000th element doesn't require going to adress of first element + 1000 but going over each of the previous 999 elements.
In any case the simplest solution if you want to stick with a queue and index it is to replace your example of
queue[19]
with
queue.ElementAt(19)
So the full example would be :
private void CalculateABC(FixedSizedQueue<Bar> q)
{
// Replace your summing of each item's close property with a simple LINQ sum
decimal sum = q.Queue.Sum(item=>item.close);
decimal ABCvalue = decimal.Round(sum / q.Limit, 5);
// No need for any casting, you're already working on generics, it's already a Bar, don't cast a Bar to a Bar
q.Queue.ElementAt(19).ABC = ABCvalue;
}
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.
I'm doing some work with strings, and I have a scenario where I need to determine if a string (usually a small one < 10 characters) contains repeated characters.
`ABCDE` // does not contain repeats
`AABCD` // does contain repeats, ie A is repeated
I can loop through the string.ToCharArray() and test each character against every other character in the char[], but I feel like I am missing something obvious.... maybe I just need coffee. Can anyone help?
EDIT:
The string will be sorted, so order is not important so ABCDA => AABCD
The frequency of repeats is also important, so I need to know if the repeat is pair or triplet etc.
If the string is sorted, you could just remember each character in turn and check to make sure the next character is never identical to the last character.
Other than that, for strings under ten characters, just testing each character against all the rest is probably as fast or faster than most other things. A bit vector, as suggested by another commenter, may be faster (helps if you have a small set of legal characters.)
Bonus: here's a slick LINQ solution to implement Jon's functionality:
int longestRun =
s.Select((c, i) => s.Substring(i).TakeWhile(x => x == c).Count()).Max();
So, OK, it's not very fast! You got a problem with that?!
:-)
If the string is short, then just looping and testing may well be the simplest and most efficient way. I mean you could create a hash set (in whatever platform you're using) and iterate through the characters, failing if the character is already in the set and adding it to the set otherwise - but that's only likely to provide any benefit when the strings are longer.
EDIT: Now that we know it's sorted, mquander's answer is the best one IMO. Here's an implementation:
public static bool IsSortedNoRepeats(string text)
{
if (text.Length == 0)
{
return true;
}
char current = text[0];
for (int i=1; i < text.Length; i++)
{
char next = text[i];
if (next <= current)
{
return false;
}
current = next;
}
return true;
}
A shorter alternative if you don't mind repeating the indexer use:
public static bool IsSortedNoRepeats(string text)
{
for (int i=1; i < text.Length; i++)
{
if (text[i] <= text[i-1])
{
return false;
}
}
return true;
}
EDIT: Okay, with the "frequency" side, I'll turn the problem round a bit. I'm still going to assume that the string is sorted, so what we want to know is the length of the longest run. When there are no repeats, the longest run length will be 0 (for an empty string) or 1 (for a non-empty string). Otherwise, it'll be 2 or more.
First a string-specific version:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Now we can also do this as a general extension method on IEnumerable<T>:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Then you can call "AABCD".LongestRun() for example.
This will tell you very quickly if a string contains duplicates:
bool containsDups = "ABCDEA".Length != s.Distinct().Count();
It just checks the number of distinct characters against the original length. If they're different, you've got duplicates...
Edit: I guess this doesn't take care of the frequency of dups you noted in your edit though... but some other suggestions here already take care of that, so I won't post the code as I note a number of them already give you a reasonably elegant solution. I particularly like Joe's implementation using LINQ extensions.
Since you're using 3.5, you could do this in one LINQ query:
var results = stringInput
.ToCharArray() // not actually needed, I've left it here to show what's actually happening
.GroupBy(c=>c)
.Where(g=>g.Count()>1)
.Select(g=>new {Letter=g.First(),Count=g.Count()})
;
For each character that appears more than once in the input, this will give you the character and the count of occurances.
I think the easiest way to achieve that is to use this simple regex
bool foundMatch = false;
foundMatch = Regex.IsMatch(yourString, #"(\w)\1");
If you need more information about the match (start, length etc)
Match match = null;
string testString = "ABCDE AABCD";
match = Regex.Match(testString, #"(\w)\1+?");
if (match.Success)
{
string matchText = match.Value; // AA
int matchIndnex = match.Index; // 6
int matchLength = match.Length; // 2
}
How about something like:
string strString = "AA BRA KA DABRA";
var grp = from c in strString.ToCharArray()
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in grp)
{
Console.WriteLine(
string.Format("Character:{0} Appears {1} times",
item.Key.ToString(), item.Count));
}
Update Now, you'd need an array of counters to maintain a count.
Keep a bit array, with one bit representing a unique character. Turn the bit on when you encounter a character, and run over the string once. A mapping of the bit array index and the character set is upto you to decide. Break if you see that a particular bit is on already.
/(.).*\1/
(or whatever the equivalent is in your regex library's syntax)
Not the most efficient, since it will probably backtrack to every character in the string and then scan forward again. And I don't usually advocate regular expressions. But if you want brevity...
I started looking for some info on the net and I got to the following solution.
string input = "aaaaabbcbbbcccddefgg";
char[] chars = input.ToCharArray();
Dictionary<char, int> dictionary = new Dictionary<char,int>();
foreach (char c in chars)
{
if (!dictionary.ContainsKey(c))
{
dictionary[c] = 1; //
}
else
{
dictionary[c]++;
}
}
foreach (KeyValuePair<char, int> combo in dictionary)
{
if (combo.Value > 1) //If the vale of the key is greater than 1 it means the letter is repeated
{
Console.WriteLine("Letter " + combo.Key + " " + "is repeated " + combo.Value.ToString() + " times");
}
}
I hope it helps, I had a job interview in which the interviewer asked me to solve this and I understand it is a common question.
When there is no order to work on you could use a dictionary to keep the counts:
String input = "AABCD";
var result = new Dictionary<Char, int>(26);
var chars = input.ToCharArray();
foreach (var c in chars)
{
if (!result.ContainsKey(c))
{
result[c] = 0; // initialize the counter in the result
}
result[c]++;
}
foreach (var charCombo in result)
{
Console.WriteLine("{0}: {1}",charCombo.Key, charCombo.Value);
}
The hash solution Jon was describing is probably the best. You could use a HybridDictionary since that works well with small and large data sets. Where the letter is the key and the value is the frequency. (Update the frequency every time the add fails or the HybridDictionary returns true for .Contains(key))