This question already has an answer here:
Generating numbers list in C#
(1 answer)
Closed 9 years ago.
I want to get a sequence of integers from a value A to a value B.
For example A=3 and B=9. Now I want to create a sequence 3,4,5,6,7,8,9 with one line of code and without a loop. I played around with Enumerable.Range, but I find no solution that works.
Has anybody an idea?
var sequence = Enumerable.Range(min, max - min + 1);
?
For info, though - personally I'd still be tempted to use a loop:
for(int i = min; i <= max ; i++) { // note inclusive of both min and max
// good old-fashioned honest loops; they still work! who knew!
}
int A = 3;
int B = 9;
var seq = Enumerable.Range(A, B - A + 1);
Console.WriteLine(string.Join(", ", seq)); //prints 3, 4, 5, 6, 7, 8, 9
if you have lots and lots of numbers and the nature of their processing is streaming (you handle items one at a time), then you don't need to hold all of the in memory via array and it's comfortable to work with them via IEnumerable<T> interface.
Related
I'm trying to solve a problem on code wars and the unit tests provided make absolutely no sense...
The problem is as follows and sounds absolutely simple enough to have something working in 5 minutes
Consider a sequence u where u is defined as follows:
The number u(0) = 1 is the first one in u.
For each x in u, then y = 2 * x + 1 and z = 3 * x + 1 must be in u too.
There are no other numbers in u.
Ex: u = [1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...]
1 gives 3 and 4, then 3 gives 7 and 10, 4 gives 9 and 13, then 7 gives 15 and 22 and so on...
Task:
Given parameter n the function dbl_linear (or dblLinear...) returns the element u(n) of the ordered (with <) sequence u.
Example:
dbl_linear(10) should return 22
At first I used a sortedset with a linq query as I didnt really care about efficiency, I quickly learned that this operation will have to calculate to ranges where n could equal ~100000 in under 12 seconds.
So this abomination was born, then butchered time and time again since a for loop would generate issues for some reason. It was then "upgraded" to a while loop which gave slightly more passed unit tests ( 4 -> 8 ).
public class DoubleLinear {
public static int DblLinear(int n) {
ListSet<int> table = new ListSet<int> {1};
for (int i = 0; i < n; i++) {
table.Put(Y(table[i]));
table.Put(Z(table[i]));
}
table.Sort();
return table[n];
}
private static int Y(int y) {
return 2 * y + 1;
}
private static int Z(int z) {
return 3 * z + 1;
}
}
public class ListSet<T> : List<T> {
public void Put(T item) {
if (!this.Contains(item))
this.Add(item);
}
}
With this code it still fails the calculation in excess of n = 75000, but passes up to 8 tests.
I've checked if other people have passed this, and they have. However, i cannot check what they wrote to learn from it.
Can anyone provide insight to what could be wrong here? I'm sure the answer is blatantly obvious and I'm being dumb.
Also is using a custom list in this way a bad idea? is there a better way?
ListSet is slow for sorting, and you constantly get memory reallocation as you build the set. I would start by allocating the table in its full size first, though honestly I would also tell you using a barebones array of the size you need is best for performance.
If you know you need n = 75,000+, allocate a ListSet (or an ARRAY!) of that size. If the unit tests start taking you into the stratosphere, there is a binary segmentation technique we can discuss, but that's a bit involved and logically tougher to build.
I don't see anything logically wrong with the code. The numbers it generates are correct from where I'm standing.
EDIT: Since you know 3n+1 > 2n+1, you only ever have to maintain 6 values:
Target index in u
Current index in u
Current x for y
Current x for z
Current val for y
Current val for z
public static int DblLinear(int target) {
uint index = 1;
uint ind_y = 1;
uint ind_z = 1;
uint val_y = 3;
uint val_z = 4;
if(target < 1)
return 1;
while(index < target) {
if(val_y < val_z) {
ind_y++;
val_y = 2*ind_y + 1;
} else {
ind_z++;
val_z = 3*ind_z + 1;
}
index++;
}
return (val_y < val_z) ? val_y : val_z;
}
You could modify the val_y if to be a while loop (more efficient critical path) if you either widen the branch to 2 conditions or implement a backstep loop for when you blow past your target index.
No memory allocation will definitely speed your calculations up, even f people want to (incorrectly) belly ache about branch prediction in such an easily predictable case.
Also, did you turn optimization on in your Visual Studio project? If you're submitting a binary and not a code file, then that can also shave quite a bit of time.
I am currently trying to write C# code that finds multiple arrays of integers that equal a specified total when they are summed up. I would like to find these combinations while each integer in the array is given a range it can be.
For example, if our total is 10 and we have an int array of size 3 where the first number can be between 1 and 4, the second 2 and 4, and the third 3 and 6, some possible combination are [1, 3, 6], [2, 2, 6], and [4, 2, 4].
What sort of algorithm would help with solving a problem like this that can run in them most efficient amount of time? Also, what other things should I keep in mind when transitioning this problem into C# code?
I would do this using recursion. You can simply iterate over all possible values and see if they give a required sum.
Input
Let's suppose we have the following input pattern:
N S
min1 min2 min3 ... minN
max1 max2 max3 ... maxN
For your example
if our total is 10 and we have an int array of size 3 where the first
number can be between 1 and 4, the second 2 and 4, and the third 3 and
6
it will be:
3 10
1 2 3
4 4 6
Solution
We have read our input values. Now, we just try to use each possible number for our solution.
We will have a List which will store the current path:
static List<int> current = new List<int>();
The recursive function is pretty simple:
private static void Do(int index, int currentSum)
{
if (index == length) // Termination
{
if (currentSum == sum) // If result is a required sum - just output it
Output();
return;
}
// try all possible solutions for current index
for (int i = minValues[index]; i <= maxValues[index]; i++)
{
current.Add(i);
Do(index + 1, currentSum + i); // pass new index and new sum
current.RemoveAt(current.Count() - 1);
}
}
For non-negative values we can also include such condition. This is the recursion improvement which will cut off a huge amount of incorrect iterations. If we already have a currentSum greater than sum then it is useless to continue in this recursion branch:
if (currentSum > sum) return;
Actually, this algorithm is a simple "find combinations that give a sum S" problem solution with one difference: inner loop indices within minValue[index] and maxValue[index].
Demo
Here is the working IDEOne demo of my solution.
You cannot do much better than nested for loops/recursion. Though if you are familiar with the 3SUM problem you will know a little trick to reduce the time complexity of this sort of algorithm! If you have n ranges then you know what number you have to pick from the nth range after you make your first n-1 choices!
I will use an example to walk through my suggestion.
if our total is 10 and we have an int array of size 3 where the first number can be between 1 and 4, the second 2 and 4, and the third 5 and 6
First of all lets process the data to be a bit nicer to deal with. I personally like the idea of working with ranges that start at 0 instead of arbitrary numbers! So we subtract the lower bounds from the upper bounds:
(1 to 4) -> (0 to 3)
(2 to 4) -> (0 to 2)
(5 to 6) -> (0 to 1)
Of course now we need to adjust our target sum to reflect the new ranges. So we subtract our original lower bounds from our target sum as well!
TargetSum = 10-1-2-5 = 2
Now we can represent our ranges with just the upper bound since they share a lower bound! So a range array would look something like:
RangeArray = [3,2,1]
Lets sort this (it will become more obvious why later). So we have:
RangeArray = [1,2,3]
Great! Now onto the beef of the algorithm... the summing! For now I will use for loops as it is easier to use for example purposes. You will have to use recursion. Yeldar's code should give you a good starting place.
result = []
for i from 0 to RangeArray[0]:
SumList = [i]
newSum = TargetSum - i
for j from 0 to RangeArray[1]:
if (newSum-j)>=0 and (newSum-j)<=RangeArray[2] then
finalList = SumList + [j, newSum-j]
result.append(finalList)
Note the inner loop. This is what was inspired by the 3SUM algorithm. We take advantage of the fact that we know what value we have to pick from the third range (since it is defined by our first 2 choices).
From here you have to of course re-map the results back to the original ranges by adding the original lowerbounds to the values that came from the corresponding ranges.
Notice that we now understand why it may be a good idea to sort RangeList. The last range gets absorbed into the secondlast range's loop. We want the largest range to be the one that does not loop.
I hope this helps to get you started! If you need any help translating my pseudocode into c# just ask :)
This question already has answers here:
Add all natural numbers that are multiples of 3 and 5 : What is the bug in the following code
(5 answers)
Project Euler: Problem 1 (Possible refactorings and run time optimizations)
(13 answers)
Closed 9 years ago.
Project Euler - Problem 1: Find the sum of all the multiples of 3 or 5 below 1000.
Looking through the questions here about the same problem I assume the way I tried to solve is is quite bad. What is the best way to solve this?
And my other question: The sum value doesn't match the answer. I think the problem is that when I use foreach to write out the list value its starts from 705 instead of 3, but I have no idea why. I would appreciate if someone could explain it to me.
This is the code that I'm using now:
List<int> numbers = new List<int>();
for (int i = 3; i < 1000; i += 3)
{
numbers.Add(i);
}
for (int j = 5; j < 1000; j += 5)
{
numbers.Add(j);
}
numbers.ForEach(Console.WriteLine);
int sum1 = numbers.Sum();
Console.WriteLine(sum1);
Console.ReadLine();
This is because numbers allows duplicates. Note that you are going to have some duplicates, there - for example, numbers 15, 30, 45, and so on, will be added twice.
Replace
List<int> numbers = new List<int>();
with
ISet<int> numbers = new HashSet<int>();
and it's going to work because a HashSet won't allow duplicate values.
This is the first problem on Project Euler.
Personally, I used a one liner :
Enumerable.Range(0, 1000).Where(n => n % 3 == 0 || n % 5 == 0).Sum()
But you can also use the long way for more readability :
int sum = 0;
for (int i = 0; i < 1000; i++)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
sum = sum + i;
}
}
If you don't know how the modulo (%) operator works, I suggest you read it here
If you need more details about the problem itself, just create an account on Project Euler, enter the answer, and read the Problem Overview.
You're not accounting for numbers that are both multiples of 3 and 5
If I were you, I'd have something like the following
for(int i=1; i<1000; i++)
{
if(i is a multiple of 15)
//account for 15
else if(i is a multiple of 3)
//account for 3
else if(i is a multiple of 5)
//account for 5
}
The reason your output starts with 705 is because your list of numbers is quite long (532 numbers to be exact). Your Console window can only contain a couple of lines before it starts scrolling.
So you do start with the number 3, it's just not visible.
As others have pointed out, the issue is that your code counts multiples of 15 twice. Of course, this task is pretty easy using Linq's Range and Where methods:
var numbers = Enumerable.Range(0, 1000)
.Where(n => n % 3 == 0 || n % 5 == 0);
foreach(var n in numbers)
{
Console.WriteLine(n);
}
var sum = numbers.Sum();
Console.WriteLine(sum);
Console.ReadLine();
You have duplicate values in the list. Thats why total sum is invalid. You better change the Data Structure to HashSet which not allow duplicates.
If you can't do that or you have to proceed with this way, try below
call numbers = numbers.Distinct().ToList(); before numbers.ForEach(Console.WriteLine);
I think the problem is that when I use foreach to write out the list
value its starts from 705 instead of 3, but I have no idea why.
Problem is duplicate values, foreach will print correctly but you may not able to scroll console to beginning of printing.
try Console.WriteLine(string.Join(",", numbers));
You could also solve it with Linq. Use Enumerable.Range to get all numbers between 0 and 999 (inclusive). Then use Where to filter those out which are divisible by 3 or divisible by 5. Finally use Sum.
I have some tasks about sorting arrays in C#. I've been trying everything I could think of - no luck.
The task is to sort an array of integers by known sorting algorithms (insertion, selection, bubble, quick). Thing is, I have to sort ONLY the smallest M elements.
Example: I have an array of 7 elements 2 9 8 3 4 15 11 and I need to sort the smallest 3 elements so that my array becomes 2 3 4 9 8 15 11.
Please help, I can't seem to find anything neither here in SO, nor anywhere through Google. I don't ask to do all the algorithms for me, I just need one of those just to get hold on how's that possible.
E: Thank you for your thoughts. I've reviewed all of your recommendations and have accomplished to make an insertion sort like that:
static int[] insertSort(int[] arr, out int swaps, out int checks) {
int step = 0;
swaps = 0;
checks = 0;
for (int i = 0; i < arr.Length; i++) {
int min = arr[i], minind = i;
for (int j = i + 1; j < arr.Length; j++) {
checks++;
if (arr[j] < min) {
min = arr[j];
minind = j;
}
}
int temp = arr[minind];
if (step < M) {
for (int j = minind; j > i; j--) {
swaps++;
arr[j] = arr[j - 1];
}
arr[i] = temp;
swaps++;
step++;
}
}
return arr;
}
Swaps and checks - requirement for my application.
P.S. I've seen many times that SO doesn't like to do homework for someone. That's why I haven't asked for code, I've just asked for thoughts on how to accomplish that.
Thanks again for those who have helped me out here.
Since there is no efficiency limitations:
Set i to 0.
Look for the minimum among the not sorted elements.
Insert it into the position i, shift the array.
Increment i.
Repeat M times.
Complexity is O(N * M).
Without seeing your implementation, this is hard to answer. There are many ways to do this, and most are straight-forward.
Here are a few ideas though:
Create a "temporary" array that only holds the numbers to sort, sort it, then replace in original array (probably a sub-optimal solution)
Use a for loop that iterates the number of times you need (3 or whatever). This is probably the best solution
Post your code here on SO and some naive person will probably give you a solution so you don't have to do your schoolwork yourself. (This is a lazy and unbecoming solution)
I think here is what you are looking for, this is an example sorting of array ascending based on specific indixes.
int startIndex=2;
int endIndex=5;
int[] elements=new int[7];
elements[0]=2;
elements[1]=9;
elements[2]=8;
elements[3]=3;
elements[4]=4;
elements[5]=15;
elements[6]=11;
for (int a=startIndex-1;a<endIndex;a++){
for(int b=startIndex-1;b<endIndex;b++){
if (elements[a]<elements[b]){
int temp =elements[a];
elements[a]=elements[b];
elements[b]=temp;
}
}
}
for (int c=0;c<elements.Length;c++){
Console.Write(elements[c]+",");
}
Just change the "<" to ">" if you want to sort it desc.
You'd want to take a look at what sorting algorithm you're required to use. Say for example we're using one that uses a for loop. Most cases you'd see something like this
for(int i = 0; i < arrayName.length(); i++)
{}
In your case, just change the parameters of the for loop
for(int i = 0; i < M; i++)
{}
Where M is less than arrayName.length(); and is the number of positions from the beginning you would like to sort.
The rest of the array, untouched, should remain the same.
Couple things. Most sorting algorithms use array.length as the maximum range.
Could you just use m there instead? ie
for (int i = 0; i < m; i++)
Also, you could use a temporary array of the first m characters, sort it, then reassign.
int[] temp;
for (int i = 0; i < m; i++)
{
temp[i] = realArray[i];
}
//sort, then
for (int i = 0; i < m; i++)
{
realArray[i] = temp[i];
}
I would sort the full array and put it into the an other one.
Truncate the new array to only keep the smallest x elements.
Get the largest number from that array (in your example, 4).
Loop through the initial array and append all numbers that are higher.
Input: 2 9 8 3 4 15 11
Sort all: 2 3 4 8 9 11 15
Truncate: 2 3 4
Get highest value from this array (4)
Loop through original array and append
Is 2 higher than 4? no
Is 9 higher than 4? yes, append (we now have: 2 3 4 9)
Is 8 higher than 4? yes, append (we now have: 2 3 4 9 8)
Is 3 higher than 4? no
Is 4 higher than 4? no
Is 15 higher than 4? yes, append (we now have: 2 3 4 9 8 15)
Is 11 higher than 4? yes, append (we now have: 2 3 4 9 8 11)
*This is not the most efficient way and might cause problems if you have duplicate numbers
Any prescriptions on using LINQ?
int a[] = new int[] {2, 9, 8, 3, 4, 15, 11};
const int M = 5;
a = a.Take(M).OrderBy(e => e).ToArray(); // EDIT: Added .ToArray()
I need to do an algorithm that search a specific int in array of int.
That number must appear >= than arraySize/2 times.
example: [] = 4 4 3 5 5 5 5 5 5 6
arraysize: 10
number 5 exists 6x -> so this is the result of algorithm
but I need to do this without additionam memory, and in time O(n) -> in one pass.
Is this even possible? Any suggestions how to start it?
It is indeed possible; the task is known as "Dominant Element," and used for interviews and as a homework. Read the article below for a proper analysis; the solution itself is simple but not easy: proving that it indeed does what it promises is not quite trivial (unless of course you know the answer).
http://www.cse.iitk.ac.in/users/sbaswana/Courses/ESO211/problem.pdf
element x;
int count ← 0;
For(i = 0 to n − 1)
{
if(count == 0) { x ← A[i]; count ++; }
else if (A[i] == x) count ++;
else count −−
}
Check if x is dominant element by scanning array A.
Note though that the time is O(n), but as far as I'm aware, it is not possible to do it in one pass unless you know for sure there is a dominant element.
As of additional memory, you will need memory for i, the counter; x, the element to check and return; and count, the size of the imaginary working set. That's O(1) and is usually considered OK for such problems.
Moore describes the solution to this problem on his web site (with an example here).
Edit: Here is some Java code demonstrating the algorithm as described:
public class Majority
{
public static void main(String[] args)
{
int[]a = new int[]{4, 4, 3, 5, 5, 5, 5, 5, 5, 6};
int count = 0;
int candidateIndex = 0;
for (int i = 0; i < a.length; i++)
{
if (count == 0)
{
candidateIndex = i;
count++;
}
else
{
if (a[i] == a[candidateIndex])
count++;
else
count--;
}
}
System.out.println("Majority element: " + a[candidateIndex]);
}
}
After you get your candidateIndex, you can iterate though the array again to verify that it indeed occurs more than N / 2 times.