Let's say i have some items, that have a defined length and horizontal position (both are constant) :
1 : A
2 : B
3 : CC
4 : DDD (item 4 start at position 1, length = 3)
5 : EE
6 : F
I'd like to pack them vertically, resulting in a rectangle having smallest height as possible.
Until now, I have some very simple algorithm that loops over the items and that check row by row if placing them in that row is possible (that means without colliding with something else). Sometimes, it works perfectly (by chance) but sometimes, it results in non-optimal solution.
Here is what it would give for the above example (step by step) :
A | A B | ACC B | ACC B | ACC B | ACC B |
DDD | DDD | FDDD |
EE | EE |
While optimal solution would be :
ADDDB
FCCEE
Note : I have found that sorting items by their length (descending order) first, before applying algorithm, give better results (but it is still not perfect).
Is there any algorithm that would give me optimal solution in reasonable time ? (trying all possibilities is not feasible)
EDIT : here is an example that would not work using sorting trick and that would not work using what TylerOhlsen suggested (unless i dont understand his answer) :
1 : AA
2 : BBB
3 : CCC
4 : DD
Would give :
AA BBB
CCC
DD
Optimal solution :
DDBBB
AACCC
Just spitballing (off the top of my head and just pseudocode ). This algorithm is looping through positions of the current row and attempts to find the best item to place at the position and then moves on to the next row when this row completes. The algorithm completes when all items are used.
The key to the performance of this algorithm is creating an efficient method which finds the longest item at a specific position. This could be done by creating a dictionary (or hash table) of: key=positions, value=sorted list of items at that position (sorted by length descending). Then finding the longest item at a position is as simple as looking up the list of items by position from that hash table and popping the top item off that list.
int cursorRow = 0;
int cursorPosition = 0;
int maxRowLength = 5;
List<Item> items = //fill with item list
Item[][] result = new Item[][];
while (items.Count() > 0)
(
Item item = FindLongestItemAtPosition(cursorPosition);
if (item != null)
{
result[cursorRow][cursorPosition] = item;
items.Remove(item);
cursorPosition += item.Length;
}
else //No items remain with this position
{
cursorPosition++;
}
if (cursorPosition == maxRowLength)
{
cursorPosition = 0;
cursorRow++;
}
}
This should result in the following steps for Example 1 (at the beginning of each loop)...
Row=0 | Row=0 | Row=0 | Row=1 | Row=1 | Row=1 | Row=2 |
Pos=0 | Pos=1 | Pos=4 | Pos=0 | Pos=1 | Pos=3 | Pos=0 |
| A | ADDD | ADDDB | ADDDB | ADDDB | ADDDB |
F | FCC | FCCEE |
This should result in the following steps for Example 2 (at the beginning of each loop)...
Row=0 | Row=0 | Row=0 | Row=1 | Row=1 | Row=1 | Row=2 |
Pos=0 | Pos=2 | Pos=4 | Pos=0 | Pos=1 | Pos=3 | Pos=0 |
| AA | AACCC | AACCC | AACCC | AACCC | AACCC |
DD | DDBBB |
This is a classic Knapsack Problem. As #amit said, it is NP-Complete. The most efficient solution makes use of Dynamic Programming to solve.
The Wikipedia page is a very good start. I've never implemented any algorithm to solve this problem, but I've studied it relation with the minesweeper game, which is also NP-Complete.
Wikipedia: Knapsack Problem
Related
I am a little confused about why the logic here isn't working, and I feel like I have been staring at this bit of code for so long that I am missing something here. I have this method that gets called by another method:
private async Task<bool> Method1(int start, int end, int increment, IEnumerable<ModelExample> examples)
{
for (int i = start; i<= end; i++)
{
ModelExample example = examples.Where(x => x.id == i).Select(i => i).First();
example.id = example.id + increment; //Line X
// do stuff
}
return true;
}
I debuged the code above and it seems like when "Line X" gets executed not only is example.id changed individually but now that example in the List "examples" gets updated with the new id value.
I am not sure why? I want the list "examples" to remain the same for the entirety of the for loop, I am confused why updating the value for example.id updates it in the list as well?
(i.e. if the list before "Line X" had an entry with id = 0, after "Line X" that same entry has its id updated to 1, how can I keep the variable "examples" constant here?)
Any help appreciated, thanks.
This is what your list looks like:
+---------------+
| List examples | +-----------+
+---------------+ | Example |
| | +-----------+
| [0] ---------------> | Id: 1 |
| | | ... |
+---------------+ +-----------+
| |
| [1] ---------------> +-----------+
| | | Example |
+---------------+ +-----------+
| | | Id: 2 |
| ... | | ... |
| | +-----------+
+---------------+
In other words, your list just contains references to your examples, not copies. Thus, your variable example refers to one of the entities on the right-hand side and modifies it in-place.
If you need a copy, you need to create one yourself.
The game is that you have N piles of stones, on each player's turn he must remove at least 1 stone from a pile, and the player who removes the last stone loses.
I wrote out the winner in a dozen or so cases starting with the base case
/*
stones | winner | N | ones
========================================
{1} | Second | 1 | 1
{i}, i>1 | First | 1 | 0
{1,1} | First | 2 | 2
{1,i}, i>1 | First | 2 | 1
{i,j}, i,j>1 | Second | 2 | 0
{1,1,1} | Second | 3 | 3
{1,1,i}, i>1 | First | 3 | 2
{1,i,j}, i,j>1 | First | 3 | 1
{i,j,k}, i,j,k>1 | First | 3 | 0
{1,1,1,1} | First | 4 | 4
{1,1,1,i} | First | 4 | 3
{1,1,i,j}, i,j>1 | Second | 4 | 2
{1,i,j,k}, i,j,k>1 | First | 4 | 1
{i,j,k,m}, ... | Second | 4 | 0
*/
and from that I think I deduced a formula
static string GetWinner(int[] piles)
{
int n = piles.Length, m = piles.Count(stones => stones == 1);
if(m == n) // one stone per pile
return n % 2 == 0 ? "First" : "Second";
// if here, m < n
return n % 2 == 0 ? (m % 2 == 0 ? "Second" : "First") : "First";
}
but this is failing the test case {2,1,3} which should result in "Second".
I try to use the following fact.
Any number of stones in a pile that is greater than 2 would give the same results if it were 2. The reason is because if it's greater than 2 and the player doesn't shrink the pile to 1 on that turn then the player has basically give his opponent the turn.
However, there might be something I'm wrong about ..
I think your following statement is off:
Any number of stones in a pile that is greater than 2 would give the same results if it were 2
If the state is {1,2,2} The first player can win by removing the 1 stone. If the state is {1,2,3} the first player cannot win. So there is a difference between if the number of stones is 2 or 3.
because if it's greater than 2 and the player doesn't shrink the pile to 1 on that turn then the player has basically give his opponent the turn.
This is correct, except that it is sometimes 'desirable' to give the turn to the other player, i.e. passing the turn.
The optimal strategy has to do with the XOR of the number of items in each pile in binary representation. See https://en.wikipedia.org/wiki/Nim for the optimal solution and details.
I can not deeply understand the math behind the answer, but after some research and optimisation, this is the solution I came up with for python3:
from functools import reduce
def misereNim(s):
if(max(s)==1):
return "First" if (len(s) % 2 ==0) else "Second"
else:
xor = reduce((lambda x, y: x ^ y), s)
return "Second" if xor == 0 else "First"
if __name__ == '__main__':
s = [9, 8, 4, 4, 4, 7]
result = misereNim(s)
print(result)
This is almost an impossible question to ask, but any advice on the algorithm would be greatly appreciated (I will explain the best I can);
I have an array of size ~4000 bytes which contains data in byte format.
For this demonstration, I am going to simplify things a bit; say it's size 7 (to represent 'blocks' of data, not single values!);
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
I am adding a value at position 0, with the reset of the array being '0'
key: N = newest, O = oldest, X = Filled
| N | | | | | | |
I now need to add another value. this will be entered at the next available position.
| O | N | | | | | |
So now position [0] is now the 'oldest' part of the array, and position [1] is the newest.
This has been (currently) worked out by looking all the way right, seeing no values, and then starting from position [0] until it sees a value.
Let's add another:
| O | X | N | | | | |
Note, the oldest value hasn't changed position, as it is still the oldest part of the array.
I am now going to 'clear' the oldest part of the array (in this example it is currently pos [0]). this makes 'O' move over to the next position.
| | O | N | | | | |
Lets add another value. Since it will go to the first 'empty' space, it will go to position [0]; this means the first position is now at position [0].
| N | O | X | | | | |
I'm going to clear another one now; so again, by looking from the right of the newest value, I see a value is at position 1. So i'm going to clear it.
| | | O/N | | | | |
this means position [2] is now both the newest and oldest value available.
Adding another makes;
| N | | O | | | | |
Adding another;
| X | N | O | | | | |
and adding another;
| X | X | O | N | | | |
I am looking to delete the oldest value now. So by looking right from position of the 'newest' variable, I see pos[0] has a value, so that must be it. UH-OH that's not the oldest value!
As you can (hopefully) tell, I am unable to get the oldest ticket by looking to the right for my next value - this problem only occurs every so often, and has been hard to find a solution.
I only know the index of the most recent value added, and this is very hard to find a solution. (lots of scribbliing and diagrams have been attempted, lots of scrumpled up paper).
So if anyone had any ideas as to how I could ALWAYS find the oldest value's index, I would be greatly appreciative! (I also know this is quite a complex question, so if anyone wants/needs clarification, I'll be happy to edit/explain further!) I have tagged c#, but realistically I only need a BASIC algorithm for any progress to be honest!!!
====================================================================================
EDIT
Answers have suggested to allocate to the right of the 'newest' position;
like:
| | | O | N | | | |
| | | O | X | N | | |
| | | O | X | X | N | |
| | | O | X | X | X | N |
| N | | O | X | X | X | X |
| X | N | O | X | X | X | X |
Which I think COULD work, but anyone know if this would fail (say, I removed a value at a certain time/etc?)
I guess you are forced to use an array; if not then you should consider switching to an adequate data structure such as a Queue.
If you are indeed forced to use an array, and can only keep a pointer to the latest block, then i would recommend always adding new blocks the to the right of the latest block, with a index wrapping back to zero at array size.
This lets you determine what the oldest block is by looking to the blocks right of the latest block, until you find a non empty block: this is your oldest block. Null it to remove it from the array and carry on :)
Let's illustrate:
| N | | | | | | | // newBlockIndex at 0, adding, newBlockIndex becomes 1
| X | N | | | | | | // newBlockIndex at 1, adding, newBlockIndex becomes 2
| X | X | N | | | | | // newBlockIndex at 2, adding, newBlockIndex becomes 3
| | X | N | | | | | // newBlockIndex at 3, removing, no item before index 0, we delete it
| | X | X | N | | | | // newBlockIndex at 3, adding, newBlockIndex becomes 4
...
EDIT TO ADD
Regarding your edit, I think the mechanism is quite robust. Even if you were to remove an item (any item, even the latest one) by error, the next operation can succeed because latest and newest are defined in regards to their position to the current index. Newest item is the first on the left of the index, oldest the first on the right.
Even if you don't check for your array size and fill it completely (which I don't recommend, though), the algorithm will overwrite the oldest item with the newest: it may not be good but it is coherent with the notion of a queue. Of course if the array fills up you can always decide to allocate a new one larger and copy the current one to the larger array
What you are looking for is a queue data structure.
Queues can be conveniently implemented with a circular buffer where you have a head index and a tail index.
Head and Tail are both initially set to zero.
Add a new element by writing it to where Tail points, then increment Tail. Wrap as needed if incrementing makes it go off the end of the array.
Delete an old element by incrementing Head. Again, wrap as needed if incrementing makes it go off the end of the array.
Head always points at the oldest element.
Tail always points to the right of the newest element.
Use a System.Collections.Generic.Queue<T>, where T is a byte block.
Queue<byte[]> queue = new Queue<byte[]>();
byte[] block;
queue.Enqueue(new byte[] { 10, 11, 12, 13 });
queue.Enqueue(new byte[] { 20, 21, 22, 23 });
queue.Enqueue(new byte[] { 30, 31, 32, 33 });
block = queue.Dequeue();
queue.Enqueue(new byte[] { 40, 41, 42, 43 });
block = queue.Dequeue();
block = queue.Dequeue();
queue.Enqueue(new byte[] { 50, 51, 52, 53 });
queue.Enqueue(new byte[] { 60, 61, 62, 63 });
queue.Enqueue(new byte[] { 70, 71, 72, 73 });
block = queue.Dequeue();
// ...
Dequeue always removes the oldest element!
Since you have clarified in comments that it must be an array, here is a solution that encapsulates an array-queue in a class. It treats consecutive elements as data block of a defined size. It also allows you to access array elements by index and the array itself. This not typical for queues, but since you need the array...
public class ArrayBlocksQueue<T>
{
private T[] _array;
private int _in, _out, _count, _length, _blockSize;
public ArrayBlocksQueue(int maxBlocks, int blockSize)
{
_length = maxBlocks * blockSize;
_blockSize = blockSize;
_array = new T[_length];
}
public void Enqueue(params T[] block)
{
if (block == null) {
throw new ArgumentNullException();
}
if (block.Length != _blockSize) {
throw new ArgumentException("Data does not have required block size.");
}
if (_count + _blockSize > _length) {
throw new ApplicationException("Queue is full");
}
block.CopyTo(_array, _in);
_in = (_in + _blockSize) % _length;
_count += _blockSize;
}
public T[] Dequeue()
{
if (_count == 0) {
throw new ApplicationException("Queue is empty");
}
T[] temp = new T[_blockSize];
System.Array.Copy(_array, _out, temp, 0, _blockSize);
_out = (_out + _blockSize) % _length;
_count -= _blockSize;
return temp;
}
public int Count { get { return _count; } }
public int BlockCount { get { return _count / _blockSize; } }
public T[] Array { get { return _array; } }
public T this[int index]
{
get
{
if (!IsIndexValid(index)) {
throw new IndexOutOfRangeException();
}
return _array[index];
}
set
{
if (!IsIndexValid(index)) {
throw new IndexOutOfRangeException();
}
_array[index] = value;
}
}
public bool IsIndexValid(int index)
{
if (index < 0 || index >= _length) {
return false;
}
if (_count == _length) {
return true;
}
return _out > _in
? index < _in || index >= _out
: index >= _out && index < _in;
}
}
I have a list of object (with id) and a list int, what is the best way to query that list object provided the list int.
class CommonPartRecord {
public int Id {get;set;}
public object Others {get;set;}
}
var listObj = new List<CommonPartRecord>();
// Load listObj
var listId = new List<int>();
// Load listId
Now select the listObj, for those Id is contained in listId, I currently do this way:
var filterItems = listObj.Where(x => listId.Contains(x.Id));
What would be the faster way to perform this?
Thanks,
Huy
var tmpList = new HashSet<int>(listId);
var filterItems = listObj.Where(x => tmpList.Contains(x.Id));
This could give you a performance boost or a performance drop, it depends heavily on the size of both listObj and listId.
You will need to profile it to see if you get any improvement from it.
Explaining the boost or drop:
I am going to use some really exagrated numbers to make the math easier, lets say the following
listObj.Where(x => listId.Contains(x.Id)); takes 5 seconds per row.
listObj.Where(x => tmpList.Contains(x.Id)) takes 2 seconds per row.
var tmpList = new HashSet<int>(listId); takes 10 seconds to build.
Lets plot out the times of how long it would take to process the data varying by the number of rows in listObj
+----------------+------------------------------+----------------------------------+
| Number of rows | Seconds to process with list | Seconds to process with hash set |
+----------------+------------------------------+----------------------------------+
| 1 | 5 | 12 |
| 2 | 10 | 14 |
| 3 | 15 | 16 |
| 4 | 20 | 18 |
| 5 | 25 | 20 |
| 6 | 30 | 22 |
| 7 | 35 | 24 |
| 8 | 40 | 26 |
+----------------+------------------------------+----------------------------------+
So you can see if listObj has 1 to 3 rows your old way is faster, however once you have 4 rows or more the new way is faster.
(Note I totally made these numbers up, I can guarantee that the per row for HashSet is faster than per row for List, but I can not tell you how much faster. You will need to test to see if the point you get better performance is at 4 rows or 4,000 rows. The only way to know is try both ways and test.)
I've got a WPF DataGrid, and I've got it so that you can sort it by clicking on the column headers. It works, but it's unstable. How do I make it do stable sorting?
By this I mean, if I have this table:
Class | Student | Grade
-----------------------------
Art | James | A
Art | Amy | B
Art | Charlie | A
Science | James | D
Science | Amy | A
Science | Charlie | C
History | James | B
History | Amy | A
History | Charlie | C
If I sort by student, it works like you'd expect:
Class | Student | Grade
-----------------------------
Art | Amy | B
Science | Amy | A
History | Amy | A
Art | Charlie | A
Science | Charlie | C
History | Charlie | C
Art | James | A
Science | James | D
History | James | B
But if I now sort by class:
Class | Student | Grade
-----------------------------
Art | James | A
Art | Amy | B
Art | Charlie | A
History | James | B
History | Amy | A
History | Charlie | C
Science | James | D
Science | Amy | A
Science | Charlie | C
It's destroyed the sort order of the students (unstable sorting). What I want is stable sorting, where it preserves the order:
Class | Student | Grade
-----------------------------
Art | Amy | B
Art | Charlie | A
Art | James | A
History | Amy | A
History | Charlie | C
History | James | B
Science | Amy | A
Science | Charlie | C
Science | James | D
Seems like it should work like this by default, or at least be a toggle. Does anyone have any suggestions? #Eirik's idea of shift-clicking works, and that shows that the behaviour is present. However, what I'd really like is for to work like that without any modifiers. It shouldn't be a cause of "sort by this, then this, then this", it should be case of swapping the algorithm for a different one.
See this: http://en.wikipedia.org/wiki/Sorting_algorithm#Stability
You should be able to sort by multiple columns by holding down shift when clicking on the columns.
Try clicking on the class column then hold down shift and click on the student column.
Here's a solution for adding sorting in code behind:
private void myDataGridPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is DataGridColumnHeader))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
if (dep is DataGridColumnHeader)
{
DataGridColumnHeader columnHeader = dep as DataGridColumnHeader;
ICollectionView view = CollectionViewSource.GetDefaultView((sender as DataGrid).ItemsSource);
if (columnHeader.Content.Equals("Class") || columnHeader.Content.Equals("Student"))
{
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Class", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("Student", ListSortDirection.Ascending));
}
}
}
For this to work you have to disable the standard sorting. One way to do this is to stop the Sorting event, like so:
private void myDataGridSorting(object sender, DataGridSortingEventArgs e)
{
e.Handled = true;
}
Edit:
After reading hbarck's comment I read your question again, and it seems I missed some parts. If you change this code:
if (columnHeader.Content.Equals("Class") || columnHeader.Content.Equals("Student"))
{
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Class", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("Student", ListSortDirection.Ascending));
}
to this:
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
view.SortDescriptions.Clear();
}
view.SortDescriptions.Insert(0, new SortDescription(columnHeader.Content.ToString(), ListSortDirection.Ascending));
you will have stable sorting. Click on Student to sort by Student, then click on Class to sort by Class, Student.
If you hold down ctrl when clicking you clear previous sorting before sorting by the column that was clicked.
I've managed to get a stable sorting using a custom Comparer, but it kinda feels like a big hack...
I use ListCollectionView's CustomSort property to set my custom Comparer, which needs me to pass the collection to it when instantiating it.
private void Sorting(IEnumerable collection)
{
var view = CollectionViewSource.GetDefaultView(collection) as ListCollectionView;
if (view != null)
{
view.CustomSort = new StableComparer(collection);
}
}
In my custom Comparer, I use the collection during the Compare method just to fallback to the items indexes when the regular comparison returns a zero (they are the same or have the same value).
public class StableComparer : IComparer
{
public IEnumerable Collection { get; set; }
public StableComparer(IEnumerable collection)
{
Collection = collection;
}
public int Compare(object x, object y)
{
IComparable x_Comparable = x as IComparable;
IComparable y_Comparable = y as IComparable;
if (x_Comparable != null && y_Comparable != null)
{
var comparison = x_Comparable.CompareTo(y_Comparable);
// A zero value means x and y are equivalent for sorting, and they could
// be rearranged by an unstable sorting algorithm
if (comparison == 0 && Collection != null)
{
// IndexOf is an extension method for IEnumerable (not included)
var x_Index = Collection.IndexOf(x);
var y_Index = Collection.IndexOf(y);
// By comparing their indexes in the original collection, we get to
// preserve their relative order
if (x_Index != -1 && y_Index != -1)
comparison = x_Index.CompareTo(y_Index);
}
return comparison;
}
return 0;
}
}
I'm still testing this, so I can't guarantee this would work all the time... One problem would be keeping the Collection property inside the Comparer updated, for instance. Or supporting two sort directions (working on it now, shouldn't be difficult). Or checking how this works, performance-wise.
But I think the idea is clear; though hacky, like I said.