C# Find the Next X and Previous Numbers in a sequence - c#

I have a list of numbers, {1,2,3,4,...,End} where End is specified. I want to display the X closest numbers around a given number Find within the list. If x is odd I want the extra digit to go on the greater than side.
Example (Base Case)
End: 6
X: 2
Find: 3
The result should be: {2,3,4}
Another Example (Bound Case):
End: 6
X: 4
Find: 5
The result should be: {2,3,4,5,6}
Yet Another Example (Odd Case):
End: 6
X: 3
Find: 3
The result should be: {2,3,4,5}
I'm assuming it would be easier to simply find a start and stop value, rather than actually generating the list, but I don't really care one way or another.
I'm using C# 4.0 if that matters.
Edit: I can think of a way to do it, but it involves way too many if, else if cases.
if (Find == 1)
{
Start = Find;
Stop = (Find + X < End ? Find + X : End);
}
else if (Find == 2)
{
if (X == 1)
{
Start = Find;
End = (Find + 1 < End ? Find + 1 : End);
}
...
}
You can hopefully see where this is going. I assuming I'm going to have to use a (X % 2 == 0) for odd/even checking. Then some bound thats like less = Find - X/2 and more = Find + X/2. I just can't figure out the path of least if cases.
Edit II: I should also clarify that I don't actually create a list of {1,2,3,4...End}, but maybe I need to just start at Find-X/2.

I realise that you are learning, and out of respect from this I will not provide you with the full solution. I will however do my best to nudge you in the right direction.
From looking at your attempted solution, I think you need to figure out the algorithm you need before trying to code up something that may or may not solve your problem. As you say yourself, writing one if statement for every possible permutation on the input is not a manageble solution. You need to find an algorithm that is general enough that you can use it for any input you get, and still get the right results out.
Basically, there are two questions you need to answer before you'll be able to code up a working solution.
How do I find the lower bound of the list I want to return?
How do I find the upper bound of the list I want to return?
Considering the example base case, you know that the given parameter X contains a number that tells you how many numbers around Find you should display. Therefore you need to divide X equally on both sides of Find.
Thus:
If I get an input X = 4 and Find = 3, the lower bound will be 3 - 4/2 or Find - X/2.
The higher bound will be 3 + 4/2 or Find + X/2.
Start by writing a program that runs and works for the base case. Once that is done, sit down and figure out how you would find the higher and lower bounds for a more complicated case.
Good luck!

You can look at Extension methods. skip and take.
x.Skip(3).Take(4);
this will help u in what u r trying to do

Related

Refer to a specific index of an array depending on user input

