How to generate list of prime pairs that can be concatenated to new prime?

徘徊边缘 提交于 2020-01-06 06:59:31

问题


I have a list of primes stored in a variable primes-list-split that are represented in a list format by a number->list method. The format is as follows: the prime list of 2, 3, 5, 7, and 11 would be '((2) (3) (5) (7) (1 1)).

get-prime-pairs takes as input this list, and tries to find every combination that concatenates to another prime. Then it should return these pairs in a list in the list representation. So the pair 3 367 which concatenates to 3367 which is also prime should be in the list in the representation ((3) (3 6 7)).

To achieve this my idea was to walk over the list and for every prime represented as a list concatenate it with all other primes represented as lists. If the combined list representation is also prime after a conversion to a number via the list->number method I add it to the final list which is returned.

The code is implemented as follows:

(define (prime? n)
  (define (check-divisible n divisor)
    (cond ((= divisor 1) #t)
          ((= 0 (modulo n divisor)) #f)
          (else (check-divisible n (- divisor 1)))))
  (cond ((<= n 1) #f)
        ((= n 2) #t)
        ((even? n) #f)
        (else (check-divisible n (truncate (sqrt n))))))

; Copyright (C) 2011 Toby Thain, toby@telegraphics.com.au
(define (primes-up-to n)
  (let ((sieve (make-vector (+ n 1) #t)))
    (define (test-prime i)
      (define (is-prime? idx)
        (vector-ref sieve idx))
      (define (not-prime! idx)
        (vector-set! sieve idx #f))
      (define (remove-multiples i step)
        (when (<= i n)
          (not-prime! i)
          (remove-multiples (+ i step) step)))
      (if (> i n)
          '()
          (if (is-prime? i)
              (begin
                (remove-multiples i i)
                (cons i (test-prime (+ i 1))))
              (test-prime (+ i 1)))))
    (test-prime 2)))

(define primes-list (primes-up-to 100000))


;; From list generate split arrays of allowed pairs

; www.stackoverflow.com/questions/12834562/scheme-number-to-list#12841962
(define (number->list n)
  (let loop ((n n) (acc '()))
    (if (< n 10)
        (cons n acc)
        (loop (quotient n 10)
              (cons (remainder n 10) acc)))))

; www.stackoverflow.com/questions/1683479/how-to-convert-a-list-to-num-in-scheme#1688960
(define (list->number lst)
  (let loop ((n 0) (lst lst))
    (if (empty? lst)
        n
        (loop (+ (* 10 n) (car lst)) (cdr lst)))))

; http://stackoverflow.com/questions/31909685/how-can-i-filter-null-values-from-this-list
(define primes-list-split 
  (map number->list primes-list))

(define (get-prime-pairs lst)
  (define (split lst pos)
    (list (drop-right lst pos) (take-right lst pos)))
  (define (get-prime-pairs-iter n acc)
    (if (zero? n) 
        (if 
         (or (null? acc) 
             ; filter out those values that start with leading zero
             (zero? (caar acc)) 
             (zero? (caadr acc))) 
         '() 
         (list acc))
        (get-prime-pairs-iter 
         (- n 1) 
         (let ((s (split lst n)))
           (if (and (prime? (list->number (car s)))
                    (prime? (list->number (cadr s))))
               (append s acc)
               acc)))))
  (get-prime-pairs-iter (- (length lst) 1) '()))

(define split-array-of-allowed-pairs 
  (append-map get-prime-pairs primes-list-split))

split-array-of-allowed-pairs 

Unfortunately, sometimes it returns 'pairs' that contains of four or more values. For example, split-array-of-allowed-pairs contains pairs like this:

((...)
((3) (6 4 3))
((3) (6 5 9))
((3 6 7) (3) (3) (6 7 3))
((3 6 7) (7) (3) (6 7 7))
(...))

We see here that longer combinations are returned. I want ((3 6 7) (3)) and ((3) (3 6 7)) to be both represented separately as a pair of two. Somehow they end up combined.

What is wrong in my method and does anyone know how I can fix it?

Thanks in advance.

See the gist here for the code with two tests below that should both return true: https://gist.github.com/erooijak/2d462ad429e6e05ddd25.


回答1:


Your function get-prime-pairs has several problems. Here is a working, non-tail recursive version:

(define (get-prime-pairs lst)
  (define (find-all-prime-pairs prime lst)
    (if (null? lst)
        '()
        (if (prime? (list->number (append prime (car lst))))
            (cons (list prime (car lst))
                  (find-all-prime-pairs prime (cdr lst)))
            (find-all-prime-pairs prime (cdr lst)))))
  (append-map (lambda (x) (find-all-prime-pairs x lst)) lst))

(define split-array-of-allowed-pairs (get-prime-pairs primes-list-split))

Here is how it works.

The function get-prime-pairs tries for all the element of list lst to combine them with all the elements of list, by calling the function find-all-prime-pairs.

The auxiliary function find-all-prime-pairs tries to combine its first argument (prime) with all the elements of the list second argument (lst), and returns all the pairs where the combination is a prime number. In this case the recursion is on the second argument, lst: if it is empty, then no pair can be found, otherwise it appends prime to the car of lst to see if this is a prime number. If this is true then the function returns the list obtained by the first pair and the result of the recursive call to the rest of lst, otherwise it returns simply the result of the recursive call.

It seems to me that the main problem for which your recursion does not work is that writing a recursive function as tail-recursive as first try is not the best way to get it correct. So, I dare to suggest you to consider the foundamental rule of programming:

First, make your program work, then, and if it necessary, make it efficient.

In other words, I suggest you first to write the function as a "normal" recursive function, and then, when you are sure that it works, rewrite it as tail recursive (or iterative) if necessary (and in the above case this is left as an exercise).

As final note, consider that 3367 is not a prime number, being equal to 7 * 13 * 37.




回答2:


public class PrimeConcatenation {
    public static void main(String[] args) {
        Scanner s1=new  Scanner(System.in);
        int num =s1.nextInt();
        int[] arr=new int[num];
        int[] res;
        int index=0;
        int count=0;
        for (int i = 2; i <=num; i++) {            
            if(prime(i))
            {
                arr[index]=i;
                index++;
//              System.out.println(""+i+""+prime(i));  
            }            
        }
        res=new int[index*index];
        int res_index=0;        
        for(int i=0;i<index;i++)
        {
            for(int j=0;j<index;j++)
            {
                String str=""+arr[i]+arr[j];
                if(prime(Integer.parseInt(str)))
                {
//                    System.out.println("val is "+str);
                    res[res_index]=Integer.parseInt(str);
                    res_index++;
                    count++;
                }                
            }
        }
        System.out.println(""+count);        
    }
    static boolean prime(int num)
    {
        boolean res;
        for(int i=2;i<num;i++)
        {
            if(num%i==0)
            {
                res=false;
                return res;
            }            
        }
        return true;
    }   
}


来源:https://stackoverflow.com/questions/31998531/how-to-generate-list-of-prime-pairs-that-can-be-concatenated-to-new-prime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!