合并字符串检查器(自定义规则)

时间:2015-10-26 10:08:28

标签: c# string algorithm

编写算法以检查给定字符串s是否可以由其他两个字符串part1part2组成。

限制是part1part2中的字符与s中的字符顺序相同。

示例:

'codewars' is a merge from 'cdw' and 'oears':

s:  c o d e w a r s   = codewars
part1:  c   d   w         = cdw
part2:    o   e   a r s   = oears

但是在测试案例中,要让它起作用并不容易......

规则说它们必须是相同的长度和相同的顺序,但随机测试用例,它们也是随机排列的。 所以这些规则与规则冲突,我怎样才能使它发挥作用?

遵循规则的测试用例:

[Test]
public void SadPath2()
{
    Assert.IsFalse(StringMerger.isMerge("codewars", "code", "wasr"), "Codewars can't be created from code and wasr");
}
SadPath2 == false;

[Test]
public void SadPath1()
{
    Assert.IsFalse(StringMerger.isMerge("codewars", "cod", "wars"), "Codewars are not codwars");
}
SadPath1 == false;

[Test]
public void HappyPath2()
{
     Assert.IsTrue(StringMerger.isMerge("codewars", "cdwr", "oeas"), "codewars can be created from cdwr and oeas");
}
HappyPath2 == true;

[Test]
public void HappyPath1()
{
     Assert.IsTrue(StringMerger.isMerge("codewars", "code", "wars"), "codewars can be created from code and wars");
}
HappyPath1 == true;

一些可能完全不符合规则的随机测试:

[Test]
public void RandomTest()
{
    Assert.IsTrue(StringMerger.isMerge("[W`meSnw(R1qaLLqc[=]=UAvTa_3%", "W`mnwqaLL]=va%", "[eS(R1qc[=UAT_3"), "'[W`meSnw(R1qaLLqc[=]=UAvTa_3%' is a merge of 'W`mnwqaLL]=va%' and '[eS(R1qc[=UAT_3'");
}    
RandomTest == true;

[Test]
public void RandomTest2()
{
    Assert.IsTrue(StringMerger.isMerge("]ftUNn7-XoX4AZ3i1+", "U7oX4A1+", "]ftNn-XZ3i"), "']ftUNn7-XoX4AZ3i1+' is a merge of 'U7oX4A1+' and ']ftNn-XZ3i");
}
RandomTest2 == true;

我班上的第一个例子,它可以成功运行除SadPath2以外的所有测试:

public class StringMerger
{
    public static bool isMerge(string s, string part1, string part2)
    {
        int num = 0;
        string txt1 = "";
        Console.WriteLine("S - " + s + " - P1 - " + part1 + " - P2 - " + part2);

        #region Sorting
        foreach (var itm in s)
        {
            if (part1.Contains(itm.ToString()))
                num++;
            else if (part2.Contains(itm.ToString()))
                num++;
        }
        #endregion

        if (num == s.Length && num == (part1.Length + part2.Length))
                return true;


        return false;
    }
}

enter image description here

除了随机测试之外它可以运行的第二个例子:

public class StringMerger
{
    public static bool isMerge(string s, string part1, string part2)
    {
        int num = 0;
        int P1 = 0;
        int P2 = 0;
        bool p2 = false;
        string txt1 = "";

        #region Sorting
        foreach (var itm in s)
        {
            if (part1.Contains(itm.ToString()))
                num++;
            else if (part2.Contains(itm.ToString()))
                num++;

            try
            {
                if (p2 == false)
                {
                    txt1 = txt1 + GetLetterP1(part1, itm.ToString(), P1);
                    P1++;
                    p2 = true;
                }
                else
                {
                    txt1 = txt1 + GetLetterP2(part2, itm.ToString(), P2);
                    P2++;
                    p2 = false;
                }
            }
            catch { }
        }
        #endregion

        if (num == s.Length && num == (part1.Length + part2.Length))
        {
            if (s.Contains(part1 + part2))
                return true;
            else if (txt1 == s)
                return true;
        }


        return false;
    }

    static string GetLetterP1(string p1, string letter, int n)
    {
        string itm = "";
        if (p1.Contains(letter))
            itm = p1[n].ToString();
        return itm;
    }

    static string GetLetterP2(string p2, string letter, int n)
    {
        string itm = "";
        if (p2.Contains(letter))
            itm = p2[n].ToString();
        return itm;
    }
}

enter image description here

Kvam回答结果:(使用最新修补程序)

enter image description here

