Magnanimous numbers: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Task clarifiction)
(Add Factor)
Line 31: Line 31:





=={{header|Factor}}==
{{works with|Factor|0.99 2020-01-23}}
<lang factor>USING: arrays grouping io kernel lists lists.lazy
lists.lazy.examples math math.parser math.primes math.ranges
prettyprint sequences ;

! Optimization for numbers > 1001;
! first and last digits must have opposite parity.
! Thanks to Raku entry for this.
: mixed-parity? ( str -- ? )
[ first even? ] [ last even? xor ] bi ;

: >stringy ( l -- l ) [ number>string ] lmap-lazy ;
: 1001- ( -- l ) naturals [ 1002 < ] lwhile >stringy ;
: 1002+ ( -- l ) 1002 lfrom >stringy [ mixed-parity? ] lfilter ;
: candidates ( -- l ) 1001- 1002+ lappend-lazy ;

: (magnanimous?) ( str -- ? )
dup length 1 - [1,b] [ cut 2array ] with map
[ [ string>number ] map-sum ] map [ prime? ] all? ;

: magnanimous? ( str -- ? )
dup length 1 = [ drop t ] [ (magnanimous?) ] if ;

: magnanimous ( -- l ) candidates [ magnanimous? ] lfilter ;

: show ( seq from to -- ) rot subseq 15 group simple-table. nl ;

400 magnanimous ltake list>array
[ "First 45 magnanimous numbers" print 0 45 show ]
[ "241st through 250th magnanimous numbers" print 240 250 show ]
[ "391st through 400th magnanimous numbers" print 390 400 show ]
tri</lang>
{{out}}
<pre>
First 45 magnanimous numbers
0 1 2 3 4 5 6 7 8 9 11 12 14 16 20
21 23 25 29 30 32 34 38 41 43 47 49 50 52 56
58 61 65 67 70 74 76 83 85 89 92 94 98 101 110

241st through 250th magnanimous numbers
17992 19972 20209 20261 20861 22061 22201 22801 22885 24407

391st through 400th magnanimous numbers
486685 488489 515116 533176 551558 559952 595592 595598 600881 602081
</pre>


=={{header|Raku}}==
=={{header|Raku}}==

Revision as of 01:54, 20 March 2020

Magnanimous numbers is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

A magnanimous number is an integer where there is no place in the number where a + (plus sign) could be added between any two digits to give a non-prime sum.


E.G.
  • 6425 is a magnanimous number. 6 + 425 == 431 which is prime; 64 + 25 == 89 which is prime; 642 + 5 == 647 which is prime.
  • 3538 is not a magnanimous number. 3 + 538 == 541 which is prime; 35 + 38 == 73 which is prime; but 353 + 8 == 361 which is not prime.


Traditionally the single digit numbers 0 through 9 are included as magnanimous numbers as there is no place in the number where you can add a plus between two digits at all. (Kind of weaselly but there you are...) Except for the actual value 0, leading zeros are not permitted. Internal zeros are fine though, 1001 -> 1 + 001 (prime), 10 + 01 (prime) 100 + 1 (prime).

There are only 571 known magnanimous numbers. It is strongly suspected, though not rigorously proved, that there are no magnanimous numbers above 97393713331910, the largest one known.


Task
  • Write a routine (procedure, function, whatever) to find magnanimous numbers.
  • Use that function to find and display, here on this page the first 45 magnanimous numbers.
  • Use that function to find and display, here on this page the 241st through 250th magnanimous numbers.
  • Stretch: Use that function to find and display, here on this page the 391st through 400th magnanimous numbers


See also


Factor

Works with: Factor version 0.99 2020-01-23

<lang factor>USING: arrays grouping io kernel lists lists.lazy lists.lazy.examples math math.parser math.primes math.ranges prettyprint sequences ;

! Optimization for numbers > 1001; ! first and last digits must have opposite parity. ! Thanks to Raku entry for this.

mixed-parity? ( str -- ? )
   [ first even? ] [ last even? xor ] bi ;
>stringy ( l -- l ) [ number>string ] lmap-lazy ;
1001- ( -- l ) naturals [ 1002 < ] lwhile >stringy ;
1002+ ( -- l ) 1002 lfrom >stringy [ mixed-parity? ] lfilter ;
candidates ( -- l ) 1001- 1002+ lappend-lazy ;
(magnanimous?) ( str -- ? )
   dup length 1 - [1,b] [ cut 2array ] with map
   [ [ string>number ] map-sum ] map [ prime? ] all? ;
magnanimous? ( str -- ? )
   dup length 1 = [ drop t ] [ (magnanimous?) ] if ;
magnanimous ( -- l ) candidates [ magnanimous? ] lfilter ;
show ( seq from to -- ) rot subseq 15 group simple-table. nl ;

400 magnanimous ltake list>array [ "First 45 magnanimous numbers" print 0 45 show ] [ "241st through 250th magnanimous numbers" print 240 250 show ] [ "391st through 400th magnanimous numbers" print 390 400 show ] tri</lang>

Output:
First 45 magnanimous numbers
0  1  2  3  4  5  6  7  8  9  11 12 14 16  20
21 23 25 29 30 32 34 38 41 43 47 49 50 52  56
58 61 65 67 70 74 76 83 85 89 92 94 98 101 110

241st through 250th magnanimous numbers
17992 19972 20209 20261 20861 22061 22201 22801 22885 24407

391st through 400th magnanimous numbers
486685 488489 515116 533176 551558 559952 595592 595598 600881 602081

Raku

Works with: Rakudo version 2020.02

<lang perl6>my @magnanimous = lazy flat ^10, (10 .. 1001).hyper.map( {

   my $last;
   (1 .. .chars - 1).map: -> \c { ++$last and last unless (.substr(0,c) + .substr(c)).is-prime }
   next if $last;
   $_

} ),

(1002 .. โˆž).hyper.map: {

   # optimization for numbers > 1001; First and last digit can not both be even or both be odd
   next if (.substr(0,1) % 2 + .substr(*-1) % 2) %% 2;
   my $last;
   (1 .. .chars - 1).map: -> \c { ++$last and last unless (.substr(0,c) + .substr(c)).is-prime }
   next if $last;
   $_

}

put 'First 45 magnanimous numbers'; put @magnanimous[^45]ยป.fmt('%3d').batch(15).join: "\n";

put "\n241st through 250th magnanimous numbers"; put @magnanimous[240..249];

put "\n391st through 400th magnanimous numbers"; put @magnanimous[390..399];</lang>

Output:
First 45 magnanimous numbers
  0   1   2   3   4   5   6   7   8   9  11  12  14  16  20
 21  23  25  29  30  32  34  38  41  43  47  49  50  52  56
 58  61  65  67  70  74  76  83  85  89  92  94  98 101 110

241st through 250th magnanimous numbers
17992 19972 20209 20261 20861 22061 22201 22801 22885 24407

391st through 400th magnanimous numbers
486685 488489 515116 533176 551558 559952 595592 595598 600881 602081