Knuth's algorithm for solving MasterMind with 5 guesses [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I read knuth's algorithm in wikipedia and I wonder about the 3rd step. If I understand correct for each option (even if not removed in step 2), we calculate how many possible guesses would have removed for every ffedback. for that step we take minimum. after, we find the maximum on the minimums and take the code the max belong to it. that will be our second guess. Im not sure what can be done next because,each time we dont change the max on the minimums (or what is the minimum). In addition, how can I implement this step in c# for example. How can I procceed and how can I implement that step? What does the minimum on the feedbacks really mean?

You need a constant collection of all possible outcomes, a collection of the remaining alternatives, and a method that can compute the outcome given a guess and a solution.
First, model the relevant domain objects:
public class Outcome
{
public int White { get; set; }
public int Black { get; set; }
}
public class Combination
{
// however you like to model this
}
Then, create the method that checks the guess against the secret:
public static Outcome Check(Combination guess, Combination solution)
{
// your implementation
}
Now the algorithm is as follows:
Outcome[] outcomes = new[] { new Outcome { White = 0, Black = 0 },
new Outcome { White = 1, Black = 0 },
// ... all other possibilities
};
// assume we have some list of combinations
int min = Integer.MaxValue;
Combination minCombination = null;
foreach (var guess in combinations)
{
int max = 0;
foreach (var outcome in outcomes)
{
var count = 0;
foreach (var solution in combinations)
{
if (Check(guess, solution) == outcome)
count++;
}
if (count > max)
max = count;
}
if (max < min)
{
min = max;
minCombination = guess;
}
}
At the end of the loop, minCombination is your next guess.
EDIT I messed up min and max in the first version, that is fixed now. The inner count gives the number of remaining options, provided the chosen combination and the assumed outcome. We want the maximum over the outcomes (the worst possible result for the chosen combination is the one that leaves most options remaining). After that we want the minimum over the combinations (the best possible combination is the one that leaves least options remaining in the worst case).
If you like Linq, you could also write the algorithm as
combinations.MaxBy(guess =>
outcomes.Min(outcome =>
combinations.Count(solution =>
Check(guess, solution) == outcome)));
in which I used MaxBy from the MoreLinq project.

Related

