【问题标题】:Sum of Numbers as Distinct Primes作为不同素数的数字总和
【发布时间】:2016-09-13 05:41:24
【问题描述】:
//List Style


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


public class pr{

    static public void Main (){

            int n, i, j, k, l, sum,flag = 0;
            //int sum = i+j;
            //int k = (n-i);
            //int l = (n-j);

            //System.Console.WriteLine ("Enter a number");
            //n = Convert.ToInt32 (Console.ReadLine());

            //List <int> primes = new List <int>(); //list to handle the numbers
            //HashSet <int> myPrimes = new HashSet <int> (primes);


                 System.Console.WriteLine ("Enter a number");
                 n = Convert.ToInt32 (Console.ReadLine());
                 //myPrimes.Add(n);
                 //myPrimes.Add(i);
                 //myPrimes.Add(j);

                // var count = string.Join(", ", primes);
                  //System.Console.WriteLine("The value of n is {0}",myPrimes);

                    for(i=3; i<n/2; i++){

                        for(j=3; j<n/2; j++){

                            if(checkPrime(i) == 1){

                                if(checkPrime(j) == 1){

                                    if (checkPrime(n-i) == 1){

                                        if (checkPrime(n-j) == 1){

                                                //if(i == j){
                                                //sum = i+j;


                                            System.Console.WriteLine("{0}={1}+{2}\n",n,i,n-i);
                                        //}

                                    }
                                }
                            }
                        }

                            if (flag == 0 && (n-i) <= 0 && (n-j) <= 0){ //check to avoid dupes

                                    if (n <= 0 && i <= 0 && j <= 0){

                                        Console.Write("{0}\n",n);
                                    }


                            }


                        }
                    }

    }

            public static int checkPrime(int n){

                int i, j, flag = 1;

                for (i = 2; i<=(Math.Sqrt(n)); i++){ 

                    for (j = 2; j<=(Math.Sqrt(n)); j++){


                        if (n%i == 0 && n%j == 0 ){ //even number check

                                i++;
                                j++;
                                flag = 0;
                    } 

                }

            }

                return flag;
            }






}

所以我已经尝试了一段时间了。我似乎无法打印所有可能的解决方案。例如对于 24,我可以打印 7+17 但不能打印 2+5+17。还有一些答案被重复,这可能与我没有重复检查的事实有关。我尝试将整数推送到列表中,然后使用哈希集来仅具有不同的整数,但我被卡住并试图暴力破解它。所有要打印的数字都应该是不同的素数。我不明白如何打印所有不同的数字,是否有一种优雅的方式可以打印出所有可能的数字。

感谢您的帮助!

【问题讨论】:

  • 你能检查你的代码吗?似乎括号没有正确关闭
  • 更好的缩进也有很大帮助!

标签: c# algorithm primes


【解决方案1】:

不知道它对你来说是否足够优雅,但我只是捣碎了一种肮脏的方式来让它发挥作用:

static void Main()
    {
        Console.WriteLine("Enter a number");
        var numberToSum = Convert.ToInt32(Console.ReadLine());

        var primesInRange = GetPrimesUpTo(numberToSum);
        var foundSolutions = primesInRange.SubSetsOf().Where(prime => prime.Sum() == numberToSum);

        foreach (var solution in foundSolutions.ToList())
        {
            var formatOperation = solution
                .Select(x => x.ToString())
                .Aggregate((a, n) => a + " + " + n) + " = " + numberToSum;

            Console.WriteLine(formatOperation);
        }

        Console.ReadLine();
    }

    public static IEnumerable<int> GetPrimesUpTo(int end)
    {
        var primes = new HashSet<int>();

        for (var i = 2; i <= end; i++)
        {
            var ok = true;

            foreach (var prime in primes)
            {
                if (prime * prime > i)
                    break;

                if (i % prime == 0)
                {
                    ok = false;
                    break;
                }
            }

            if (ok)
                primes.Add(i);
        }

        return primes;
    }

    public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(this IEnumerable<T> source)
    {
        if (!source.Any())
            return Enumerable.Repeat(Enumerable.Empty<T>(), 1);

        var element = source.Take(1);

        var haveNots = SubSetsOf(source.Skip(1));
        var haves = haveNots.Select(set => element.Concat(set));

        return haves.Concat(haveNots);
    }

