using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace RegexNegativePatternsForString
{
internal class Program
{
public static void Main()
{
//
// 「文字列 ab を含まない」という正規表現は
// [^a]*|[^a]*a[^b]*
// であってるのかテスト
//
string ng_word2 = "ab";
Regex regex2 = new Regex(@"[^a]*|[^a]*a[^b]*");
Test(regex2, ng_word2);
//
// 「文字列 abc を含まない」という正規表現は
// [^a]*|[^a]*a[^b]*|[^a]*a[^b]*b[^c]*
// であってるのかテスト
//
string ng_word3 = "abc";
Regex regex3 = new Regex(@"[^a]*|[^a]*a[^b]*|[^a]*a[^b]*b[^c]*");
Test(regex3, ng_word3);
}
static void Test(Regex regex, string ng_word)
{
// aからz
var a2z = Enumerable.Range(0, 26).Select(it => Convert.ToChar('a' + it));
// 任意の2文字でテスト
StringBuilder sb = new StringBuilder();
foreach (var item in DP(a2z, a2z))
{
sb.Clear();
sb.Append(item.Item1);
sb.Append(item.Item2);
string input = sb.ToString();
Test(input, regex, ng_word);
}
// 任意の3文字でテスト
foreach (var item in DP(a2z, a2z, a2z))
{
sb.Clear();
sb.Append(item.Item1);
sb.Append(item.Item2);
sb.Append(item.Item3);
string input = sb.ToString();
Test(input, regex, ng_word);
}
// 任意の4文字でテスト
foreach (var item in DP(a2z, a2z, a2z, a2z))
{
sb.Clear();
sb.Append(item.Item1);
sb.Append(item.Item2);
sb.Append(item.Item3);
sb.Append(item.Item4);
string input = sb.ToString();
Test(input, regex, ng_word);
}
// 任意の5文字でテスト
foreach (var item in DP(a2z, a2z, a2z, a2z, a2z))
{
sb.Clear();
sb.Append(item.Item1);
sb.Append(item.Item2);
sb.Append(item.Item3);
sb.Append(item.Item4);
sb.Append(item.Item5);
string input = sb.ToString();
Test(input, regex, ng_word);
}
Console.WriteLine("===== PASS! NG-word: {0} =====", ng_word);
}
static void Test(string input, Regex regex, string ng)
{
bool actual = regex.IsMatch(input);
bool expected = !input.Contains(ng);
if (actual != expected)
{
string errMsg = string.Format("assertion failure! input: {0}, regex: {1}, NG-word: {2}", input, regex.ToString(), ng);
throw new Exception(errMsg);
}
}
static IEnumerable<Tuple<T1, T2>> DP<T1, T2>(IEnumerable<T1> set1, IEnumerable<T2> set2)
{
foreach (var item1 in set1)
{
foreach (var item2 in set2)
{
yield return Tuple.Create(item1, item2);
}
}
}
static IEnumerable<Tuple<T1, T2, T3>> DP<T1, T2, T3>(IEnumerable<T1> set1, IEnumerable<T2> set2, IEnumerable<T3> set3)
{
foreach (var item1 in set1)
{
foreach (var item2 in set2)
{
foreach (var item3 in set3)
{
yield return Tuple.Create(item1, item2, item3);
}
}
}
}
static IEnumerable<Tuple<T1, T2, T3, T4>> DP<T1, T2, T3, T4>(IEnumerable<T1> set1, IEnumerable<T2> set2, IEnumerable<T3> set3, IEnumerable<T4> set4)
{
foreach (var item1 in set1)
{
foreach (var item2 in set2)
{
foreach (var item3 in set3)
{
foreach (var item4 in set4)
{
yield return Tuple.Create(item1, item2, item3, item4);
}
}
}
}
}
static IEnumerable<Tuple<T1, T2, T3, T4, T5>> DP<T1, T2, T3, T4, T5>(IEnumerable<T1> set1, IEnumerable<T2> set2, IEnumerable<T3> set3, IEnumerable<T4> set4, IEnumerable<T5> set5)
{
foreach (var item1 in set1)
{
foreach (var item2 in set2)
{
foreach (var item3 in set3)
{
foreach (var item4 in set4)
{
foreach (var item5 in set5)
{
yield return Tuple.Create(item1, item2, item3, item4, item5);
}
}
}
}
}
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkxpbnE7CnVzaW5nIFN5c3RlbS5UZXh0Owp1c2luZyBTeXN0ZW0uVGV4dC5SZWd1bGFyRXhwcmVzc2lvbnM7CgpuYW1lc3BhY2UgUmVnZXhOZWdhdGl2ZVBhdHRlcm5zRm9yU3RyaW5nCnsKCWludGVybmFsIGNsYXNzIFByb2dyYW0KCXsKCQlwdWJsaWMgc3RhdGljIHZvaWQgTWFpbigpCgkJewoJCQkvLwoJCQkvLyDjgIzmloflrZfliJcgYWIg44KS5ZCr44G+44Gq44GE44CN44Go44GE44GG5q2j6KaP6KGo54++44GvCgkJCS8vIFteYV0qfFteYV0qYVteYl0qCgkJCS8vIOOBp+OBguOBo+OBpuOCi+OBruOBi+ODhuOCueODiAoJCQkvLwoJCQlzdHJpbmcgbmdfd29yZDIgPSAiYWIiOwoJCQlSZWdleCByZWdleDIgPSBuZXcgUmVnZXgoQCJbXmFdKnxbXmFdKmFbXmJdKiIpOwoJCQlUZXN0KHJlZ2V4Miwgbmdfd29yZDIpOwoKCQkJLy8KCQkJLy8g44CM5paH5a2X5YiXIGFiYyDjgpLlkKvjgb7jgarjgYTjgI3jgajjgYTjgYbmraPopo/ooajnj77jga8KCQkJLy8gW15hXSp8W15hXSphW15iXSp8W15hXSphW15iXSpiW15jXSoKCQkJLy8g44Gn44GC44Gj44Gm44KL44Gu44GL44OG44K544OICgkJCS8vCgkJCXN0cmluZyBuZ193b3JkMyA9ICJhYmMiOwoJCQlSZWdleCByZWdleDMgPSBuZXcgUmVnZXgoQCJbXmFdKnxbXmFdKmFbXmJdKnxbXmFdKmFbXmJdKmJbXmNdKiIpOwoJCQlUZXN0KHJlZ2V4Mywgbmdfd29yZDMpOwoJCX0KCgkJc3RhdGljIHZvaWQgVGVzdChSZWdleCByZWdleCwgc3RyaW5nIG5nX3dvcmQpCgkJewoJCQkvLyBh44GL44KJegoJCQl2YXIgYTJ6ID0gRW51bWVyYWJsZS5SYW5nZSgwLCAyNikuU2VsZWN0KGl0ID0+IENvbnZlcnQuVG9DaGFyKCdhJyArIGl0KSk7CgoKCQkJLy8g5Lu75oSP44GuMuaWh+Wtl+OBp+ODhuOCueODiAoJCQlTdHJpbmdCdWlsZGVyIHNiID0gbmV3IFN0cmluZ0J1aWxkZXIoKTsKCQkJZm9yZWFjaCAodmFyIGl0ZW0gaW4gRFAoYTJ6LCBhMnopKQoJCQl7CgkJCQlzYi5DbGVhcigpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTEpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTIpOwoKCQkJCXN0cmluZyBpbnB1dCA9IHNiLlRvU3RyaW5nKCk7CgkJCQlUZXN0KGlucHV0LCByZWdleCwgbmdfd29yZCk7CgkJCX0KCgkJCS8vIOS7u+aEj+OBrjPmloflrZfjgafjg4bjgrnjg4gKCQkJZm9yZWFjaCAodmFyIGl0ZW0gaW4gRFAoYTJ6LCBhMnosIGEyeikpCgkJCXsKCQkJCXNiLkNsZWFyKCk7CgkJCQlzYi5BcHBlbmQoaXRlbS5JdGVtMSk7CgkJCQlzYi5BcHBlbmQoaXRlbS5JdGVtMik7CgkJCQlzYi5BcHBlbmQoaXRlbS5JdGVtMyk7CgoJCQkJc3RyaW5nIGlucHV0ID0gc2IuVG9TdHJpbmcoKTsKCQkJCVRlc3QoaW5wdXQsIHJlZ2V4LCBuZ193b3JkKTsKCQkJfQoKCQkJLy8g5Lu75oSP44GuNOaWh+Wtl+OBp+ODhuOCueODiAoJCQlmb3JlYWNoICh2YXIgaXRlbSBpbiBEUChhMnosIGEyeiwgYTJ6LCBhMnopKQoJCQl7CgkJCQlzYi5DbGVhcigpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTEpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTIpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTMpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTQpOwoKCQkJCXN0cmluZyBpbnB1dCA9IHNiLlRvU3RyaW5nKCk7CgkJCQlUZXN0KGlucHV0LCByZWdleCwgbmdfd29yZCk7CgkJCX0KCgkJCS8vIOS7u+aEj+OBrjXmloflrZfjgafjg4bjgrnjg4gKCQkJZm9yZWFjaCAodmFyIGl0ZW0gaW4gRFAoYTJ6LCBhMnosIGEyeiwgYTJ6LCBhMnopKQoJCQl7CgkJCQlzYi5DbGVhcigpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTEpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTIpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTMpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTQpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTUpOwoKCQkJCXN0cmluZyBpbnB1dCA9IHNiLlRvU3RyaW5nKCk7CgkJCQlUZXN0KGlucHV0LCByZWdleCwgbmdfd29yZCk7CgkJCX0KCgkJCUNvbnNvbGUuV3JpdGVMaW5lKCI9PT09PSBQQVNTISBORy13b3JkOiB7MH0gPT09PT0iLCBuZ193b3JkKTsKCQl9CgoJCXN0YXRpYyB2b2lkIFRlc3Qoc3RyaW5nIGlucHV0LCBSZWdleCByZWdleCwgc3RyaW5nIG5nKQoJCXsKCQkJYm9vbCBhY3R1YWwgPSByZWdleC5Jc01hdGNoKGlucHV0KTsKCQkJYm9vbCBleHBlY3RlZCA9ICFpbnB1dC5Db250YWlucyhuZyk7CgkJCWlmIChhY3R1YWwgIT0gZXhwZWN0ZWQpCgkJCXsKCQkJCXN0cmluZyBlcnJNc2cgPSBzdHJpbmcuRm9ybWF0KCJhc3NlcnRpb24gZmFpbHVyZSEgaW5wdXQ6IHswfSwgcmVnZXg6IHsxfSwgTkctd29yZDogezJ9IiwgaW5wdXQsIHJlZ2V4LlRvU3RyaW5nKCksIG5nKTsKCQkJCXRocm93IG5ldyBFeGNlcHRpb24oZXJyTXNnKTsKCQkJfQoJCX0KCgkJc3RhdGljIElFbnVtZXJhYmxlPFR1cGxlPFQxLCBUMj4+IERQPFQxLCBUMj4oSUVudW1lcmFibGU8VDE+IHNldDEsIElFbnVtZXJhYmxlPFQyPiBzZXQyKQoJCXsKCQkJZm9yZWFjaCAodmFyIGl0ZW0xIGluIHNldDEpCgkJCXsKCQkJCWZvcmVhY2ggKHZhciBpdGVtMiBpbiBzZXQyKQoJCQkJewoJCQkJCXlpZWxkIHJldHVybiBUdXBsZS5DcmVhdGUoaXRlbTEsIGl0ZW0yKTsKCQkJCX0KCQkJfQoJCX0KCgkJc3RhdGljIElFbnVtZXJhYmxlPFR1cGxlPFQxLCBUMiwgVDM+PiBEUDxUMSwgVDIsIFQzPihJRW51bWVyYWJsZTxUMT4gc2V0MSwgSUVudW1lcmFibGU8VDI+IHNldDIsIElFbnVtZXJhYmxlPFQzPiBzZXQzKQoJCXsKCQkJZm9yZWFjaCAodmFyIGl0ZW0xIGluIHNldDEpCgkJCXsKCQkJCWZvcmVhY2ggKHZhciBpdGVtMiBpbiBzZXQyKQoJCQkJewoJCQkJCWZvcmVhY2ggKHZhciBpdGVtMyBpbiBzZXQzKQoJCQkJCXsKCQkJCQkJeWllbGQgcmV0dXJuIFR1cGxlLkNyZWF0ZShpdGVtMSwgaXRlbTIsIGl0ZW0zKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgoJCXN0YXRpYyBJRW51bWVyYWJsZTxUdXBsZTxUMSwgVDIsIFQzLCBUND4+IERQPFQxLCBUMiwgVDMsIFQ0PihJRW51bWVyYWJsZTxUMT4gc2V0MSwgSUVudW1lcmFibGU8VDI+IHNldDIsIElFbnVtZXJhYmxlPFQzPiBzZXQzLCBJRW51bWVyYWJsZTxUND4gc2V0NCkKCQl7CgkJCWZvcmVhY2ggKHZhciBpdGVtMSBpbiBzZXQxKQoJCQl7CgkJCQlmb3JlYWNoICh2YXIgaXRlbTIgaW4gc2V0MikKCQkJCXsKCQkJCQlmb3JlYWNoICh2YXIgaXRlbTMgaW4gc2V0MykKCQkJCQl7CgkJCQkJCWZvcmVhY2ggKHZhciBpdGVtNCBpbiBzZXQ0KQoJCQkJCQl7CgkJCQkJCQl5aWVsZCByZXR1cm4gVHVwbGUuQ3JlYXRlKGl0ZW0xLCBpdGVtMiwgaXRlbTMsIGl0ZW00KTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCgkJc3RhdGljIElFbnVtZXJhYmxlPFR1cGxlPFQxLCBUMiwgVDMsIFQ0LCBUNT4+IERQPFQxLCBUMiwgVDMsIFQ0LCBUNT4oSUVudW1lcmFibGU8VDE+IHNldDEsIElFbnVtZXJhYmxlPFQyPiBzZXQyLCBJRW51bWVyYWJsZTxUMz4gc2V0MywgSUVudW1lcmFibGU8VDQ+IHNldDQsIElFbnVtZXJhYmxlPFQ1PiBzZXQ1KQoJCXsKCQkJZm9yZWFjaCAodmFyIGl0ZW0xIGluIHNldDEpCgkJCXsKCQkJCWZvcmVhY2ggKHZhciBpdGVtMiBpbiBzZXQyKQoJCQkJewoJCQkJCWZvcmVhY2ggKHZhciBpdGVtMyBpbiBzZXQzKQoJCQkJCXsKCQkJCQkJZm9yZWFjaCAodmFyIGl0ZW00IGluIHNldDQpCgkJCQkJCXsKCQkJCQkJCWZvcmVhY2ggKHZhciBpdGVtNSBpbiBzZXQ1KQoJCQkJCQkJewoJCQkJCQkJCXlpZWxkIHJldHVybiBUdXBsZS5DcmVhdGUoaXRlbTEsIGl0ZW0yLCBpdGVtMywgaXRlbTQsIGl0ZW01KTsKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCX0KfQo=