In my office there was a jackpot programming event was conducted, in that event they asked 3 questions, but 1 of the puzzles was really tough for us and I just tried in my own interest
Question:
A = {10, 15, 25}
B = {1, 5, 20, 30}
Expected output:
10 20
10 20 25 30
10 30
15 20
15 20 25 30
15 30
25 30
In output:
10 20 --> A's 1st element and B's 1st smallest element that greater than A's 1st element
10 20 25 30 --> A's 1st element Check with B array, which is greater than A, and again Check with A , repeat it until B doesn't have any greater element in compared to A, if B doesn't have to end up with previous B value.
10 30 --> A's 1st element and B's largest element that greater than A's 1st element
the above method will iterate all over the A elements.
Here is my solution, the only thing that didn't make sense was why he skipped 15 in the first set of sets, and since you don't have any more information I had to suppose the reason for skipping it(call it an exception)
int[] A = { 10, 15, 25 };
int[] B = { 1, 5, 20, 30 };
//10 20
//10 20 25 30
//10 30
//15 20
//15 20 25 30
//15 30
//25 30
var result = A.SelectMany(x => GetIllogicalPermutations(x, A, B)).DistinctBy(x => x.Sum());
for (int i = 0; i < result.Count(); i++)
{
Console.WriteLine(string.Join(' ', result.ElementAt(i).Select(x => x.ToString())));
}
Console.ReadLine();
static IEnumerable<int[]> GetIllogicalPermutations(int item, int[] setA, int[] setB)
{
yield return new int[] { item, setB.Where(x => x > item).Min() };
yield return setA.Where(x => x > item && x != (setA.Max() - setA.Min())).Concat(setB.Where(x => x > item)).Prepend(item).OrderBy(x => x).ToArray();
yield return new int[] { item, setB.Where(x => x > item).Max() };
}
If I understood your problem correctly it is like this
class Solution
{
int[] a;
int[] b;
public Solution(int[] a, int[] b)
{
this.a = a;
this.b = b;
}
void InterateA(int min, string output)
{
foreach (var a in a.OrderBy(n => n).SkipWhile(n => n <= min))
{
InterateB(a, $"{output}\t{a}");
}
}
void InterateB(int min, string output)
{
foreach (var b in b.OrderBy(n => n).SkipWhile(n => n <= min))
{
var str = $"{output} {b}";
Console.WriteLine(str);
InterateA(b, str);
}
output = null;
}
public void Print()
{
InterateA(a.OrderBy(n => n).First() - 1, null);
}
}
Test code
static void Main(string[] args)
{
var a = new int[] { 10, 15, 25, 35 };
var b = new int[] { 1, 5, 20, 30, 40 };
var solution = new Solution(a, b);
solution.Print();
Console.ReadKey();
}
Performance is minimum as this is initial trivial solution and canbe optimized if it does the job correctly.
Related
I need to add the following intervals to the for loop (I tried with if statements and the teacher asked me to reduce the amount of coding).
Intervals (Pizza Diameters)
12 - 20 = 8 slices
21 - 24 = 12 slices
25 - 30 = 16 slices
31 - 36 = 24 slices
The following code gives me output that's pretty close to what I need, except that it doesn't adhere to the conditions above. For example if I enter 24 it should only give me the output for 8 and 12 slices.
int[] pizzaSlices = new int[4] { 8, 12, 16, 24 };
for (int i = pizzaSlices[0]; i < inputDiameter; i++) {
if (i == pizzaSlices[0] || i == pizzaSlices[1] || i == pizzaSlices[2] ||
i == pizzaSlices[3]) {
Console.WriteLine("cut in " + i + " slices results in a slice area of " +
Math.Round(areaOfThePizza / i, 2) + " per slices");
}
}
Current Output:
Desired Output:
I couldn't resist adding a somewhat LINQ'y solution:
[Test]
[TestCase(37, Result = 0)]
[TestCase(36, Result = 24)]
[TestCase(35, Result = 24)]
[TestCase(30, Result = 16)]
[TestCase(29, Result = 16)]
[TestCase(26, Result = 16)]
[TestCase(22, Result = 12)]
[TestCase(12, Result = 8)]
[TestCase(11, Result = 0)]
[TestCase(10, Result = 0)]
public int GetNumberOfSlices(int diameter)
{
var pizzas = new[] {
new[] { 11, 0 },
new[] { 20, 8 },
new[] { 24, 12 },
new[] { 30, 16 },
new[] { 36, 24 }
};
var pizza = pizzas.FirstOrDefault(p => diameter <= p[0]);
return pizza == null ? 0 : pizza[1];
}
I added another int array to hold the pizza diameters. The for loop iterates from 0 to the length of pizzaSlices, so 0 to 3.
The if statement in the for loop checks if the user entered diameter is in the range of the current iteration's pizzaDims counterpart.
int[] pizzaSlices = new int[4] { 8, 12, 16, 24 };
int[] pizzaDims = new int[4] { 12, 21, 25, 31 }; // pizza diameters array
if(inputDiameter >= smallest) {
for (int i = 0; i <= pizzaSlices.Length; i++) {
if(inputDiameter >= pizzaDims[i] {
Console.WriteLine("cut in " + pizzaSlices[i] +
" slices results in a slice area of " +
Math.Round(areaOfThePizza / pizzaSlices[i], 2) +
" per slices");
} else {
break; // no need to continue iterating, if one condition is false then
// the rest will be as well
}
}
}
Hi I want to replace a byte[] where ever there is 10 by 10 10. here is my code.
if i have my data as "10 20 10 20 40 50 50 50 50 10 03" i want to replce it by
"10 20 10 10 20 40 50 50 50 50 10 10 03"
note: first byte is untouched
plse follow my comment, my idea is to push the byte array to nxt position and add another 10.
foreach (var b in command.ToBytes())
{
// var c = b;
transmitBuffer[count++] = b; data is formed here
addedbuffer[addall++] = b; duplication is made
}
if (addedbuffer[0] == 16 && addedbuffer[1] == 32 || addedbuffer[50] == 16 && addedbuffer[51] == 03) /
{
/condition on which to enter here
addedbuffer[0] = 0; //making 1st and 2nd value as null
addedbuffer[1] = 0;
for (int i = 0; i < addedbuffer.Length; i++) //till length i will chk
{
if (addedbuffer[i] == 10) //replace 10 by 10 10
addedbuffer[i] = 1010; // error,
}
}
You can't insert into array (you can do it with List<T>), so it looks that you have to create a new array; Linq solution:
Byte[] source = new Byte[] {
20, 10, 20, 40, 50, 50, 50, 50, 10, 03
};
var result = source
.SelectMany((item, index) =>
item == 10 && index != 0 ? new Byte[] { item, item } : new Byte[] { item })
.ToArray();
However, using List<Byte> (in order just to insert 10's) instead of Byte[] is a better way out:
List<Byte> list = List<Byte>() {
20, 10, 20, 40, 50, 50, 50, 50, 10, 03
};
// In order not to read inserted 10's we loop backward
// i >= 1: 1st byte should be preserved as is even if its == 10
for (int i = list.Count - 1; i >= 1; --i)
if (list[i] == 10)
list.Insert(i + 1, 10);
It helps to think of sequences like arrays (IEnumerable<T> in C#) as things that can be transformed into new sequences. Much like numbers can be transformed when you send them into a function, sequences can be, too.
Consider if I have a function that is defined as Add10If10(Byte b). It might looks like this:
public static Byte Add10If10(Byte b)
{
if (b == 10)
{
return b + 10;
}
return b;
}
Numbers which go into this are transformed based on the condition, and come out either 10 larger or the same. The same can be done with sequences, you can take a sequence with some number of elements, and transform it so it has more elements. The result is a new sequence:
public static IEnumerable<Byte> AddAdditional10If10(IEnumerable<Byte> values)
{
foreach (var b in values)
{
if (b == 10)
{
yield return 10;
}
yield return b;
}
}
This function returns an additional 10 for every 10 it encounters. Now that you have the right sequence, you can change how it is stored by changing it to an array:
AddAdditional10If10(addedbuffer).ToArray();
This works via conversion to strings, using String.Replace and converting back:
byte[] source = new Byte[] { 20, 10, 20, 40, 50, 50, 50, 50, 10, 03 };
string[] strArr = Array.ConvertAll(source, b => b.ToString());
string[] replArr = String.Join(" ", strArr).Replace("10", "10 10").Split();
byte[] newArr = Array.ConvertAll(replArr, str => Byte.Parse(str));
Edit:
Another approach with LINQ - elements at first and last indexes and all elements not equal to 10 are unchanged, for all remaining 10s it returns a sequence of 2 10s:
byte[] res = source.SelectMany((b, index) => index == 0
|| index == source.Length - 1
|| b != 10 ?
Enumerable.Repeat(b, 1) : Enumerable.Repeat(b, 2))
.ToArray();
This is a fairly efficient way to do it (requires two passes over the input array, but does not require any resizing of the output array):
public static byte[] Replace10With1010ExcludingFirstByte(byte[] input)
{
// Count 10s excluding first byte.
int count = input.Skip(1).Count(b => b == 10);
// Create output array of appropriate size.
byte[] result = new byte[input.Length + count];
// Copy input to output, duplicating all 10s that are not the first byte.
result[0] = input[0];
for (int i = 1, j = 1; i < input.Length; ++i, ++j)
{
result[j] = input[i];
if (input[i] == 10)
result[++j] = 10;
}
return result;
}
Call it with your original array, and use the returned array instead.
Test code (for use in a Console app):
byte[] input = {10, 20, 10, 20, 40, 50, 50, 50, 50, 10, 03};
var result = Replace10With1010ExcludingFirstByte(input);
Console.WriteLine(string.Join(", ", result));
[EDIT] It seems from one of your comments to another answer that you also want to also exclude the last byte from conversion too.
If so, use this code instead:
public static byte[] Replace10With1010ExcludingFirstAndLastByte(byte[] input)
{
// Count 10s excluding first and last byte.
int count = input.Skip(1).Take(input.Length-2).Count(b => b == 10);
// Create output array of appropriate size.
byte[] result = new byte[input.Length + count];
// Copy input to output, duplicating all 10s that are not the first byte.
result[0] = input[0];
for (int i = 1, j = 1; i < input.Length; ++i, ++j)
{
result[j] = input[i];
if ((input[i] == 10) && (i != (input.Length-1)))
result[++j] = 10;
}
return result;
}
Anyone can elaborate some details on this code or even give a non-Linq version of this algorithm:
public static IEnumerable<IEnumerable<T>> Combinations<T>
(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] }
: elements.SelectMany(
(e, i) =>
elements
.Skip(i + 1)
.Combinations(k - 1)
.Select(c => (new[] {e}).Concat(c)));
}
The best way to understand this code is to read the amazing serial post from Eric Lippert:
Producing combinations, part one
Producing combinations, part two
Producing combinations, part three
Producing combinations, part four
Producing combinations, part five
Basically, if we have a IEnumerable of 5 items, and want to get all combinations size of 3, we need to produce something like this:
{
// 50, 60, 70, 80, 90
{50, 60, 70}, // T T T F F
{50, 60, 80}, // T T F T F
{50, 60, 90}, // T T F F T
{50, 70, 80}, // T F T T F
{50, 70, 90}, // T F T F T
{50, 80, 90}, // T F F T T
{60, 70, 80}, // F T T T F
{60, 70, 90}, // F T T F T
{60, 80, 90}, // F T F T T
{70, 80, 90} // F F T T T
}
Eric's recursive implementation:
// Takes integers n and k, both non-negative.
// Produces all sets of exactly k elements consisting only of
// integers from 0 through n - 1.
private static IEnumerable<TinySet> Combinations(int n, int k)
{
// Base case: if k is zero then there can be only one set
// regardless of the value of n: the empty set is the only set
// with zero elements.
if (k == 0)
{
yield return TinySet.Empty;
yield break;
}
// Base case: if n < k then there can be no set of exactly
// k elements containing values from 0 to n - 1, because sets
// do not contain repeated elements.
if (n < k)
yield break;
// A set containing k elements where each is an integer from
// 0 to n - 2 is also a set of k elements where each is an
// integer from 0 to n - 1, so yield all of those.
foreach(var r in Combinations(n-1, k))
yield return r;
// If we add n - 1 to all the sets of k - 1 elements where each
// is an integer from 0 to n - 2, then we get a set of k elements
// where each is an integer from 0 to n - 1.
foreach(var r in Combinations(n-1, k-1))
yield return r.Add(n-1);
}
In your case, the code is working like this:
return k == 0
// if we are done, return empty array
? new[] {new T[0]}
// for each element and each number from 0 to enumerable size
: elements.SelectMany((e, i) =>
elements
//skip first i elements, as we already produced combination with them
.Skip(i + 1)
//get all the combinations with size k - 1
.Combinations(k - 1)
//add current element to all produced combinations
.Select(c => (new[] {e}).Concat(c)));
This code in non-recursive form will be very huge and unreadable, try to understand the recursion:
Say, we have a 5 elements IEnumerable: { 16, 13, 2, 4, 100 }, and we need to all the combinations from it with size of 2 (total numbers of resulting sets is equal to Binomial coefficient from 5 to 2 = 5! / (2! * 3!) = 10)
Your code will be producing:
For the 16 we need all the combinations of size 1, starting from second position:
For the element 13 we need all the combinations of size 0 starting from the third position
First result: { 16, 13 }
Skip the 13, For the element 2 we need all the combinations of size 0 starting from the fourth position
Second result: { 16, 2 }
Skip the 13, 2, For the element 4 we need all the combinations of size 0 starting from the fifth position
Third result: { 16, 4 }
Skip the 13, 2, 4, For the element 100 we need all the combinations of size 0 starting from the sixth position
Fourth result: { 16, 100 }
... repeat all the above from 13, 2, 4:
{ 13, 2 }, { 13, 4 }, { 13, 100 }, { 2, 4 }, { 2, 100 }, { 4, 100 }
And we got all the 10 combinations we need. The overload the code author is using is this: Enumerable.SelectMany<TSource, TResult> Method (IEnumerable<TSource>, Func<TSource, Int32, IEnumerable<TResult>>):
selector
Type: System.Func<TSource, Int32, IEnumerable<TResult>>
A transform function to apply to each source element;
the second parameter of the function represents the index of the source element.
My none linq version, should be correct!
Test results:
Linq style:
123
124
125
134
135
145
234
235
245
345
My way:
123
124
125
134
135
145
234
235
245
345
My Code
/// <summary>
/// Get the full combinations of k elements from a given list.
/// </summary>
public static List<List<T>> MyCombinations<T>(this List<T> elements, int k)
{
int n = elements.Count;
//Given the same sequence, what if we wish to choose none of them? There does exist a subsequence which has zero elements, so we should produce it; the answer would be { { } }
if (k == 0)
{
return new List<List<T>> {new List<T> {}};
}
if (k == n)
{
return new List<List<T>> {elements};
}
// What if we have a sequence of five items and we wish to choose six of them? There is no way to do that; there is no six-element subsequence. So the answer should be { }, the empty sequence of sequences
if (k > n)
{
return new List<List<T>> {};
}
var result = new List<List<T>> {};
for (int i = 0; i < n; i++)
{
T cur = elements[i];
var rest = elements.Skip(i + 1).ToList();//take out current elment to fetch combinations of the rest set
var combinationsOfRest = MyCombinations<T>(rest, k - 1);
var currentList = new List<T> {cur};
foreach (List<T> combination in combinationsOfRest)
{
result.Add(currentList.Concat(combination).ToList());
//combination.Add(cur);
//result.Add(combination);
}
}
return result;
}
I have a multidimentional array like this one with about 3000 rows and 200 columns:
+--+--+--+
|21|23|41|
+--+--+--+
|11|14|16| // 11 is the smalles value in 2nd row
+--+--+--+
|43|35|23|
+--+--+--+
I want to determine the smalles value of the second row.
Is there a better / more readable / linq solution? I currently use a for-loop?
My current Approach:
int min = array[0,1];
for (int i= 1; i<len;i++)
{
if (array[i,1] < min)
{
min = array[i,1];
}
}
Let arr be the array and l.u == 1 suggests second row:
arr.Select((t, u) => new { u, t }).Where(l => l.u == 1).FirstOrDefault().t.Min();
found a working solution
int[,] array = new int[3, 3] { { 21, 23, 41 }, { 11, 14, 16 }, { 43, 35, 23 } };
int min = Enumerable.Range(0, array.GetLength(1)).Min(i => array[1, i]);
Console.WriteLine(min); // 11
I have a set of numbers List<int> (for example) : 1, 3, 4, 5, 7, 12, 13, 14, 15, 20, 22, 24, 28, 29, 30
I want to have them grouped as sequential like :
Sequence1 = from 1 amount 1 (1)
Sequence2 = from 3 amount 3 (3, 4, 5)
Sequence3 = from 7 amount 1 (7)
Sequence4 = from 12 amount 4 (12, 13, 14, 15)
Sequence5 = from 20 amount 1 (20)
Sequence6 = from 22 amount 1 (22)
Sequence7 = from 24 amount 1 (24)
Sequence8 = from 28 amount 3 (28, 29, 30)
I know how to do it with a for and checking for each number. Is there an more elegant way or an algorithm, or some sql/lambda command that would help me ?
If the input is sorted, and you really want to avoid a foreach loop, you can use:
list.Select((value,index)=>new {value,index}).GroupBy(x=>x.value-x.index,x=>x.value).Select(g=>g.AsEnumerable())
One could also write a general helper method:
public static IEnumerable<IEnumerable<T>> SplitBetween<T>(this IEnumerable<T> sequence, Func<T,T,bool> predicate)
{
T previous=default(T);
List<T> list=new List<T>();
int index=0;
foreach(T current in sequence)
{
if((index>0)&&predicate(previous,current))
{
yield return list.ToArray();
list.Clear();
}
list.Add(current);
previous=current;
index++;
}
if(list.Count>0)
yield return list.ToArray();
}
And then use it with list.SplitBetween((previous,current) => previous+1 != current)
I don't think that this is very "elegant", but here is my suggestion, hopefully it helps you:
var list = new List<int> { 1, 3, 4, 5, 7, 12, 13, 14, 15, 20, 22, 24, 28, 29, 30 };
int offset = 0;
int sequence = 0;
do
{
int offset1 = offset;
var subList = list.Skip(offset).TakeWhile((item, index) => (index == 0) || (item == (list[offset1 + index - 1] + 1))).ToList();
offset += subList.Count();
sequence++;
Debug.WriteLine("Sequence {0} from {1} amount {2} ({3})", sequence, subList[0], subList.Count(), string.Join(" ", subList));
}
while (offset < list.Count);
int n = 12;//your number
int x = list.IndexOf(n);
var result = list.Skip(x).TakeWhile((value, index) => value - index == n);