Increment Guid in C# - c#

I have an application that has a guid variable which needs to be unique (of course). I know that statistically any guid should just be assumed to be unique, but due to dev/test environment reasons, the same value may be seen multiple times. So when that happens, I want to "increment" the value of the Guid, rather than just creating a whole new one. There does not seem to be a simple way to do this. I found a hack, which I will post as a possible answer, but want a cleaner solution.

You can get the byte components of the guid, so you can just work on that:
static class GuidExtensions
{
private static readonly int[] _guidByteOrder =
new[] { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
public static Guid Increment(this Guid guid)
{
var bytes = guid.ToByteArray();
bool carry = true;
for (int i = 0; i < _guidByteOrder.Length && carry; i++)
{
int index = _guidByteOrder[i];
byte oldValue = bytes[index]++;
carry = oldValue > bytes[index];
}
return new Guid(bytes);
}
}
EDIT: now with correct byte order

Thanks to Thomas Levesque's byte order, here's a nifty LINQ implementation:
static int[] byteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
static Guid NextGuid(Guid guid)
{
var bytes = guid.ToByteArray();
var canIncrement = byteOrder.Any(i => ++bytes[i] != 0);
return new Guid(canIncrement ? bytes : new byte[16]);
}
Note it wraps around to Guid.Empty if you manage to increment it that far.
It would be more efficient if you were to keep incrementing a single copy of bytes rather than calling ToByteArray on each GUID in turn.

Possible solution -- I think this works (not really tested), but want a better solution.
public static Guid Increment(this Guid value)
{
var bytes = value.ToByteArray();
// Note that the order of bytes in the returned byte array is different from the string representation of a Guid value.
// Guid: 00112233-4455-6677-8899-aabbccddeeff
// byte array: 33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF
// So the byte order of the following indexes indicates the true low-to-high sequence
if (++bytes[15] == 0) if (++bytes[14] == 0) if (++bytes[13] == 0) if (++bytes[12] == 0) if (++bytes[11] == 0) if (++bytes[10] == 0) // normal order
if (++bytes[9] == 0) if (++bytes[8] == 0) // normal order
if (++bytes[6] == 0) if (++bytes[7] == 0) // reverse order
if (++bytes[5] == 0) if (++bytes[4] == 0) // reverse order
if (++bytes[3] == 0) if (++bytes[2] == 0) if (++bytes[1] == 0) { ++bytes[0]; } // reverse order
return new Guid(bytes);
}
Edit: here is the code I ended up using; props to the answers above for the general technique, although without the "unchecked" clause they both would throw exceptions in some cases. But I also tried to make the below as readable as possible.
private static int[] _guidByteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
public static Guid NextGuid(this Guid guid)
{
var bytes = guid.ToByteArray();
for (int i = 0; i < 16; i++)
{
var iByte = _guidByteOrder[i];
unchecked { bytes[iByte] += 1; }
if (bytes[iByte] != 0)
return new Guid(bytes);
}
return Guid.Empty;
}

Verified Solution for Ordered Strings:
private static Guid Increment(Guid guid)
{
byte[] bytes = guid.ToByteArray();
byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
for (int i = 0; i < 16; i++)
{
if (bytes[order[i]] == byte.MaxValue)
{
bytes[order[i]] = 0;
}
else
{
bytes[order[i]]++;
return new Guid(bytes);
}
}
throw new OverflowException("Congratulations you are one in a billion billion billion billion etc...");
}
Verification:
private static Guid IncrementProof(Guid guid, int start, int end)
{
byte[] bytes = guid.ToByteArray();
byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
for (int i = start; i < end; i++)
{
if (bytes[order[i]] == byte.MaxValue)
{
bytes[order[i]] = 0;
}
else
{
bytes[order[i]]++;
return new Guid(bytes);
}
}
throw new OverflowException("Congratulations you are one in a billion billion billion billion etc...");
}
static void Main(string[] args)
{
Guid temp = new Guid();
for (int j = 0; j < 16; j++)
{
for (int i = 0; i < 255; i++)
{
Console.WriteLine(temp.ToString());
temp = IncrementProof(temp, j, j + 1);
}
}
}

Related

Get the shortest path between two linked object

I have a "Contact" object which contains a list called "Linked" containing the "Contact" linked to it.
public class Contact
{
public int Id { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public List<Contact> Linked { get; set; }
}
For example, Contact "A" has 3 linked contacts: B, C and D.
As the links are made in both directions each time, B, C and D all have A in their "Linked" contacts.
B can then have E as a contact, and so on. There is no limit.
I have to make an algo which takes a starting contact and an ending contact as a parameter and which finds the shortest path that links them.
The result must be in the form: A > B > F > H > X, if I have to find the path that goes from A to X. We must therefore find all the steps of the path in the result.
I've tried a lot of stuff (recursion, ...) but it's still getting stuck somewhere.
Do you have an idea?
Dijkstra's algorithm is probably what you are looking for.
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
Dijkstra's algorithm (/ˈdaɪkstrəz/ DYKE-strəz) is an algorithm for finding the shortest paths between nodes in a graph, which may represent, for example, road networks. It was conceived by computer scientist Edsger W. Dijkstra in 1956 and published three years later.[4][5][6]
It should be relatively straight forward to find examples in your given language. Here is one in C#, stolen from programmingalgorithms.com
private static int MinimumDistance(int[] distance, bool[] shortestPathTreeSet, int verticesCount)
{
int min = int.MaxValue;
int minIndex = 0;
for (int v = 0; v < verticesCount; ++v)
{
if (shortestPathTreeSet[v] == false && distance[v] <= min)
{
min = distance[v];
minIndex = v;
}
}
return minIndex;
}
private static void Print(int[] distance, int verticesCount)
{
Console.WriteLine("Vertex Distance from source");
for (int i = 0; i < verticesCount; ++i)
Console.WriteLine("{0}\t {1}", i, distance[i]);
}
public static void Dijkstra(int[,] graph, int source, int verticesCount)
{
int[] distance = new int[verticesCount];
bool[] shortestPathTreeSet = new bool[verticesCount];
for (int i = 0; i < verticesCount; ++i)
{
distance[i] = int.MaxValue;
shortestPathTreeSet[i] = false;
}
distance[source] = 0;
for (int count = 0; count < verticesCount - 1; ++count)
{
int u = MinimumDistance(distance, shortestPathTreeSet, verticesCount);
shortestPathTreeSet[u] = true;
for (int v = 0; v < verticesCount; ++v)
if (!shortestPathTreeSet[v] && Convert.ToBoolean(graph[u, v]) && distance[u] != int.MaxValue && distance[u] + graph[u, v] < distance[v])
distance[v] = distance[u] + graph[u, v];
}
Print(distance, verticesCount);
}
It would then be used like so:
int[,] graph = {
{ 0, 4, 0, 0, 0, 0, 0, 8, 0 },
{ 4, 0, 8, 0, 0, 0, 0, 11, 0 },
{ 0, 8, 0, 7, 0, 4, 0, 0, 2 },
{ 0, 0, 7, 0, 9, 14, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },
{ 0, 0, 4, 0, 10, 0, 2, 0, 0 },
{ 0, 0, 0, 14, 0, 2, 0, 1, 6 },
{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },
{ 0, 0, 2, 0, 0, 0, 6, 7, 0 }
};
Dijkstra(graph, 0, 9);
The example above consist of 9 nodes, and the distance to each of the other nodes. If it has 0, there is no connection. In your case, there is no weight - so either there is a connection (1), or there isn't (0).
You have to change the algorithm to take in a list of contacts, instead of a two dimensional array. Try to think of the two dimensional array as a list of lists - very similar to a list of contacts, where each contact has another list of contacts.
Lets for example create a simple contacts list and their contacts:
Peter can contact Mary
Mary can contact Peter and John
John can contact Mary
This would be represented something like this in a two dimensional array:
int[,] contacts = new int[]
{
{ 0, 1, 0 }, //Peter: Peter no, Mary yes, John no
{ 1, 0, 1 }, //Mary: Peter yes, Mary no, John yes
{ 0, 1, 0 } //John: Peter no, Mary yes, John no
}
You would also have to modify the algorithm to keep track of the current path. That should be a relatively straight forward change.
Hope that it helps!

Interview test - adding using A Recursive Algorithm c#

Below is an interview question about using recursion to add two arrays.
I can't figure it out though because it does not seem to allow any kind of index to keep track of where you are, I have been down a few roads - trying to test for null / default values in the array but because it is a byte[] type nothing worked.
Any help would be great thanks - this is not a homework question.
public AddResult UsingARecursiveAlgorithm_ValuesAreAdded(byte[] a, byte[] b)
{
var result = AddRecursive(a, b);
// Assert
return new AddResult(a, b, result);
}
e.g.
Input : { 1, 1, 1 }, { 1, 1, 1 }
Result: { 2, 2, 2 }
Input : { 1, 1, 255 }, { 0, 0, 1 }
Result: { 1, 2, 0 }
Conditions:
a & b are never null, and are always of the same length.
The algorithm should be non destructive to the inputs.
Edit: the second result is incorrect. It should be { 1,1,0 } -that's the way it was presented though.
private int carry = 0;
public byte[] AddRecursive(byte[] a, byte[] b)
{
//Start from bottom of the byte[] array
a = a.Reverse().ToArray();
b = b.Reverse().ToArray();
if (a.Length == 0) return new byte[] { };
int tempresult = a[0] + b[0] + carry;
byte[] z = new byte[]
{ (byte)(tempresult) };
carry = tempresult / (byte.MaxValue + 1);
return z.Concat(AddRecursive(a.Skip(1).ToArray(), b.Skip(1).ToArray())).ToArray();
}
//Test//
[Test]
public void Add_UsingARecursiveAlgorithm_ValuesAreAdded()
{
//First Test
byte[] expectedResult = addthisaddthat.AddRecursive(new byte[] { 1, 1, 1 }, new byte[] { 1, 1, 1 }).Reverse().ToArray();
Assert.That(expectedResult, Is.EqualTo(new byte[] { 2, 2, 2 }));
//Sec Test
expectedResult = addthisaddthat.AddRecursive(new byte[] { 1, 1, 255 }, new byte[] { 0, 0, 1 }).Reverse().ToArray();
Assert.That(expectedResult, Is.EqualTo(new byte[] { 1, 2, 0 }));
//Third Test
expectedResult = addthisaddthat.AddRecursive(new byte[] { 255, 255, 255 }, new byte[] { 255, 255, 255 }).Reverse().ToArray();
Assert.That(expectedResult, Is.EqualTo(new byte[] { 255, 255, 254 }));
}
Ok here is some rather "ugly" code that does what you want. I tried to write it for clarity rather than brevity:
static byte[] AddArray(byte[] ary1, byte[] ary2) {
System.Diagnostics.Debug.Assert(ary1.Length == ary2.Length);
if ((ary1 == null) || (ary2 == null)) {
throw new ArgumentException("Empty or null array");
}
// sum the last element
var ix = ary1.Length - 1;
var sum = (ary1[ix] + ary2[ix]);
if (sum > byte.MaxValue) {
if (ix == 0) {
throw new ArgumentException("Overflow");
}
// Add carry by recursing on ary1
var carry = (byte) (sum - byte.MaxValue);
var carryAry = new byte[ary1.Length];
carryAry[ix - 1] = carry;
ary1 = AddArray(ary1, carryAry);
}
if ((ary1.Length == 1) || (ary2.Length == 1)) {
return new byte[] { (byte) sum }; // end recursion
}
// create the remainder, elements from 0 it (len-1)
var ary1Remainder = new byte[ary1.Length - 1];
var ary2Remainder = new byte[ary2.Length - 1];
Array.Copy(ary1, 0, ary1Remainder, 0, ary1.Length - 1);
Array.Copy(ary2, 0, ary2Remainder, 0, ary2.Length - 1);
// recurse
var remainder = AddArray(ary1Remainder, ary2Remainder);
// build return array (using linq Concat)
var rv = (remainder.Concat(new byte[] { (byte) sum }));
return rv.ToArray(); // return as an array
}
This would be cleaner without all the casting and ToArray required because the values are byte[] and not IEnumerable<int>, but:
private byte[] AddRecursive(byte[] a, byte[] b) {
if (a.Length == 0) return new byte[]{};
return
new byte[] { (byte)(a[0] + b[0]) }.Concat(
AddRecursive(a.Skip(1).ToArray(), b.Skip(1).ToArray())
).ToArray();
}
Maybe your interviewer had something like this in mind:
using System;
using System.Linq;
public class Program
{
public static byte[] Add(byte[] a, byte[] b, int index = -1)
{
if (index < 0)
{
return Add((byte[])a.Clone(), b, 0);
}
if (index < a.Length)
{
Add(a, b, index + 1);
a[index] += b[index];
}
return a;
}
public static void Main(string[] args)
{
var r1 = Add(new byte[] { 1, 1, 1 }, new byte[] { 1, 1, 1 });
var r2 = Add(new byte[] { 1, 1, 255 }, new byte[] { 0, 0, 1 });
var r3 = Add(new byte[] { 0, 100, 200 }, new byte[] { 3, 2, 1 });
// Outputs: 2, 2, 2
Console.WriteLine(string.Join(", ", r1.Select(n => "" + n).ToArray()));
// Outputs: 1, 1, 0
Console.WriteLine(string.Join(", ", r2.Select(n => "" + n).ToArray()));
// Outputs: 3, 102, 201
Console.WriteLine(string.Join(", ", r3.Select(n => "" + n).ToArray()));
}
}
https://dotnetfiddle.net/UqSQb3
Note this (only partial) solution doesn't handle the carry on byte overflows, though.
'Hope this helps,

Find all k-size subsets with sum s of an n-size bag of duplicate unsorted positive integers

Please note that this is required for a C# .NET 2.0 project (Linq not allowed).
I know very similar questions have been asked here and I have already produce some working code (see below) but still would like an advice as to how to make the algorithm faster given k and s conditions.
This is what I've learnt so far:
Dynamic programming is the most efficient way to finding ONE (not all) subsets. Please correct me if I am wrong. And is there a way of repeatedly calling the DP code to produce newer subsets till the bag (set with duplicates) is exhausted?
If not, then is there a way that may speed up the backtracking recursive algorithm I have below which does produce what I need but runs in O(2^n), I think, by taking s and k into account?
Here is my fixed bag of numbers that will NEVER change with n=114 and number range from 3 to 286:
int[] numbers = new int[]
{
7, 286, 200, 176, 120, 165, 206, 75, 129, 109,
123, 111, 43, 52, 99, 128, 111, 110, 98, 135,
112, 78, 118, 64, 77, 227, 93, 88, 69, 60,
34, 30, 73, 54, 45, 83, 182, 88, 75, 85,
54, 53, 89, 59, 37, 35, 38, 29, 18, 45,
60, 49, 62, 55, 78, 96, 29, 22, 24, 13,
14, 11, 11, 18, 12, 12, 30, 52, 52, 44,
28, 28, 20, 56, 40, 31, 50, 40, 46, 42,
29, 19, 36, 25, 22, 17, 19, 26, 30, 20,
15, 21, 11, 8, 8, 19, 5, 8, 8, 11,
11, 8, 3, 9, 5, 4, 7, 3, 6, 3,
5, 4, 5, 6
};
Requirements
Space limit to 2-3GB max but time should be O(n^something) not
(something^n).
The bag must not be sorted and duplicate must not be removed.
The result should be the indices of the numbers in the matching
subset, not the numbers themselves (as we have duplicates).
Dynamic Programming Attempt
Here is the C# dynamic programming version adapted from an answer to a similar question here on stackoverflow.com:
using System;
using System.Collections.Generic;
namespace Utilities
{
public static class Combinations
{
private static Dictionary<int, bool> m_memo = new Dictionary<int, bool>();
private static Dictionary<int, KeyValuePair<int, int>> m_previous = new Dictionary<int, KeyValuePair<int, int>>();
static Combinations()
{
m_memo.Clear();
m_previous.Clear();
m_memo[0] = true;
m_previous[0] = new KeyValuePair<int, int>(-1, 0);
}
public static bool FindSubset(IList<int> set, int sum)
{
//m_memo.Clear();
//m_previous.Clear();
//m_memo[0] = true;
//m_previous[0] = new KeyValuePair<int, int>(-1, 0);
for (int i = 0; i < set.Count; ++i)
{
int num = set[i];
for (int s = sum; s >= num; --s)
{
if (m_memo.ContainsKey(s - num) && m_memo[s - num] == true)
{
m_memo[s] = true;
if (!m_previous.ContainsKey(s))
{
m_previous[s] = new KeyValuePair<int, int>(i, num);
}
}
}
}
return m_memo.ContainsKey(sum) && m_memo[sum];
}
public static IEnumerable<int> GetLastIndex(int sum)
{
while (m_previous[sum].Key != -1)
{
yield return m_previous[sum].Key;
sum -= m_previous[sum].Value;
}
}
public static void SubsetSumMain(string[] args)
{
int[] numbers = new int[]
{
7, 286, 200, 176, 120, 165, 206, 75, 129, 109,
123, 111, 43, 52, 99, 128, 111, 110, 98, 135,
112, 78, 118, 64, 77, 227, 93, 88, 69, 60,
34, 30, 73, 54, 45, 83, 182, 88, 75, 85,
54, 53, 89, 59, 37, 35, 38, 29, 18, 45,
60, 49, 62, 55, 78, 96, 29, 22, 24, 13,
14, 11, 11, 18, 12, 12, 30, 52, 52, 44,
28, 28, 20, 56, 40, 31, 50, 40, 46, 42,
29, 19, 36, 25, 22, 17, 19, 26, 30, 20,
15, 21, 11, 8, 8, 19, 5, 8, 8, 11,
11, 8, 3, 9, 5, 4, 7, 3, 6, 3,
5, 4, 5, 6
};
int sum = 400;
//int size = 4; // don't know to use in dynamic programming
// call dynamic programming
if (Numbers.FindSubset(numbers, sum))
{
foreach (int index in Numbers.GetLastIndex(sum))
{
Console.Write((index + 1) + "." + numbers[index] + "\t");
}
Console.WriteLine();
}
Console.WriteLine();
Console.ReadKey();
}
}
}
Recursive Programming Attempt
and Here is the C# recursive programming version adapted from an answer to a similar question here on stackoverflow.com:
using System;
using System.Collections.Generic;
namespace Utilities
{
public static class Combinations
{
private static int s_count = 0;
public static int CountSubsets(int[] numbers, int index, int current, int sum, int size, List<int> result)
{
if ((numbers.Length <= index) || (current > sum)) return 0;
if (result == null) result = new List<int>();
List<int> temp = new List<int>(result);
if (current + numbers[index] == sum)
{
temp.Add(index);
if ((size == 0) || (temp.Count == size))
{
s_count++;
}
}
else if (current + numbers[index] < sum)
{
temp.Add(index);
CountSubsets(numbers, index + 1, current + numbers[index], sum, size, temp);
}
CountSubsets(numbers, index + 1, current, sum, size, result);
return s_count;
}
private static List<List<int>> m_subsets = new List<List<int>>();
public static List<List<int>> FindSubsets(int[] numbers, int index, int current, int sum, int size, List<int> result)
{
if ((numbers.Length <= index) || (current > sum)) return m_subsets;
if (result == null) result = new List<int>();
List<int> temp = new List<int>(result);
if (current + numbers[index] == sum)
{
temp.Add(index);
if ((size == 0) || (temp.Count == size))
{
m_subsets.Add(temp);
}
}
else if (current + numbers[index] < sum)
{
temp.Add(index);
FindSubsets(numbers, index + 1, current + numbers[index], sum, size, temp);
}
FindSubsets(numbers, index + 1, current, sum, size, result);
return m_subsets;
}
public static void SubsetSumMain(string[] args)
{
int[] numbers = new int[]
{
7, 286, 200, 176, 120, 165, 206, 75, 129, 109,
123, 111, 43, 52, 99, 128, 111, 110, 98, 135,
112, 78, 118, 64, 77, 227, 93, 88, 69, 60,
34, 30, 73, 54, 45, 83, 182, 88, 75, 85,
54, 53, 89, 59, 37, 35, 38, 29, 18, 45,
60, 49, 62, 55, 78, 96, 29, 22, 24, 13,
14, 11, 11, 18, 12, 12, 30, 52, 52, 44,
28, 28, 20, 56, 40, 31, 50, 40, 46, 42,
29, 19, 36, 25, 22, 17, 19, 26, 30, 20,
15, 21, 11, 8, 8, 19, 5, 8, 8, 11,
11, 8, 3, 9, 5, 4, 7, 3, 6, 3,
5, 4, 5, 6
};
int sum = 17;
int size = 2;
// call backtracking recursive programming
Console.WriteLine("CountSubsets");
int count = Numbers.CountSubsets(numbers, 0, 0, sum, size, null);
Console.WriteLine("Count = " + count);
Console.WriteLine();
// call backtracking recursive programming
Console.WriteLine("FindSubsets");
List<List<int>> subsets = Numbers.FindSubsets(numbers, 0, 0, sum, size, null);
for (int i = 0; i < subsets.Count; i++)
{
if (subsets[i] != null)
{
Console.Write((i + 1).ToString() + ":\t");
for (int j = 0; j < subsets[i].Count; j++)
{
int index = subsets[i][j];
Console.Write((index + 1) + "." + numbers[index] + " ");
}
Console.WriteLine();
}
}
Console.WriteLine("Count = " + subsets.Count);
Console.ReadKey();
}
}
}
Please let me know how to restrict the dynamic programming version to subsets of size k and if I can call it repeatedly so it returns different subsets on every call until there are no more matching subsets.
Also I am not sure where to initialize the memo of the DP algorithm. I did it in the static constructor which auto-runs when accessing any method. Is this the correct initialization place or does it need to be moved to inside the FindSunset() method [commented out]?
As for the recursive version, is it backtracking? and how can we speed it up. It works correctly and takes k and s into account but totally inefficient.
Let's make this thread the mother of all C# SubsetSum related questions!
My previous answer works on the principle of cutting off the number of combinations to check. But this can be improved significantly once you sort the array. The principle is similar, but since the solution is entirely different, I've decided to put it in a separate answer.
I was careful to use only .Net Framework 2.0 features. Might add a visual explanation later, but the comments should be enough.
class Puzzle
{
private readonly int[] _tailSums;
public readonly SubsetElement[] Elements;
public readonly int N;
public Puzzle(int[] numbers)
{
// Set N and make Elements array
// (to remember the original index of each element)
this.N = numbers.Length;
this.Elements = new SubsetElement[this.N];
for (var i = 0; i < this.N; i++)
{
this.Elements[i] = new SubsetElement(numbers[i], i);
}
// Sort Elements descendingly by their Number value
Array.Sort(this.Elements, (a, b) => b.Number.CompareTo(a.Number));
// Save tail-sums to allow immediate access by index
// Allow immedate calculation by index = N, to sum 0
this._tailSums = new int[this.N + 1];
var sum = 0;
for (var i = this.N - 1; i >= 0; i--)
{
this._tailSums[i] = sum += this.Elements[i].Number;
}
}
public void Solve(int s, Action<SubsetElement[]> callback)
{
for (var k = 1; k <= this.N; k++)
this.Solve(k, s, callback);
}
public void Solve(int k, int s, Action<SubsetElement[]> callback)
{
this.ScanSubsets(0, k, s, new List<SubsetElement>(), callback);
}
private void ScanSubsets(int startIndex, int k, int s,
List<SubsetElement> subset, Action<SubsetElement[]> cb)
{
// No more numbers to add, and current subset is guranteed to be valid
if (k == 0)
{
// Callback with current subset
cb(subset.ToArray());
return;
}
// Sum the smallest k elements
var minSubsetStartIndex = this.N - k;
var minSum = this._tailSums[minSubssetStartIndex];
// Smallest possible sum is greater than wanted sum,
// so a valid subset cannot be found
if (minSum > s)
{
return;
}
// Find largest number that satisfies the condition
// that a valid subset can be found
minSum -= this.Elements[minSubsetStartIndex].Number;
// But remember the last index that satisfies the condition
var minSubsetEndIndex = minSubsetStartIndex;
while (minSubsetStartIndex > startIndex &&
minSum + this.Elements[minSubsetStartIndex - 1].Number <= s)
{
minSubsetStartIndex--;
}
// Find the first number in the sorted sequence that is
// the largest number we just found (in case of duplicates)
while (minSubsetStartIndex > startIndex &&
Elements[minSubsetStartIndex] == Elements[minSubsetStartIndex - 1])
{
minSubsetStartIndex--;
}
// [minSubsetStartIndex .. maxSubsetEndIndex] is the
// full range we must check in recursion
for (var subsetStartIndex = minSubsetStartIndex;
subsetStartIndex <= minSubsetEndIndex;
subsetStartIndex++)
{
// Find the largest possible sum, which is the sum of the
// k first elements, starting at current subsetStartIndex
var maxSum = this._tailSums[subsetStartIndex] -
this._tailSums[subsetStartIndex + k];
// The largest possible sum is less than the wanted sum,
// so a valid subset cannot be found
if (maxSum < s)
{
return;
}
// Add current number to the subset
var x = this.Elements[subsetStartIndex];
subset.Add(x);
// Recurse through the sub-problem to the right
this.ScanSubsets(subsetStartIndex + 1, k - 1, s - x.Number, subset, cb);
// Remove current number and continue loop
subset.RemoveAt(subset.Count - 1);
}
}
public sealed class SubsetElement
{
public readonly int Number;
public readonly int Index;
public SubsetElement(int number, int index)
{
this.Number = number;
this.Index = index;
}
public override string ToString()
{
return string.Format("{0}({1})", this.Number, this.Index);
}
}
}
Usage and performance testing:
private static void Main()
{
var sw = Stopwatch.StartNew();
var puzzle = new Puzzle(new[]
{
7, 286, 200, 176, 120, 165, 206, 75, 129, 109,
123, 111, 43, 52, 99, 128, 111, 110, 98, 135,
112, 78, 118, 64, 77, 227, 93, 88, 69, 60,
34, 30, 73, 54, 45, 83, 182, 88, 75, 85,
54, 53, 89, 59, 37, 35, 38, 29, 18, 45,
60, 49, 62, 55, 78, 96, 29, 22, 24, 13,
14, 11, 11, 18, 12, 12, 30, 52, 52, 44,
28, 28, 20, 56, 40, 31, 50, 40, 46, 42,
29, 19, 36, 25, 22, 17, 19, 26, 30, 20,
15, 21, 11, 8, 8, 19, 5, 8, 8, 11,
11, 8, 3, 9, 5, 4, 7, 3, 6, 3,
5, 4, 5, 6
});
puzzle.Solve(2, 17, PuzzleOnSubsetFound);
sw.Stop();
Console.WriteLine("Subsets found: " + _subsetsCount);
Console.WriteLine(sw.Elapsed);
}
private static int _subsetsCount;
private static void PuzzleOnSubsetFound(Puzzle.SubsetElement[] subset)
{
_subsetsCount++;
return; // Skip prints when speed-testing
foreach (var el in subset)
{
Console.Write(el.ToString());
Console.Write(" ");
}
Console.WriteLine();
}
Output:
Each line is a found subset, numbers in () are the original index of the number used in the subset
14(60) 3(107)
14(60) 3(109)
14(60) 3(102)
13(59) 4(105)
13(59) 4(111)
12(64) 5(96)
12(64) 5(104)
12(64) 5(112)
12(64) 5(110)
12(65) 5(96)
12(65) 5(104)
12(65) 5(112)
12(65) 5(110)
11(100) 6(108)
11(100) 6(113)
11(61) 6(108)
11(61) 6(113)
11(92) 6(108)
11(92) 6(113)
11(62) 6(108)
11(62) 6(113)
11(99) 6(108)
11(99) 6(113)
9(103) 8(93)
9(103) 8(94)
9(103) 8(97)
9(103) 8(98)
9(103) 8(101)
Subsets found: 28
00:00:00.0017020 (measured when no printing is performed)
The higher k is, the more cutoffs can be made. This is when you'll see the major performance difference. Your current code (the recursive version) also performs significantly slower when s is goes higher.
With k=5, s=60
Your current code: found 45070 subsets in 2.8602923 seconds
My code: found 45070 subsets in 0.0116727 seconds
That is 99.6% speed improvement
There are multiple solutions, but nobody showed how to use dynamic programming to find the answer.
The key is to use dynamic programming to build up a data structure from which all solutions can later be found.
In addition to the requested function, I collected information about how many solutions there are, and wrote FindSolution(node, position) to return the solution at position position starting with node without calculating the rest. If you want all of them, using that function would be inefficient. But, for example, with this function it is doable to calculate the billionth way to express 10000 as a sum of 20 primes. That would not be feasible with the other approaches given.
using System;
using System.Collections.Generic;
public class SubsetSum
{
public class SolutionNode<T>
{
// The index we found the value at
public int Index {get; set;}
// The value we add for this solution
public T Value {get; set;}
// How many solutions we have found.
public int Count {get; set;}
// The rest of this solution.
public SolutionNode<T> Tail {get; set;}
// The next solution.
public SolutionNode<T> Next {get; set;}
}
// This uses dynamic programming to create a summary of all solutions.
public static SolutionNode<int> FindSolution(int[] numbers, int target, int subsetSize)
{
// By how many are in our list, by what they sum to, what SolutionNode<int> has our answer?
List<Dictionary<int, SolutionNode<int>>> solutionOf = new List<Dictionary<int, SolutionNode<int>>>();
// Initialize empty solutions.
for (int i = 0; i <= subsetSize; i++)
{
solutionOf.Add(new Dictionary<int, SolutionNode<int>>());
}
// We discover from the last number in the list forward.
// So discovering from the last index forward makes them ordered.
for (int i = numbers.Length - 1; -1 < i; i--)
{
int number = numbers[i];
// Descending here so we don't touch solutionOf[j-1] until after we have solutionOf[j] updated.
for (int j = subsetSize; 0 < j; j--)
{
// All previously found sums with j entries
Dictionary<int, SolutionNode<int>> after = solutionOf[j];
// All previously found sums with j-1 entries
Dictionary<int, SolutionNode<int>> before = solutionOf[j-1];
foreach (KeyValuePair<int, SolutionNode<int>> pair in before)
{
SolutionNode<int> newSolution = new SolutionNode<int>();
int newSum = pair.Key + number;
newSolution.Index = i;
newSolution.Value = number;
newSolution.Count = pair.Value.Count;
newSolution.Tail = pair.Value;
if (after.ContainsKey(newSum))
{
newSolution.Next = after[newSum];
newSolution.Count = pair.Value.Count + after[newSum].Count;
}
after[newSum] = newSolution;
}
// And special case empty set.
if (1 == j)
{
SolutionNode<int> newSolution = new SolutionNode<int>();
newSolution.Index = i;
newSolution.Value = number;
newSolution.Count = 1;
if (after.ContainsKey(number))
{
newSolution.Next = after[number];
newSolution.Count = after[number].Count;
}
after[number] = newSolution;
}
}
}
// Return what we found.
try
{
return solutionOf[subsetSize][target];
}
catch
{
throw new Exception("No solutions found");
}
}
// The function we were asked for.
public static IEnumerable<List<int>> ListSolutions (SolutionNode<int> node)
{
List<int> solution = new List<int>();
List<SolutionNode<int>> solutionPath = new List<SolutionNode<int>>();
// Initialize with starting information.
solution.Add(0); // This will be removed when we get node
solutionPath.Add(node); // This will be our start.
while (0 < solutionPath.Count)
{
// Erase the tail of our previous solution
solution.RemoveAt(solution.Count - 1);
// Pick up our next.
SolutionNode<int> current = solutionPath[solutionPath.Count - 1];
solutionPath.RemoveAt(solutionPath.Count - 1);
while (current != null)
{
solution.Add(current.Index);
solutionPath.Add(current.Next);
if (current.Tail == null)
{
yield return solution;
}
current = current.Tail;
}
}
}
// And for fun, a function that dynamic programming makes easy - return any one of them!
public static List<int> FindSolution(SolutionNode<int> node, int position)
{
// Switch to counting from the end.
position = node.Count - position - 1;
List<int> solution = new List<int>();
while (node != null)
{
while (node.Next != null && position < node.Next.Count)
{
node = node.Next;
}
solution.Add(node.Index);
node = node.Tail;
}
return solution;
}
public static void Main(string[] args)
{
SolutionNode<int> solution = FindSolution(
new[]{
7, 286, 200, 176, 120, 165, 206, 75, 129, 109,
123, 111, 43, 52, 99, 128, 111, 110, 98, 135,
112, 78, 118, 64, 77, 227, 93, 88, 69, 60,
34, 30, 73, 54, 45, 83, 182, 88, 75, 85,
54, 53, 89, 59, 37, 35, 38, 29, 18, 45,
60, 49, 62, 55, 78, 96, 29, 22, 24, 13,
14, 11, 11, 18, 12, 12, 30, 52, 52, 44,
28, 28, 20, 56, 40, 31, 50, 40, 46, 42,
29, 19, 36, 25, 22, 17, 19, 26, 30, 20,
15, 21, 11, 8, 8, 19, 5, 8, 8, 11,
11, 8, 3, 9, 5, 4, 7, 3, 6, 3,
5, 4, 5, 6}
, 400, 4);
IEnumerable<List<int>> listing = ListSolutions(solution);
foreach (List<int> sum in listing)
{
Console.WriteLine ("solution {0}", string.Join(", ", sum.ToArray()));
}
}
}
Incidentally this is my first time trying to write C#. It was...painfully verbose.
Simply search for all combinations of size K, and check each if it satisfies the condition.
The fastest algorithm for k combinations, suiting your case, would be:
for (var i1 = 0; i1 <= n; i1++)
{
for (var i2 = i1 + 1; i2 <= n; i2++)
{
for (var i3 = i2 + 1; i3 <= n; i3++)
{
...
for (var ik = iOneBeforeK + 1; ik <= n; ik++)
{
if (arr[i1] + arr[i2] + ... + arr[ik] == sum)
{
// this is a valid subset
}
}
}
}
}
But you are talking about numbers and summing them up, meaning you could make cutoffs with a smarter algorithm.
Since all numbers are positive, you know that if a single number is big enough, you cannot add to it any more positive numbers and have it sum up to s. Given s=6 and k=4, the highest number to include in the search is s-k+1=3. 3+1+1+1 is k numbers, 1 being your lowest possible number, sums up to 6. Any number above 3 couldn't have 3 other positives added to it, and have the sum <= 6.
But wait, your minimum possible value isn't 1, it is 3. That's even better. So assume k=10, n=60, min=3. The "highest number scenario" is x+min(k-1)=n -> x=60-3*9=33. So the highest number to even consider would be 33.
This cuts the amount of relevant numbers in the array to consider, hence it cuts the amount of combinations to look for.
But it gets even better. Assume k=10, n=60, min=3. The first number in the array happens to be 20, so it is relevant and should be checked. Lets find the relevant subsets that include that 20:
A new "puzzle" appears! k=10-1, n=60-20, min=3. You can now cutoff many numbers from the subpuzzle, and again and again which each step further in.
This can be improved even further by calculating the average of the k-1 lowest numbers in the subpuzzle and use that as min.
It is possible to improve this even further by precalculating the k lowest numbers average in subpuzzle [0..n], and k-1 lowest numbers average in subpuzzle [1..n], and k-2 lowest numbers average in subpuzzle [2..n] and so on, and use them instead of recalculating same stuff again and again within each subpuzzle assessment.
Try to use code below. Sorry, i had not time to optimise code. You can compare all methods that you have, and and make conclusion which is faster, don't forgot to share results.
C# (you can try to rid from List may be it will give you performance improvement:
public static IEnumerable<List<int>> findSubsetsWithLengthKAndSumS2(Tuple<int, int> ks, List<int> set, List<int> subSet, List<int> subSetIndex)
{
if (ks.Item1 == 0 && ks.Item2 == 0)
{
var res = new List<List<int>>();
res.Add(subSetIndex);
return res;
}
else if (ks.Item1 > 0 && ks.Item2 > 0)
{
var res = set.Select((x, i) =>
{
var newSubset = subSet.Select(y => y).ToList();
newSubset.Add(x);
var newSubsetIndex = subSetIndex.Select(y => y).ToList();
newSubsetIndex.Add(i);
var newSet = set.Skip(i).ToList();
return findSubsetsWithLengthKAndSumS2(Tuple.Create(ks.Item1 - 1, ks.Item2 - x), newSet, newSubset, newSubsetIndex).ToList();
}
).SelectMany(x => x).ToList();
return res;
}
else
return new List<List<int>>();
}
...
var res = findSubsetsWithLengthKAndSumS2(Tuple.Create(2, 293), numbers.ToList(), new List<int>(), new List<int>());
F# (I added it Just for fun =), it is not optimized too, i beleive the slowest place in code is 'skip' ):
let skip (list:List<int>) index =
list |> List.mapi (fun i x -> if i > index then Some(x) else None) |> List.filter (fun x -> x.IsSome) |> List.map (fun x -> x.Value)
let rec findSubsetsWithLengthKAndSumS (ks:int*int) (set:list<int>) (subSet:list<int>) =
[
match ks with
|0,0 -> yield subSet
| x,y when x > 0 && y > 0 -> yield! set |> List.mapi (fun i x-> findSubsetsWithLengthKAndSumS ((fst ks)-1,(snd ks)-x) (skip set i ) (x::subSet)) |> Seq.concat
| _,_-> yield []
]
...
let res = Subsets.findSubsetsWithLengthKAndSumS (2,293) numbers [] |> List.filter (fun x-> x.Length >0)
I beleive this Iterative version would be faster than others in many times. It uses .net 2.0:
public delegate IEnumerable< IEnumerable< int > > findSubset();
public delegate bool findSubsetsIterativeFilter( int[] sourceSet, int[] indiciesToSum, int expected );
public static bool Summ( int[] sourceSet, int[] indicies, int expected )
{
var sum = 0;
for( int i = 0; i < indicies.Length; i++ )
sum += sourceSet[ indicies[ i ] ];
return sum == expected;
}
public static IEnumerable< IEnumerable< int > > findSubsetsIterative( int k, int[] sourceSet, findSubsetsIterativeFilter specialCondition, int expected )
{
var a = new int[ k ];
for( int i = 0; i < k; i++ )
a[ i ] = i;
var p = k - 1;
while( p >= 0 )
{
if( specialCondition( sourceSet, a, expected ) )
yield return ( int[] )a.Clone();
p = ( a[ k - 1 ] == sourceSet.Length - 1 ) ? p - 1 : k - 1;
if( p >= 0 )
for( int i = k - 1; i >= p; i-- )
a[ i ] = a[ p ] + i - p + 1;
}
}
...
findSubsetsIterative( 2, a, Summ, 293 );
I had measured my code and Yorye's and here is what i get. My code is faster in 4-10x. Did you used 'findSubsetsIterative' from my answer in your experiments?
findSubsetsIterative( 4, GenerateSOurceData(1), Summ, 400 ) Elapsed:
00:00:00.0012113 puzzle.Solve(4, 400, PuzzleOnSubsetFound) Elapsed:
00:00:00.0046170
findSubsetsIterative( 5, GenerateSOurceData(1), Summ, 60 ) Elapsed:
00:00:00.0012960 puzzle.Solve(5, 60, PuzzleOnSubsetFound) Elapsed:
00:00:00.0108568
Here i increased incoming array in 5x (just copied array 5 times into new big array):
findSubsetsIterative( 5, GenerateSOurceData(5), Summ, 60 )
Elapsed: 00:00:00.0013067
puzzle.Solve(5, 60, PuzzleOnSubsetFound)
Elapsed: 00:00:21.3520840
it can be solved by a similar solution as the knapsack problem
dp[i][j][k]=number of k-size subsets with sum equal to j using first "i" elements
dp[i][j][k]=dp[i-1][j][k] + dp[i-1][j-a[i]][k-1]
is the update of the dp (using the ith element or not using it)
for(int i=0;i<=n;i++) dp[i][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=w;j++){
for(int k=1;k<=i;k++){
dp[i][j][k]=dp[i-1][j][k] ;
if(j>=a[i-1]){
dp[i][j][k]+=dp[i-1][j-a[i-1]][k-1];
}
}
}
}

Problems converting ADPCM to PCM in XNA

I'm looking to convert ADPCM data into PCM data from an XNA's .xnb file. (So many abbreviations!)
I've used a couple of places for references, including:
http://www.wooji-juice.com/blog/iphone-openal-ima4-adpcm.html
http://www.cs.columbia.edu/~hgs/audio/dvi/p34.jpg and a couple of others.
I believe that I'm close, as I'm getting a sound that's somewhat similar, but there's a lot of static/corruption in the output sound and I can't seem to figure out why.
The conversion comes down to two functions.
private static byte[] convert(byte[] data)
{
byte[] convertedData = new byte[(data.Length) * 4];
stepSize = 7;
newSample = 0;
index = 0;
var writeCounter = 0;
for (var x = 4; x < data.Length; x++)
{
// First 4 bytes of a block contain initialization information
if ((x % blockSize) < 4)
{
if (x % blockSize == 0) // New block
{
// set predictor/NewSample and index from
// the preamble of the block.
newSample = (short)(data[x + 1] | data[x]);
index = data[x + 2];
}
continue;
}
// Get the first 4 bits from the byte array,
var convertedSample = calculateNewSample((byte)(data[x] >> 4)); // convert 4 bit ADPCM sample to 16 bit PCM sample
// Store 16 bit PCM sample into output byte array
convertedData[writeCounter++] = (byte)convertedSample >> 8;
convertedData[writeCounter++] = (byte)convertedSample & 0x0ff;;
// Convert the next 4 bits of the 8 bit array.
convertedSample = calculateNewSample((byte)(data[x] & 0x0f)); // convert 4 bit ADPCM sample to 16 bit PCM sample.
// Store 16 bit PCM sample into output byte array
convertedData[writeCounter++] = (byte)(convertedSample >> 8);
convertedData[writeCounter++] = (byte)(convertedSample & 0x0ff);
}
// Conversion complete, return data
return convertedData;
}
private static short calculateNewSample(byte sample)
{
Debug.Assert(sample < 16, "Bad sample!");
var indexTable = new int[16] { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 };
var stepSizeTable = new int[89] { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767};
var sign = sample & 8;
var delta = sample & 7;
var difference = stepSize >> 3;
// originalsample + 0.5 * stepSize / 4 + stepSize / 8 optimization.
//http://www.cs.columbia.edu/~hgs/audio/dvi/p34.jpg
if ((delta & 4) != 0)
difference += stepSize;
if ((delta & 2) != 0)
difference += stepSize >> 1;
if ((delta & 1) != 0)
difference += stepSize >> 2;
if (sign != 0)
newSample -= (short)difference;
else
newSample += (short)difference;
// Increment index
index += indexTable[sample];
index = (int)MathHelper.Clamp(index, 0, 88);
newSample = (short)MathHelper.Clamp(newSample, -32768, 32767); // clamp between appropriate ranges
// compute new stepSize.
stepSize = stepSizeTable[index];
return newSample;
}
I don't believe the actual calculateNewSample() function is incorrect, as I've passed it the input values from http://www.cs.columbia.edu/~hgs/audio/dvi/p35.jpg and recieved the same output they have. I've tried flipping between the high/low order bytes to see if I've got that backwards to no avail as well. I feel like there's possibly something fundamental that I'm missing out on, but am having trouble finding it.
Any help would be seriously appreciated.

How to search an array with array?

I have 2 byte arrays:
Dim A() As Byte = {1, 2, 3, 4, 5, 6, 7, 8, 9}
Dim B() As Byte = {5, 6, 7}
Now I want to find the occurance of the full B in A. I tried Array.IndexOf(A, B) with no luck. Is there a simple way to search an array by array without the need to use any loops?
It should find the index (position) of 5,6,7 in the same order as in B().
If A() contains {1,2,3,4,7,6,5,9} it should return false or -1 because they are not in the same order.
The following Linq statement will give an IEnumerable<int> containing the positions of b in a (or an empty set if none occur):
Enumerable
.Range( 0, 1 + a.Length - b.Length )
.Where( i => a.Skip(i).Take(b.Length).SequenceEqual(b) );
I have no idea how to translate to VB.NET.
This might work, but it's C# and uses a loop:
private static int[] GetIndicesOf(byte[] needle, byte[] haystack)
{
int[] foundIndices = new int[needle.Length];
int found = 0;
for (int i = 0; i < haystack.Length; i++)
{
if (needle[found] == haystack[i])
{
foundIndices[found++] = i;
if (found == needle.Length)
return foundIndices;
}
else
{
i -= found; // Re-evaluate from the start of the found sentence + 1
found = 0; // Gap found, reset, maybe later in the haystack another occurrance of needle[0] is found
continue;
}
}
return null;
}
Tested with input:
Byte[] haystack = { 5, 6, 7, 8, 9, 0, 5, 6, 7 };
Byte[] needle = { 5, 6, 7 };
// Returns {0, 1, 2}
Byte[] haystack = { 5, 6, 0, 8, 9, 0, 5, 6, 7 };
Byte[] needle = { 5, 6, 7 };
// Returns {6, 7, 8}
Byte[] haystack = { 5, 6, 0, 7, 9, 0, 5, 6, 8 };
Byte[] needle = { 5, 6, 7 };
// Returns null
Byte[] haystack = { 1, 2, 1, 2, 2 };
Byte[] needle = { 1, 2, 2 };
// Returns {2, 3, 4}
Byte[] haystack = { 1, 2, 1, 2, 1, 2, 3 };
Byte[] needle = { 1, 2, 1, 2, 3 };
// Returns {2, 3, 4, 5, 6}
Byte[] haystack = { 1, 1, 1, 1, 2 };
Byte[] needle = { 1, 2 };
// Returns {3, 4}
But the Linq implementation of #spender looks nicer. :-P
How about creating a method that:
Concatinates the elements of the searched list to one string
Concatinates the elements of the list to search for to one string
Looks in the first string for the precense of the second string
Like so:
public bool IsSubSetOf(IList<int> list1, IList<int> list2){
var string1 = string.Join("", list1);
var string2 = string.Join("", list2);
return string1.Contains(string2);
}
Not tested...
An efficient way of solving this problem in general is the KMP algorithm. Quick googling suggest that a .NET implementation may be found here. It's implementational pseudocode is availible from Wikipedia.
An inefficient, but harmlessly easy to code way is presented in one of the links above as follows:
int[] T = new[]{1, 2, 3, 4, 5};
int[] P = new[]{3, 4};
for (int i = 0; i != T.Length; i++)
{
int j = 0
for (;i+j != T.Length && j != P.Length && T[i+j]==P[j]; j++);
if (j == P.Length) return i;
}
My take would be:
public static int Search<T>(T[] space, T[] searched) {
foreach (var e in Array.FindAll(space, e => e.Equals(searched[0]))) {
var idx = Array.IndexOf(space, e);
if (space.ArraySkip(idx).Take(searched.Length).SequenceEqual(searched))
return idx;
}
return -1;
}
public static class Linqy {
public static IEnumerable<T> ArraySkip<T>(this T[] array, int index) {
for (int i = index; i < array.Length; i++) {
yield return array[i];
}
}
}
As always, it depends on your data whether this is "good enough" or you will have to resort to more complex yet efficient algorithms. I introduced an arrayskip as the Linq skip does indeed only assume the IEnumerable interface and would enumerate up to the index.

Categories