C# Iterating an If statement with new value each time - c#

Is it possible to iterate nested if statements with a new value with every single iteration? I am trying to build a 1-dimensional cellular automata (for homework, I cannot deny it) and I'm completely new to C# as the following code will no doubt assure. I have tried to create this program using the most straightforward, basic, DIY methods available and have run myself into a rut.
I've got a string of 1's and 0's of length 8, say
string y;
y = "11110000";
I want to break this set up in 8 substring sets of 3 with each set comprising of a value in y together with a single value on either side of it. So counting from 0, the 3rd set would be 110, the 7th would be 001. However substrings will only provide the 1st to 6th set as I can't loop them around y to my liking so I defined the following-
y1=y.Substring(7,1)+y+y.Substring(0,1);
Using y1 I was able to get out all the substrings necessary. These were defined pretty basically as follows-
string a0, a1, a2, a3, a4, a5, a6, a7;
a0 = y1.Substring(0, 3);
a1 = y1.Substring(1, 3);
a2 = y1.Substring(2, 3);
a3 = y1.Substring(3, 3);
a4 = y1.Substring(4, 3);
a5 = y1.Substring(5, 3);
a6 = y1.Substring(6, 3);
a7 = y1.Substring(7, 3);
The rules for the next generation of cellular automata are up to the user in this program- that is to say the user can choose whether or not a substring, say 111->0 or 1 for all iterations. I used (an awful lot of) if tables in the following way for each substring
{
if (a0=="000")
{
Console.Write(a);
}
else if (a0=="001")
{
Console.Write(b);
}
else if (a0 =="010")
{
Console.Write(c);
}
else if (a0 == "011")
{
Console.Write(d);
}
else if (a0 == "100")
{
Console.Write(e);
}
else if (a0 == "101")
{
Console.Write(f);
}
else if (a0 == "110")
{
Console.Write(g);
}
else if (a0 == "111")
{
Console.Write(h);
}
}
where a,b,c,d,e,f,g,h are ints and are rules chosen by the user. So say for instance the user decides that each set 000 should result in a 1 value, then a=1. b corresponds to {0,0,1}, c to {0,1,0} and so on. However the fairly obvious problem with this method is that I end up with only 1 generation in ints that I can't get at. I'd love to replace y1 with this new generation (converted into a string). If this isn't possible let me know!
This link might also clear things up a bit

and here's how you COULD have gotten an A+ :D
private static int[,] HipPriestsHomework()
{
string y = "11110000";
Console.WriteLine(y);
var rules = new[]
{
new {pattern = 0, result = 0},
new {pattern = 1, result = 1},
new {pattern = 2, result = 1},
new {pattern = 3, result = 1},
new {pattern = 4, result = 1},
new {pattern = 5, result = 0},
new {pattern = 6, result = 0},
new {pattern = 7, result = 0},
};
Dictionary<int, int> rulesLookup = new Dictionary<int, int>();
foreach(var rule in rules)
{
rulesLookup.Add(rule.pattern, rule.result);
}
int numGenerations = 10;
int inputSize = y.Length;
int[,] output = new int[numGenerations, inputSize];
int[] items = new int[y.Length];
for(int inputIndex = 0; inputIndex< y.Length; inputIndex++)
{
string token = y.Substring(inputIndex, 1);
int item = Convert.ToInt32(token);
items[inputIndex] = item;
}
int[] working = new int[items.Length];
items.CopyTo(working, 0);
for (int generation = 0; generation < numGenerations; generation++)
{
for (uint y_scan = 0; y_scan < items.Length; y_scan++)
{
int a = items[(y_scan - 1) % items.Length];
int b = items[y_scan % items.Length];
int c = items[(y_scan + 1) % items.Length];
int pattern = a << 2 | b << 1 | c;
var match = rules[pattern];
output[generation, y_scan] = match.result;
working[y_scan] = match.result;
Console.Write(match.result);
}
working.CopyTo(items, 0);
Console.WriteLine();
}
return output;
}

Related

Find subsets of a string but just which is neighbours

