2016-09-13 3 views
1
//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. Также повторяются некоторые ответы, и это может иметь отношение к тому, что у меня нет дубликатов чеков. Я попытался нажать целые числа в списке, а затем использовать hashset, чтобы иметь только целые числа, но я застрял и попытался переборщить его. Все числа, подлежащие печати, должны быть разными целыми числами. Я не понимаю, как печатать все отдельные цифры, и есть ли элегантный способ распечатать все возможное.Сумма чисел как отдельные цифры

Спасибо за помощь!

+0

Не могли бы вы проверить свой код? кажется, скобка не закрыта должным образом – Prisoner

+0

Также лучший отступ помогает! –

ответ

0

Не знаю, если это достаточно элегантное для вас, но я просто пюре грязного способа заставить его работать:

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 возвращает комбинацию чисел, которые суммируются, равно количеству вводимых вами номеров, и, наконец, foreach в Main производит форматированный вывод, который легко на глаза. Надеюсь, поможет!

+0

Хорошо, я понимаю, где я сейчас ошибся в своей реализации.Я пытался добавить «n». Я был только грубым, заставляя мой путь для двух разных решений, а не для вычисления остальных решений. Не могли бы вы объяснить мне последнее прошлое вашего решения. Начиная с «public static IEnumerable > SubSetsOf (этот источник IEnumerable )« Я хочу реплицировать это, используя мою версию. –

+0

Он берет список элементов и использует рекурсию для возврата всех возможных подмножеств, т. Е. Если вы предоставляете массив простых чисел [2, 3, 5], он будет генерировать [2, 3, 5], [2, 3], [2, 5], [2], [3, 5], [3]. Имея эту информацию, мы можем суммировать каждый из них и сравнивать с ценностью, которую мы хотим получить. Это будут возможные решения. Это далеко не оптимальный, но самый понятный, как я мог. теперь понимаешь? –

+0

Да, сейчас это имеет смысл. Извините, я начал писать код на C# с недели назад. Но, глядя на мой код, были какие-то вопиющие ошибки или проблемы, отличные от целой отдельной части простого числа. Я собираюсь попытаться реализовать как можно больше в моем коде, основываясь на приведенной здесь информации, поскольку мне нужно повторить эту задачу на других языках. –

0

При условии, что у вас есть коллекция простых чисел и 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); 
} 

Вы можете реализовать recoursive решение

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 
0

Если вы действительно хотите, чтобы реализовать его в других языках просто выбросить ваше решение мусорное ведро. Вы должны быть более откровенными о том, что происходит во время выполнения. Вложенные для циклов с несколькими операторами if явно не явны. Что еще хуже в примере - вам нужно будет добавлять новый цикл for каждый раз, когда вам нужно больше чисел в сумме. Я действительно считаю, что это трудно понять для новичков, но я нахожу рекурсию единственным способом пойти сюда.

Смотрите сами:

  1. это трудно сказать, почему выход из вашей программы не так, из-за логики
  2. Переменные должны быть им по значению, так что вы знаете, что они хранят вместо слепого гаданием.
  3. Ваш checkPrime метод возвращает Int, даже если вы возвращаете 0 или 1, так что действительно надо возвращать BOOL Типу

Используйте отладчик и кусок бумаги, чтобы понять, как рекурсия работает либо в моем предыдущем ответе, или тот, предоставленной Дмитрий Быченко