C# Method which may execute any code in the loop - c#

For example if i have to type something like that multiple time, is there any way to put this loop in the method with parameters like LoopMethod(Code lines, int count)
for (int i = 0; i <= 1000; i++)
{
code line 1;
code line 2;
...
code line N;
}
for (int i = 0; i <= 1000; i++)
{
code line 1;
code line 2;
...
code line N;
}
if result to have something like that.
LoopMethod{
code line 1,
code line 2,
...
code line N,
1000
}

Here's a variant:
public static LoopMethod(int iterations, Action<int> body)
{
for (int i = 0; i < iterations; i++)
body(i);
}
You'd call it like this:
LoopMethod(100, i =>
{
code line;
code line;
});

A more generic form would be to first create an extension method:
public static class Extension
{
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach(var currentItem in enumerable)
{
action(currentItem);
}
}
}
Then using that you can do the following:
Enumerable.Range(0, 1000).ForEach(i =>
{
Console.WriteLine(i);
});
Which would iterate from 0 to 999 (use 1001 as the second param for inclusive). The added benefit is that this then works on any enumerable type.

Well, you can do that with delegates rather easily:
public static void LoopMethod(Action loopCode, int count)
{
for (int i = 0; i < count ; ++i) loopCode();
}
public static void Main()
{
LoopMethod(() => {
code line 1;
code line 2;
code line 3;
}, 100);
}
You can alter that any way you like, even changing it to Action<int> which takes as a parameter the current loop counter. See #Gabe's answer for the Action<int> variant :)
Of course, I have to wonder why you want to reproduce such an obviously built-in construct like looping?

