Напишите алгоритм, проверяющий, может ли данная строка, s, быть сформирована из двух других строк, part1 и part2.

Ограничение состоит в том, что символы в part1 и part2 находятся в том же порядке, что и в 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

0
ArchAngel 26 Окт 2015 в 13:08

3 ответа

Лучший ответ

Я думаю, что это должно соответствовать требованиям, хотя вы можете переписать его, чтобы избежать создания строк повсюду.

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;
}
2
Kvam 26 Окт 2015 в 11:45

Мои 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);
}
0
codersl 26 Окт 2015 в 13:21

Вот мои 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;
}
0
Max 26 Окт 2015 в 11:36