I'm trying to solve a simple algorithm a specific way where it takes the current row and adds it to the top most row. I know there are plenty of ways to solve this but currently I have a text file that gets read line by line. Each line is converted to an sbyte (there's a certain reason why I am using sbyte but it's irrelevant to my post and I won't mention it here) and added to a list. From there, the line is reversed and added to another list. Here's the code I have for that first part:
List<List<sbyte>> largeNumbers = new List<List<sbyte>>();
List<string> total = new List<string>();
string bigIntFile = #"C:\Users\Justin\Documents\BigNumbers.txt";
string result;
StreamReader streamReader = new StreamReader(bigIntFile);
while ((result = streamReader.ReadLine()) != null)
{
List<sbyte> largeNumber = new List<sbyte>();
for (int i = 0; i < result.Length; i++)
{
sbyte singleConvertedDigit = Convert.ToSByte(result.Substring(i, 1));
largeNumber.Add(singleConvertedDigit);
}
largeNumber.Reverse();
largeNumbers.Add(largeNumber);
}
From there, I want to use an empty list that stores strings which I will be using later for adding my numbers. However, I want to be able to add numbers to this new list named "total". The numbers I'll be adding to it are not all the same length and because so, I need to check if an index exists at a certain location, if it does I'll be adding the value I'm looking at to the number that resides in that index, if not, I need to create that index and set it's value to 0. In trying to do so, I keep getting an IndexOutOfRange exception (obviously because that index doesn't exist). :
foreach (var largeNumber in largeNumbers)
{
int totalIndex = 0;
foreach (var digit in largeNumber)
{
if (total.Count == 0)
{
total[totalIndex] = digit.ToString(); //Index out of Range exception occurs here
}
else
{
total[totalIndex] = (Convert.ToSByte(total[totalIndex]) + digit).ToString();
}
totalIndex ++;
}
}
I'm just at a loss. Any Ideas on how to check if that index exists; if it does not create it and set it's underlying value equal to 0? This is just a fun exercise for me but I am hitting a brick wall with this lovely index portion. I've tried to use SingleOrDefault as well as ElementAtOrDefault but they don't seem to be working so hot for me. Thanks in advance!
Depending on if your result is have small number of missing elements (i.e. have more than 50% elements missing) consider simply adding 0 to the list till you reach neccessary index. You may use list of nullable items (i.e. List<int?>) instead of regular values (List<int>) if you care if item is missing or not.
Something like (non-compiled...) sample:
// List<long> list; int index; long value
if (index >= list.Count)
{
list.AddRange(Enumerable.Repeat(0, index-list.Count+1);
}
list[index] = value;
If you have significant number of missing elements use Dictionary (or SortedDictionary) with (index, value) pairs.
Dictionary<int, long> items;
if (items.ContainsKey(index))
{
items[key] = value;
}
else
{
items.Add(index, value);
}
Related
so my problem is that I don't know how to go forward in the list and print the next same integer if there is one.
Here is what I have at the moment:
while (list.Contains(input1))
{
Console.WriteLine(input1 + " is at index " + list.IndexOf(input1))
}
I am trying to list all of the integers that are in the list and print the index of them. But not remove after finding one of the integers (this was at least my first idea.).
IndexOf has an overload with two parameters, which allows you to start searching at a later position in the list.
Since this is obviously a learning exercise, I won't spoil it by providing the full code, but rather suggest that you try to implement the following algorithm:
Find the index of input starting at position 0.
If not found (i.e., IndexOf returns -1): we're done. Otherwise:
Print and remember that index.
Start again at step 1, but this time, don't start searching at 0 but at the index you remembered + 1.
You can do the following:
go through the list/array using for statement
for(int i=0; i < list.length; i++) // loop though list
then inside the loop check the value of the current item using if statement:
if(list[i] == input1)
//do smothing
The list[0] represent the first item in the array, which means the index is 0.
so in the example above the i will be the current index so long that you in the loop.
I didn't write the full code for learning purpose in reference to #Heinzi answer.
Hope that could be helpful!
This is an implementation possibility. It is longer than it has to be, but it makes it clearer for beginners how one could tackle this problem.
Since you wanted to only show numbers that come up more than once here is an implementation method. If you want to show numbers that come up only once too just erase everything about lastindex
List<int> yourlist = new List<int> { 1,1,1,1,1,11,2,3,3,4,4,5 };
int input = 0;
input = Convert.ToInt32(Console.ReadLine());
var index = yourlist.IndexOf(input);
//this checks if your input is in the list
var lastindex = yourlist.LastIndexOf(input);
//this does the same but it searches for the last implementation of your input
if (index != -1 && lastindex != index)
//this if checks if your number comes up more than once. IndexOf returns -1 if there is no occurence of your input
{
Console.Write($"the index of {input} is {index}");
for (int i = index+1; i <= yourlist.Count; i++)
//this loop takes the position of the first occurence of your number and then counts up from there
{
var tempindex = yourlist.IndexOf(input, i);
if (tempindex != -1)
//this if lets everything except -1 through
{
Console.Write($" and {tempindex}");
}
}
}
else
{
Console.WriteLine("your number cannot be found twice in the list");
}
I am trying to filter a list of int based on multiples of a specific number, but I am not sure how to do this. I have searched this forum and found nothing related, but apologies in advance if I'm wrong.
Here is my code:
int val = 28;
List<int> divisible = new List<int>();
for (int i = 1; i <= val; i++) {
divisible.Add(i);
}
foreach(var d in divisible)
{
if(val % d == 0)
{
// do something
}
else
{
// get rid of all multiples of the number that "val" is not divisible by
}
}
Basically, this code should create a divisible list from 1 to 28. If val is divisible by one of the numbers in the list, thats fine, but if it falls into else, I want to be able to filter out all multiples of that number out of the current list we are looping through.
The next number that wouldn't be divisible would be 3 in this example, so in the else get rid of 6, 9, 12, ... etc.
Your code is fine, but you're just missing the actual code to remove the item. But there is a caveat: You cannot modify a list when you are looping through it using foreach. There are a couple ways to handle that:
Depending on your requirements, maybe just don't add them in the first place. Move your val % d == 0 condition into the for loop that adds the values, and just don't add the values that are divisible by d.
Make a new list (List<int> toRemove) where you keep track of all the values you need to remove. After you're done the foreach loop, loop through your toRemove list and use divisible.Remove(value) to remove those.
Change your foreach to a for loop, which will allow you to use divisible.RemoveAt(i). But you will have to make sure you don't skip a value on the next iteration of the for loop (since removing a value changes the size of the list).
I agree with Gabriel. You cannot alter a underlying enumeration while traversing it with with foreach. The easiest thing to do would be to convert it to a for loop.
Also in the initial population of your list try using the newer way
var divisible = Enumerable.Range(1, val).ToList();
then do
for(int 0 = 1; i < val; i++)
{
if(val % d == 0)
{
// do something
}
else
{
divisible.RemoveAt(i);
}
}
I'm looking for a data structure or a solution which allows me to find an element faster than O(n) AND to get the previous elements of the found element
In my case, I have a list of finacial quote already filled and sorted, I need to find an element by DateTime, and I need to returns the previous x elements.
I tried with a LinkedList but the find is too slow o(n).
I also thought about using a Dictionary so I can find by DateTime, but I don't know how to loop in reverse order to get the previous elements.
class FinancialQuote
{
public DateTime TradingDate;
public double Price;
protected bool Equals(FinancialQuote other)
{
return TradingDate.Equals(other.TradingDate);
}
}
public void Main()
{
var quotes = new LinkedList<FinancialQuote>();
// quotes are populated here
var result = new List<FinancialQuote>();
var howManyQuotes = 2;
// the goal here is to find quote4 and returns quote3 and quote2
var currentNode = quotes.Find(quote4); // O(N) which is too slow
for (int i = 0; i < howManyQuotes; i++)
{
var previousClose = currentNode.Previous.Value;
result.Add(previousClose);
currentNode = currentNode.Previous;
}
}
So my variable Result should contains quote3 and quote2
List type already guarantees O(1) time to access an element by index. Therefore, you can achieve O(logN) time to find an element of a sorted list by applying binary search algorithm.
After that, you can simply iterate through predecessors of that element.
int index = quotes.BinarySearch(searchValue);
if (index >= 0)
{
int lowIndex = Math.Max(index - howManyQuotes, 0);
for (int cur = lowIndex; cur <= index; cur++)
{
// do something with quotes[cur];
}
}
You should use a normal List<FinancialQuote> which must be sorted on date.
Use the BinarySearch for the index where the DateTime should be (inserted). Use this function also for building the list. It returns a positive index when the dateTime is found (exact match) and a negative index where this datetime should be inserted.
Use that index as upper bound. (iterate 0 to found index)
I'm trying to find how many elements are in my string array, so I can add to that array from the first empty element.
Here's what I've tried to do:
int arrayLength = 0;
string[] fullName = new string[50];
if (fullName.Length > 0)
{
arrayLength = fullName.Length - 1;
}
and then from that refer to the first available empty element as:
fullName[arrayLength] = "Test";
I can also use this to see if the array is full or not, but my problem is arrayLength is always equal to 49, so my code seems to be counting the size of the entire array, not the size of the elements that are not empty.
Cheers!
you can use this function to calculate the length of your array.
private int countArray(string[] arr)
{
int res = arr.Length;
foreach (string item in arr)
{
if (String.IsNullOrEmpty(item))
{
res -= 1;
}
}
return res;
}
EDIT : To find the first empty element
private int firstEmpty(string[] arr)
{
int res = 0;
foreach (string item in arr)
{
if (String.IsNullOrEmpty(item))
{
return res;
}
res++;
}
return -1; // Array is full
}
I'm trying to find how many elements are in my string array,
array.Length
so I can add to that array from the first empty element.
Array's don't have empty elements; there's always something in there, though it could be null.
You could find that by scanning through until you hit a null, or by keeping track each time you add a new element.
If you're going to add new elements then, use List<string> this has an Add() method that will do what you want for you, as well as resizing when needed and so on.
You can likely then just use the list for the next part of the task, but if you really need an array it has a ToArray() method which will give you one.
So if you want to use the array instead of a list you still simply can get the number of empty elements like this:
int numberOfEmptyElements = fullName.Count(x => String.IsNullOrEmpty(x));
Try the below code
string[] fullName = new string[50];
fullName[0] = "Rihana";
fullName[1] = "Ronaldo";
int result = fullName.Count(i => i != null);
in result you will have the number of occupied positions. In this case 2, cause 2 arrays are filled. From there you can count the empty. :)
Sorry for the newbie question. Could someone help me out? Simple array here. What's the best/easiest method to check all the user input is unique and not duplicated? Thanks
private void btnNext_Click(object sender, EventArgs e)
{
string[] Numbers = new string[5];
Numbers[0] = txtNumber1.Text;
Numbers[1] = txtNumber2.Text;
Numbers[2] = txtNumber3.Text;
Numbers[3] = txtNumber4.Text;
Numbers[4] = txtNumber5.Text;
foreach (string Result in Numbers)
{
lbNumbers.Items.Add(Result);
}
txtNumber1.Clear();
txtNumber2.Clear();
txtNumber3.Clear();
txtNumber4.Clear();
txtNumber5.Clear();
}
}
}
I should have added I need to check to happen before the numbers are output. Thanks
One simple approach is via LINQ:
bool allUnique = Numbers.Distinct().Count() == Numbers.Length;
Another approach is using a HashSet<string>:
var set = new HashSet<string>(Numbers);
if (set.Count == Numbers.Count)
{
// all unique
}
or with Enumerable.All:
var set = new HashSet<string>();
// HashSet.Add returns a bool if the item was added because it was unique
bool allUnique = Numbers.All(text=> set.Add(text));
Enunmerable.All is more efficient when the sequence is very large since it does not create the set completely but one after each other and will return false as soon as it detects a duplicate.
Here's a demo of this effect: http://ideone.com/G48CYv
HashSet constructor memory consumption: 50 MB, duration: 00:00:00.2962615
Enumerable.All memory consumption: 0 MB, duration: 00:00:00.0004254
msdn
The HashSet<T> class provides high-performance set operations.
A set is a collection that contains no duplicate elements, and whose
elements are in no particular order.
The easiest way, in my opinion, would be to insert all values inside a set and then check if its size is equal to the array's size. A set can't contain duplicate values, so if any value is duplicate, it won't be inserted into the set.
This is also OK in complexity if you don't have millions of values, because insertion in a set is done in O(logn) time, so total check time will be O(nlogn).
If you want something optimal in complexity, you can do this in O(n) time by going through the array, and putting each value found into a hash map while incrementing its value: if value doesn't exist in set, you add it with count = 1. If it does exist, you increment its count.
Then, you go through the hash map and check that all values have a count of one.
If you are just trying to make sure that your listbox doesn't have dups then use this:
if(!lbNumbers.Items.Contains(Result))
lbNumbers.Items.Add(Result);
What about this:
public bool arrayContainsDuplicates(string[] array) {
for (int i = 0; i < array.Length - 2; i++) {
for (int j = i + 1; j < array.Length - 1; j++) {
if (array[i] == array[j]) return true;
}
}
return false;
}