Assign specific initial parameters from random values, among a pool of parameters - c#

I am using a function to initialize values for a constructor.
In the constructor I call this function, and initialize parameters based on the specific type passed in the constructor.
public class myclass()
{
// class parameters of type int\
public myclass()
{
GenerateValues(1);
}
private void GenerateValues( int type_of_worker)
{
Random rnd = new Random();
//generate random values for the params
}
}
With this I can generate random values based on the type of worker passed to the constructor, so I can have a basic worker, a technician, a director, a manager and so on.
Each role has requirements though, so when I create the worker of type "manager", it has to have at least 2 parameters that are above 50 (min 0 max 99). If is a director, it needs 3 parameters equal or above 75.
How can I tell C# to create random values for X parameters, but if the type is manager, 2 of them has to be above 50, or if it is a director, 3 parameters ahs to be above 75?
For example, if I create a manager, I would use this in GenerateValues:
// main parameters - any value between 1-99 is fine
par1 = rnd.Next(1.99);
par2 = rnd.Next(1.99);
par3 = rnd.Next(1.99);
par4 = rnd.Next(1.99);
par5 = rnd.Next(1.99);
//extra parameters - ANY 2 of these above 50 for manager
par6 = rnd.Next(1.99);
par7 = rnd.Next(50.99);
par8 = rnd.Next(50.99);
par9 = rnd.Next(1.99);
The problem here is that I don't want to specify which of the extra parameters is between 50 and 99; but would like that any 2 of the extra parameters has to be between 50 and 99.
I could assign values and then read them, changing them again, but it is pretty inefficient.

I would do it in more OOP way, since it's C#. See implementation below.
First I define an interface to define a contract. From each worker type we should get integer parameters. Not sure how your parameters look like, I used just an array of integers.
Then I add abstract class to share a code for generating N random numbers from given interval.
Then I just create concrete types implementing only specific logic.
For simplicity I used LINQ helper functions.
The following rules are applied to get set of random numbers:
Technician - 2 values from interval [0, 99] and 5 values from [0, 50]. Notice int Next function min parameter is inclusive whereas max parameter is exclusive.
Director - 2 values from interval [50, 99] and 5 values from [0, 50].
Manager - 3 values from interval [75, 99] and 5 values from [0, 50].
using System.Linq;
using System.Collections.Generic;
public interface IWorker {
int[] GetParameters();
}
abstract class Worker : IWorker {
public abstract int[] GetParameters();
protected IEnumerable<int> GenerateNValues(int quanity, int min, int max) {
var theRandom = new Random();
var theResult = new List<int>(quanity);
for (int i = 0; i < quanity; i++)
theResult.Add(theRandom.Next(min, max));
return theResult;
}
protected IEnumerable<int> Shuffle(IEnumerable<int> array) {
var theRandom = new Random();
return array.OrderBy(x => theRandom.Next()).ToArray();
}
}
class Technician : Worker {
public override int[] GetParameters() {
return GenerateNValues(2, 0, 100).Concat(GenerateNValues(5, 10, 51)).ToArray();
}
}
class Director : Worker {
public override int[] GetParameters() {
return GenerateNValues(2, 50, 100).Concat(GenerateNValues(5, 10, 51)).ToArray();
}
}
class Manager : Worker {
public override int[] GetParameters() {
return Shuffle(GenerateNValues(3, 75, 100).Concat(GenerateNValues(5, 10, 51))).ToArray();
}
}
public class MyClass
{
public MyClass(IWorker aWorker)
{
var theParameters = aWorker.GetParameters();
// do stuff with parameters
}
}

Related

Why I can't change an array element obtained from another class?

