Assume I have a list of integers of any length, for an example I have the list of 1,3,5 and 7.
I would like an algorithm to pick a combination of X elements from the list.
For example, X = 1 would return:
1
3
5
7
x = 2 would return:
1 + 1
1 + 3
1 + 5
1 + 7
3 + 3
3 + 5
3 + 7
5 + 5
5 + 7
7 + 7
var listOfInts = new List<int> { 1, 3, 5, 7 };
var combinedInts = new List<int>();
// x = 1 solution
// This is only picking one item from the list.
for (int i = 0; i < listOfInts.Count(); i++)
{
combinedInts.Add(listOfInts[i]);
}
// x = 2 solution
// This is how to pick two. I wrap it around another for loop.
for (int i = 0; i < listOfInts.Count(); i++)
{
for (int j = i; j < listOfInts.Count(); j++)
{
combinedInts.Add(listOfInts[i] + listOfInts[j]);
}
}
// x = 3 solution
// If I go up another level I have to wrap it around another for loop. This solution won't scale.
for (int i = 0; i < listOfInts.Count(); i++)
{
for (int j = i; j < listOfInts.Count(); j++)
{
for (int k = j; k < listOfInts.Count(); k++)
{
combinedInts.Add(listOfInts[i] + listOfInts[j] + listOfInts[k]);
}
}
}
This solution doesn't scale as I have to continually wrap around another for loop for each number of element I'm picking. For example X = 7 would need 7-nested for loops. Is there a better way to write this method that doesn't involve nesting for loops?
You can use the following to get combinations of the sequences:
public static class LinqHelper
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int? k = null)
{
if (!k.HasValue)
k = elements.Count();
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) => elements.Skip(i).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
}
var list = new List<int> { 1, 3, 5, 7 };
int x = 2; //Change to 3, 4, 5, etc
var result = list.Combinations(x);
Yields:
1 1
1 3
1 5
1 7
3 3
3 5
3 7
5 7
7 7
To get the sum of each one, you'd aggregate the result:
var result = list.Combinations(x).Select(g => g.Aggregate((left, right) => left + right));
Which produces:
2
4
6
8
6
8
10
10
12
14
There is also a purely iterative way to do this. It requires a great deal more thought and complexity, but can be made very efficient. The basic idea is to simulate the same nested loops, but track the iterations of each nested loop as an array of loop counters, which are iterated forward in the same manner as the original nested loop code. Here is a fully working example:
var listOfInts = new List<int> { 1, 3, 5, 7 };
var combinedInts = new List<int>();
var numInts = listOfInts.Count;
var numElements = 5; // number of "nested loops", or ints selected in each combination
var loopCounters = new int[numElements]; // make one loop counter for each "nested loop"
var lastCounter = numElements - 1; // iterate the right-most counter by default
// maintain current sum in a variable for efficiency, since most of the time
// it is changing only by the value of one loop counter change.
var tempSum = listOfInts[0] * numElements;
// we are finished when the left/outer-most counter has looped past number of ints
while (loopCounters[0] < numInts) {
// you can use this to verify the output is iterating correctly:
// Console.WriteLine(string.Join(",", loopCounters.Select(x => listOfInts[x])) + ": " + loopCounters.Select(x => listOfInts[x]).Sum() + "; " + tempSum);
combinedInts.Add(tempSum);
tempSum -= listOfInts[loopCounters[lastCounter]];
loopCounters[lastCounter]++;
if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
// if last element reached in inner-most counter, increment previous counter(s).
while (lastCounter > 0 && loopCounters[lastCounter] == numInts) {
lastCounter--;
tempSum -= listOfInts[loopCounters[lastCounter]];
loopCounters[lastCounter]++;
if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
}
// if a previous counter was advanced, reset all future counters to same
// starting number to start iteration forward again.
while (lastCounter < numElements - 1) {
lastCounter++;
if (loopCounters[lastCounter] < numInts) tempSum -= listOfInts[loopCounters[lastCounter]];
loopCounters[lastCounter] = loopCounters[lastCounter - 1];
if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
}
}
At the end of the iteration, combinedInts should contains a list of all sum combinations, similar to the original code or the other recursive solutions. If you are working with small sets, and small combinations, then this level of efficiency is unnecessary and you should prefer a recursive solution which is easier to reason about correctness. I present this as an alternative way to think about the problem. Cheers!
This works for me:
Func<IEnumerable<int>, int, IEnumerable<IEnumerable<int>>> generate = null;
generate = (xs, n) =>
(xs == null || !xs.Any())
? Enumerable.Empty<IEnumerable<int>>()
: n == 1
? xs.Select(x => new [] { x })
: xs.SelectMany(x => generate(xs, n - 1).Select(ys => ys.Concat(new [] { x })));
int[] array = { 1, 3, 5, 7, };
var results =
generate(array, 3)
.Select(xs => String.Join("+", xs));
With this call I get:
1+1+1, 3+1+1, 5+1+1, 7+1+1, 1+3+1, 3+3+1, 5+3+1, 7+3+1, 1+5+1, 3+5+1, 5+5+1, 7+5+1, 1+7+1, 3+7+1, 5+7+1, 7+7+1, 1+1+3, 3+1+3, 5+1+3, 7+1+3, 1+3+3, 3+3+3, 5+3+3, 7+3+3, 1+5+3, 3+5+3, 5+5+3, 7+5+3, 1+7+3, 3+7+3, 5+7+3, 7+7+3, 1+1+5, 3+1+5, 5+1+5, 7+1+5, 1+3+5, 3+3+5, 5+3+5, 7+3+5, 1+5+5, 3+5+5, 5+5+5, 7+5+5, 1+7+5, 3+7+5, 5+7+5, 7+7+5, 1+1+7, 3+1+7, 5+1+7, 7+1+7, 1+3+7, 3+3+7, 5+3+7, 7+3+7, 1+5+7, 3+5+7, 5+5+7, 7+5+7, 1+7+7, 3+7+7, 5+7+7,7+7+7
Related
I have an array where the first two smallest values have to be added, and consequently the result has to be added to next smallest and so on until it reaches the end of the array to give a final total.
However, how can I dynamically modify the method/function so if the values changes and I have 6 vehicles and 6 specs values in the array, the return of the method/function total is not restricted to just 4 indexes.
The array values are unsorted, so in order to add the first smallest, it has to be sorted. Once that's done it adds the values of the new array.
Here's what I've tried:
public static int vehicles = 4;
public static int[] specs = new int[] { 40, 8, 16, 6 };
public static int time(int vehicles, int[] specs)
{
int newValue = 0;
for (int i = 1; i < vehicles; i++)
{
newValue = specs[i];
int j = i;
while (j > 0 && specs[j - 1] > newValue)
{
specs[j] = specs[j - 1];
j--;
}
specs[j] = newValue;
}
// How can I dynamically change this below:
int result1 = specs[0] + specs[1];
int result2 = result1 + specs[2];
int result3 = result2 + specs[3];
int total = result1 + result2 + result3;
return total; // Returns 114
}
Here's the idea of how it works:
4, [40, 8, 16, 6] = 14 --> [40, 14, 16] = 30 --> [40, 30] = 70 ==>> 14 + 30 + 70 = 114
6, [62, 14, 2, 6, 28, 41 ] = 8 --> [62, 14, 8, 28, 41 ] --> 22 [62, 22, 28, 41 ] --> 50
[62, 50, 41 ] --> 91 [62, 91 ] --> 153 ==> 8 + 22 + 50 + 91 + 153 = 324
First off, if you are not restricted to arrays for some weird reason use List<int> and your life will be easier.
List<int> integers = { 14, 6, 12, 8 };
integers.Sort();
integers.Reverse();
while( integers.Count > 1 )
{
int i = integers[integers.Count - 1];
int j = integers[integers.Count - 2];
integers[integers.Count - 2] = i + j;
integers.RemoveAt(integers.Count - 1);
}
var result = integers[0];
P.S.: This can be easily modified to operate on the array version, you can't RemoveAt() from an array but can separately maintain a lastValidIndex.
I would go with the simplest version of a one line solution using LINQ:
Array.Sort(specs);
int total = specs.Select((n, i) => specs.Take(i + 1).Sum()).Sum() - (specs.Length > 1 ? specs[0] : 0);
I would use Linq.
Enumerable.Range(2, specs.Length - 1)
.Select(i => specs
.Take(i)
.Sum())
.Sum();
Explanation:
We take a range starting from 2 ending with specs.Length.
We sum the first i values of specs where i is the current value in the range.
After we have all those sums, we sum them up as well.
To learn more about linq, start here.
This code only works if the values have been sorted already.
If you want to sort the values using linq, you should use this:
IEnumerable<int> sorted = specs.OrderBy(x => x);
Enumerable.Range(2, sorted.Count() - 1)
.Select(i => sorted
.Take(i)
.Sum())
.Sum();
The OrderBy function needs to know how to get the value it should use to compare the array values. Because the array values are the values we want to compare we can just select them using x => x. This lamba takes the value and returns it again.
See comments in code for explanation.
using System;
using System.Linq;
class Program
{
static void Main()
{
//var inputs = new [] { 40, 8, 16, 6 }; // total = 114
var inputs = new[] { 62, 14, 2, 6, 28, 41 }; // total = 324
var total = 0;
var query = inputs.AsEnumerable();
while (query.Count() > 1)
{
// sort the numbers
var sorted = query.OrderBy(x => x).ToList();
// get sum of the first two smallest numbers
var sumTwoSmallest = sorted.Take(2).Sum();
// count total
total += sumTwoSmallest;
// remove the first two smallest numbers
query = sorted.Skip(2);
// add the sum of the two smallest numbers into the numbers
query = query.Append(sumTwoSmallest);
}
Console.WriteLine($"Total = {total}");
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}
}
I benchmark my code and the result was bad when dealing with large dataset. I suspect it was because of the sorting in the loop. The sorting is needed because I need to find the 2 smallest numbers in each iteration. So I think I need a better way to solve this. I use a PriorityQueue (from visualstudiomagazine.com) because the elements are dequeued based on priority, smaller numbers have higher priority in this case.
long total = 0;
while (pq.Count() > 0)
{
// get two smallest numbers when the priority queue is not empty
int sum = (pq.Count() > 0 ? pq.Dequeue() : 0) + (pq.Count() > 0 ? pq.Dequeue() : 0);
total += sum;
// put the sum of two smallest numbers in the priority queue if the queue is not empty
if (pq.Count() > 0) pq.Enqueue(sum);
}
Here's some benchmark results of the new (priority queue) code and the old code in release build. Results are in milliseconds. I didn't test the 1 million data with the old code because it's too slow.
+---------+----------+-------------+
| Data | New | Old |
+---------+----------+-------------+
| 10000 | 3.9158 | 5125.9231 |
| 50000 | 16.8375 | 147219.4267 |
| 1000000 | 406.8693 | |
+---------+----------+-------------+
Full code:
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
class Program
{
static void Main()
{
const string fileName = #"numbers.txt";
using (var writer = new StreamWriter(fileName))
{
var random = new Random();
for (var i = 0; i < 10000; i++)
writer.WriteLine(random.Next(100));
writer.Close();
}
var sw = new Stopwatch();
var pq = new PriorityQueue<int>();
var numbers = File.ReadAllLines(fileName);
foreach (var number in numbers)
pq.Enqueue(Convert.ToInt32(number));
long total = 0;
sw.Start();
while (pq.Count() > 0)
{
// get two smallest numbers when the priority queue is not empty
int sum = (pq.Count() > 0 ? pq.Dequeue() : 0) + (pq.Count() > 0 ? pq.Dequeue() : 0);
total += sum;
// put the sum of two smallest numbers in the priority queue if the queue is not empty
if (pq.Count() > 0) pq.Enqueue(sum);
}
sw.Stop();
Console.WriteLine($"Total = {total}");
Console.WriteLine($"Time = {sw.Elapsed.TotalMilliseconds}");
total = 0;
var query = File.ReadAllLines(fileName).Select(x => Convert.ToInt32(x));
sw.Restart();
while (query.Count() > 0)
{
// sort the numbers
var sorted = query.OrderBy(x => x).ToList();
// get sum of the first two smallest numbers
var sumTwoSmallest = sorted.Take(2).Sum();
// count total
total += sumTwoSmallest;
// remove the first two smallest numbers
query = sorted.Skip(2);
// add the sum of the two smallest numbers into the numbers
if (query.Count() > 0)
query = query.Append(sumTwoSmallest);
}
sw.Stop();
Console.WriteLine($"Total = {total}");
Console.WriteLine($"Time = {sw.Elapsed.TotalMilliseconds}");
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}
}
PriorityQueue code:
using System;
using System.Collections.Generic;
// From http://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx
public class PriorityQueue<T> where T : IComparable<T>
{
private List<T> data;
public PriorityQueue()
{
this.data = new List<T>();
}
public void Enqueue(T item)
{
data.Add(item);
int ci = data.Count - 1; // child index; start at end
while (ci > 0)
{
int pi = (ci - 1) / 2; // parent index
if (data[ci].CompareTo(data[pi]) >= 0)
break; // child item is larger than (or equal) parent so we're done
T tmp = data[ci];
data[ci] = data[pi];
data[pi] = tmp;
ci = pi;
}
}
public T Dequeue()
{
// assumes pq is not empty; up to calling code
int li = data.Count - 1; // last index (before removal)
T frontItem = data[0]; // fetch the front
data[0] = data[li];
data.RemoveAt(li);
--li; // last index (after removal)
int pi = 0; // parent index. start at front of pq
while (true)
{
int ci = pi * 2 + 1; // left child index of parent
if (ci > li)
break; // no children so done
int rc = ci + 1; // right child
if (rc <= li && data[rc].CompareTo(data[ci]) < 0) // if there is a rc (ci + 1), and it is smaller than left child, use the rc instead
ci = rc;
if (data[pi].CompareTo(data[ci]) <= 0)
break; // parent is smaller than (or equal to) smallest child so done
T tmp = data[pi];
data[pi] = data[ci];
data[ci] = tmp; // swap parent and child
pi = ci;
}
return frontItem;
}
public T Peek()
{
T frontItem = data[0];
return frontItem;
}
public int Count()
{
return data.Count;
}
public override string ToString()
{
string s = "";
for (int i = 0; i < data.Count; ++i)
s += data[i].ToString() + " ";
s += "count = " + data.Count;
return s;
}
public bool IsConsistent()
{
// is the heap property true for all data?
if (data.Count == 0)
return true;
int li = data.Count - 1; // last index
for (int pi = 0; pi < data.Count; ++pi)
{ // each parent index
int lci = 2 * pi + 1; // left child index
int rci = 2 * pi + 2; // right child index
if (lci <= li && data[pi].CompareTo(data[lci]) > 0)
return false; // if lc exists and it's greater than parent then bad.
if (rci <= li && data[pi].CompareTo(data[rci]) > 0)
return false; // check the right child too.
}
return true; // passed all checks
}
// IsConsistent
}
// PriorityQueue
Reference:
https://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx
https://en.wikipedia.org/wiki/Priority_queue
You can simply sort it using Array.Sort(), then get the sums in a new array which starts with the smallest value and add each next value to the most recent sum, the total will be the value of the last sum.
public static int time(int vehicles, int[] specs)
{
int i, total;
int[] sums = new int[vehicles];
Array.Sort(spec);
sums[0] = specs[0];
for (i = 1; i < vehicles; i++)
sums[i] = sums[i - 1] + spec[i];
total = sums[spec - 1];
}
I was doing a hacker rank challenge in c# to try and bring some of my c skills over to c#. Now I know hacker rank is notoriously stupid with killing programs due to time out (in this case if it lasts more than 3 seconds). But I honestly cannot think of a way to optimize this code further.
Here are the instructions:
https://www.hackerrank.com/challenges/ctci-array-left-rotation
Basically the challenge is to shift an array of numbers some x amount of times over in the left direction inside the array.
To my knowledge this code is as minimal as it can get and still do the thing they requested. The only way I can think to optimize this code further is to merge the constraint "if(a[i] > 1000000 || a[i] < 1 )" with the writeline forloop at the end of the code, but I tried that and it didn't work.
To me this is literally the minimum number of operations to move the array over by an amount x. But the code fails in test case 7 and 8 (out of 8) due to time out. Am I missing something?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
static void Main(String[] args)
{
int i, j;
int temp = 0;
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
string[] a_temp = Console.ReadLine().Split(' ');
int[] a = Array.ConvertAll(a_temp,Int32.Parse);
//constraints
if(n >= 100000 || n < 1 )
{
System.Environment.Exit(1);
}
if(k > n || n < 1 )
{
System.Environment.Exit(1);
}
for(i = 0; i< n; i++)
{
if(a[i] > 1000000 || a[i] < 1 )
{
System.Environment.Exit(1);
}
}
//double for loop. one adjust position by one. then repeat k number of times.
for(j = 0; j<k; j++)
{
for(i = 0; i< n-1; i++)
{
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
//view array
for(i = 0; i< n; i++)
{
Console.Write(a[i] + " " );
}
}
}
I used a queue mechanism to get this working. That way you don't have to do any array copy and just rotating the string to the end.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution {
static int[] leftRotation(int[] arr, int rotation) {
Queue<int> queue = new Queue<int>(arr);
for (int i = 0; i < rotation; i++)
{
queue.Enqueue(queue.Dequeue());
}
return queue.ToArray();
}
static void Main(String[] args) {
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int d = Convert.ToInt32(tokens_n[1]);
string[] a_temp = Console.ReadLine().Split(' ');
int[] a = Array.ConvertAll(a_temp,Int32.Parse);
int[] result = leftRotation(a, d);
Console.WriteLine(String.Join(" ", result));
}
}
Shuffling the values one at a time is very slow. There is no need to do this. One can think of the rotation as moving 2 blocks - the values to the left of the rotation point and the values including and to the right of the rotation point
1 2 3 4 5 6 7 8 9
Rotate this 3 times is
move 1-3 to a temp variable
move 4-9 to the start of the array
move 1-3 to the end of 4-9
Edit: Add a bit more detail
We want to rotate the array 3 places.
move 1 2 3 to a temporary array
1 2 3
1 2 3 4 5 6 7 8 9
move 4-9 to the start of the array
1 2 3
4 5 6 7 8 9 7 8 9
move 1-3 to the end of the array
1 2 3
4 5 6 7 8 9 1 2 3
We can get away without the temp array for the left hand block if we create a new target array and copy everything to it. The following passes all the tests for the problem
var result = new int[a.Length];
var block2Length = a.Length - k;
Array.Copy(a, k, result, 0, block2Length);
Array.Copy(a, 0, result, block2Length, k);
Console.WriteLine(string.Join(" ", result.Select(v => v.ToString())));
Other Points
The constraints in HackerRank are part of the problem definition - they are telling us what the values can/will do so that we don't have to worry about solving a more general problem
e.g.
1 <= a[i] < 10^6
tells us the numbers will all be within the range for standard integers, no need to use long or BigInteger. As part of the solution we don't need to confirm these. In a real world situation different rules apply but here we have as much code checking values that cannot be wrong as we have solving the problem.
This has already been answered but there is a different solution that is very fast:
The idea is that you use the periodicity of the shifting. Shifting an element n+1 times is the same as shifting it 1 time which boils down to k % n.
Thus, you can simply create a new array and move the "old" elements directly to the correct spot. See the sample code below:
static void Main(String[] args) {
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
string[] a_temp = Console.ReadLine().Split(' ');
int[] a = Array.ConvertAll(a_temp,Int32.Parse);
// use the periodicity of the shifting creating a shift between 0 and n - 1.
int shifts = k % n;
// Create a new array to hold the elements at their new positions.
int[] newPositions = new int[a.Length];
// You only need to iterate of the array once assigning each element its new position.
for(int i= 0; i < a.Length; ++i)
{
// Here is the magic: (for clarification see table below)
int position = (i - shifts + n)%n;
newPositions[position] = a[i];
}
foreach(var element in newPositions)
Console.Write($"{element} ");
}
This is more intuitive once you write it down on paper. The table might prints more values than the array contains to show the actual positions in the array.
-4 -3 -2 -1 | 0 1 2 3 4 (array indices)
=============================
2 3 4 5 | 1 2 3 4 5 (array contents without shift)
3 4 5 1 | 2 3 4 5 1 (shifted 1 time)
4 5 1 2 | 3 4 5 1 2 (shifted 2 times)
5 1 2 3 | 4 5 1 2 3 (shifted 3 times)
1 2 3 4 | 5 1 2 3 4 (shifted 4 times)
formula: i - k + n
results:
i=0: 0 - 4 + 5 = 1
i=1: 1 - 4 + 5 = 2
i=2: 2 - 4 + 5 = 3
i=3: 3 - 4 + 5 = 4
i=4: 4 - 4 + 5 = 5
i=5: 5 - 4 + 5 = 6 => 0
EDIT: I skipped the parts to check the boundaries for the sake of simplicity.
Updated answer.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
static void Main(String[] args)
{
int i, j, z;
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
string[] a_temp = Console.ReadLine().Split(' ');
int[] a = Array.ConvertAll(a_temp,Int32.Parse);
int[] temparray = new int[2*n];
//constraints
if(n >= 100000 || n < 1 )
{
System.Environment.Exit(1);
}
if(k > n || n < 1 )
{
System.Environment.Exit(1);
}
for(i = 0; i< n; i++)
{
if(a[i] > 1000000 || a[i] < 1 )
{
System.Environment.Exit(1);
}
}
for(j = 0; j<n; j++)
{
z = (j-k) %n;
if(z != 0)
{
z= (n+ z) %n;
}
temparray[z] = a[j];
}
//view array
for(i = 0; i< n; i++)
{
Console.Write(temparray[i] + " " );
}
}
}
I have a number. For instance, my number is 19 . Then I want to populate my drop down with range in multiplication of 5. So my dropdownlist will consist of items of:
1-5
6-10
11-15
16-19
I tried modulus and division, however, I can't seems to get the range. Is there a fixed method?
Sample code
List<string> range = new List<string>();
int number = 19;
int numOfOccur = (19/5);
for (int i = 1; i < numOfOccur ; i++)
{
range.Add(i + " - " + (i * 5))
}
Sometime I think that old school code, without fancy linq is a bit more clear
int maximum = 19;
int multiple = 5;
int init = 1;
while (init + multiple <= maximum )
{
string addToDDL = init.ToString() + "-" + (init + multiple - 1).ToString();
Console.WriteLine(addToDDL);
init += multiple;
}
if(init <= maximum)
{
string last = init.ToString() + "-" + maximum.ToString();
Console.WriteLine(last);
}
Linq solution (modern techs allow us to put it consize):
int number = 19;
int div = 5;
List<string> range = Enumerable
.Range(0, number / div + (number % div == 0 ? 0 : 1))
.Select(i => $"{i * div + 1} - {Math.Min((i + 1) * div, number)}")
.ToList();
Test
Console.Write(string.Join(Environment.NewLine, range));
Returns
1 - 5
6 - 10
11 - 15
16 - 19
When using modulo arithmetics, do not forget about remainders: you have an error in int numOfOccur = (19/5); line. It should be
int numOfOccur = 19 / 5 + (19 % 5 == 0 ? 0 : 1);
for the last incomplete 16 - 19 range to be proceeded.
Add this package to your project : https://www.nuget.org/packages/System.Interactive/
Then you can do this:
IEnumerable<IList<int>> buffers2 = Enumerable.Range(1, 19).Buffer(5);
IList<int>[] result2 = buffers2.ToArray();
// { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, ...
Don't forget to add System.Interactive namespace to your using block.
I need to make a function to take in an array of numbers and a target number and return how many different ways you can add or subtract those numbers to get the target number.
ie.
Values = 2, 4, 6, 8 Target = 12
2 + 4 + 6 = 12,
4 + 8 = 12,
6 + 8 - 2 = 12,
2 - 4 + 6 + 8 = 12,
Return 4
Here is what I have so far, but it only counts addition problems.
private void RecursiveSolve(int goal, int currentSum, List<int> included, List<int> notIncluded, int startIndex)
{
for (int index = startIndex; index < notIncluded.Count; index++)
{
int nextValue = notIncluded[index];
if (currentSum + nextValue == goal)
{
List<int> newResult = new List<int>(included);
newResult.Add(nextValue);
mResults.Add(newResult);
}
else if (currentSum - nextValue == goal)
{
List<int> newResult = new List<int>(included);
newResult.Add(nextValue);
mResults.Add(newResult);
}
if (currentSum - nextValue < goal && currentSum - nextValue > 0 )
{
List<int> nextIncluded = new List<int>(included);
nextIncluded.Add(nextValue);
List<int> nextNotIncluded = new List<int>(notIncluded);
nextNotIncluded.Remove(nextValue);
RecursiveSolve(goal, currentSum - nextValue, nextIncluded, nextNotIncluded, startIndex++);
}
if (currentSum + nextValue < goal)
{
List<int> nextIncluded = new List<int>(included);
nextIncluded.Add(nextValue);
List<int> nextNotIncluded = new List<int>(notIncluded);
nextNotIncluded.Remove(nextValue);
RecursiveSolve(goal, currentSum + nextValue, nextIncluded, nextNotIncluded, startIndex++);
}
}
}
Well, the simple way would be to try all of the combinations. If you have N numbers, you have 3^N combinations. The reasoning is this: You sum the numbers but put a coefficient in front of each of them. If your numbers are A1..AN, you add N coefficients (C1..CN) and sum:
Sum (Ai*Ci)
Your Cis can be 1 (meaning you add the number), -1 (meaning you subtract the number) or 0 (meaning you ignore the number).
So, go over all 3^N possible coefficient assignments, calculate the sum and compare to your target.
I am assuming all the numbers are different (as in your example). If a number can appear twice, you need to take that into account.
At the very outset let me express my sincere thanks to Marc Gravel,Dahlbyk and the rest for helping me to apply linq practically.
The following are few questions which I have faced in an interview to solve applying Linq. As I am not familiar with Linq I solved it without using Linq.
I appreciate the answers which helps me to solve them using Linq
Thanks in advance.
Question 1:
The Problem is to find different digits such that,in whatever order they are used to make a three-digit number,that number will not be divisible by:
3,5,7,11,13 or 17.
To ensure that there is no ambuigity,suppose the three digits
are a,b,and c.Then,none of the combination of the numbers:
say abc,acb,bac,bca,cab and cba will divide by 3,5,7,11,13 or 17.
Example :
When I take 248 none of its combination(284,428,482,842,824) will exactly divisible by 3,5,7,11,13 or 17.
public void FindingRareNumbers()
{
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
for (int k = 1; k <= 9; k++)
{
//to form the three digit
string digit = i.ToString() + j.ToString() + k.ToString();
//converting to integer
int StrToDigit = Convert.ToInt32(digit);
char[] digitcombination = digit.ToCharArray();
string PossibleCombination = "";
bool testpassed = false;
int dcount = 0;
#region different possible combinations
for (int p = 0; p <= 2; p++)
{
for (int q = 0; q <= 2; q++)
{
for (int r = 0; r <= 2; r++)
{
// The following condition avoid the repeatance
// of digit like 111,111,111
if (p != q && p != r && r != q)
{
PossibleCombination =
digitcombination[p].ToString() +
digitcombination[q].ToString() +
digitcombination[r].ToString();
int num = Convert.ToInt32(PossibleCombination);
if (num % 3 != 0 && num % 5 != 0 && num % 7 != 0
&& num % 11 != 0 && num % 11 != 0
&& num % 13 != 0 && num % 17 != 0)
{
//count is increment for 6 times
// it satisfies the condition
dcount++;
testpassed = true;
}
}
}
}
}
#endregion combination
if (testpassed && dcount==6)
{
Console.WriteLine(StrToDigit);
}
}
}
}
}
(coding is working)
Question 2:
The task is to arrange the element in matrix so that all rows,columns,and diagonals add up to the same total.(Bit problem in coding ,I am trying to solve it).
------------------
1 2 3
-----------------
4 5 6
-----------------
7 8 9
-----------------
example :
The one of solutions is as follows:
-----------
2 9 4
-----------
7 5 3
----------
6 1 8
----------
I agree that Marc's solution to your first problem is a reasonable approach. But I think there's a larger question here, which is "how do I solve problems like this in a LINQ-ish manner?"
Notice how your solution is completely "procedural" and "imperative". Your code specifies a series of steps that you would execute, one after the other, with deep loops. Each step along the way is meaningless unless you understand its place in the larger whole.
There are two ideas I like to use when solving problems with LINQ:
Describe what the program is doing logically, rather than listing a series of commands
Characterize the problem as a query against a data set rather than as a procedure to follow.
So, what's our data set? We wish to filter out some elements from the set of all combinations of three digits.
How do we filter them? Permute the digits and then perform a divisibility check on each permutation.
OK, so now we have a structure for our program:
var query = from c in ThreeDigitCombinations()
where DivisibilityCheckPasses(c)
select c;
foreach(Combination result in query) Console.WriteLine(result);
And now you can continue breaking down each of those further, solving each sub-problem using LINQ in turn.
Same goes for your "magic square" problem; you're looking for a permutation that has a certain property, so write a generator of permutations, write a filter, and execute it.
For the first:
static IEnumerable<int> Permute(int x, int y, int z)
{
yield return x * 100 + y * 10 + z;
yield return x * 100 + z * 10 + y;
yield return y * 100 + x * 10 + z;
yield return y * 100 + z * 10 + x;
yield return z * 100 + x * 10 + y;
yield return z * 100 + y * 10 + x;
}
static void Main()
{
var divs = new[] {3,5,7,11,13,17};
// combinations of 1-9
var combinations =
from x in Enumerable.Range(1, 7)
from y in Enumerable.Range(x + 1, 8 - x)
from z in Enumerable.Range(y + 1, 9 - y)
select new { x, y, z };
// permute
var qry = from comb in combinations
where !Permute(comb.x, comb.y, comb.z).Any(
i => divs.Any(d => i % d == 0))
select comb;
foreach (var answer in qry)
{
Console.WriteLine("{0}, {1}, {2}", answer.x, answer.y, answer.z);
}
}
For the second - not elegant, but it works (returns the 8 permutations of the sample):
static void Main() {
var data = Enumerable.Range(1, 9);
var magicSquares =
// generate 1st row and deduce the target
from a in data let arrA = new[] { a }
from b in data.Except(arrA) let arrB = new[] { a,b }
from c in data.Except(arrB) let arrC = new[] { a,b,c }
let target = a + b + c
// generate 2nd row and filter to target matches
from d in data.Except(arrC) let arrD = new[] { a,b,c,d }
from e in data.Except(arrD) let arrE = new[] { a,b,c,d,e }
from f in data.Except(arrE) let arrF = new[] { a,b,c,d,e,f }
where d + e + f == target
// generate 3rd row and filter to target matches
from g in data.Except(arrF) let arrG = new[] { a,b,c,d,e,f,g }
from h in data.Except(arrG) let arrH = new[] { a,b,c,d,e,f,g,h }
from i in data.Except(arrH)
where g + h + i == target
// filter columns
&& a + d + g == target
&& b + e + h == target
&& c + f + i == target
// filter diagonals
&& a + e + i == target
&& c + e + g == target
select new {a,b,c,d,e,f,g,h,i};
foreach (var row in magicSquares)
{
Console.WriteLine("{0} {1} {2}", row.a, row.b, row.c);
Console.WriteLine("{0} {1} {2}", row.d, row.e, row.f);
Console.WriteLine("{0} {1} {2}", row.g, row.h, row.i);
Console.WriteLine();
}
}