using System;
using System.Diagnostics;
namespace ConsoleApplication1 {
internal class Program {
/// <summary>Looks for the next occurrence of a sequence in a byte array</summary>
/// <param name="array">Array that will be scanned</param>
/// <param name="start">Index in the array at which scanning will begin</param>
/// <param name="sequence">Sequence the array will be scanned for</param>
/// <returns>
/// The index of the next occurrence of the sequence of -1 if not found
/// </returns>
private static int findSequence(byte[] array, int start, byte[] sequence) {
int end = array.Length - sequence.Length; // past here no match is possible
byte firstByte = sequence[0]; // cached to tell compiler there's no aliasing
while(start <= end) {
// scan for first byte only. compiler-friendly.
if(array[start] == firstByte) {
// scan for rest of sequence
for (int offset = 1;; ++offset) {
if(offset == sequence.Length) { // full sequence matched?
return start;
} else if(array[start + offset] != sequence[offset]) {
break;
}
}
}
++start;
}
// end of array reached without match
return -1;
}
private static void checkSingleByteSequence() {
byte[] sequence = new byte[] { 123 };
Debug.Assert(findSequence(new byte[] { 123 }, 0, sequence) == 0);
Debug.Assert(findSequence(new byte[] { 100 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 123, 124, 125 }, 0, sequence) == 0);
Debug.Assert(findSequence(new byte[] { 122, 123, 124 }, 0, sequence) == 1);
Debug.Assert(findSequence(new byte[] { 121, 122, 123 }, 0, sequence) == 2);
Debug.Assert(findSequence(new byte[] { 123, 124, 125, 126 }, 1, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 122, 123, 124, 125 }, 2, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 123, 124, 123, 124 }, 1, sequence) == 2);
Debug.Assert(findSequence(new byte[] { 120, 121, 122, 123 }, 3, sequence) == 3);
Debug.Assert(findSequence(new byte[] { 121, 122, 123, 124 }, 3, sequence) == -1);
}
private static void checkThreeByteSequence() {
byte[] sequence = new byte[] { 150, 150, 160 };
Debug.Assert(findSequence(new byte[] { 100 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 100, 200 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 100, 110 }, 1, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 100, 110, 120 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 100, 110, 120, 130 }, 3, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 150 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 100, 150 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 150, 150 }, 1, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 100, 150, 150, 150 }, 0, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 150, 150, 120, 150 }, 3, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 150, 150, 160, 170 }, 0, sequence) == 0);
Debug.Assert(findSequence(new byte[] { 150, 150, 160, 170 }, 1, sequence) == -1);
Debug.Assert(findSequence(new byte[] { 140, 150, 150, 160 }, 0, sequence) == 1);
Debug.Assert(findSequence(new byte[] { 140, 150, 150, 160 }, 1, sequence) == 1);
Debug.Assert(findSequence(new byte[] { 140, 150, 150, 160 }, 2, sequence) == -1);
}
public static void Main(string[] args) {
checkSingleByteSequence();
checkThreeByteSequence();
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRGlhZ25vc3RpY3M7CgpuYW1lc3BhY2UgQ29uc29sZUFwcGxpY2F0aW9uMSB7CgogIGludGVybmFsIGNsYXNzIFByb2dyYW0gewoKICAgIC8vLyA8c3VtbWFyeT5Mb29rcyBmb3IgdGhlIG5leHQgb2NjdXJyZW5jZSBvZiBhIHNlcXVlbmNlIGluIGEgYnl0ZSBhcnJheTwvc3VtbWFyeT4KICAgIC8vLyA8cGFyYW0gbmFtZT0iYXJyYXkiPkFycmF5IHRoYXQgd2lsbCBiZSBzY2FubmVkPC9wYXJhbT4KICAgIC8vLyA8cGFyYW0gbmFtZT0ic3RhcnQiPkluZGV4IGluIHRoZSBhcnJheSBhdCB3aGljaCBzY2FubmluZyB3aWxsIGJlZ2luPC9wYXJhbT4KICAgIC8vLyA8cGFyYW0gbmFtZT0ic2VxdWVuY2UiPlNlcXVlbmNlIHRoZSBhcnJheSB3aWxsIGJlIHNjYW5uZWQgZm9yPC9wYXJhbT4KICAgIC8vLyA8cmV0dXJucz4KICAgIC8vLyAgIFRoZSBpbmRleCBvZiB0aGUgbmV4dCBvY2N1cnJlbmNlIG9mIHRoZSBzZXF1ZW5jZSBvZiAtMSBpZiBub3QgZm91bmQKICAgIC8vLyA8L3JldHVybnM+CiAgICBwcml2YXRlIHN0YXRpYyBpbnQgZmluZFNlcXVlbmNlKGJ5dGVbXSBhcnJheSwgaW50IHN0YXJ0LCBieXRlW10gc2VxdWVuY2UpIHsKICAgICAgaW50IGVuZCA9IGFycmF5Lkxlbmd0aCAtIHNlcXVlbmNlLkxlbmd0aDsgLy8gcGFzdCBoZXJlIG5vIG1hdGNoIGlzIHBvc3NpYmxlCiAgICAgIGJ5dGUgZmlyc3RCeXRlID0gc2VxdWVuY2VbMF07IC8vIGNhY2hlZCB0byB0ZWxsIGNvbXBpbGVyIHRoZXJlJ3Mgbm8gYWxpYXNpbmcKCiAgICAgIHdoaWxlKHN0YXJ0IDw9IGVuZCkgewogICAgICAgIC8vIHNjYW4gZm9yIGZpcnN0IGJ5dGUgb25seS4gY29tcGlsZXItZnJpZW5kbHkuCiAgICAgICAgaWYoYXJyYXlbc3RhcnRdID09IGZpcnN0Qnl0ZSkgewogICAgICAgICAgLy8gc2NhbiBmb3IgcmVzdCBvZiBzZXF1ZW5jZQogICAgICAgICAgZm9yIChpbnQgb2Zmc2V0ID0gMTs7ICsrb2Zmc2V0KSB7CiAgICAgICAgICAgIGlmKG9mZnNldCA9PSBzZXF1ZW5jZS5MZW5ndGgpIHsgLy8gZnVsbCBzZXF1ZW5jZSBtYXRjaGVkPwogICAgICAgICAgICAgIHJldHVybiBzdGFydDsKICAgICAgICAgICAgfSBlbHNlIGlmKGFycmF5W3N0YXJ0ICsgb2Zmc2V0XSAhPSBzZXF1ZW5jZVtvZmZzZXRdKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgKytzdGFydDsKICAgICAgfQoKICAgICAgLy8gZW5kIG9mIGFycmF5IHJlYWNoZWQgd2l0aG91dCBtYXRjaAogICAgICByZXR1cm4gLTE7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgdm9pZCBjaGVja1NpbmdsZUJ5dGVTZXF1ZW5jZSgpIHsKICAgICAgYnl0ZVtdIHNlcXVlbmNlID0gbmV3IGJ5dGVbXSB7IDEyMyB9OwoKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTIzIH0sIDAsIHNlcXVlbmNlKSA9PSAwKTsKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTAwIH0sIDAsIHNlcXVlbmNlKSA9PSAtMSk7CgogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMjMsIDEyNCwgMTI1IH0sIDAsIHNlcXVlbmNlKSA9PSAwKTsKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTIyLCAxMjMsIDEyNCB9LCAwLCBzZXF1ZW5jZSkgPT0gMSk7CiAgICAgIERlYnVnLkFzc2VydChmaW5kU2VxdWVuY2UobmV3IGJ5dGVbXSB7IDEyMSwgMTIyLCAxMjMgfSwgMCwgc2VxdWVuY2UpID09IDIpOwoKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTIzLCAxMjQsIDEyNSwgMTI2IH0sIDEsIHNlcXVlbmNlKSA9PSAtMSk7CiAgICAgIERlYnVnLkFzc2VydChmaW5kU2VxdWVuY2UobmV3IGJ5dGVbXSB7IDEyMiwgMTIzLCAxMjQsIDEyNSB9LCAyLCBzZXF1ZW5jZSkgPT0gLTEpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMjMsIDEyNCwgMTIzLCAxMjQgfSwgMSwgc2VxdWVuY2UpID09IDIpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMjAsIDEyMSwgMTIyLCAxMjMgfSwgMywgc2VxdWVuY2UpID09IDMpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMjEsIDEyMiwgMTIzLCAxMjQgfSwgMywgc2VxdWVuY2UpID09IC0xKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyB2b2lkIGNoZWNrVGhyZWVCeXRlU2VxdWVuY2UoKSB7CiAgICAgIGJ5dGVbXSBzZXF1ZW5jZSA9IG5ldyBieXRlW10geyAxNTAsIDE1MCwgMTYwIH07CgogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMDAgfSwgMCwgc2VxdWVuY2UpID09IC0xKTsKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTAwLCAyMDAgfSwgMCwgc2VxdWVuY2UpID09IC0xKTsKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTAwLCAxMTAgfSwgMSwgc2VxdWVuY2UpID09IC0xKTsKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTAwLCAxMTAsIDEyMCB9LCAwLCBzZXF1ZW5jZSkgPT0gLTEpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMDAsIDExMCwgMTIwLCAxMzAgfSwgMywgc2VxdWVuY2UpID09IC0xKTsKCiAgICAgIERlYnVnLkFzc2VydChmaW5kU2VxdWVuY2UobmV3IGJ5dGVbXSB7IDE1MCB9LCAwLCBzZXF1ZW5jZSkgPT0gLTEpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMDAsIDE1MCB9LCAwLCBzZXF1ZW5jZSkgPT0gLTEpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxNTAsIDE1MCB9LCAxLCBzZXF1ZW5jZSkgPT0gLTEpOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxMDAsIDE1MCwgMTUwLCAxNTAgfSwgMCwgc2VxdWVuY2UpID09IC0xKTsKICAgICAgRGVidWcuQXNzZXJ0KGZpbmRTZXF1ZW5jZShuZXcgYnl0ZVtdIHsgMTUwLCAxNTAsIDEyMCwgMTUwIH0sIDMsIHNlcXVlbmNlKSA9PSAtMSk7CgogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxNTAsIDE1MCwgMTYwLCAxNzAgfSwgMCwgc2VxdWVuY2UpID09IDApOwogICAgICBEZWJ1Zy5Bc3NlcnQoZmluZFNlcXVlbmNlKG5ldyBieXRlW10geyAxNTAsIDE1MCwgMTYwLCAxNzAgfSwgMSwgc2VxdWVuY2UpID09IC0xKTsKCiAgICAgIERlYnVnLkFzc2VydChmaW5kU2VxdWVuY2UobmV3IGJ5dGVbXSB7IDE0MCwgMTUwLCAxNTAsIDE2MCB9LCAwLCBzZXF1ZW5jZSkgPT0gMSk7CiAgICAgIERlYnVnLkFzc2VydChmaW5kU2VxdWVuY2UobmV3IGJ5dGVbXSB7IDE0MCwgMTUwLCAxNTAsIDE2MCB9LCAxLCBzZXF1ZW5jZSkgPT0gMSk7CiAgICAgIERlYnVnLkFzc2VydChmaW5kU2VxdWVuY2UobmV3IGJ5dGVbXSB7IDE0MCwgMTUwLCAxNTAsIDE2MCB9LCAyLCBzZXF1ZW5jZSkgPT0gLTEpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBNYWluKHN0cmluZ1tdIGFyZ3MpIHsKICAgICAgY2hlY2tTaW5nbGVCeXRlU2VxdWVuY2UoKTsKICAgICAgY2hlY2tUaHJlZUJ5dGVTZXF1ZW5jZSgpOwogICAgfQoKICB9CiAgCn0=