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,
Related
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!
I need to write a function that will add two byte arrays using recursion. The test for this function is as follows :
[Test]
[TestCaseSource("Add_Function")]
public AddResult Add_WithRecursiveAlgorithm(byte[] a, byte[] b)
{
// Arrange
// Act
var result = AddRecursion(a, b);
// Assert
return new AddResult(a, b, result);
}
For example:
Input : { 1, 1, 1 }, { 1, 1, 1 }
Result: {2,2,2}
Input : { 1, 1, 255 }, {0, 0, 1 }
Result: {1,2,0}
The general rules are as follows:
• Assume inputs a & b are never null and will always be the same length.
• The algorithm should be non-destructive to the inputs.
• The algorithm should be able to handle large input lengths, >1000, but the input will never be large enough to cause a stack overflow.
Any ideas how I can do this?
public object[] Add_Function()
{
return new object[]
{
new object[]
{
new byte[] { 1, 1, 1 }, new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }
},
new object[]
{
new byte[] { 1, 1, 255 }, new byte[] { 0, 0, 1 }, new byte[] { 1, 2, 0 }
}
};
}
[TestCaseSource("Add_Function")]
public void Add(byte[] a, byte[] b, byte[] expected)
{
// arrange
int len = Math.Max(a.Length, b.Length);
Array.Resize(ref a, len);
Array.Resize(ref b, len);
byte[] result = new byte[len];
//act
DoAdd(a, b, result, 0, len - 1);
//assert
CollectionAssert.AreEqual(expected, result);
}
private void DoAdd(byte[] a, byte[] b, byte[] result, int broughtForward, int index)
{
int carriedForward = (a[index] + b[index] + broughtForward) / (byte.MaxValue + 1);
result[index] =(byte)((a[index] + b[index] + broughtForward) % (byte.MaxValue + 1));
if (index > 0)
{
DoAdd(a,b,result, carriedForward, index-1);
}
}
I have b1 and b2 which are all in byte, I am using serialport.write to send them separately. Can I send them at the same time? As in using one command instead of two. My existing code:
private void SConvert_Click(object sender, EventArgs e)
{
byte[] b1 = null, b2 = null;
string[] coords = textBox1.Text.Split('\n');
for (int i = 0; i <= coords.Length - 1; i++)
{
if (coords[i].Length > 0)
{
GetValue(coords[i], out b1, out b2);
}
if (serialPort.IsOpen)
{
serialPort.Write(b1, 0, 4);
serialPort.Write(b2, 0, 4);
}
}
}
private void GetValue(string strValue, out byte[] b1, out byte[] b2)
{
string S1, S2, S = strValue;
string[] x = S.Split(',');
string y = x[0].ToString();//{lat=-36.123333
string z = x[1].ToString();//lng=174.333333} // index outside bounds of the array
S1 = y.Substring(y.IndexOf('=') + 1);
string z1 = z.Replace("}", "0"); // replace } by 0 since do not know length of }
S2 = z1.Substring(z1.IndexOf('=') + 1);
float f1 = float.Parse(S1), f2 = float.Parse(S2);
b1 = System.BitConverter.GetBytes(f1);
b2 = System.BitConverter.GetBytes(f2);
}
Instead of
serialPort.Write(b1, 0, 4);
serialPort.Write(b2, 0, 4);
you could do just
serialPort.Write(b1.Concat(b2).ToArray(), 0, b1.Length + b2.Length);
I assume you'd like to send two byte arrays at once. Solution is simple: merge them, and send it.
byte[] buf = new byte[b1.Length + b2.Length];
Array.Copy(buf, 0, b1);
Array.Copy(buf, 0, b2, b1.Length, b2.Length);
serialPort.Write(buf, 0, buf.Length);
See also: Merging two arrays in .NET
public void parse_table(BinaryReader inFile)
{
byte[] idstring = inFile.ReadBytes(6);
Console.WriteLine(Convert.ToString(idstring));
}
It is a simple snippet: read the first 6 bytes of the file and convert that to a string.
However the console shows System.Byte[].
Maybe I'm using the wrong class for conversion. What should I be using? It will eventually be parsing filenames encoded in UTF-8, and I'm planning to use the same method to read all filenames.
It's actually:
Console.WriteLine(Encoding.Default.GetString(value));
or for UTF-8 specifically:
Console.WriteLine(Encoding.UTF8.GetString(value));
I was in a predicament where I had a signed byte array (sbyte[]) as input to a Test class and I wanted to replace it with a normal byte array (byte[]) for simplicity. I arrived here from a Google search but Tom's answer wasn't useful to me.
I wrote a helper method to print out the initializer of a given byte[]:
public void PrintByteArray(byte[] bytes)
{
var sb = new StringBuilder("new byte[] { ");
foreach (var b in bytes)
{
sb.Append(b + ", ");
}
sb.Append("}");
Console.WriteLine(sb.ToString());
}
You can use it like this:
var signedBytes = new sbyte[] { 1, 2, 3, -1, -2, -3, 127, -128, 0, };
var unsignedBytes = UnsignedBytesFromSignedBytes(signedBytes);
PrintByteArray(unsignedBytes);
// output:
// new byte[] { 1, 2, 3, 255, 254, 253, 127, 128, 0, }
The ouput is valid C# which can then just be copied into your code.
And just for completeness, here is the UnsignedBytesFromSignedBytes method:
// http://stackoverflow.com/a/829994/346561
public static byte[] UnsignedBytesFromSignedBytes(sbyte[] signed)
{
var unsigned = new byte[signed.Length];
Buffer.BlockCopy(signed, 0, unsigned, 0, signed.Length);
return unsigned;
}
I've used this simple code in my codebase:
static public string ToReadableByteArray(byte[] bytes)
{
return string.Join(", ", bytes);
}
To use:
Console.WriteLine(ToReadableByteArray(bytes));
byte[] bytes = { 1,2,3,4 };
string stringByte= BitConverter.ToString(bytes);
Console.WriteLine(stringByte);
This is just an updated version of Jesse Webbs code that doesn't append the unnecessary trailing , character.
public static string PrintBytes(this byte[] byteArray)
{
var sb = new StringBuilder("new byte[] { ");
for(var i = 0; i < byteArray.Length;i++)
{
var b = byteArray[i];
sb.Append(b);
if (i < byteArray.Length -1)
{
sb.Append(", ");
}
}
sb.Append(" }");
return sb.ToString();
}
The output from this method would be:
new byte[] { 48, ... 135, 31, 178, 7, 157 }
For some fun with linq and string interpolation:
public string ByteArrayToString(byte[] bytes)
{
if ( bytes == null ) return "null";
string joinedBytes = string.Join(", ", bytes.Select(b => b.ToString()));
return $"new byte[] {{ {joinedBytes} }}";
}
Test cases:
byte[] bytes = { 1, 2, 3, 4 };
ByteArrayToString( bytes ) .Dump();
ByteArrayToString(null).Dump();
ByteArrayToString(new byte[] {} ) .Dump();
Output:
new byte[] { 1, 2, 3, 4 }
null
new byte[] { }
I have a byte array in memory, read from a file. I would like to split the byte array at a certain point (index) without having to just create a new byte array and copy each byte at a time, increasing the in memory foot print of the operation. What I would like is something like this:
byte[] largeBytes = [1,2,3,4,5,6,7,8,9];
byte[] smallPortion;
smallPortion = split(largeBytes, 3);
smallPortion would equal 1,2,3,4
largeBytes would equal 5,6,7,8,9
In C# with Linq you can do this:
smallPortion = largeBytes.Take(4).ToArray();
largeBytes = largeBytes.Skip(4).Take(5).ToArray();
;)
FYI. System.ArraySegment<T> structure basically is the same thing as ArrayView<T> in the code above. You can use this out-of-the-box structure in the same way, if you'd like.
This is how I would do that:
using System;
using System.Collections;
using System.Collections.Generic;
class ArrayView<T> : IEnumerable<T>
{
private readonly T[] array;
private readonly int offset, count;
public ArrayView(T[] array, int offset, int count)
{
this.array = array;
this.offset = offset;
this.count = count;
}
public int Length
{
get { return count; }
}
public T this[int index]
{
get
{
if (index < 0 || index >= this.count)
throw new IndexOutOfRangeException();
else
return this.array[offset + index];
}
set
{
if (index < 0 || index >= this.count)
throw new IndexOutOfRangeException();
else
this.array[offset + index] = value;
}
}
public IEnumerator<T> GetEnumerator()
{
for (int i = offset; i < offset + count; i++)
yield return array[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
IEnumerator<T> enumerator = this.GetEnumerator();
while (enumerator.MoveNext())
{
yield return enumerator.Current;
}
}
}
class Program
{
static void Main(string[] args)
{
byte[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
ArrayView<byte> p1 = new ArrayView<byte>(arr, 0, 5);
ArrayView<byte> p2 = new ArrayView<byte>(arr, 5, 5);
Console.WriteLine("First array:");
foreach (byte b in p1)
{
Console.Write(b);
}
Console.Write("\n");
Console.WriteLine("Second array:");
foreach (byte b in p2)
{
Console.Write(b);
}
Console.ReadKey();
}
}
Try this one:
private IEnumerable<byte[]> ArraySplit(byte[] bArray, int intBufforLengt)
{
int bArrayLenght = bArray.Length;
byte[] bReturn = null;
int i = 0;
for (; bArrayLenght > (i + 1) * intBufforLengt; i++)
{
bReturn = new byte[intBufforLengt];
Array.Copy(bArray, i * intBufforLengt, bReturn, 0, intBufforLengt);
yield return bReturn;
}
int intBufforLeft = bArrayLenght - i * intBufforLengt;
if (intBufforLeft > 0)
{
bReturn = new byte[intBufforLeft];
Array.Copy(bArray, i * intBufforLengt, bReturn, 0, intBufforLeft);
yield return bReturn;
}
}
As Eren said, you can use ArraySegment<T>. Here's an extension method and usage example:
public static class ArrayExtensionMethods
{
public static ArraySegment<T> GetSegment<T>(this T[] arr, int offset, int? count = null)
{
if (count == null) { count = arr.Length - offset; }
return new ArraySegment<T>(arr, offset, count.Value);
}
}
void Main()
{
byte[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
var p1 = arr.GetSegment(0, 5);
var p2 = arr.GetSegment(5);
Console.WriteLine("First array:");
foreach (byte b in p1)
{
Console.Write(b);
}
Console.Write("\n");
Console.WriteLine("Second array:");
foreach (byte b in p2)
{
Console.Write(b);
}
}
I'm not sure what you mean by:
I would like to split the byte array at a certain point(index) without having to just create a new byte array and copy each byte at a time, increasing the in memory foot print of the operation.
In most languages, certainly C#, once an array has been allocated, there is no way to change the size of it. It sounds like you're looking for a way to change the length of an array, which you can't. You also want to somehow recycle the memory for the second part of the array, to create a second array, which you also can't do.
In summary: just create a new array.
You can't. What you might want is keep a starting point and number of items; in essence, build iterators. If this is C++, you can just use std::vector<int> and use the built-in ones.
In C#, I'd build a small iterator class that holds start index, count and implements IEnumerable<>.
I tried different algorithms :
Skip().Take() => the worst, by far
Array.Copy
ArraySegment
new Guid(int, int16, int16 ...)
The latest being the fastest I'm now using this extension method:
public static Guid ToGuid(this byte[] byteArray, int offset)
{
return new Guid(BitConverter.ToInt32(byteArray, offset), BitConverter.ToInt16(byteArray, offset + 4), BitConverter.ToInt16(byteArray, offset + 6), byteArray[offset + 8], byteArray[offset + 9], byteArray[offset + 10], byteArray[offset + 11], byteArray[offset + 12], byteArray[offset + 13], byteArray[offset + 14], byteArray[offset + 15]);
}
With a byte array with 10000000 guids:
Done (Skip().Take()) in 1,156ms (for only 100000 guids :))
Done (Array.Copy) in 1,219ms
Done (ToGuid extension) in 994ms
Done (ArraySegment) in 2,411ms