结果Max答案:(使用最新修订)

enter image description here

结果codersl答案:(使用最新修订)

enter image description here

3 个答案:

答案 0 :(得分:2)

我认为这应该涵盖了这些要求,尽管您可能希望重写它以避免全部创建字符串。

public bool IsMatch(string target, string part1, string part2)
{
    if (target.Length != part1.Length + part2.Length)
    {
        return false;
    }
    if (target == "")
    {
        return true;
    }

    if (part1.Length > 0 && target[0] == part1[0])
    {
        if (IsMatch(target.Substring(1), part1.Substring(1), part2.Substring(0)))
        {
            return true;
        }
    }
    if (part2.Length > 0 && target[0] == part2[0])
    {
        if (IsMatch(target.Substring(1), part1.Substring(0), part2.Substring(1)))
        {
            return true;
        }
    }

    return false;
}

答案 1 :(得分:0)

这里是我的2美分

public bool IsMerge(string target, string part1, string part2)
{
    if (String.IsNullOrEmpty(target))
    {
        throw new ArgumentNullException("target");
    }

    if (String.IsNullOrEmpty(part1))
    {
        throw new ArgumentNullException("part1");
    }

    if (String.IsNullOrEmpty(part2))
    {
        throw new ArgumentNullException("part2");
    }

    if (target.Length == (part1.Length + part2.Length))
    {
        return this.IsPart(target, part1) && this.IsPart(target, part2);
    }

    return false;
}

private bool IsPart(string target, string part)
{
    int idx = -1;
    int lastIdx = 0;

    for (int i = 0; i < part.Length; i++)
    {
        idx = (target.IndexOf(part[i], lastIdx));
        if (!(idx > -1))
        {
            return false;
        }

        lastIdx = idx;
    }

    return true;
}

答案 2 :(得分:0)

我的2美分

public static void Main()
{
    Console.WriteLine(Check("codewars", "code", "wasr")); //false
    Console.WriteLine(Check("codewars", "cod", "wars")); //false
    Console.WriteLine(Check("codewars", "cdwr", "oeas"));
    Console.WriteLine(Check("codewars", "code", "wars"));
    Console.WriteLine(Check("[W`meSnw(R1qaLLqc[=]=UAvTa_3%", "W`mnwqaLL]=va%", "[eS(R1qc[=UAT_3"));
    Console.WriteLine(Check("]ftUNn7-XoX4AZ3i1+", "U7oX4A1+", "]ftNn-XZ3i"));
    Console.WriteLine(Check("acab", "ab", "ac"));
    Console.WriteLine(Check("b]aDw- !oKJnOJ", "b]aDwoKJ", "- !nOJ"));
    Console.WriteLine(Check("codewars", "codewarss", "")); //false
    Console.WriteLine(Check("codewars", "", "")); //false
    Console.WriteLine(Check("codewars", "codewars", null));
    Console.WriteLine(Check("Bananas from Bahamas", "Bahas", "Bananas from am"));
}

private static bool Check(string s, string part1, string part2)
{
    if (part1 == null)
        part1 = "";

    if (part2 == null)
        part2 = "";

    var part1Index = 0;
    var part2Index = 0;
    var bothMatch = "";

    foreach(var c in s)
    {
        // handle both strings matching
        if (part1Index < part1.Length && part2Index < part2.Length && c == part1[part1Index] && c == part2[part2Index])
        {
            bothMatch += c;
            part1Index++;
            part2Index++;
            continue;
        }

        if (bothMatch.Length > 0 && c == part1[part1Index])
        {
            // part2 doesn't match anymore so roll back its index
            part2Index -= bothMatch.Length;
            bothMatch = "";
        }
        else if (bothMatch.Length > 0 && c == part2[part2Index])
        {
            // part1 doesn't match anymore so roll back its index
            part1Index -= bothMatch.Length;
            bothMatch = "";
        }

        // handle one string matching
        if (part1Index < part1.Length && c == part1[part1Index])
        {
            //Console.WriteLine("c={0}, p1={1}", c, part1[part1Index]);
            part1Index++;
            continue;
        }
        if (part2Index < part2.Length && c == part2[part2Index])
        {
            //Console.WriteLine("c={0}, p2={1}", c, part2[part2Index]);
            part2Index++;
            continue;
        }

        //Console.WriteLine("c={0}, p1={1}, p2={2}, both={3}", c, part1[part1Index], part2[part2Index], bothMatch);
        return false;
    }
    return (part1Index == part1.Length) && (part2Index == part2.Length);
}