Trying to make a program where it takes in an equation from user and outputs the answer. Having to develop all code for it to work, and wondering how I could refer to either array index value either side of a specific index?
Example:
User input: X = 5 + 5 * 6
Wanting to be able to locate the ***** and retrieve the value of the 5 & 6 either side of it. Tried multiple things and tried searching here too, cannot find a answer.
Thankyou in advance to anyone who takes the time to help!
One way to do it is to use regular expressions. I would remove all whitespaces first to make it easier. For example:
string input = "X = 5 + 5 * 6";
Regex r = new Regex(#"(\d+)\*(\d+)");
Match m = r.Match(input.Replace(" ", ""));
var a = m.Groups[1].Value; // a = 5
var b = m.Groups[2].Value; // b = 6
Explanation of this regex can be found here: https://regex101.com/r/k7rthI/1
You would have to improve the regex to handle decimals and many other cases when the equation gets more complex. It is a long dark rabbit hole to go down if you get more complex than what you have. So you might be better off finding a math library you can use. No reason to reinvent the wheel.

Possible to do this in better than O(n^2) time?

The problem I'm trying to solve gives me a matrix like
10101
11100
11010
00101
where the rows are supposed to represented topics that a person knows; e.g. Person 1, represented by 10101, knows topics 1, 3 and 5, but not 2 or 4. I need to find the maximum number of topics that a 2-person team could know; e.g. the team that is Person 1 and 3 knows all the topics because between 10101 and 11010 there are 1s at every index.
I have an O(n^2) solution
string[] topic = new string[n];
for(int topic_i = 0; topic_i < n; topic_i++)
{
topic[topic_i] = Console.ReadLine();
}
IEnumerable<int> teamTopics =
from t1 in topic
from t2 in topic
where !Object.ReferenceEquals(t1, t2)
select t1.Zip(t2, (c1, c2) => c1 == '1' || c2 == '1').Sum(b => b ? 1 : 0);
int max = teamTopics.Max();
Console.WriteLine(max);
which is passing all the test cases it doesn't time out on. I suspect the reason it's not fast enough has to do with the time complexity rather than the overhead of the LINQ machinery. But I can't think of a better way to do it.
I thought that maybe I could map the indices of topics to the persons who know them, like
1 -> {1,2,3}
2 -> {2,3}
3 -> {1,2,4}
4 -> {3}
5 -> {1,4}
but I can't think of where to go from there.
Can you supply me with a "hint"?
Let's say we have n people and m topics.
I would argue that your algorithm is O(n^2 * m), where n is number of people, because:
from t1 in topic gets you O(n)
from t2 in topic gets you to O(n^2)
t1.Zip(t2 ... get you to O(n^2 * m)
An optimisation that I see is first to modify strings a bit:
s1 = '0101', where i-th element shows whether a person i knows 1st topic
s2 = '1111', where i-th element shows whether a person i knows 2nd topic.
etc...
Then you analyse string s1. You pick all possible pairs of 1s (O(n^2) elements) that show pairs of people that together know 1st topic. Then go pick a pair from that list and check whether they know 2nd topic as well and so on. When they don't, delete it from the list and move on to another pair.
Unfortunately this looks to be O(n^2 * m) as well, but this should be quicker in practise. For very sparse matrix, it should be close to O(n2), and for dense matrices it should find a pair pretty soon.
Thoughts:
as a speculative optimization: you could do an O(n) sweep to find the individual with the highest number of skills (largest hamming weight); note them, and stop if they have everything: pair them with anyone, it doesn't matter
you can exclude anyone without testing who only has skilled shared with the "best" individual - we already know about everything they can offer and have tested against everyone; so only test if (newSkills & ~bestSkills) != 0 - meaning: the person being tested has something that the "best" worker didn't have; this leaves m workers with complementary skills plus the "best" worker (you must include them explicitly, as the ~/!=0 test above will fail for them)
now do another O(m) sweep of possible partners - checking to see if the "most skilled" plus any other gives you all the skills (obviously stop earlier if a single member has all the skills); but either way: keep track of best combination for later reference
you can further half the time by only considering the triangle, not the square - meaning: you compare row 0 to rows 1-(m-1), but row 1 to rows 2-(m-1), row 5 to 6-(m-1), etc
you can significantly improve things by using integer bit math along with an efficient "hamming weight" algorithm (to count the set bits) rather than strings and summing
get rid of the LINQ
short-circuit if you get all ones (compare to ~((~0)<<k), where k is the number of bits being tested for)
remember to compare any result to the "best" combination we found against the most skilled worker
This is still O(n) + O(m^2) where m <= n is the number of people with skills different to the most skilled worker
Pathological but technically correct answer:
insert a Thread.Sleep(FourYears) - all solutions are now essentially O(1)
Your solution is asymptotically as efficient as it gets, because you need to examine all pairs to arrive at the maximum. You can make your code more efficient by replacing strings with BitArray objects, like this:
var topic = new List<BitArray>();
string line;
while ((line = Console.ReadLine()) != null) {
topic.Add(new BitArray(line.Select(c => c=='1').ToArray()));
}
var res =
(from t1 in topic
from t2 in topic
select t1.Or(t2).Count).Max();
Console.WriteLine(res);
Demo.

Why would this method need to be recursive?

On a whim, I've decided to go back and seek certification, starting with 98-361, Fundamentals of Software Development. (I'm doing this more for myself than anything else. I want to fill in gaps in my knowledge.)
In the very early course of the book, they present this interesting scenario in the Proficient Assessment section:
You are developing a library of utility functions for your
application. You need to write a method that takes an integer and
counts the number of significant digits in it. You need to create a recursive program
to solve this problem. How would you write such a
program?
I find myself gaping at this scenario in befuddlement. If I understand "significant digits" correctly, there's no need whatsoever for a function that counts an integer's significant digits to be recursive. And, any architect who insisted that it be recursive should have his head examined.
Or am I not getting it? Did I completely miss something here? From what I understand, the significant digits are the digits of a number, starting from the left, and proceeding right, excluding any leading zeroes.
Under what conditions would this need to be recursive? (The whole point of this exercise for me is to learn new things. Someone throw me a bone.)
EDIT: I don't want an answer to the problem question. I can figure that out on my own. It just seems to me that this "problem" could be solved far more easily with a simple foreach loop over the characters in a string.
Final Edit
Given the sage advice of the awesome posters below, this was the simple solution I came up with to solve the problem. (Despite what misgivings I may have.)
using System;
class Program
{
static void Main(string[] args)
{
var values = new[] { 5, 15, 150, 250, 2500, 25051, 255500005, -10, -1005 };
foreach (var value in values)
{
Console.WriteLine("Signficiant digits for {0} is {1}.", value, SignificantDigits(value));
}
}
public static int SignificantDigits(int n)
{
if (n == 0)
{
return 0;
}
return 1 + SignificantDigits((int)(n / 10));
}
}
There's no need for such an algorithm to be recursive. But the intent here is not to write real-world code, it's to ensure you understand recursion.
Since you stated you weren't after code, I'll be careful here, but I need to provide something to compare the complexity of the solutions, so I'll use pseudo-code. A recursive solution may be something like:
def sigDigits (n):
# Handle negative numbers.
if n < 0:
return sigDigits (-n)
# 0..9 is one significant digit.
if n < 10:
return 1
# Otherwise it's one plus the count in n/10 (truncated).
return 1 + sigDigits (n / 10)
And you're right, it equally doable as iteration.
def sigDigits (n):
# Handle negative numbers.
if n < 0:
n = -n
# All numbers have at least one significant digit.
digits = 1
# Then we add one and divide by ten (truncated), until we get low enough.
while n > 9:
n = n / 10
digits = digits + 1
return digits
There are some (usually of a mathematical bent, and including myself) that consider recursive algorithms much more elegant where they're suitable (such as where the "solution search space" reduces very quickly so as to not blow out your stack).
I question the suitability in this particular case since the iterative solution is not too complex, but the questioner had to provide some problem and this one is relatively easy to solve.
And, as per your edit:
... could be solved far more easily with a simple foreach loop over the characters in a string
You don't have a string, you have an integer. I don't doubt that you could turn that into a string and then count characters but that seems a roundabout way of doing it.
It doesn't need to be recursive. It's simply that the question is asking you to write a recursive implementation, presumably to test your understanding of how a recursive function works.
That seems like a pretty forced example. The problem can be solved with an simpler iterative algorithm.
A lot of teaching resources really struggle to provide useful examples of when to use recursion. Technically you never need to use it, but for a large class of (mostly algorithmic) problems, it can really simplify things.
For example, consider any operation on a binary tree. Because the physical structure of a binary tree is recursive, the algorithms that operate on it are also naturally recursive. You can also write imperative algorithms to operate on binary trees, but the recursive ones are simpler to write and understand.

Find the Discrete Pair of {x,y} that Satisfy Inequality Constriants

I have a few inequalities regarding {x,y}, that satisfies the following equations:
x>=0
y>=0
f(x,y)=x^2+y^2>=100
g(x,y)=x^2+y^2<=200
Note that x and y must be integer.
Graphically it can be represented as follows, the blue region is the region that satisfies the above inequalities:
The question now is, is there any function in Matlab that finds every admissible pair of {x,y}? If there is an algorithm to do this kind of thing I would be glad to hear about it as well.
Of course, one approach we can always use is brute force approach where we test every possible combination of {x,y} to see whether the inequalities are satisfied. But this is the last resort, because it's time consuming. I'm looking for a clever algorithm that does this, or in the best case, an existing library that I can use straight-away.
The x^2+y^2>=100 and x^2+y^2<=200 are just examples; in reality f and g can be any polynomial functions of any degree.
Edit: C# code are welcomed as well.
This is surely not possible to do in general for a general set of polynomial inequalities, by any method other than enumerative search, even if there are a finite number of solutions. (Perhaps I should say not trivial, as it is possible. Enumerative search will work, subject to floating point issues.) Note that the domain of interest need not be simply connected for higher order inequalities.
Edit: The OP has asked about how one might proceed to do a search.
Consider the problem
x^3 + y^3 >= 1e12
x^4 + y^4 <= 1e16
x >= 0, y >= 0
Solve for all integer solutions of this system. Note that integer programming in ANY form will not suffice here, since ALL integer solutions are requested.
Use of meshgrid here would force us to look at points in the domain (0:10000)X(0:10000). So it would force us to sample a set of 1e8 points, testing every point to see if they satisfy the constraints.
A simple loop can potentially be more efficient than that, although it will still require some effort.
% Note that I will store these in a cell array,
% since I cannot preallocate the results.
tic
xmax = 10000;
xy = cell(1,xmax);
for x = 0:xmax
% solve for y, given x. This requires us to
% solve for those values of y such that
% y^3 >= 1e12 - x.^3
% y^4 <= 1e16 - x.^4
% These are simple expressions to solve for.
y = ceil((1e12 - x.^3).^(1/3)):floor((1e16 - x.^4).^0.25);
n = numel(y);
if n > 0
xy{x+1} = [repmat(x,1,n);y];
end
end
% flatten the cell array
xy = cell2mat(xy);
toc
The time required was...
Elapsed time is 0.600419 seconds.
Of the 100020001 combinations that we might have tested for, how many solutions did we find?
size(xy)
ans =
2 4371264
Admittedly, the exhaustive search is simpler to write.
tic
[x,y] = meshgrid(0:10000);
k = (x.^3 + y.^3 >= 1e12) & (x.^4 + y.^4 <= 1e16);
xy = [x(k),y(k)];
toc
I ran this on a 64 bit machine, with 8 gig of ram. But even so the test itself was a CPU hog.
Elapsed time is 50.182385 seconds.
Note that floating point considerations will sometimes cause a different number of points to be found, depending on how the computations are done.
Finally, if your constraint equations are more complex, you might need to use roots in the expression for the bounds on y, to help identify where the constraints are satisfied. The nice thing here is it still works for more complicated polynomial bounds.

C# - Suggestions of control statement needed

I'm a student and I got a homework i need some minor help with =)
Here is my task:
Write an application that prompts the user to enter the size of a square and display a square of asterisks with the sides equal with entered integer. Your application works for side’s size from 2 to 16. If the user enters a number less than 2 or greater then 16, your application should display a square of size 2 or 16, respectively, and an error message.
This is how far I've come:
start:
int x;
string input;
Console.Write("Enter a number between 2-16: ");
input = Console.ReadLine();
x = Int32.Parse(input);
Console.WriteLine("\n");
if (x <= 16 & x >= 2)
{
control statement
code
code
code
}
else
{
Console.WriteLine("You must enter a number between 2 and 16");
goto start;
}
I need help with...
... what control statment(if, for, while, do-while, case, boolean) to use inside the "if" control.
My ideas are like...
do I write a code that writes out the boxes for every type of number entered? That's a lot of code...
..there must be a code containing some "variable++" that could do the task for me, but then what control statement suits the task best?
But if I use a "variable++" how am I supposed to write the spaces in the output, because after all, it has to be a SQUARE?!?! =)
I'd love some suggestions on what type of statements to use, or maybe just a hint, of course not the whole solution as I am a student!
It's not the answer you're looking for, but I do have a few suggestions for clean code:
Your use of Int32.Parse is a potential exception that can crash the application. Look into Int32.TryParse (or just int.TryParse, which I personally think looks cleaner) instead. You'll pass it what it's parsing and an "out" parameter of the variable into which the value should be placed (in this case, x).
Try not to declare your variables until you actually use them. Getting into the habit of declaring them all up front (especially without instantiated values) can later lead to difficult to follow code. For my first suggestions, x will need to be declared ahead of time (look into default in C# for default instantiation... it's, well, by default, but it's good information to understand), but the string doesn't need to be.
Try to avoid using goto when programming :) For this code, it would be better to break out the code which handles the value and returns what needs to be drawn into a separate method and have the main method just sit around and wait for input. Watch for hard infinite loops, though.
It's never too early to write clean and maintainable code, even if it's just for a homework assignment that will never need to be maintained :)
You do not have to write code for every type of number entered. Instead, you have to use loops (for keyword).
Probably I must stop here and let you do the work, but I would just give a hint: you may want to do it with two loops, one embedded in another.
I have also noted some things I want to comment in your code:
Int32.Parse: do not use Int32, but int. It will not change the meaning of your code. I will not explain why you must use int instead: it is quite difficult to explain, and you would understand it later for sure.
Avoid using goto statement, except if you were told to use it in the current case by your teacher.
Console.WriteLine("\n");: avoid "\n". It is platform dependent (here, Linux/Unix; on Windows it's "\r\n", and on MacOS - "\n\r"). Use Environment.NewLine instead.
x <= 16 & x >= 2: why & and not ||?
You can write string input = Console.ReadLine(); instead of string input; followed by input = Console.ReadLine();.
Since it's homework, we can't give you the answer. But here are some hints (assuming solid *'s, not white space in-between):
You're going to want to iterate from 1 to N. See for (int...
There's a String constructor that will allow you to avoid the second loop. Look at all of the various constructors.
Your current error checking does not meet the specifications. Read the spec again.
You're going to throw an exception if somebody enters a non-parsable integer.
goto's went out of style before bell-bottoms. You actually don't need any outer control for the spec you were given, because it's "one shot and go". Normally, you would write a simple console app like this to look for a special value (e.g., -1) and exit when you see that value. In that case you would use while (!<end of input>) as the outer control flow.
If x is greater or equal to 16, why not assign 16 to it (since you'll eventually need to draw a square with a side of length 16) (and add an appropriate message)?
the control statement is:
for (int i = 0; i < x; i++)
{
for ( int j = 0; j < x; j++ )
{
Console.Write("*");
}
Console.WriteLine();
}
This should print a X by X square of asterisks!
I'ma teacher and I left the same task to my students a while ago, I hope you're not one of them! :)

Categories