I am trying to extract subsets but not all of them, just which is a neighbour. The simple example below;
Input : "123456789"
Result :
3.Level Subset: out3 : [123,234,345,456,567,678,789]
..
5.Level Subset : out5 :[12345,23456,34567,45678,56789]
..
8.Level Subset: out8 :[12345678,23456789]
result = [out1,..,out5,..out8]
If there is a cool solution for this and if it can be string operation it will be good.
Many thanks
You'll need to do additional error checks to see if level is longer than the length of the string etc.
public static void Main(string[] args)
{
var results = FindSubsets("123456789", 3);
Console.Read();
}
public static List<string> FindSubsets(string data, int level)
{
if (level > data.Length || level < 1)
return null;
var results = new List<string>();
for (int i = 0; i < data.Length - level + 1; i++)
{
results.Add(data.Substring(i, level));
}
return results;
}
Edit:
Added string length check against level.
Edit2:
If you want to find subsets of certain length, you can do something like the following. Create a List<int> with all the levels you want to find subsets of, then repeatedly call the function. For example, let's say you want to find subsets for levels 3, 5, and 8. Then:
var data = "123456789";
var levels = new List<int>() { 3, 5, 8 };
var results = new List<List<string>>();
foreach(var level in levels)
{
results.Add(FindSubsets(data, level));
}
public IEnumerable<string> GetSubsets(string input, int length)
{
if (string.IsNullOrEmpty(input))
throw new ArgumentException("Invalid string");
if (length <= 0)
throw new ArgumentException("Length must be greater than 0.");
if (length > input.Length)
throw new ArgumentException("The desired set length is longer than the string");
for(int i = 0; i<=input.Length - length;i++)
{
yield return input.Substring(i, length);
}
}
Yes this can be done using Regex:
string input = "123456789";
int size = 3; // set to whatever
MatchCollection split = Regex.Matches(input, #$"\d{{size}}");
string delimited = string.Join(",", split);
Or as an extension method:
public static string Delimit(this string s, int size)
{
MatchCollection split = Regex.Matches(input, #$"\d{{size}}");
return delimited = string.Join(",", split);
}
I basically just brute forced the answer:
import java.util.ArrayList;
public class MyClass {
public static ArrayList<ArrayList<String>> getAllSubets(String input){
ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>();
ArrayList<String> out = new ArrayList<String>();
for(int i= input.length(); i>=0; i--){
int z = i;
for(int j = 0; j+i<input.length() ;j++){
z++;
out.add(input.substring(j, z));
}
}
list.add(out);
return list;
}
public static void main(String args[]) {
System.out.println(MyClass.getAllSubets("123456789"));
}
}
Output:
[[123456789, 12345678, 23456789, 1234567, 2345678, 3456789, 123456, 234567, 345678, 456789, 12345, 23456, 34567, 45678, 56789, 1234, 2345, 3456, 4567, 5678, 6789, 123, 234, 345, 456, 567, 678, 789, 12, 23, 34, 45, 56, 67, 78, 89, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
This was a fun question to do its easy to get tripped up with the indexes.
Finding all Subsets:
var Input = "123456789";
var Result = Enumerable
.Range(1, Input.Length)
.Select(i => Enumerable
.Range(0, Input.Length - i + 1)
.Select(j => Input.Substring(j, i)))
.ToList();
To restrain to only some levels, like 3, 5, or 8, simply filter before performing the work, as is done below:
var Levels = new List<int>{ 3, 5, 8 };
var Input = "123456789";
var Result = Enumerable
.Range(1, Input.Length)
.Where(i => Levels.Contains(i)) // Filter the levels you need before constructing the subsets.
.Select(i => Enumerable
.Range(0, Input.Length - i + 1)
.Select(j => Input.Substring(j, i)))
.ToList();
Results:
123, 234, 345, 456, 567, 678, 789
12345,
23456,
34567,
45678,
56789
12345678,
23456789

how to multiply each element in an array with a loop c#

im trying to multiply each element in three different arrays by 2 with a loop but im having trouble. im really new at this so please excuse any obvious mistakes lol im not even sure ive im using the right kind of loop but heres what i have so far:
int[] firstArray = new int[] { 1, 2, 5, 6, 9 };
int[] secondArray = new int[] { 12, 3, 8, 20, 7 };
int[] thirdArray = new int[] { 2, 4, 6, 8, 10, 12 };
foreach(new int [5] in firstArray)
{
int newArray1= firstArray.Length * 2;
Console.WriteLine(newArray1);
}
i want it to print out the first new array as "2, 4, 10, 12, 18" in the console but when i run it, i get the error type and identifier are both required in a foreach statement.
any help would be greatly appreciated!
Do this with Linq
int[] resultFirstArray = firstArray.Select(r=> r * 2).ToArray();
int[] resultSecondArray = secondArray.Select(r=> r * 2).ToArray();
int[] resultThirdArray = thirdArray.Select(r=> r * 2).ToArray();
Or you can use Array.ConvertAll
Array.ConvertAll converts an entire array. It converts all elements in one array to another type.
var resultFirstArray = Array.ConvertAll(firstArray, x => 2 * x);
var resultSecondArray = Array.ConvertAll(secondArray, x => 2 * x);
var resultThirdArray = Array.ConvertAll(thirdArray, x => 2 * x);
If you just want to show the doubled values:
foreach(int value in firstArray)
{
Console.WriteLine(2 * value);
}
If you want to double the values in the array, then:
for(int i = 0 ; i < firstArray.Length ; i++)
{
firstArray[i] *= 2;
}
Then perhaps to show those values:
foreach(int value in firstArray)
{
Console.WriteLine(value);
}
If you want to create a new array with the values doubled:
var doubledArray = Array.ConvertAll(firstArray, x => 2 * x);
And to output those values:
foreach(int value in doubledArray)
{
Console.WriteLine(value);
}

Converting a long nested Excel formula to c#

I am tasked to transform an Excel VBA to a web-based application. I am using Web Forms. I am stuck with a long Excel formula but I have converted half of the long formula into C#.
Here is the Excel formula:
IF(AND(D7="u", H7/F7>1), 0, INDEX(Scoring!$O$8:$O$10, SUMPRODUCT(--(E28 <= Scoring!$N8:$N10),--(E28 >= Scoring!$N8:$N10), ROW(INDIRECT("'Scoring'!$M1:$M3"))))
While here is my progress on the C# method. I need help on the ELSE part:
IF (variable = "u" && ((CurrentValue / AcceptedValue) > 1)){
return 0;
ELSE {
// the INDEX clause on the Excel Formula
}
O8 - O10 values are {2, 1, 0}
N8 - N10 values are {1, 1.5, 9999999999}
E28 is 0
I have also got the result of the remainder of the formula piece by piece. I just need guidance on how to put it in C#.
=INDEX(Scoring!$O$8:$O$10, SUMPRODUCT({1,1,1}, {0,0,0}, 1))
The double minus(--) made it return 0/1 instead of true/false. ROW(INDIRECT($M1-$M3)) is equivalent to 1.
I could use some help on transforming the Excel formula into C# code.
Here is some C# code to replicate this part of your formula:
INDEX(Scoring!$O$8:$O$10, SUMPRODUCT(--(E28 <= Scoring!$N8:$N10),--(E28 >= Scoring!$N8:$N10), ROW(INDIRECT("'Scoring'!$M1:$M3")))
In the code I've had to assign the array {1, 1, 1} for ROW(INDIRECT("'Scoring'!$M1:$M3")). There is some ambiguity in your question around the action of SUMPRODUCT. According to support.office.com
Multiplies corresponding components in the given arrays, and returns the sum of those products.
But some of your detail in the question makes me think you are thinking that each array get summed up and then those results get multiplied together. Anyway, check out the comments in the code below to follow the logic:
// inputs
double[] o8o10 = new double[] { 2, 1, 0 }; // Scoring!$O$8:$O$10
double[] n8n10 = new double[] { 1, 1.5, 9999999999 }; // Scoring!$N8:$N10
double e28 = 0; // E28
// entries to SUMPRODUCT
List<int> test1 = new List<int>();
List<int> test2 = new List<int>();
Array.ForEach(n8n10, x => { test1.Add((e28 <= x) ? 0 : 1); });
Array.ForEach(n8n10, x => { test2.Add((e28 >= x) ? 0 : 1); });
// ROW(INDIRECT("'Scoring'!$M1:$M3")) should be an array !
List<int> test3 = new List<int> { 1, 1, 1 };
// evalue SUMPRODUCT
int sumProductResult = 0;
for (var i=0; i<test1.Count; i++)
{
sumProductResult += test1[i] * test2[i] * test3[i];
}
// evalute INDEX
double indexResult = 0;
indexResult = o8o10[sumProductResult];
// output
Console.WriteLine(indexResult);
Console.ReadKey();
The output for me is 2 because that is the 0th element of the o8o10 array. We get 0 for the array index because
=SUMPRODUCT({1, 1, 1}, {0, 0, 0}, {1, 1, 1})
resolves to:
=SUM(1*0*1, 1*0*1, 1*0*1}
Which gives 0.
HTH
ROW(INDIRECT("'Scoring'!$M1:$M3")) actually evaluates to {1; 2; 3} and
--(E28 <= Scoring!$N8:$N10),--(E28 >= Scoring!$N8:$N10) is --(E28 = Scoring!$N8:$N10)
so the SUMPRODUCT formula is just:
(E28 = Scoring!$N8) * 1 + (E28 = Scoring!$N9) * 2 + (E28 = Scoring!$N10) * 3
and in C#:
double[] n8n10 = { 1, 2, 3 }; double e28 = 2;
double sumProduct = n8n10.Select((d, i) d == e28 ? i + 1 : 0).Sum();
But! because Scoring!$O$8:$O$10 is only 3 cells and the SUMPRODUCT can in theory result in more than 3, the actual aim of the INDEX SUMPRODUCT part seems to be something like this:
double[] o8o10 = { 4, 5, 6 }, n8n10 = { 1, 2, 3 };
double e28 = 2, result = o8o10[0]; // INDEX(array, 0) results in array
if (n8n10[1] == e28) result = o8o10[1];
else if (n8n10[2] == e28) result = o8o10[2];

Replace recursion with TimerCallback for iterations over all variations

I'm trying to find an algorithm to print with intervals all variation of values in array. It looks simple to understand it, but I can't find how to manage the data for this...
For example I have the list of following objects (the number of arguments in list can vary):
List<Arg> lst = new List<Arg>();
lst.Add(new Arg { Name = "a", InitValue = 1, MaxValue = 2, Step = 1 });
lst.Add(new Arg { Name = "b", InitValue = 2, MaxValue = 6, Step = 2 });
lst.Add(new Arg { Name = "c", InitValue = 4, MaxValue = 12, Step = 4 });
Now I need to iterate over all args variations (each iteration has all arguments) and print them. The challenge is how to do it with intervals between the iterations and not to use Thread.Sleep. I want to use System.Threading.Timer and print each variation in TimerCallback method.
Example output:
a = 1, b = 2, c = 4
a = 1, b = 2, c = 8
a = 1, b = 2, c = 12
a = 1, b = 4, c = 4
a = 1, b = 4, c = 8
a = 1, b = 4, c = 12
a = 1, b = 6, c = 4
a = 1, b = 6, c = 8
a = 1, b = 6, c = 12
a = 2, b = 2, c = 4
a = 2, b = 2, c = 8
a = 2, b = 2, c = 12
a = 2, b = 4, c = 4
a = 2, b = 4, c = 8
a = 2, b = 4, c = 12
a = 2, b = 6, c = 4
a = 2, b = 6, c = 8
a = 2, b = 6, c = 12
I can do it easily with recursion, but it will not work with TimerCallback...
Thanks
I believe you can easily do it with recursion and yield.
With yield, you can write your code very similar to the way you normally would, and have your function return an IEnumerator instead, using yield return to return the next item from the enumerator. Then, at each timer event, simply get the next element.
Here's a little example I constructed of how you would use yield in a similar way:
public class Test
{
static System.Collections.IEnumerator enumerator;
static void Main()
{
// Display powers of 2 up to the exponent of 8:
enumerator = Power(2, 8);
bool done = false;
while (!done)
done = !timerEvent();
}
static bool timerEvent()
{
if (!enumerator.MoveNext())
return false;
else
Console.Write("{0} ", enumerator.Current);
return true;
}
// This will be your function
static System.Collections.IEnumerator Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
Live demo.
Since you mentioned that you can easily do it with recursion, I'll leave applying this to your problem up to you.
To use yield with recursion, you may have to change your code a little.

LINQ to find the closest number that is greater / less than an input

Suppose I have this number list:
List<int> = new List<int>(){3,5,8,11,12,13,14,21}
Suppose that I want to get the closest number that is less than 11, it would be 8
Suppose that I want to get the closest number that is greater than 13 that would be 14.
The numbers in list can't be duplicated and are always ordered. How can I write Linq for this?
with Linq assuming that the list is ordered I would do it like this:
var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var lessThan11 = l.TakeWhile(p => p < 11).Last();
var greaterThan13 = l.SkipWhile(p => p <= 13).First();
EDIT:
As I have received negative feedback about this answer and for the sake of people that may see this answer and while it's accepted don't go further, I explored the other comments regarding BinarySearch and decided to add the second option in here (with some minor change).
This is the not sufficient way presented somewhere else:
var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var indexLessThan11 = ~l.BinarySearch(10) -1;
var value = l[indexLessThan11];
Now the code above doesn't cope with the fact that the value 10 might actually be in the list (in which case one shouldn't invert the index)! so the good way is to do it:
var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var indexLessThan11 = l.BinarySearch(10);
if (indexLessThan11 < 0) // the value 10 wasn't found
{
indexLessThan11 = ~indexLessThan11;
indexLessThan11 -= 1;
}
var value = l[indexLessThan11];
I simply want to note that:
l.BinarySearch(11) == 3
//and
l.BinarySearch(10) == -4;
Use Array.BinarySearch - no need for LINQ or visiting on average half the elements to find your target.
There are also a variety of SortedXXX classes that may be suitable for what you're doing [that will have such efficient O(log N) searches built-in]
You can do this using a binary search. If your searching for 11, well obviously you'll get the index your after. If you search for 10 and use the bitwise complement of the result, you'll get the closest match.
List<int> list = new List<int>(){3,5,8,11,12,13,14,21};
list.Sort();
int index = list.BinarySearch(10);
int found = (~index)-1;
Console.WriteLine (list[found]); // Outputs 8
The same goes searching in the other direction
int index = list.BinarySearch(15);
Console.WriteLine("Closest match : " + list[+~index]); // Outputs 21
Binary searches are also extremely fast.
closest number below 11:
int someNumber = 11;
List<int> list = new List<int> { 3, 5, 8, 11, 12, 13, 14, 21 };
var intermediate = from i in list
where i < someNumber
orderby i descending
select i;
var result = intermediate.FirstOrDefault();
closest number above 13:
int someNumber = 13;
List<int> list = new List<int> { 3, 5, 8, 11, 12, 13, 14, 21 };
var intermediate = from i in list
where i > someNumber
orderby i
select i;
var result = intermediate.FirstOrDefault();
This is my answer
List<int> myList = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
int n = 11;
int? smallerNumberCloseToInput = (from n1 in myList
where n1 < n
orderby n1 descending
select n1).First();
int? largerNumberCloseToInput = (from n1 in myList
where n1 > n
orderby n1 ascending
select n1).First();
var list = new List<int> {14,2,13,11,5,8,21,12,3};
var tested = 11;
var closestGreater = list.OrderBy(n => n)
.FirstOrDefault(n => tested < n); // = 12
var closestLess = list.OrderByDescending(n => n)
.FirstOrDefault(n => tested > n); // = 8
if (closestGreater == 0)
System.Diagnostics.Debug.WriteLine(
string.Format("No number greater then {0} exists in the list", tested));
if (closestLess == 0)
System.Diagnostics.Debug.WriteLine(
string.Format("No number smaler then {0} exists in the list", tested));
Here is my way hope this helps somebody!
List<float> list = new List<float> { 4.0f, 5.0f, 6.0f, 10.0f, 4.5f, 4.0f, 5.0f, 6.0f, 10.0f, 4.5f, 4.0f, 5.0f, 6.0f, 10.0f };
float num = 4.7f;
float closestAbove = list.Aggregate((x , y) => (x < num ? y : y < num ? x : (Math.Abs(x - num)) < Math.Abs(y - num) ? x : y));
float closestBelow = list.Aggregate((x , y) => (x > num ? y : y > num ? x : (Math.Abs(x - num)) < Math.Abs(y - num) ? x : y));
Console.WriteLine(closestAbove);
Console.WriteLine(closestBelow);
This means you dont have to order the list
Credit: addapted from here: How to get the closest number from a List<int> with LINQ?
The Expanded Code
float closestAboveExplained = list.Aggregate((closestAbove , next) => {
if(next < num){
return closestAbove;
}
if(closestAbove < num){
return next;
}
else{
if(Math.Abs(closestAbove - num) < Math.Abs(next - num)){
return closestAbove;
}
}
return next;
});
You can use a query for this such as:
List<int> numbers = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
List<int> output = (from n in numbers
where n > 13 // or whatever
orderby n ascending //or descending
select n).ToList();

Categories

Resources