You could use lambda expression like this:
LoopMethod(() => {code line 1; code line 2;}, 100);
The method declaration would look something like
void LoopMethod (Action code, int count) {
for (int i = 0; i < count; i++) {
code();
}
}
There may be odd syntactical error there ( I haven't tested it), but the approach should work.

Related

Return all powers of 2 less then n in C# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
For a given number n, I need to return all powers of 2 less than n, as a string in a way that elements are separated with "-". If n < 2, it needs to return an empty string.
For example:
n = 20 => 1-2-4-8-16
n = 8 => 1-2-4
I'm a beginner, so any help would be much appreciated! :)
EDIT: this is not working
using System;
class N
{
static int[] powerof2(int n)
{
int[] array = new int[n];
if (n < 2)
return new int[0];
for (int i = 0; i < 8 * sizeof(uint); i++)
{
int curr = 1 << i;
if (curr > n)
break;
array[i] = curr;
}
return array;
public override string ToString()
{
for (int i = 0; i < array.length; i++)
return (array[i] + "-");
}
}
static public void Main ()
{
int n = 10;
Console.WriteLine(powerof2(n).ToString());
}
}
You need to run the for loop with the following rule
for (int i = 1; i < n; i *= 2)
Whole solution
class Program
{
static void powerof2(int n)
{
if (n < 2)
Console.WriteLine(string.Empty);
for (int i = 1; i < n; i *= 2)
{
if (i > 1)
Console.Write("-");
Console.Write(i);
}
}
static void Main(string[] args)
{
powerof2(20);
}
Using iterator methods makes this case trivial (Fiddle):
using System;
using System.Collections.Generic;
public class Program
{
public static IEnumerable<int> GetPowersOf2(int maxN)
{
for (int p = 1; p < maxN; p *= 2)
{
yield return p;
}
}
public static void Main(string[] args)
{
IEnumerable<int> powersOf2LessThan20 = GetPowersOf2(20);
Console.WriteLine(string.Join("-", powersOf2LessThan20));
}
}
I suppose this is what you're looking for:
class Program
{
public static string Pow2LessThan(ulong n)
{
if (n < 2)
return "";
// start with 2^0
string res = "1";
// try further
int p = 1;
ulong cnum = 2;
while (cnum < n)
{
res += "-" + cnum.ToString();
++p;
cnum = (ulong)(1 << p);
}
return res;
}
static void Main(string[] args)
{
ulong n = 20;
Console.WriteLine(Pow2LessThan(n));
Console.ReadLine();
}
}
The reason that it's not working is: you never access the class N in any way. The call should be
Console.WriteLine(N.powerof2(n).ToString());
^^
With that modification, you'll be notified that the method powerof2() is inaccessible due to its protection level. You need to make it at least internal like so:
internal static int[] powerof2(int n)
Next, note that you're missing a } for that method.
return array;
}
With that fixed, the compiler will tell you that you can't access array inside ToString(), because the scope of array is limited to powerof2(). Make the array a field of the class like
static int[] array;
Now, the compiler complains about array.length in ToString(). Fix that by capitalizing Length.
Mistake number 6: ToString() will return in the first iteration of the loop. It will not return anything if array.Length is 0. The function should look a little bit like this:
public override string ToString()
{
string result = "";
for (int i = 0; i < array.Length; i++)
result += array[i] + "-";
return result;
}
Now, this will still not work, because the main method calls ToString() on the return value of powerof2(), which is of type int[] and not of type N. That's because your stuff is static. Make it non-static instead and create an instance of N.
static public void Main ()
{
var n = new N();
n.powerof2(10);
Console.WriteLine(n.ToString());
}
With 7 issues fixed, the output is now 1-2-4-8-0-0-0-0-0-0-, so there's still stuff to fix. Maybe you get a little bit of a feeling why everyone proposes a totally different solution.
What else to fix:
the output of course is still incorrect.
if someone inputs 4000000000 as the number, you certainly don't want to allocate 4 GB of RAM in the array.
Why allocate an array at all and not construct the string right away?
Why 8*sizeof(uint)? You can't shift more often than sizeof(uint).
class Program
{
static string powerof2(int n)
{
var str="1" ;
if (n < 2)
return "" ;
else
{
var i=1;
while(Math.Pow(i, 2)<n)
{
str+="-" +Math.Pow(2, i);
i++;
}
return str;
}
}
static void Main(string[] args)
{
powerof2(50);
}
}

Cannot apply indexing with [] to an expression of type 'Array''

I am getting the "Cannot apply indexing with [] to an expression of type 'Array''" for the below code.. Aim is to create a calculator template and then call these methods to run the various operations.
Errors are coming in the areas marked //HERE.. Please help. I am a newbie when it comes to c# coding, so, all help is appreciated and I would like it if someone could explain me the issue too. Thanks
private static Array NumberFeedLengthDecider()
{
Console.WriteLine("Please enter how many numbers that you would like to add.");
int i = Convert.ToInt32(Console.ReadLine());
int[] numbers = new int[i];
return numbers;
}
private static int NumberFeed(Array numbers)
{
Console.WriteLine("Please enter the numbers one by one, each followed by the 'Enter' key.");
int i = numbers.Length;
for (int counter = 0; counter < i; counter++)
{
int temp = Convert.ToInt32(Console.ReadLine());
numbers[counter] = temp; //HERE
}
return i;
}
private static void NumberDisplay(Array numbers)
{
Console.WriteLine("The numbers you have entered are: ");
int i = (numbers.Length);
for (int x = 0; x < i; x++)
{
Console.WriteLine(numbers[x]); //HERE
}
}
Basically, I want to create a method for deciding the number of numbers the operations are to be run on which is the first one (numberFeedLengthDecider), then another method to feed the numbers into that array (NumberFeed), and then another method to display that group of numbers (NumberDisplay). but for some reason, I can't seem to get it to work
Array is the base class for arrays, its elements aren't "strongly typed"; you can put any object in it.
Since you seem to be dealing with int elements only, you should be using int[] where you now use Array. You can then access elements with the [] indexing, and you ensure that each element is an int to boot.
You could rewrite this code with something like this
Check the IEnumerable interface and List class
This code is cleaner and removes NumberFeedLengthDecider method, this method is making noise in the code. When you don't know how many inputs you will have use List class, it uses more memory than classic array, but gets the job done in situations like this. For better conversions check out TryParse and Parse method (ex. int.TryParse() and int.Parse()) and work more with exception handling.
public List<int> Insert()
{
//Output here something to the console
List<int> numbers = new List<int>();
while(true)
{
var input = Console.ReadLine();
if(input.ToLower() == "done") break;
try
{
numbers.Add(Convert.Int32(input));
}
catch(FormatException e)
{
Console.WriteLine(e.Message);
}
}
return numbers;
}
public void Print(IEnumerable<int> numbers)
{
foreach(var num in numbers)
{
Console.WriteLine(num);
}
}
Use "SetValue". Example:
Array? arr = Array.CreateInstance(arrayType, source.Count);
for (int i = 0; i < source.Count; i++)
{
arr.SetValue(source[i], i);
}
Or, in your case:
for (int counter = 0; counter < i; counter++)
{
int temp = Convert.ToInt32(Console.ReadLine());
numbers.SetValue[counter] = temp;
// to read back...
Console.WriteLine(arr.GetValue(counter));
}

Randomizing List with Guid

I have a problem about my c# project. In the program I have a list
private static void FillData(List<Question> questions)
{
AddQuestion(questions,
"DotA isimli MOBA oyununun açılımı nedir? ",
2,
"Defense of the Arkham",
"Defence of the Ancients",
"Defense of the Ancients",
"Dance of the Architectures"
);
like that and i wanna make that list randomizely showned in every opening with shuffle. In the example my teacher used
private static void Shuffle(Soru[] array)
{
int length = array.Length;
for (int i = 0; i < length; i++)
{
int index = i + ((int) (_random.NextDouble() * (length - i)));
Soru soru = array[index];
array[index] = array[i];
array[i] = soru;
}
this and i wanna make that in Guid.NewGuid(). Can anyone help me with replacing that with Guid?
(edited from comments) This is what I tried so far:
private static void Shuffle(List<Question> List)
{
List = List.OrderBy(o => Guid.NewGuid().ToString()).ToList();
foreach (Question question in ....) { Console.WriteLine(question);
}
but I can't fullfill foreach loop. And yes I want to use Guid instead of random.
The problem is that you only modified the input parameter to hold a reference of another List. As it is not passed as reference, in the place where you have called it will hold the reference of the original List.
You could try this way:
private static void Shuffle(List<Question> List)
{
var randomOrderList = List.OrderBy(o => Guid.NewGuid().ToString()).ToList();
for (int i = 0; i < List.Count; i++)
{
List[i] = randomOrderList[i];
}
}

Separate functions without duplicating code

I am currently working on a program to traverse through a list of numbers with two different functions to find the sum and a specific value. Here is the code that I have implemented
class Program
{
static int i, sum;
static List<int> store = new List<int>();
static void Main(string[] args)
{
for (i = 0; i < 100; i++)
{
store.Add(i);
}
i = 0;
TraverseList();
Console.ReadLine();
}
static void TraverseList()
{
while (i < store.Count)
{
FindValue();
FindSum();
i++;
}
Console.WriteLine("The sum is {0}", sum);
}
static void FindValue()
{
if (store[i] == 40)
{
Console.WriteLine("Value is 40");
}
}
static void FindSum()
{
sum = sum + store[i];
}
}
I was thinking of separating FindSum and FindValue into two different functions and not calling them in TraverseList. Is there any other way of doing it rather the duplicating the common code of list traversal in those two functions as I have done here
class Program
{
static int i, sum;
static List<int> store = new List<int>();
static void Main(string[] args)
{
for (i = 0; i < 100; i++)
{
store.Add(i);
}
i = 0;
FindValue();
i = 0;
FindSum();
Console.ReadLine();
}
static void FindValue()
{
while (i < store.Count)
{
if (store[i] == 40)
{
Console.WriteLine("Value is 40");
}
i++;
}
}
static void FindSum()
{
while (i < store.Count)
{
sum = sum + store[i];
i++;
}
Console.WriteLine("The sum is {0}", sum);
}
}
To find the sum of a series of numbers you can use the simple LINQ function:
List<int> numbers = new List<int>();
int sum = numbers.Sum();
I am not sure what you mean by find a value. If you want to check if one of the numbers in a series is equal to a certain value you can use the LINQ function Any:
int myValue = 40;
bool hasMyValue = numbers.Any(i => i == myValue);
This uses a lambda expression which executes a function and passes each element in the collection to the function. The function returns true or false to indicate that the element is a match for the Any test.
If instead you want to check for how many numbers in a sequence match a certain value you can instead use the Count function like so:
int numberOfMatches = numbers.Count(i => i == myValue);
First thing - I would use foreach instead of while, regarding the duplicate code (assuming you are not using Linq) - I think it's fine
A taste how Linq can simplify your code:
var FindSum = store.Sum();
var FindValue = store.FindAll(x => x == 40);
I cannot stress enough how bad it is to have i and sum as class members. Especially i. It will make your code very fragile, and hard to work with. Try to make each method as isolated from the rest of the code as possible.
Try something like this instead:
static void Main( string[] args )
{
List<int> store = new List<int>();
for( int i = 0; i < 100; i++ )
store.Add( i );
FindValue( store );
FindSum( store );
Console.ReadLine();
}
static void FindValue( List<int> list )
{
for( int i = 0; i < list.Count; i++ )
{
if( list[i] == 40 )
Console.WriteLine( "Value is 40" );
}
}
static void FindSum( List<int> list )
{
int sum = 0;
for( int i = 0; i < list.Count; i++ )
sum += list[i];
Console.WriteLine( "The sum is {0}", sum );
}
It is perfectly fine (and normal) to duplicate the looping, it's just a single line. You could also use a foreach here.
Also, disregard everyone telling you to use LINQ. You're obviously new to programming and you should learn the basics first.

mergesort - with an insignificant change throws SystemInvalidOperationException

A very strange thing occured in my program. Here is the simplified code.
class Program
{
static void Main(string[] args)
{
ArrayList numbers = new ArrayList();
numbers.Add(1);
numbers.Add(3);
numbers.Add(4);
numbers.Add(2);
var it = Sorts.MergeSort((ArrayList)numbers.Clone());
Sorts.PrintArray(it, "mergesort");
Console.WriteLine("DONE");
Console.ReadLine();
}
}
public static class Sorts
{
public static ArrayList BubbleSort(ArrayList numbers)
{
bool sorted = true;
for (int i = 0; i < numbers.Count; i++)
{
for (int j = 1; j < numbers.Count; j++)
{
if ((int)numbers[j - 1] > (int)numbers[j])
{
int tmp = (int)numbers[j - 1];
numbers[j - 1] = numbers[j];
numbers[j] = tmp;
sorted = false;
}
}
if (sorted)
{
return numbers;
}
}
return numbers;
}
public static ArrayList MergeSort(ArrayList numbers, int switchLimit = 3)
{
//if I use this if - everything works
if (numbers.Count <= 1)
{
// return numbers;
}
//the moment I use this condition - it throws SystemInvalidOperationException in function Merge in the line of a "for"-loop
if (numbers.Count <=switchLimit)
{
return Sorts.BubbleSort(numbers);
}
ArrayList ret = new ArrayList();
int middle = numbers.Count / 2;
ArrayList L = numbers.GetRange(0, middle);
ArrayList R = numbers.GetRange(middle, numbers.Count - middle);
L = MergeSort(L);
R = MergeSort(R);
return Merge(L, R);
}
private static ArrayList Merge(ArrayList L, ArrayList R)
{
ArrayList ret = new ArrayList();
int l = 0;
int r = 0;
for (int i = 0; i < L.Count + R.Count; i++)
{
if (l == L.Count)
{
ret.Add(R[r++]);
}
else if (r == R.Count)
{
ret.Add(L[l++]);
}
else if ((int)L[l] < (int)R[r])
{
ret.Add(L[l++]);
}
else
{
ret.Add(R[r++]);
}
}
return ret;
}
//---------------------------------------------------------------------------------
public static void PrintArray(ArrayList arr, string txt = "", int sleep = 0)
{
Console.WriteLine("{1}({0}): ", arr.Count, txt);
for (int i = 0; i < arr.Count; i++)
{
Console.WriteLine(arr[i].ToString().PadLeft(10));
}
Console.WriteLine();
System.Threading.Thread.Sleep(sleep);
}
}
There is a problem with my Sorts.MergeSort function.
When I use it normally (take a look at the first if-condition in a function - all works perfectly.
But the moment when I want it to switch to bubblesort with smaller input (the second if-condition in the function) it throws me an SystemInvalidOperationException. I have no idea where is the problem.
Do you see it?
Thanks. :)
Remark: bubblesort itself works - so there shouldn't be a problem in that sort...
The problem is with your use of GetRange:
This method does not create copies of the elements. The new ArrayList is only a view window into the source ArrayList. However, all subsequent changes to the source ArrayList must be done through this view window ArrayList. If changes are made directly to the source ArrayList, the view window ArrayList is invalidated and any operations on it will return an InvalidOperationException.
You're creating two views onto the original ArrayList and trying to work with both of them - but when one view modifies the underlying list, the other view is effectively invalidated.
If you change the code to create copies of the sublists - or if you work directly with the original list within specified bounds - then I believe it'll work fine.
(As noted in comments, I'd also strongly recommend that you use generic collections.)
Here's a short but complete program which demonstrates the problem you're running into:
using System;
using System.Collections;
class Program
{
static void Main()
{
ArrayList list = new ArrayList();
list.Add("a");
list.Add("b");
ArrayList view1 = list.GetRange(0, 1);
ArrayList view2 = list.GetRange(1, 1);
view1[0] = "c";
Console.WriteLine(view2[0]); // Throws an exception
}
}
on this line R = MergeSort(R); you alter the range of numbers represented by L. This invalidates L. Sorry I have to go so can't explain any further now.

Categories