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+[^ab])*[^a]*a*$
// であってるのかテスト
//
string ng_word2 = "ab";
Regex regex2 = new Regex(@"^([^a]*a+[^ab])*[^a]*a*$");
Test(regex2, ng_word2);
}
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++44GvCgkJCS8vIF4oW15hXSphK1teYWJdKSpbXmFdKmEqJAoJCQkvLyDjgafjgYLjgaPjgabjgovjga7jgYvjg4bjgrnjg4gKCQkJLy8KCQkJc3RyaW5nIG5nX3dvcmQyID0gImFiIjsKCQkJUmVnZXggcmVnZXgyID0gbmV3IFJlZ2V4KEAiXihbXmFdKmErW15hYl0pKlteYV0qYSokIik7CgkJCVRlc3QocmVnZXgyLCBuZ193b3JkMik7CgkJfQoKCQlzdGF0aWMgdm9pZCBUZXN0KFJlZ2V4IHJlZ2V4LCBzdHJpbmcgbmdfd29yZCkKCQl7CgkJCS8vIGHjgYvjgol6CgkJCXZhciBhMnogPSBFbnVtZXJhYmxlLlJhbmdlKDAsIDI2KS5TZWxlY3QoaXQgPT4gQ29udmVydC5Ub0NoYXIoJ2EnICsgaXQpKTsKCgkJCS8vIOS7u+aEj+OBrjLmloflrZfjgafjg4bjgrnjg4gKCQkJU3RyaW5nQnVpbGRlciBzYiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7CgkJCWZvcmVhY2ggKHZhciBpdGVtIGluIERQKGEyeiwgYTJ6KSkKCQkJewoJCQkJc2IuQ2xlYXIoKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0xKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0yKTsKCgkJCQlzdHJpbmcgaW5wdXQgPSBzYi5Ub1N0cmluZygpOwoJCQkJVGVzdChpbnB1dCwgcmVnZXgsIG5nX3dvcmQpOwoJCQl9CgoJCQkvLyDku7vmhI/jga4z5paH5a2X44Gn44OG44K544OICgkJCWZvcmVhY2ggKHZhciBpdGVtIGluIERQKGEyeiwgYTJ6LCBhMnopKQoJCQl7CgkJCQlzYi5DbGVhcigpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTEpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTIpOwoJCQkJc2IuQXBwZW5kKGl0ZW0uSXRlbTMpOwoKCQkJCXN0cmluZyBpbnB1dCA9IHNiLlRvU3RyaW5nKCk7CgkJCQlUZXN0KGlucHV0LCByZWdleCwgbmdfd29yZCk7CgkJCX0KCgkJCS8vIOS7u+aEj+OBrjTmloflrZfjgafjg4bjgrnjg4gKCQkJZm9yZWFjaCAodmFyIGl0ZW0gaW4gRFAoYTJ6LCBhMnosIGEyeiwgYTJ6KSkKCQkJewoJCQkJc2IuQ2xlYXIoKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0xKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0yKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0zKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW00KTsKCgkJCQlzdHJpbmcgaW5wdXQgPSBzYi5Ub1N0cmluZygpOwoJCQkJVGVzdChpbnB1dCwgcmVnZXgsIG5nX3dvcmQpOwoJCQl9CgoJCQkvLyDku7vmhI/jga415paH5a2X44Gn44OG44K544OICgkJCWZvcmVhY2ggKHZhciBpdGVtIGluIERQKGEyeiwgYTJ6LCBhMnosIGEyeiwgYTJ6KSkKCQkJewoJCQkJc2IuQ2xlYXIoKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0xKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0yKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW0zKTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW00KTsKCQkJCXNiLkFwcGVuZChpdGVtLkl0ZW01KTsKCgkJCQlzdHJpbmcgaW5wdXQgPSBzYi5Ub1N0cmluZygpOwoJCQkJVGVzdChpbnB1dCwgcmVnZXgsIG5nX3dvcmQpOwoJCQl9CgoJCQlDb25zb2xlLldyaXRlTGluZSgiPT09PT0gUEFTUyEgTkctd29yZDogezB9ID09PT09Iiwgbmdfd29yZCk7CgkJfQoKCQlzdGF0aWMgdm9pZCBUZXN0KHN0cmluZyBpbnB1dCwgUmVnZXggcmVnZXgsIHN0cmluZyBuZykKCQl7CgkJCWJvb2wgYWN0dWFsID0gcmVnZXguSXNNYXRjaChpbnB1dCk7CgkJCWJvb2wgZXhwZWN0ZWQgPSAhaW5wdXQuQ29udGFpbnMobmcpOwoJCQlpZiAoYWN0dWFsICE9IGV4cGVjdGVkKQoJCQl7CgkJCQlzdHJpbmcgZXJyTXNnID0gc3RyaW5nLkZvcm1hdCgiYXNzZXJ0aW9uIGZhaWx1cmUhIGlucHV0OiB7MH0sIHJlZ2V4OiB7MX0sIE5HLXdvcmQ6IHsyfSIsIGlucHV0LCByZWdleC5Ub1N0cmluZygpLCBuZyk7CgkJCQl0aHJvdyBuZXcgRXhjZXB0aW9uKGVyck1zZyk7CgkJCX0KCQl9CgoJCXN0YXRpYyBJRW51bWVyYWJsZTxUdXBsZTxUMSwgVDI+PiBEUDxUMSwgVDI+KElFbnVtZXJhYmxlPFQxPiBzZXQxLCBJRW51bWVyYWJsZTxUMj4gc2V0MikKCQl7CgkJCWZvcmVhY2ggKHZhciBpdGVtMSBpbiBzZXQxKQoJCQl7CgkJCQlmb3JlYWNoICh2YXIgaXRlbTIgaW4gc2V0MikKCQkJCXsKCQkJCQl5aWVsZCByZXR1cm4gVHVwbGUuQ3JlYXRlKGl0ZW0xLCBpdGVtMik7CgkJCQl9CgkJCX0KCQl9CgoJCXN0YXRpYyBJRW51bWVyYWJsZTxUdXBsZTxUMSwgVDIsIFQzPj4gRFA8VDEsIFQyLCBUMz4oSUVudW1lcmFibGU8VDE+IHNldDEsIElFbnVtZXJhYmxlPFQyPiBzZXQyLCBJRW51bWVyYWJsZTxUMz4gc2V0MykKCQl7CgkJCWZvcmVhY2ggKHZhciBpdGVtMSBpbiBzZXQxKQoJCQl7CgkJCQlmb3JlYWNoICh2YXIgaXRlbTIgaW4gc2V0MikKCQkJCXsKCQkJCQlmb3JlYWNoICh2YXIgaXRlbTMgaW4gc2V0MykKCQkJCQl7CgkJCQkJCXlpZWxkIHJldHVybiBUdXBsZS5DcmVhdGUoaXRlbTEsIGl0ZW0yLCBpdGVtMyk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoKCQlzdGF0aWMgSUVudW1lcmFibGU8VHVwbGU8VDEsIFQyLCBUMywgVDQ+PiBEUDxUMSwgVDIsIFQzLCBUND4oSUVudW1lcmFibGU8VDE+IHNldDEsIElFbnVtZXJhYmxlPFQyPiBzZXQyLCBJRW51bWVyYWJsZTxUMz4gc2V0MywgSUVudW1lcmFibGU8VDQ+IHNldDQpCgkJewoJCQlmb3JlYWNoICh2YXIgaXRlbTEgaW4gc2V0MSkKCQkJewoJCQkJZm9yZWFjaCAodmFyIGl0ZW0yIGluIHNldDIpCgkJCQl7CgkJCQkJZm9yZWFjaCAodmFyIGl0ZW0zIGluIHNldDMpCgkJCQkJewoJCQkJCQlmb3JlYWNoICh2YXIgaXRlbTQgaW4gc2V0NCkKCQkJCQkJewoJCQkJCQkJeWllbGQgcmV0dXJuIFR1cGxlLkNyZWF0ZShpdGVtMSwgaXRlbTIsIGl0ZW0zLCBpdGVtNCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgoJCXN0YXRpYyBJRW51bWVyYWJsZTxUdXBsZTxUMSwgVDIsIFQzLCBUNCwgVDU+PiBEUDxUMSwgVDIsIFQzLCBUNCwgVDU+KElFbnVtZXJhYmxlPFQxPiBzZXQxLCBJRW51bWVyYWJsZTxUMj4gc2V0MiwgSUVudW1lcmFibGU8VDM+IHNldDMsIElFbnVtZXJhYmxlPFQ0PiBzZXQ0LCBJRW51bWVyYWJsZTxUNT4gc2V0NSkKCQl7CgkJCWZvcmVhY2ggKHZhciBpdGVtMSBpbiBzZXQxKQoJCQl7CgkJCQlmb3JlYWNoICh2YXIgaXRlbTIgaW4gc2V0MikKCQkJCXsKCQkJCQlmb3JlYWNoICh2YXIgaXRlbTMgaW4gc2V0MykKCQkJCQl7CgkJCQkJCWZvcmVhY2ggKHZhciBpdGVtNCBpbiBzZXQ0KQoJCQkJCQl7CgkJCQkJCQlmb3JlYWNoICh2YXIgaXRlbTUgaW4gc2V0NSkKCQkJCQkJCXsKCQkJCQkJCQl5aWVsZCByZXR1cm4gVHVwbGUuQ3JlYXRlKGl0ZW0xLCBpdGVtMiwgaXRlbTMsIGl0ZW00LCBpdGVtNSk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9Cgl9Cn0K