Недостаточно памяти при поиске продуктов и простых чисел - PullRequest
1 голос
/ 24 ноября 2010

Итак, я написал быстрое приложение, чтобы проверить домашнее задание моего сына, и, похоже, оно работает нормально.Он принимает число, находит все простые числа, а затем находит все комбинации продуктов.Так, например, вы передаете ему «210», и он вернет:2 х 3 х 5 х 75 х 6 х 77 х 306 х 355 х 423 х 7 х 1010 х 213 х 703 х 5 х 1414 х 152 х 7 х 152 х 1052 х 5 х 212 х 3 х 35

Проблема, которую я имею, состоит в том, чтобы делать большие числа.Он будет обрабатывать 256 (2 ^ 8) только после минутного колебания, но когда я делаю 512 (2 ^ 9), я получаю исключение OutOfMemoryException.Кто-то может порекомендовать лучший способ найти наборы продуктов?Мой код ниже.

class Program
{
    private static List<List<int>> coll = new List<List<int>>();

    public static List<int> PrimeFactors(int i)
    {
        if (i < 2)
        {
            throw new ArgumentOutOfRangeException("Numbers less than 2 don't have prime factors");
        }

        List<int> result = new List<int>();

        int divisor = 2;

        while (divisor <= i)
        {
            if (i % divisor == 0)
            {
                result.Add(divisor);
                i /= divisor;
            }
            else
            {
                divisor++;
            }
        }

        return result;
    }

    private static void GetFactors(List<int> l)
    {
        for (int i = 0; i < l.Count - 1; i++)
        {
            for (int x = i + 1; x < l.Count; x++)
            {
                List<int> loopList = new List<int>(l);
                int newProd = l[i] * l[x];
                loopList.RemoveAt(i);
                loopList.RemoveAt(x-1);
                loopList.Add(newProd);
                loopList.Sort();
                coll.Add(loopList);
                if (loopList.Count > 2)
                {
                    GetFactors(loopList);
                }
            }
        }
    }

    static void Main(string[] args)
    {
        int target = Convert.ToInt16(args[0]);
        List<int> results = PrimeFactors(target);
        results.Sort();
        coll.Add(results);
        GetFactors(results);
        List<string> factors = new List<string>();
        foreach (List<int> lst in coll)
        {
            string listString = "";
            for (int i = 0; i < lst.Count; i++)
            {
                if (i == lst.Count - 1)
                {
                    listString += String.Format("{0}", lst[i]);
                }
                else
                {
                    listString += String.Format("{0} x ", lst[i]);
                }
            }
            factors.Add(listString);
        }

        foreach (String factorString in factors.Select(x => x).Distinct())
        {
            Console.WriteLine(factorString);
        }
    }
}

РЕДАКТИРОВАТЬ: Вот новый код, основанный на ответах ниже.Работает для любого Int16, который я кидаю.

    class Program
{
    private static List<List<int>> coll = new List<List<int>>();

    public static List<int> PrimeFactors(int i)
    {
        if (i < 2)
        {
            throw new ArgumentOutOfRangeException("Numbers less than 2 don't have prime factors");
        }

        List<int> result = new List<int>();

        int divisor = 2;

        while (divisor <= i)
        {
            if (i % divisor == 0)
            {
                result.Add(divisor);
                i /= divisor;
            }
            else
            {
                divisor++;
            }
        }

        return result;
    }

    private static void GetFactors(List<int> l)
    {
        for (int i = 0; i < l.Count - 1; i++)
        {
            for (int x = i + 1; x < l.Count; x++)
            {
                List<int> loopList = new List<int>(l);
                int newProd = l[i] * l[x];
                loopList.RemoveAt(i);
                loopList.RemoveAt(x-1);
                loopList.Add(newProd);
                bool existsInCollection = false;
                foreach (List<int> existingList in coll)
                {
                    if (ListEquality(existingList, loopList))
                    {
                        existsInCollection = true;
                        break;
                    }
                }
                if (!existsInCollection)
                {
                    coll.Add(loopList);
                    if (loopList.Count > 2)
                    {
                        GetFactors(loopList);
                    }
                }
            }
        }
    }

    private static bool ListEquality(List<int> listA, List<int> listB)
    {
        if (listA.Count != listB.Count)
            return false;

        listA.Sort();
        listB.Sort();

        for (int idx = 0; idx < listA.Count; idx++)
        {
            if (listA[idx] != listB[idx])
                return false;
        }
        return true;
    }

    static void Main(string[] args)
    {
        int target = Convert.ToInt16(args[0]);
        List<int> results = PrimeFactors(target);
        results.Sort();
        coll.Add(results);
        GetFactors(results);
        foreach (List<int> lst in coll)
        {
            string listString = "";
            for (int i = 0; i < lst.Count; i++)
            {
                if (i == lst.Count - 1)
                {
                    listString += String.Format("{0}", lst[i]);
                }
                else
                {
                    listString += String.Format("{0} x ", lst[i]);
                }
            }
            Console.WriteLine(listString);
        }
    }
}

Еще раз спасибо всем.

1 Ответ

2 голосов
/ 24 ноября 2010

Есть много вещей, которые могли бы быть лучше с этой программой.

Вот некоторые из них:

  • Не используйте глобальный (coll)
  • Не используйте неправильные имена переменных (i, l, x)
  • Не используйте List<int>, когда int [] будет работать так же или лучше.
  • Используйте join для распечатки вашего списка.

Некоторые вещи, которые могли бы сделать эту программу быстрее

  • Не повторять, повторять.(Подсказка - поможет объект абстрактного стека или объект абстрактного множества.)
  • Не сортируйте так много, это не должно иметь значения и фактически может замедлить работу.
  • Сократите временное хранилище какВы идете - ожидание до конца, чтобы сделать отличное, просто означает, что вы сделали ПУТЬ К МНОГОМУ одной и той же вещи несколько раз.Прежде чем добавить его в коллекцию, проверьте, есть ли он там.
...