I created a class that implements the wrapper over the array double [] but I can not change the element of the received array. These are tests
public void SetCorrectly ()
public void IndexerDoesNotCopyArray ()
The problem sounds like this. Write the class Indexer, which is created as a wrapper over the array double [], and opens access to its subarray of some length, starting with some element. Your decision must pass the tests contained in the project. As always, you must monitor the integrity of the data in Indexer.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Incapsulation.Weights
{
public class Indexer
{
double[] array;
int start;
int length;
public int Length
{
get { return length; }
}
public Indexer(double[] array, int start, int length)
{
if (start < 0 || start >= array.Length) throw new ArgumentException();
this.start = start;
if (length < start || length > array.Length) throw new ArgumentException();
this.length = length;
this.array = array.Skip(start).Take(length).ToArray();
}
public double this[int index]
{
get { return array[index]; }
set { array[index] = value; }
}
}
}
This is tests
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Incapsulation.Weights
{
[TestFixture]
public class Indexer_should
{
double[] array = new double[] { 1, 2, 3, 4 };
[Test]
public void HaveCorrectLength()
{
var indexer = new Indexer(array, 1, 2);
Assert.AreEqual(2, indexer.Length);
}
[Test]
public void GetCorrectly()
{
var indexer = new Indexer(array, 1, 2);
Assert.AreEqual(2, indexer[0]);
Assert.AreEqual(3, indexer[1]);
}
[Test]
public void SetCorrectly()
{
var indexer = new Indexer(array, 1, 2);
indexer[0] = 10;
Assert.AreEqual(10, array[1]);
}
[Test]
public void IndexerDoesNotCopyArray()
{
var indexer1 = new Indexer(array, 1, 2);
var indexer2 = new Indexer(array, 0, 2);
indexer1[0] = 100500;
Assert.AreEqual(100500, indexer2[1]);
}
}
The problem you are facing here is that the last test requires that your wrapper provides access to the underlying array. In other words, whatever number of Indexers are created, they all point to the same underlying array.
Your line here this.array = array.Skip(start).Take(length).ToArray(); violates this requirement creating a new instance of Array class. Because of this the value changed by first indexer is not reflected in the second one - they point to different memory areas.
To fix this, instead of creating a new Array using LINQ, simply store the original array passed through constructor. Your this[] indexer property must take care of passed start and end adding start to the index and checking the out-of-boundaries condition manually.
All linq extension methods create a new enumeration, they do not mutate or return the one the method is called on:
var newArray = array.Skip(...).ToArray();
ReferenceEquals(array, newArray); //returns false
Any change you might make in an element of newArray will not change anything whatsoever in array.
Your SetCorrectly test is comparing indexer and array and it will always fail. Your other test also fails because indexer1 and indexer2 reference two different arrays.
However because Linq is lazy, modifying array can be seen by the result of the Linq extension method depending on when you materialize the enumeration; this can happen:
var skippedA = array.Skip(1); //deferred execution
array[1] = //some different value...,
var newArray =skipped.ToArray(); //Skip is materialized here!
newArray[1] == array[1]; //true!

Parallel.Foreach with modulo partitioning

When using Parallel.Foreach() for 100 items using 4 threads, it will divide the list into 4 blocks (0-24,25-49,50-74,75-99) of items, which means, that items 0, 25, 50 and 75 are processed in parallel.
Is it somehow possible to partition the items in a modulo way to handle those with lower indices first? Like:
Thread 1: 0, 5, 9,..
Thread 2: 1, 6, 10,...
Thread 3: 2, 7, 11,...
Thread 4: 3, 8, 12,...
This partitioning method is known as Round Robin, or Striping. The primary challenge of using this with Parallel.ForEach() is that ForEach() requires partitioners to support dynamic partitions, which would not be possible with this type of partitioning as the number of partitions must be fixed prior to execution of the loop.
One way to achieve this type of partitioning is to create a custom class derived from System.Collections.Concurrent.Partitioner<TSource> and use the ParallelQuery.ForAll() method, which does not have the dynamic partitioning support requirement. For most applications this should be equivalent to using ForEach().
Below is an example of a custom Partitioner and a basic implementation. The Partitioner will generate the same number of partitions as the degree of parallelism.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace RoundRobinPartitioning
{
public class RoundRobinPartitioner<TSource> : Partitioner<TSource>
{
private readonly IList<TSource> _source;
public RoundRobinPartitioner(IList<TSource> source)
{
_source = source;
}
public override bool SupportsDynamicPartitions { get { return false; } }
public override IList<IEnumerator<TSource>> GetPartitions(int partitionCount)
{
var enumerators = new List<IEnumerator<TSource>>(partitionCount);
for (int i = 0; i < partitionCount; i++)
{
enumerators.Add(GetEnumerator(i, partitionCount));
}
return enumerators;
}
private IEnumerator<TSource> GetEnumerator(
int partition,
int partitionCount)
{
int position = partition;
TSource value;
while (position < _source.Count)
{
value = _source[position];
position += partitionCount;
yield return value;
}
}
}
class Program
{
static void Main(string[] args)
{
var values = Enumerable.Range(0, 100).ToList();
var partitioner = new RoundRobinPartitioner<int>(values);
partitioner.AsParallel()
.WithDegreeOfParallelism(4)
.ForAll(value =>
{
// Perform work here
});
}
}
}

Adding CustomClassObjects to Dictionary as values

I have a task where I need to have two values for one key in Dictionary.
Solution found in web is to make new class with two fields and use it's objects as values.
But how can I assign value to my CustomClassObjects from Dictionary's for loop?
Here is the code:
Dictionary<char, Huffmans> HuffmanDictionary = new Dictionary<char, Huffmans>();
Program.text = File.ReadAllText(Program.sourcetext);
char character;
for (int i = 0; i < Program.text.Length; i++)
{
counter++;
character = Convert.ToChar(Program.text[i]);
if (HuffmanDictionary.ContainsKey(character))
HuffmanDictionary[character].probability++;
else
HuffmanDictionary.Add(character, 1);// here is the problem, obviously program can't assign value directly to class...
}
public class Huffmans
{
public int code = 0;
public double probability = 0;
}
Basically, I need to assign only "probability" values on this step. Should I call constructor for "Huffmans " on each iteration?
Big thanks for any help, Alex
You need to instantiate your class before adding the value:
HuffmanDictionary.Add(character, 1);
Should be:
HuffmanDictionary.Add(character, new Huffmans{ code = 1 });
Alternatively you can create a constructor for your class:
public class Huffmans
{
public Huffmans(int _code)
{
code = _code;
}
public int code = 0;
public double probability = 0;
}
then you can do:
HuffmanDictionary.Add(character, new Huffmans(1));
EDIT:
Some more clarification:
HuffmanDictionary.Add(character, 1);
fails because you are passing a type int into the dictionary but it is expecting the type Huffmans. Our dictionary is : Dictionary<char,Huffmans>()
HuffmanDictionary.Add(character, new Huffmans{ code = 1 });
works because now we are creating a new object of type Huffmans and we are setting the code value to 1.
Not sure if I understood your comment correctly, but effectively we are doing the same as:
var newHuffmans = new Huffmans{ code = 1 };
HuffmanDictionary.Add(character, newHuffmans);
But rather than writing out all that code and creating a named variable with our class, we skip this and pass it directly into the dictionary.

How Can I Get The Value of an Item in an Array via Reflection

Skip to the third paragraph for the question.
Context: I'm creating a 2D spaceship game, and one of the game mechanics is routing power to the 7 different parts of the ship to suit the current situation you're in. There are presets that you can switch to at any time, called power configurations. I have the power configurations stored in 3 different arrays, like so:
int[] powerConfiguration1 = new int[7] {10,10,10,10,20,20,20};
int[] powerConfiguration2 = new int[7] {20,20,20,10,10,10,10};
int[] powerConfiguration3 = new int[7] {10,20,10,20,10,20,10};
When you switch configurations, it calls a method for doing so. The method makes some calculations to determine how long it will take to switch configurations. However, instead of making a switch statement and copy/pasting the code several times in the case of the player switching to any of the three configurations, I want to use PropertyInfo in System.Reflections to choose which property I need to pull values from.
Question: The problem is that I don't know how to get an item from an array. Here is what I have so far, where I'm attempting to determine how much power will need to be rerouted in total and adding it all to a variable. 0 is the index in the configuration at which I have decided to store the shield power. powerToShields is the current power being routed to the shields.
void switchConfiguration(int number) {
PropertyInfo powerConfiguration = GetType().GetProperty("powerConfiguration" + number);
int powerToReroute = 0;
powerToReroute += Mathf.Abs(powerToShields - powerConfiguration[0]);
Could someone please explain what I'm doing wrong and/or show me how to fix it? Or, is there a better way to do this?
EDIT 1: This is coded in C# (Unity).
Side thought
I guess my first question is why not store the arrays in a list. So, instead of powerConfiguration1, powerConfiguration2, powerConfiguration3, why not just store a list of int[], so
List<int[]> powerConfigurationList = new List<int[]>;
powerConfigurationList.Add(new int[7] {10,10,10,10,20,20,20});
powerConfigurationList.Add(new int[7] {20,20,20,10,10,10,10});
powerConfigurationList.Add(new int[7] {10,20,10,20,10,20,10});
That way you can get the item via:
powerToReroute = (powerConfigurationList[number])[0]
Answer to your question
However, assuming that there is some good reason that you can't, and in order to answer your exact question, do the following:
...
PropertyInfo powerConfiguration = GetType().GetProperty("powerConfiguration" + number); //this line is taken from your example above
//then you need to do something like the below
var value = (int[])powerConfiguration.GetValue(instanceThatHasTheProperty);
int powerToReroute = 0;
powerToReroute += Mathf.Abs(powerToShields - value[0]);
From your code snippet, I see you have GetType().GetProperty("powerConfiguration" + number);. I'm not sure what the actual instance is that your getting that type from. So you need to replace instanceThatHasTheProperty in my above snippet, by whatever instance you're trying to get the property's value from.
The thing that is immediately obvious to me is that the code is unnecessarily obfuscated and seems an awful lot like an X-Y problem. Using jagged arrays and reflection seems like a whole lot of work to end-around object oriented programming. My recommendation would be to create a class to store your power configurations, store multiple power configurations in a list, and then select the configuration from the list.
Sample Class for Power Configurations
public class PowerConfiguration
{
public int ID { get; set; }
public string Name { get; set; }
public int Shields { get; set; }
public int Weapons { get; set; }
public int LifeSupport { get; set; }
public int Propulsion { get; set; }
}
Inserting and Accessing your Power Configurations
public class DoStuff
{
public void LoadPowerConfiguration()
{
// Create a List to store configurations
List<PowerConfiguration> allPowerConfigurations = new List<PowerConfiguration>();
// Add some mock data to the list
allPowerConfigurations.Add(new PowerConfiguration()
{
ID = 0,
Name = "Balanced Combat",
Shields = 30,
Weapons = 30,
LifeSupport = 20,
Propulsion = 20
});
allPowerConfigurations.Add(new PowerConfiguration()
{
ID = 1,
Name = "Offensive",
Shields = 20,
Weapons = 50,
LifeSupport = 10,
Propulsion = 20
});
// Figure out which ID you what (eg. from the user pressing '0')
int selectedConfigurationID = 0;
// Get the configuration from the list
PowerConfiguration selectedConfiguration =
allPowerConfigurations.FirstOrDefault(p => p.ID == selectedConfigurationID);
// Now perform your operations against the PowerConfiguration object's properties
int powerToShields = 100;
int powerToReroute = 0;
powerToReroute += Math.Abs(powerToShields - selectedConfiguration.Shields);
}
}

c# Confusion over what type of array and usage

I am new to c# and am trying to build an array of arrays of items. I have looked at 2d arrays and jagged arrays and simply can't work out what i'm supposed to be using and can not get it to work. It's not so much building the array it's then looping through it to interrogate the array elements. I'm working within an existing library which is where all the variables come from, most of the other supporting code I've left out as it's not relevant. Once a instance is found i'm then trying to update a field from 0 to 1. Many thanks for any help in advance.
//Declare array
private double[,] myOpenTrades;
private void mymethod (double score, double RSIComboScore, int type, int line)
{
myOpenTrades[line,0] = type;
myOpenTrades[line,1] = CurrentBar;
myOpenTrades[line,2] = Close[0];
myOpenTrades[line,3] = rewardClose;
myOpenTrades[line,4] = riskClose;
myOpenTrades[line,5] = score;
myOpenTrades[line,6] = RSIComboScore;
myOpenTrades[line,7] = this.getSMATrend();
myOpenTrades[line,8] = Math.Round(NSRSICS(5, 15, 60, 240).Rsi200AVGPlot[0]);
myOpenTrades[line,9] = myReward;
myOpenTrades[line,10] = myRisk;
myOpenTrades[line,11] = 0;
}
protected override void OnMyChange()
{
foreach(double[] row in myOpenTrades)
{
if(Close[0] >= row[3] && row[11]==0)
{
Print("WIN:"+row[10]);
row[11]=1;
}
else if(Close[0] >= row[4] && row[11]==0)
{
Print("LOSE:"+row[9]);
row[11]=1;
}
}
{
I don't know why this is being downvoted, it seems like a legitimate question from a new user who made some effort.
To answer your question, an array of arrays is not the best choice, because from a logical organization perspective you don't have a "grid" (i.e. 2D array) of the same item, you have multiple items as one record, and an array of records. Not to mention that you appear to be trying to mix and match types; your array is declared as double but the first record type is an integer.
I would recommend using a class as follows:
class OpenTrades
{
public int Type;
public Bar CurrentBar;
public double Score;
// etc...
}
(This is assume that CurrentBar's type is Bar; you'll have to substitute Bar with whatever that type actually is.)
Then you would instantiate an array of your class like this:
OpenTrades[] myOpenTrades = new OpenTrades[11]; // This will create an array of 11 elements, indices 0 to 10
Now in your mymethod function you can assign values to each of your members.
myOpenTrades[line].Type = type;
myOpenTrades[line].Bar = CurrentBar;
myOpenTrades[line].Score = score;
// etc ...

Categories