How do i deterministically generate n unique numbers within a range from a GUID? [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 5 years ago.
Improve this question
A concrete example.
If i have a range of 1-300, how can a generate 5 unique numbers within that range using GUID "EDAAE218-FBF0-4B66-AEAF-FB036FBF69F4". Applying the same algorithm to the GUID should result in the same 5 numbers being chosen every time.
The input doesn't have to be a GUID, it's just acting as some sort of key.
Some context for the problem i am trying to solve. I have a hard coded List of values that contains roughly 300 or so elements. I am trying to find a way to select 20 elements from this list that always produces the same elements.
My idea was to generate a GUID which could be handed out to multiple users. When those users input the GUID into the app, the same 20 elements would be returned for everyone.
A guid is effectively a 128-bit number. So you can easily do this provided that the number of bits required to represent your numbers are fewer than the number of bits in the guid (128). You don't need to hash the guid or anything like that.
EDIT:
Now that I know what you need (i.e. a unique seed to be derived from a guid, you could do it this way) - but you could equally hand out a 32-bit number and avoid the guid-to-int conversion.
EDIT2: Using GetHashCode as per suggestion from comments above.
EDIT 3: Producing unique numbers.
static void Main(string[] args)
{
var guid = new Guid("bdc39e63-5947-4704-9e12-ec66c8773742");
Console.WriteLine(guid);
var numbers = FindNumbersFromGuid(guid, 16, 8);
Console.WriteLine("Numbers: ");
foreach (var elem in numbers)
{
Console.WriteLine(elem);
}
Console.ReadKey();
}
private static int[] FindNumbersFromGuid(Guid input,
int maxNumber, int numberCount)
{
if (numberCount > maxNumber / 2) throw new ArgumentException("Choosing too many numbers.");
var seed = input.GetHashCode();
var random = new Random(seed);
var chosenSoFar = new HashSet<int>();
return Enumerable.Range(0, numberCount)
.Select(e =>
{
var ret = random.Next(0, maxNumber);
while (chosenSoFar.Contains(ret))
{
ret = random.Next(0, maxNumber);
}
chosenSoFar.Add(ret);
return ret;
}).ToArray();
}

Generating a variable number of random numbers to a list, then comparing those numbers to a target?

How would I go about generating a serializable variable of random numbers to a list, then comparing those generated numbers to a target number?
What I want to do is make a program that takes in a number, such as 42, and generates that number of random numbers to a list while still keeping the original variable, in this case 42, to be referenced later. Super ham-handed pseudo-code(?) example:
public class Generate {
[SerializeField]
int generate = 42;
List<int> results = new List<int>;
public void Example() {
int useGenerate = generate;
//Incoming pseudo-code (rather, code that I don't know how to do, exactly)
while (useGenerate => 1) {
results.add (random.range(0,100)); //Does this make a number between 0 and 99?
int useGenerate = useGenerate - 1;
}
}
}
I think this will do something to that effect, once I figure out how to actually code it properly (Still learning).
From there, I'd like to compare the list of results to a target number, to see how many of them pass a certain threshold, in this case greater than or equal to 50. I assume this would require a "foreach" thingamabobber, but I'm not sure how to go about doing that, really. With each "success", I'd like to increment a variable to be returned at a later point. I guess something like this:
int success = 50;
int target = 0;
foreach int in List<results> {
if (int => success) {
int target = target + 1;
}
}
If I have the right idea, please just teach me how to properly code it. If you have any suggestions on how to improve it (like the whole ++ and -- thing I see here and there but don't know how to use), please teach me that, too. I looked around the web for using foreach with lists and it seemed really complicated and people were seemingly pulling some new bit of information from the Aether to include in the operation. Thanks for reading, and thanks in advance for any advice!

Where is likely the performance bug here? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Many of the test cases are timing out. I've made sure I'm using lazy evaluation everywhere, linear (or better) routines, etc. I'm shocked that this is still not meeting the performance benchmarks.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Mine
{
public int Distance { get; set; } // from river
public int Gold { get; set; } // in tons
}
class Solution
{
static void Main(String[] args)
{
// helper function for reading lines
Func<string, int[]> LineToIntArray = (line) => Array.ConvertAll(line.Split(' '), Int32.Parse);
int[] line1 = LineToIntArray(Console.ReadLine());
int N = line1[0], // # of mines
K = line1[1]; // # of pickup locations
// Populate mine info
List<Mine> mines = new List<Mine>();
for(int i = 0; i < N; ++i)
{
int[] line = LineToIntArray(Console.ReadLine());
mines.Add(new Mine() { Distance = line[0], Gold = line[1] });
}
// helper function for cost of a move
Func<Mine, Mine, int> MoveCost = (mine1, mine2) =>
Math.Abs(mine1.Distance - mine2.Distance) * mine1.Gold;
int sum = 0; // running total of move costs
// all move combinations on the current list of mines,
// given by the indicies of the mines
var indices = Enumerable.Range(0, N);
var moves = from i1 in indices
from i2 in indices
where i1 != i2
select new int[] { i1, i2 };
while(N != K) // while number of mines hasn't been consolidated to K
{
// get move with the least cost
var cheapest = moves.Aggregate(
(prev, cur) => MoveCost(mines[prev[0]],mines[prev[1]])
< MoveCost(mines[cur[0]], mines[cur[1]])
? prev : cur
);
int i = cheapest[0], // index of source mine of cheapest move
j = cheapest[1]; // index of destination mine of cheapest move
// add cost to total
sum += MoveCost(mines[i], mines[j]);
// move gold from source to destination
mines[j].Gold += mines[i].Gold;
// remove from moves any that had the i-th mine as a destination or source
moves = from move in moves
where move[0] == i || move[1] == i
select move;
// update size number of mines after consolidation
--N;
}
Console.WriteLine(sum);
}
}
Lazy evaluation will not make bad algorithms perform better. It will just delay when those performance problems will affect you. What lazy evaluation can help with is space complexity, i.e. reducing the amount of memory you need to execute your algorithm. Since the data is generated lazily, you will not (necessarily) have all the data in the memory at the same time.
However, relying on lazy evaluation to fix your space (or time) complexity problems can easily shoot you in the foot. Look the following example code:
var moves = Enumerable.Range(0, 5).Select(x => {
Console.WriteLine("Generating");
return x;
});
var aggregate = moves.Aggregate((p, c) => {
Console.WriteLine("Aggregating");
return p + c;
});
var newMoves = moves.Where(x => {
Console.WriteLine("Filtering");
return x % 2 == 0;
});
newMoves.ToList();
As you can see, both the aggregate and the newMoves rely on the lazily evaluated moves enumerable. Since the original count of moves is 5, we will see 4 “Aggregating” lines in the output, and 5 “Filtering” lines. But how often do you expect “Generating” to appear in the console?
The answer is 10. This is because moves is a generator and is being evaluated lazily. When multiple places request it, an iterator will be created for each, which ultimately means that the generator will execute multiple times (to generate independent results).
This is not necessarily a problem, but in your case, it very quickly becomes one. Assume that we continue above example code with another round of aggregating. That second aggregate will consume newMoves which in turns will consume the original moves. So to aggregate, we will re-run the original moves generator, and the newMoves generator. And if we were to add another level of filtering, the next round of aggregating would run three interlocked generators, again rerunning the original moves generator.
Since your original moves generator creates an enumerable of quadratic size, and has an actual time complexity of O(n²), this is an actual problem. With each iteration, you add another round of filtering which will be linear to the size of the moves enumerable, and you actually consume the enumerable completely for the aggregation. So you end up with O(n^2 + n^3 + n^4 + n^5 + …) which will eventually be the sum of n^j for j starting at 2 up to N-K. That is a very bad time complexity, and all just because you were trying to save memory by evaluating the moves lazily.
So the first step to make this better is to avoid lazy evaluation. You are constantly iterating moves and filtering it, so you should have it in memory. Yes, that means that you have an array of quadratic size, but you won’t actually need more than that. This also limits the time complexity you have. Yes, you still need to filter the list in linear time (so O(n²) since the size is n²) and you do that inside a loop, so you will end up with cubic time (O(n³)) but that would already be your upper limit (iterating the list a constant amount of times within the loop will only increase the time complexity by a constant, and that doesn’t matter).
Once you have done that, you should consider your original problem, think about what you are actually doing. I believe you could probably reduce the computational complexity further if you use the information you have better, and use data structures (e.g. hash sets, or some graph where the move cost is already stored within) that aid you in the filtering and aggregation. I can’t give you exact ideas since I don’t know your original problem, but I’m sure there is something you can do.
Finally, if you have performance problems, always remember to profile your code. The profiler will tell you what parts of your code is the most expensive, so you can get a clear idea what you should try to optimize and what you don’t need to focus on when optimizing (since optimizing already fast parts will not help you get any faster).

Which is better for doing calcculations? Switch case, if-statment? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I have an assignment that requires a lot conversions between different units of measure. I have all of the work done except the math part. My question is, and if anyone has a better solution im all ears, would it be best to do these calculations using a switch or an if statement? Here is a little background info about my program. I have a text file that contains 9 different units of measurement along with their lengths in terms of feet separated by a comma that looks like as follows:
inch,.083333
fathom,6
foot,1
furlong,660
kilometer,3281.5
meter,3.2815
mile,5280
rod,16.5
yard,3
So, i have successfully dumped all of the information into a string array. From there i split the string array twice. The first time i split the string array, i created a new string array that would hold only the names for each unit of measure. The second time i split the string array, i did it so i could create a double array to hold all of the numeric values for each unit of measurement. Now i need to do the math portion. My program is going to display the nine different units of measure, request the unit to convert from, requests the unit to convert to, request the quantity (or total measurement) to convert, and then display the converted quantity. SO far this is what i have:
private void SandC_Load(object sender, EventArgs e)
{
splitContainer1.Panel1Collapsed = false;
splitContainer1.Panel2Collapsed = true;
string[] lengths = File.ReadAllLines("Units.txt");
int count=0;
string[] unitName=new string[count];
while (!(count==10))
{
count++;
lbLengths.Items.Add(count+"."+" "+lengths[count-1].Split(new Char[]{','})[0]);
}
}
private void btnConvert_Click(object sender, EventArgs e)
{
string orginalunits = tborginalUnits.Text;
int orginalunits1;
string desiredunits = tbDesiredunits.Text;
int desiredunits1;
string lenghttoConvert = tbConvert.Text;
double lenghttoConvert1;
string[] lengths = File.ReadAllLines("Units.txt");
int count = lengths.Length;
double[] units = new double[lengths.Length];
for (int i = 0; i < lengths.Length;i++)
{
units[i] = Convert.ToDouble(lengths[i].Split(new Char[] { ',' })[1]);
}
if ((double.TryParse(lenghttoConvert, out lenghttoConvert1)) && (Int32.TryParse(orginalunits, out orginalunits1)) && (Int32.TryParse(desiredunits, out desiredunits1)))
{
if ((desiredunits1==3)&&(orginalunits1==1))
{
double answer;
answer = units[0] * lenghttoConvert1;
Math.Round(answer, 3);
mtbOutput.Text = Convert.ToString(answer);
lblConversion.Text = "Converted to foot length";
}
}
else
MessageBox.Show("In the'Orginal and Desired Units' boxes, please enter only the numbers 1 -9, and in the 'Length to Covert' Box, please enter only numbers");
}
So as you can see in the button click event, i am at the part where the conversions should take place. My question, once again, is what would be the best method i should use to handle all of these calculations? I already have 1 if statement, and if i am going to do if statements, i feel as if it will be very tedious and was wondering if there was a more efficient way of doing this. Thanks for your help guys, i really do appreciate it.
The best approach is to use a little math to avoid conditionals altogether.
No matter what's the original and target units are, you can do the conversion through by converting the original units to feet and then converting feet to the target unit.
Let's say you want to go from X units at index i to units at index j. All you need to do is dividing X by units[i], and multiplying by units[j]. No conditionals or switches are required.
How would the program know which unit to choose?
This depends on the organization of your program. This could be a very simple task if you use drop-down boxes for unit names in your UI, because the index of the selected item will be the same as the index of the conversion rate in the units[] array.
Given this specific example, if statements and switch statements are both redundant.
Another way to solve this would be to create a mapping table (two dimensional array) where you specify the conversion multiplier between both units especially that your code already uses digits to represent units instead of their actual names.
For example
C[1][1] = 1;
C[1][2] = 3.1;
C[1][3] = 5;
C[1][4] = 0.33;
C[2][1] = 1/C[1][2];
....
....
C[4][1] = 1/C[1][4];
After creating that array, you can simply plugin the numbers depending on the source and destination currencies to do the conversion.
You can further improve on the above by creating one or two if statement that check whether the first parameter for the array is less than the second or not. If yes, then take the value as it is, if not take the reciprocal of the value. Therefore, you dont have to fill the entire array with values such as:
C[2][1] = 1/C[1][2];
C[4][1] = 1/C[1][4];
Hope that helped.

Getting average values from one Array to another Array [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I’m no programmer but I’m learning C# to build a foreign exchange trading system and Arrays are being a struggle…
The problem I have is the following…
I have a one dimensional Array with, let’s say, 100 elements in it.
Now I need to build another one dimensional array with a 10 elements rolling average based on the first Array.
Said in another way, I need to take the elements from the first Array starting in i = 0 up to i = 9 and average them and save the average in a new array. Than move one step forward and take i = 1 up to i = 10 from the original Array and average them and save the result in the new Array….and so forth….in Excel this would be extremely easy….
My need to have the data in Arrays is because later I will need to compare the last 10 elements rolling average with historical data….
Please, can anyone build a sample code that I can work with?
Many thanks
Paulo
Maybe something like this could work... Did this on my mac in sublime text so you'll still have to work with. Should get the point though.
public class Foo
{
List<int> main = new List<int>(100);
List<int> rollingAverages = new List<int>(100);
public void Add(int score)
{
main.Add(score);
if(main.Count > 10)
{
int rollingAverage = AverageLast10();
rollingAverages.Add(rollingAverage);
}
}
public int AverageLast10()
{
int sum = 0;
for(int i = main.Count - 10; i < 10; i++)
{
sum += main[i];
}
return sum / 10;
}
}
Somewhere else in the code
Foo foo = new Foo();
foo.Add(94);
foo.Add(94);
...
yadda yadda yadda

Categories