Pandigital prime: Difference between revisions
(Added Algol 68) |
|||
Line 139: | Line 139: | ||
7652413 |
7652413 |
||
</pre> |
</pre> |
||
=={{header|Julia}}== |
|||
<lang julia>using Primes |
|||
function pandigitals(N) |
|||
mask = primesmask(10^N) |
|||
ret = Int[] |
|||
for j in N:-1:1, i in 10^j:-1:10^(j-1) |
|||
if mask[i] |
|||
d = digits(i) |
|||
if length(d) == j && all(x -> count(y -> y == x, d) == 1, 1:j) |
|||
push!(ret, i) |
|||
end |
|||
end |
|||
end |
|||
return ret |
|||
end |
|||
println("The largest prime containing numerals 1 through n of length n is ", maximum(pandigitals(9))) |
|||
</lang>{{out}}<pre>The largest prime containing numerals 1 through n of length n is 7652413</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
Revision as of 21:54, 4 September 2021
- Task
The following problem is taken from Project Euler problem 41.
We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital and is also prime.
What is the largest n-digit pandigital prime that exists?
Assume that the problem is talking about decimal numbers.
ALGOL 68
Uses the observations in the Factor sample - the prime we are looking for can only have 7 or 4 digits. <lang algol68>BEGIN # Find the largest n-digit prime that contains all the digits 1..n #
# As noted in the Factor sample, only 7 and 4 digit primes need be # # considered: 1 is not prime, all 2, 3, 5, 6, 8 and 9 digit # # pandigital numbers are divisible by 3 # # permutation code from the Algol 68 Permutations by swapping task # # entry - uses Heap's algorithm - based on the pseudo code on the # # Wikipedia page for Heap's Algorithm # # generate permutations of a, the results are stored in p # PROC generate = ( INT k, REF[]INT a, REF[]INT p, REF INT p pos )VOID: IF k = 1 THEN INT a value := a[ 0 ]; FOR d TO UPB a DO a value *:= 10 +:= a[ d ] OD; p[ p pos ] := a value; p pos +:= 1 ELSE # Generate permutations with kth unaltered # # Initially k = length a # generate( k - 1, a, p, p pos ); # Generate permutations for kth swapped with each k-1 initial # FOR i FROM 0 TO k - 2 DO # Swap choice dependent on parity of k (even or odd) # INT swap item = IF ODD k THEN 0 ELSE i FI; INT t = a[ swap item ]; a[ swap item ] := a[ k - 1 ]; a[ k - 1 ] := t; generate( k - 1, a, p, p pos ) OD FI # generate # ; # generate permutations of a, p is used to hold the output # PROC permute digits = ( REF[]INT a, REF[]INT p )VOID: BEGIN INT p pos := 0; generate( ( UPB a + 1 ) - LWB a, a[ AT 0 ], p[ AT 0 ], p pos ) END # permute digits # ; # Quicksorts in-place the array of integers a, from lb to ub # PROC quicksort = ( REF[]INT a, INT lb, ub )VOID: IF ub > lb THEN # more than one element, so must sort # INT left := lb; INT right := ub; # choosing the middle element of the array as the pivot # INT pivot := a[ left + ( ( right + 1 ) - left ) OVER 2 ]; WHILE WHILE IF left <= ub THEN a[ left ] < pivot ELSE FALSE FI DO left +:= 1 OD; WHILE IF right >= lb THEN a[ right ] > pivot ELSE FALSE FI DO right -:= 1 OD; left <= right DO INT t := a[ left ]; a[ left ] := a[ right ]; a[ right ] := t; left +:= 1; right -:= 1 OD; quicksort( a, lb, right ); quicksort( a, left, ub ) FI # quicksort # ; # attenmpt to find the maximum n digit pandigital prime, return it if found, 0 otherwise # PROC try pd prime = ( INT n )INT: BEGIN # array of digits to permute for the numbers # [ 0 : n - 1 ]INT digits; FOR i TO n DO digits[ i - 1 ] := i OD; # array to hold the permuted digits, there will be n! elements # INT factorial n := 1; FOR i FROM 2 TO n DO factorial n *:= i OD; [ 0 : factorial n - 1 ]INT permuted digits; # permute the digits # permute digits( digits, permuted digits ); # sort the permuted numbers, assuming the prime is near the high end # quicksort( permuted digits, LWB permuted digits, UPB permuted digits ); # try finding a prime - use trial division to test for primality # INT pd prime := 0; FOR p pos FROM UPB permuted digits BY -1 TO LWB permuted digits WHILE pd prime = 0 DO INT p = permuted digits[ p pos ]; IF ODD p AND p MOD 10 /= 5 THEN BOOL prime := TRUE; FOR i FROM 3 BY 2 TO ENTIER sqrt(p) WHILE prime := p MOD i /= 0 DO SKIP OD; IF prime THEN # found a pandigital prime # pd prime := p FI FI OD; pd prime END # try pd prime # ; # first try a 7 digit number then a 4 digit number if we can't find a 7 digit one # IF INT pd prime := try pd prime( 7 ); pd prime > 0 THEN print( ( "max pandigital prime: ", whole( pd prime, 0 ), newline ) ) ELIF pd prime := try pd prime( 4 ); pd prime > 0 THEN print( ( "max pandigital prime: ", whole( pd prime, 0 ), newline ) ) ELSE print( ( "Can't find a pandigital prime", newline ) ) FI
END</lang>
- Output:
max pandigital prime: 7652413
Factor
<lang factor>USING: io kernel math math.combinatorics math.functions math.primes math.ranges present sequences sequences.cords ;
! If the digit-sum of a number is divisible by 3, so too is the number. ! The digit-sum of all n-digit pandigitals is the same. ! The digit sums for 9-, 8-, 6-, 5-, and 3-digit pandigitals are all divisible by 3. ! 1, 12, and 21 are not prime so 1- and 2-digit pandigitals don't need checked. ! Hence, we only need to check 4- and 7-digit pandigitals from biggest to smallest.
{ 4 7 } [ [1,b] <permutations> ] [ cord-append ] map-reduce [ reverse 0 [ 10^ * + ] reduce-index prime? ] find-last nip "The largest pandigital decimal prime is: " print [ present write ] each nl</lang>
- Output:
The largest pandigital decimal prime is: 7652413
Julia
<lang julia>using Primes
function pandigitals(N)
mask = primesmask(10^N) ret = Int[] for j in N:-1:1, i in 10^j:-1:10^(j-1) if mask[i] d = digits(i) if length(d) == j && all(x -> count(y -> y == x, d) == 1, 1:j) push!(ret, i) end end end return ret
end
println("The largest prime containing numerals 1 through n of length n is ", maximum(pandigitals(9)))
</lang>
- Output:
The largest prime containing numerals 1 through n of length n is 7652413
Phix
with javascript_semantics sequence avail function pandigital(integer i, n=0) if i=0 then ?n return iff(is_prime(n)?n:0) end if for d=length(avail) to 1 by -1 do if avail[d] then avail[d] = false integer r = pandigital(i-1,n*10+d) if r then return r end if avail[d] = true end if end for return 0 end function for i=9 to 1 by -1 do sequence digits = tagset(i) if remainder(sum(digits),3)!=0 then avail = repeat(true,i) printf(1,"Largest decimal pandigital prime:%,d\n",pandigital(i)) exit end if end for
- Output:
As you can see it does not have to generate and test many candidates for primality before it finds the answer.
7654321 7654312 7654231 7654213 7654132 7654123 7653421 7653412 7653241 7653214 7653142 7653124 7652431 7652413 Largest decimal pandigital prime:7,652,413
Raku
<lang perl6>say max (1..9).map: -> $size {
|(1..$size).permutations».join.grep(&is-prime);
}</lang>
- Output:
7652413
Ring
<lang ring> load "stdlib.ring" see "working..." + nl see "The largest pandigital prime is:" + nl
pand = 0 limit = 7654321
for n = limit to 2 step -2
flag = 1 strn = string(n) if isprime(n) for m = 1 to len(strn) ind = count(strn,string(m)) if ind != 1 flag = 0 ok next if flag = 1 pand = n exit ok ok
next
see "" + pand + nl
see "done..." + nl
func count(cString,dString)
sum = 0 while substr(cString,dString) > 0 sum++ cString = substr(cString,substr(cString,dString)+len(string(sum))) end return sum
</lang>
- Output:
The largest pandigital prime is: 7,652,413
Wren
This makes use of the optimization in the Factor entry. <lang ecmascript>import "/math" for Int import "/fmt" for Fmt
// generates all permutations in lexicographical order var permutations = Fn.new { |input|
var perms = [input] var a = input.toList var n = a.count - 1 for (c in 1...Int.factorial(n+1)) { var i = n - 1 var j = n while (a[i] > a[i+1]) i = i - 1 while (a[j] < a[i]) j = j - 1 var t = a[i] a[i] = a[j] a[j] = t j = n i = i + 1 while (i < j) { t = a[i] a[i] = a[j] a[j] = t i = i + 1 j = j - 1 } perms.add(a.toList) } return perms
}
System.print("The largest pandigital decimal prime which uses all the digits 1..n once is:") for (n in [7, 4]) {
var perms = permutations.call((1..n).toList) for (i in perms.count - 1..0) { if (perms[i][-1] % 2 == 0 || perms[i][-1] == 5) continue var p = Num.fromString(perms[i].join()) if (Int.isPrime(p)) { Fmt.print("$,d", p) return } }
}</lang>
- Output:
The largest pandigital decimal prime which uses all the digits 1..n once is: 7,652,413