我发现您的解决方案非常肮脏,因此我将问题划分为更易于理解。 GetPrimesUpTo 返回从 2 到您在输入中提供的数字的所有素数,SubSetsOf 返回总和等于您提供的输入数字的数字组合,最后 Main 中的 foreach 生成易于格式化的输出。希望对您有所帮助!

【讨论】:

  • 好的,我知道我现在在实施中出了什么问题。我试图添加“n”。我只是对 2 种不同的解决方案进行暴力破解,而不是计算其余的解决方案。您能否为我解释一下您的解决方案的最后过去。从“public static IEnumerable> SubSetsOf(this IEnumerable source)”开始,我想使用我的版本复制它。
  • 它需要一个项目列表并使用递归来返回它的每个可能的子集,即:如果你提供一个素数数组 [2, 3, 5] 它将产生 [2, 3, 5] , [2, 3], [2, 5], [2], [3, 5], [3]。有了这些信息,我们可以将它们中的每一个相加,并与我们想要获得的值进行比较。这些将是可能的解决方案。它远非最佳,但我能做到的最不言自明。你现在明白了吗?
  • 是的,现在有点道理。抱歉,我基本上是从一周左右开始用 C# 编码的。但是从查看我的代码来看,除了整个不同的质数部分之外,是否还有任何明显的错误或问题。我将尝试根据此处提供的信息在我的代码中尽可能多地实现,因为我必须用其他语言重复此任务。
  • 当你有一个像你的样本一样的嵌套结构时(for -> for -> if -> if -> if -> if)你可以 100% 确定有些事情是不对的。没有人可以遵循这个逻辑,这在所有语言中都是非常糟糕的做法。这里没有足够的地方,所以我会添加另一个回复并提供更多信息。
【解决方案2】:

假设你有质数集合和IsPrime方法

private static int[] primes = new[] { 
  2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };

private static bool IsPrime(int value) {
  return primes.Contains(value);
}

你可以实现递归解决方案

private List<List<int>> ToListOfPrimes(int value, List<int> parts = null) {
  if (null == parts)
    parts = new List<int>();

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

  if (value == 0) {
    result.Add(parts.ToList());

    return result;
  }

  int minPrime = parts.Count <= 0 ? 0 : parts[parts.Count - 1];

  if (value <= minPrime)
    return result;

  // not that efficient: binary search will be a better choice here 
  for (int i = 0; i < primes.Length; ++i) {
    int p = primes[i];

    if (p <= minPrime)
      continue;
    else if (p > value)
      break;

    var list = parts.ToList();
    list.Add(p);

    var outcome = ToListOfPrimes(value - p, list);

    foreach (var solution in outcome)
      result.Add(solution);
  }

  return result;
}

测试

var result = ToListOfPrimes(28);

string report = String.Join(Environment.NewLine, result
  .Select(line => String.Join(", ", line)));

Console.Write(report); 

结果 (28)

2, 3, 5, 7, 11
2, 3, 23
2, 7, 19
3, 5, 7, 13
5, 23
11, 17

对于24

2, 3, 19
2, 5, 17
5, 19
7, 17
11, 13

【讨论】:

    【解决方案3】:

    如果您真的想用其他语言实现它,只需将您的解决方案扔到垃圾箱即可。您应该更明确地了解执行期间发生的情况。具有多个 if 语句的嵌套 for 循环根本不明确。示例中更糟糕的是 - 每次您想要总和中的更多数字时,您都需要添加新的 for 循环。我确实相信对于新手来说很难理解它,但我发现递归是到达这里的唯一方法。

    自己看:

    1. 很难说为什么你的程序的输出是错误的,因为逻辑原因
    2. 变量的命名应该有意义,这样您就知道它们存储了什么,而不是盲目猜测。
    3. 即使您返回 0 或 1,您的 checkPrime 方法也会返回 int,因此它应该真正返回 bool 类型

    在我之前的答案或 Dmitry Bychenko 提供的答案中,使用调试器和一张纸来了解递归的工作原理

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      • 2017-04-22
      • 2023-01-08
      • 1970-01-01
      • 2018-01-28
      • 1970-01-01
      相关资源
      最近更新 更多