有简单的密码转换号系列 . ( )

为了 加密 一号(0..2147483647),以此表示,我(think I)需要:

  • 总理因式分解
  • 对于给定 p (p 是Prime),以顺序的p(ie。 PrimeOrd(2) == 0, PrimeOrd(227) == 49)

一些实例

    0   .                  6    (()())
    1   ()                 7    (...())
    2   (())               8    ((.()))
    3   (.())              9    (.(()))
    4   ((()))            10    (().())
    5   (..())            11    (....())
    227 (................................................())
    2147483648    ((..........()))

我源代码问题


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

static class P
{
    static List<int> _list = new List<int>();

    public static int Nth(int n)
    {
        if (_list.Count == 0 || _list.Count < n)
            Primes().Take(n + 1);

        return _list[n];
    }

    public static int PrimeOrd(int prime)
    {
        if (_list.Count == 0 || _list.Last() < prime)
            Primes().First(p => p >= prime);

        return (_list.Contains(prime)) ? _list.FindIndex(p => p == prime) : -1;
    }

    public static List<int> Factor(int N)
    {
        List<int> ret = new List<int>();
        for (int i = 2; i ≤ N; i++)
            while (N % i == 0)
            {
                N /= i;
                ret.Add(i);
            }

        return ret;
    }

    public static IEnumerable<int> Primes()
    {
        _list = new List<int>();

        _list.Add(2);
        yield return 2;

        Func<int, bool> IsPrime = n => _list.TakeWhile(p => p ≤ (int)Math.Sqrt(n)).FirstOrDefault(p => n % p == 0) == 0;

        for (int i = 3; i < Int32.MaxValue; i += 2)
        {
            if (IsPrime(i))
            {
                _list.Add(i);
                yield return i;
            }
        }
    }

    public static string Convert(int n)
    {
        if (n == 0) return ".";
        if (n == 1) return "()";

        StringBuilder sb = new StringBuilder();
        var p = Factor(n);
        var max = PrimeOrd(p.Last());
        for (int i = 0; i ≤ max; i++)
        {
            var power = p.FindAll((x) => x == Nth(i)).Count;
            sb.Append(Convert(power));
        }
        return "(" + sb.ToString() + ")";
    }
}

class Program
{
    static void Main(string[] args)
    {
        string line = Console.ReadLine();
        try
        {
            int num = int.Parse(line);
            Console.WriteLine("{0}: '{1}'", num, P.Convert(num));
        }
        catch
        {
            Console.WriteLine("You didn't entered number!");
        }
    }
}

问题是缓慢的过程PrimeOrd.你知道一些更快的解决方案找出了总理于素数的?

标题

如果你知道如何加速找到了总理数量,请,建议一些东西。:-)

谢谢你。


P.S.最大的首要小于2,147,483,648是 2,147,483,647 和它的 105,097,565个 总理。没有必要期望更大数量超过2^31.

有帮助吗?

解决方案

你应该高速缓存的数以_list然后用这两个因素和PrimeOrd.此外避免运营商经营皇宫像TakeWhile,创造价值,你扔掉。

这里有一个优化的版本:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

static class P
{
    private static List<int> _list = new List<int>();

    public static int Nth(int n)
    {
        if (_list.Count == 0 || _list.Count <= n)
        {
            GenerateNextPrimes().First(p => _list.Count >= n);            
        }

        return _list[n];
    }

    public static int PrimeOrd(int prime)
    {
        var primes = GrowPrimesTo(prime);
        return primes.IndexOf(prime);
    }

    public static List<int> Factor(int N)
    {
        List<int> ret = new List<int>();        
        GrowPrimesTo(N);

        for (int ixDivisor = 0; ixDivisor < _list.Count; ixDivisor++)
        {
            int currentDivisor = _list[ixDivisor];

            while (N % currentDivisor == 0)
            {
                N /= currentDivisor;
                ret.Add(currentDivisor);
            }

            if (N <= 1)
            {
                break;
            }
        }

        return ret;
    }

    private static List<int> GrowPrimesTo(int max)
    {
        if (_list.LastOrDefault() >= max)
        {
            return _list;
        }

        GenerateNextPrimes().First(prime => prime >= max);
        return _list;        
    }

    private static IEnumerable<int> GenerateNextPrimes()
    {
        if (_list.Count == 0)
        {
            _list.Add(2);
            yield return 2;
        }

        Func<int, bool> IsPrime =
            n =>
            {
                // cache upperBound
                int upperBound = (int)Math.Sqrt(n);
                for (int ixPrime = 0; ixPrime < _list.Count; ixPrime++)
                {
                    int currentDivisor = _list[ixPrime];
                    if (currentDivisor > upperBound)
                    {
                        return true;
                    }

                    if ((n % currentDivisor) == 0)
                    {
                        return false;
                    }
                }

                return true;
            };

        // Always start on next odd number
        int startNum = _list.Count == 1 ? 3 : _list[_list.Count - 1] + 2;
        for (int i = startNum; i < Int32.MaxValue; i += 2)
        {
            if (IsPrime(i))
            {
                _list.Add(i);
                yield return i;
            }
        }
    }

    public static string Convert(int n)
    {
        if (n == 0) return ".";
        if (n == 1) return "()";

        StringBuilder sb = new StringBuilder();
        var p = Factor(n);
        var max = PrimeOrd(p.Last());
        for (int i = 0; i <= max; i++)
        {
            var power = p.FindAll(x => x == Nth(i)).Count;
            sb.Append(Convert(power));
        }
        return "(" + sb.ToString() + ")";
    }
}

class Program
{
    static void Main(string[] args)
    {        
        string line = Console.ReadLine();
        int num;

        if(int.TryParse(line, out num))
        {   
            Console.WriteLine("{0}: '{1}'", num, P.Convert(num));             
        }
        else
        {
            Console.WriteLine("You didn't entered number!");
        }
    }
}

其他提示

这不是你应该做的,在运行时间。一个更好的选择是预先计算所有这些素,然后把它们放在你的程序中以某种方式(一个静态阵列,或者文件的可读)。缓慢的代码然后运行的一部分作为发展进程(这是缓慢的,反正:-), 在你需要你的速度。

那么它只是一个问题,查找某种形式的而不是计算他们的每一次你需要他们。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top