037 Truncatable primes.pl 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #!/usr/bin/perl
  2. # Author: Trizen
  3. # Date: 28 March 2023
  4. # https://github.com/trizen
  5. # Find the sum of the only eleven primes that are both truncatable from left to right and right to left.
  6. # NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.
  7. # https://projecteuler.net/problem=37
  8. # Runtime: 0.027s
  9. use 5.036;
  10. use ntheory qw(primes vecmax is_prime vecsum);
  11. use Math::Prime::Util::GMP qw(divint mulint addint subint);
  12. sub is_left_truncatable ($n, $base) {
  13. for (my $r = $base ; $r < $n ; $r = mulint($r, $base)) {
  14. is_prime(subint($n, mulint($r, divint($n, $r)))) || return 0;
  15. }
  16. return 1;
  17. }
  18. sub generate_from_prefix ($p, $base) {
  19. my @seq = ($p);
  20. foreach my $d (1 .. $base - 1) {
  21. my $n = addint(mulint($p, $base), $d);
  22. if (is_prime($n)) {
  23. push @seq, grep { is_left_truncatable($_, $base) } generate_from_prefix($n, $base);
  24. }
  25. }
  26. return @seq;
  27. }
  28. sub both_truncatable_primes_in_base ($base) {
  29. return if $base <= 2;
  30. my @truncatable;
  31. foreach my $p (@{primes(2, $base - 1)}) {
  32. push @truncatable, generate_from_prefix($p, $base);
  33. }
  34. return @truncatable;
  35. }
  36. my $base = 10;
  37. my @T = both_truncatable_primes_in_base($base);
  38. say vecsum(grep { $_ >= $base } @T);