问题
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