I'm trying to re-arrange a list of objects in different ways. Here I'll use integers but could be anything in this list.
The example code below sorts 1,2,3,4,5,6,7,8 into the following order:
1,8,2,7,3,6,4,5
So first. last. second. Second to last etc. It may be a bit clunky but it works.
Now what I'm trying to do now is to output the list in another order, so that it keeps dividing in two. I think this may be called Divide and Conquer but after trying / looking at some recursive sorting code etc. I'm not too clear on how to implement that here.
I hope to get the numbers ordered like this.
1,8,4,2,6,3,5,7
First, last, halfway, 1st half halfway, 2nd half halfway etc.
So in other words what I'm trying to do is to split the set of numbers in half... Then for each half in turn split those in half. And so on:
1 2 3 4 5 6 7 8
1 (first item)
8 (last item)
4 (mid item)
2 (mid of first half)
6 (mid of second half)
3 (mid of 1st chunk)
5 (mid of 2nd chunk)
7 (mid of 3rd chunk)
If anyone could anyone show me how to do this, with this simple example, that'd be really great.
static void Main(string[] args)
{
List<int> numberlist = new List<int>();
numberlist.Add(1);
numberlist.Add(2);
numberlist.Add(3);
numberlist.Add(4);
numberlist.Add(5);
numberlist.Add(6);
numberlist.Add(7);
numberlist.Add(8);
int rev = numberlist.Count-1;
int fwd = 0;
// order 1,8,2,7,3,6,4,5
for (int re = 0; re < numberlist.Count; re++)
{
if (re % 2 == 0)
{
Console.WriteLine(numberlist[fwd]);
fwd++;
}
else
{
Console.WriteLine(numberlist[rev]);
rev--;
}
}
Console.ReadLine();
}
Some more sample ranges and output, to be read left-to-right, top-to-bottom:
1 2 3 4 5 6 7
1 7
4
2 5
3 6
1 2 3 4 5 6 7 8 9 10 11 12
1 12
6
3 9
2 4 7 10
5 8 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 16
8
4 12
2 6 10 14
3 5 7 9 11 13 15
Let me see if I understand the problem. Let's work an example with more items:
This is the order you want?
ABCDEFGHIJKLMNOPQ
A Q
I
E M
C G K O
B D F H J L N P
That seems straightforward. Create a data structure called "Interval" that has two fields: the Greatest Lower Bound and the Least Upper Bound. That is, what are the elements that are the biggest thing that is below the interval and the smallest thing that is above the interval. The algorithm goes like this:
Input: the size of the array.
Yield the first item -- if there is one
Yield the last item -- if it is different from the first item.
Make a queue of intervals.
Enqueue the interval (0, array.Length - 1)
While the queue is not empty:
Dequeue the queue to obtain the current item.
Is the interval empty? If so, skip this interval
Otherwise, the interval has a GLB, a LUB, and a value in the middle.
Yield the middle of the interval
Enqueue the interval (bottom, middle)
Enqueue the interval (middle, top)
Let's work the example above. We have the array ABCDEFGHIJKLMNOPQ.
Yield A
Yield Q
Enqueue A-Q. The queue is now A-Q
Is the queue empty? No.
Dequeue the queue. It is now empty.
current is A-Q
Is the current interval empty? no.
The middle is I.
Yield I.
Enqueue A-I. The queue is now A-I.
Enqueue I-Q. The queue is now A-I, I-Q.
Is the queue empty? No.
Dequeue the queue. It is now I-Q.
current is A-I.
Is the current interval empty? No.
The middle is E.
Yield E.
Enqueue A-E. The queue is now I-Q, A-E.
Enqueue E-I. The queue is now I-Q, A-E, E-I
Is the queue empty? No.
Dequeue. The queue is now A-E, E-I
current is I-Q
The middle is M
Yield M.
Enqueue I-M
Enqueue M-Q. The queue is now A-E, E-I, I-M, M-Q
OK, let's start skipping some steps here. The state of the queue and the yields are:
Yield C
E-I, I-M, M-Q, A-C, C-E
Yield G
I-M, M-Q, A-C, C-E, E-G, G-I
Yield K
M-Q, A-C, C-E, E-G, G-I, I-K, K-M
yield O
A-C, C-E, E-G, G-I, I-K, K-M, M-O, O-Q
yield B
C-E, E-G, G-I, I-K, K-M, M-O, O-Q, A-B, B-C
OK, skip more steps...
Yield D, F, H, J, L, N, P
Queue is now A-B, B-C, C-D, D-E, ... P-Q
Every interval is now empty, so we skip all of htem and we are done.
Make sense?
The trick here is to notice that the order you want is a breadth-first visit of a tree. You just have to be able to "see through" the array to the tree structure that you want to traverse.
Incidentally, the ordering seems a bit weird. The ordering for the most part seems to be "divide the range into two parts and yield the middle of each range first". Why then are the two extremes yielded first, instead of last? I would find the ordering:
ABCDEFGHIJKLMNOPQ
I
E M
C G K O
B D F H J L N P
A Q
more intuitively obvious; if the things "in the middle" always get priority over things "at the extremes" then the extremes should go last, not first.
I can demonstrate a similar selection; it results in a slightly different order to yours.
Take the numbers 0 to 7, and express them in binary: 000 001 010 011 100 101 110 111.
Now, reverse them: 000 100 010 110 001 101 011 111.
In decimal, this gives 0 4 2 6 1 3 5 7. So you start with the first element, then halfway through the rest of the elements, then a quarter and three quarters, and then finally all the odd-numbered elements.
Obviously this procedure only works for exact powers of two.
Related
I’m having an issue with an algorithm I’m trying to implement in C# (the language doesn't matter much I guess).
Let’s say I have a list that could be of any length..for example:
var maxNumbers = new List<int>{5,3,2}();
The numbers in the list represent the maximum value of each entry. For example, the first entry means that it can be any number between 1 and 5 (5 is included).
Now, I want to print all combinations of every possible value for each entry in the list.
To explain:
The first number in the list is 5, so the possible values are 1,2,3,4,5
The second number in the list is 3, so the possible values
are 1,2,3
The last number in the list is 2, so the possible values
are 1,2
My algorithm should print something like:
1-1-1
1-1-2
1-2-1
1-2-2
1-3-1
1-3-2
1-2-1
etc.
I tried to implement this using recursion but wasn't able to get it. Here is my code:
void Iterate(List<int> numbers)
{
if (numbers.Count == 0)
{
Console.WriteLine("");
return;
}
int number = numbers[0];
for (int i = 1; i <= number; i++)
{
Console.WriteLine($"{i} ");
Iterate(numbers.Where((v, index) => index != 0).ToList());
}
}
Can anyone provide insights?
A non recursive approach;
We use Select(Enumerable.Range) to turn your list of maxes into a list of list of ints representing all the numbers..
Then we repeatedly use SelectMany to add another level to the list. SelectMany expects to be fed an enumerable. In the first instance there is only one item in combos, which gets crossed with 5 items from the first entry in ints, so SelectMany produces 5 items.
Second time round SelectMany effectively thinks it's expanding a "5 lists of 3 items" into a "list of 15 items". Third time round SelectMany thinks it's expanding a "15 lists of 2 items" into a "list of 30 items"...
public static string[] Combine(IEnumerable<int> maxes)
{
var ints = maxes.Select(max => Enumerable.Range(1, max));
IEnumerable<string> combos = new[] { "" };
foreach (var i in ints)
{
combos = combos.SelectMany(r => i.Select(x => r + (r == "" ? "" : "-") + x));
}
return combos.ToArray();
}
This answer fixes your code, the crucial problem with which, for me, was that the solution didn't carry any memory of where it had got to so far with making the output, so there isn't any way for iterate to repeat the earlier loop outputs
Here's the fixed code:
static void Iterate(List<int> numbers, string sofar)
{
if (numbers.Count == 0)
{
Console.WriteLine(sofar);
return;
}
for (int i = 1; i <= numbers[0]; i++)
{
Iterate(numbers.Skip(1).ToList(), sofar + i + " ");
}
}
Your code in the question hs a bit of a typo in that it does a WriteLine in the for loop which really messed up the output. Removing that to just Write you get:
1 1 1
2
2 1
2
3 1
2
2 1 1
2
2 1
2
3 1
2
3 1 1
2
2 1
2
3 1
2
4 1 1
2
2 1
2
3 1
2
5 1 1
2
2 1
2
3 1
2
If I add some spaces to change the alignment:
1 1 1
2 --> it's 1 1 2
2 1 --> it's 1 2 1
2 --> it's 1 2 2 etc
3 1
2
2 1 1
2
2 1
2
3 1
2
3 1 1
2
2 1
2
3 1
2
...
You can see it's nearly there, in that it's printing the number that changes each time, it's just lost any memory of what to print in terms of the numbers that haven't changed. The altered code passes the "string we generated so far" and devolves responsibility for printing it to just the if. Each time the loop calls Iterate it passes the string built so far so it keeps that memory of where it got up to
Prime Number Generator Code
Do know that this question should be quite basic but i have spent hours trying to figure out why my code is stuck in the loop as below. Have added a Console.WriteLine($"{counttemp} , {count1} "); in the if loop to check the 2 numbers and seems like it is not breaking out of the if condition when the condition is true
this is the console output for the writeline in the if loop
5 , 5
6 , 2
7 , 7
8 , 2
9 , 3
10 , 2
11 , 11
12 , 2
13 , 13
14 , 2
15 , 3
16 , 2
17 , 17
18 , 2
19 , 19
Problematic Loop??
for (count1 = 2; count1 <= counttemp ; ++count1)
{
if(counttemp % count1 == 0)
{
Console.WriteLine($"{counttemp} , {count1} ");
Console.ReadKey();
primetest1 = 0;
break;
}
}
full code sequence
static void Main(string[] args)
{
int prime1 = 10000, count1, primetest1, counttemp;
for (counttemp = 5; counttemp <= prime1; counttemp++)
{
primetest1 = 1;
for (count1 = 2; count1 <= counttemp ; ++count1)
{
if(counttemp % count1 == 0)
{
Console.WriteLine($"{counttemp} , {count1} ");
Console.ReadKey();
primetest1 = 0;
break;
}
}
if (primetest1 == 1)
{
Console.Write($"{counttemp}");
}
}
}
You're almost there. The problem is that you're checking if your candidate number is a prime by getting the remainder when divided by each number up to and including the number itself.
I think you'll find that N is a factor of N for all values of N. To fix this, you should only be checking up to but excluding the number.
And, as an aside, you don't really need to check all the way up to N - 1. You only need to go to the square root of N, adjusted up to the nearest integer. That's because, if it has a factor above the square root, you would already have found a factor below it.
Consider 24 as an example. It has 6, 8, and 12 as factors above the square root, but the matching values below the square root are 4, 3, and 2 respectively.
And there's a another trick you can use by realising that if a number is a multiple of a non-prime, it's also a multiple of every prime factor of that non-prime. In other words, every multiple of 12 is also a multiple of 2 and 3.
So you only need to check prime numbers up to the square root, to see if there's a factor. And prime numbers, other than two or three, are guaranteed to be of the form 6x-1 or 6x+1, so it's quite easy to filter out a large chunk of candidates very quickly, by checking only for those values.
In other words, check two and three as special cases. Then start at 5 and alternately add 2 and 4: 5, 7, 11, 13, 17, 19, .... Not every number in that set is prime (e.g, 25) every prime is guaranteed to be in that set.
You can check out an earlier answer of mine for more detail on why this is so, and how to do this sequence efficiently.
There is a wall of size 4xN. We have infinite number of bricks of size 4x1 and 1x4. What is the total number of ways in which the bricks can be arranged on the wall so that a new configuration arises every time?
For N = 1, the brick can be laid in 1 format only. For N = 7, one of the ways in which we can lay the bricks is
There are 5 ways of arranging the bricks for N = 7
I solve this problem using dynamic programming:
static int computeBricks(int n)
{
if(n <= 3) { return 1; }
int[] table = new int[n+1];
table[0] = 1;
table[1] = 1;
table[2] = 1;
table[3] = 1;
for(int i = 4; i <= n; ++i)
{
table[i] = table[i-1] + table[i-4];
}
return table[n];
}
But it's just a combination: a guess + intuition. I don't understand this solution completely. Why table[i] = table[i-1] + table[i-4]?
Doesn't it look like the coin change problem?
The number of ways to change amount a using n kinds of coins equals:
the number of ways to change amount a using all but the first kind of coin, plus the number of ways to change amount a - d using all n kinds of coins, where d is the denomination of the first kind of coin.
But I also don't understand how we can use this idea to solve the original problem
Just to be complete, you can do that using simple counting techniques, no algorithm needed.
You have N spots. You have two ways to fill the spots: either one at a time (vertical bricks), or filling 4 consecutive spots in one go (horizontal bricks). You can reformulate that: this is the number of ways you can place K piles of 4 horizontal bricks (K is between 0 and N/4) among N-(3*K) vertical bricks (for each pile of 4 horizontal bricks, you lose 3 spots compared to 1 vertical brick - this is kind of where your [n-4] comes from in your original algorithm).
Let's illustrate that with an example. First of all, the notation choose(n, k) that I use below is the mathematical combination "n choose k", i.e.
Now let's dive in the example. What can you do with N = 15 spots?
You have either K = 0 pile of horizontal bricks (H) and 15 vertical bricks (V): VVVVVVVVVVVVVVV. The number of ways to do that is choose(15, 0) = 1
Or you can place K = 1 H somewhere (you lose three spots by replacing 4 V by 1 H): VVVVHVVVVVVV. The number of ways to do that is choose(15-3, 1) = choose(12, 1) = 12
Or you can place K = 2 H (you lose six spots by replacing 8 V by 2 H): VVHVVVVVH. The number of ways to do that is choose(15-6, 2) = choose(9, 2) = 36
Or you can place K = 3 H (you lose nine spots by replacing 12 V by 3 H): HVVHHV. The number of ways to do that is choose(15-9, 3) = choose(6, 3) = 20
That's it, you have reached the maximum number of horizontal piles (max K = 15/4 = 3). Then you just sum all of these to get the total number of ways you can fill the spots: 1+ 12 + 36 + 20 = 69.
Here is the general formula that directly follows up from this explanation:
Which finally leads to:
There is obviously only one way to arrange the bricks if you have less than 4 columns:
1, 12, 123
1, 12, 123
1, 12, 123
1, 12, 123
However, there are two ways to arrange bricks for the 4-th column.
Way 1 - simply add a column to a correct solution of 3 columns:
1234
1234
1234
1234
Way 2 - remove existing three columns and place four horizontal bricks:
1111
2222
3333
4444
The same logic applies to all consequent columns - you may either take all proper arranges for N-1 and add a column to each of them or take all correct arranges for N-4 and place four bricks horizontally.
The solution is that simple because of one derivation from the problem - you can either place 4 horizontal bricks or 4 vertical bricks, because putting 1 horizontal brick will make placing vertical impossible, and vice versa.
This task would be much more difficult if wall still was 4xN, but bricks were 2x1 and 1x2.
f(n) = f(n-1) + f(n-4) if n >= 4 <p>
f(n) = 1 if 0 <= n < 4
I have a list.
1 2 3 4 5 6 7
I wish to return a list of differences (deltas) between consecutive element.
1 1 1 1 1 1
How can I do this?
I am sure there must be a simple "collections" way of doing this - but I cannot find it.
You can use Enumerable.Skip and the overload of Enumerable.Select which projects the index:
List<int> deltaList = list.Skip(1) // skip first, irrelevant
.Select((num, index) => num - list[index]) // index 0 is second number in list
.ToList();
The trick is that Skip(1) does not only skip the first number (which is desired) but also changes the indices in Select. The first number's index will be 0 but it'll refer to the second number in the list (due to Skip(1)). Therefore num - list[index] subtracts the current with the previous number.
var result = list.Zip(list.Skip(1), (x, y) => y - x);
This question already has answers here:
Algorithm to return all combinations of k elements from n
(77 answers)
Closed 8 years ago.
I have a list which has always even item count.
I need an algorithm to find all two member combinations.
For instance if item count is 4, output will be;
Items:
{1, 2, 3, 4 }
ResulSet:
{12}, {34}
{13}, {24}
{14}, {23}
Order makes no difference, {12} covers {21}.
For item count 6, output will be;
Items:
{1, 2, 3, 4, 5, 6}
ResulSet:
12 34 56
12 35 46
12 36 45
13 24 56
13 25 46
13 26 45
14 23 56
14 25 36
14 26 35
15 23 46
15 24 36
15 26 34
16 23 45
16 24 35
16 25 34
Could you show me a way please?
Thank you.
Edit:
Question is really short to read, and if you take 1 minute to read question you can see it is not duplicate like most of people think (probably they are semi-illiterate)
Combination of {1, 2, 3, 4, 5, 6} is
123456 and as you see at top, this is not what I'm looking for. Read question if you want to help or just get off.
Have a nice day.
Since you always have two members in your combination, a simple nested for loop should work:
for (int i = 0; i < data.Length - 1; i++)
for (int j = i + 1; j < data.Length; j++
Console.WriteLine({0}{1}, i, j);
We iterate over each item in the list, up to the next to last one (since we can't have 1 number combos). In each of these iterations, we iterate from the outer iteration variable plus 1 (no duplicating elements) up to the end of the list.
This will generate all unique combinations. To do more than two or three member outputs though, you'll want to look into recursion. I'll leave formatting the output to match your question as an exercise to the reader :).
For 6 element combinations, we will have to delve into the wild world of recursion. Recursion can really mess with your head, so please ask if you don't understand something. The general principle of recursion is: "Do something with the first element, call yourself and pass the rest". In this situation, the code would look something like:
public List<List<int>> GetAllCombos (int[] values)
{
//Kick it off with the 0 index
return GetCombos(values, 0);
}
private List<List<int>> GetCombos(int[] values, int myIndex)
{
//A holder for combinations from this index onward
List<List<int>> combos = new List<List<int>>();
for (int i = myIndex; i < values.Length; i++)
{
if (myIndex + 1 < values.Length)
{
foreach (List<int> combo in GetCombos(values, myIndex + 1))
{
combo.Add(values[myIndex][i]);
combos.Add(combo);
}
}
else
{
List<int> newCombination = new List<int>() { values[myIndex][i] };
combos.Add(newCombination);
}
}
return combos;
}
Again, please make sure you ask if you don't understand something. Recursion can be a really tough concept to understand!
Have you done your research? 5 minutes (not even that) with google and I get:
Algorithms for Generating Permutations and
Combinations
Algorithms for Permutations and Combinations
Tree-Based Algorithms for Computing k-Combinations and k-Compositions
Combinatorial Algorithms
All of which would show you how to do this.
Searching SO, you pretty immediately find this question, Algorithm to return all combinations of k elements from n, with even more resources (not to mention actual solutions).
And if you're a member of IEEE or the ACM, a few seconds searching their online libraries will get you pretty much everything you need.