Palindromic gapful numbers
You are encouraged to solve this task according to the task description, using any language you may know.
For this task, a number is to be understood as a positive integer expressed in base ten, and a palindromic number is one that is equal to the integer formed by reversing its decimal digits.
A number that is evenly divisible by the number formed by concatenating its first and last digits in that order is known as a gapful number. All one─ and two─digit numbers have this property and accordingly only numbers greater than or equal to 100 should be considered for this Rosetta Code task.
(Evenly divisible here means divisible with no remainder.)
- Example
1037 is a gapful number because it is evenly divisible by the number 17 which is formed by the first and last decimal digits of 1037.
- Task
-
- Show (nine sets) the first 20 palindromic gapful numbers that end with:
- the digit 1
- the digit 2
- the digit 3
- the digit 4
- the digit 5
- the digit 6
- the digit 7
- the digit 8
- the digit 9
- Show (nine sets, like above) of palindromic gapful numbers:
- the last 15 palindromic gapful numbers (out of 100)
- the last 10 palindromic gapful numbers (out of 1,000) {optional}
For other ways of expressing the (above) requirements, see the discussion page.
- Note
All palindromic gapful numbers are divisible by eleven.
- Related tasks
- Also see
-
- The OEIS entry: A108343 gapful numbers.
AppleScript
on doTask()
set part1 to {"First 20 palindromic gapful numbers > 100 ending with each digit from 1 to 9:"}
set part2 to {"86th to 100th such:"}
set part3 to {"991st to 1000th:"}
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " "
repeat with endDigit from 1 to 9
set {collector1, collector2, collector3} to {{}, {}, {}}
set outerNumber to endDigit * 11 -- Number formed from the palindromes' first and last digits.
set oddDigitCount to true -- Starting with palindromes in the hundreds.
set baseHi to endDigit * 10 -- Number formed from just the "high end" digits, initially endDigit and a middle 0.
set hi to baseHi
set carryCheck to hi + 10 -- Number reached when incrementing the "high end" number changes its first digit.
set inc to 10 -- Incrementor for the middle digit(s) of the palindromes themselves.
set counter to 0
set maxNeeded to 1000
set done to false
repeat until (done)
-- Work out every 10th palindrome (middle digit = 0) from the current "high end" number.
set pal to hi
if (oddDigitCount) then
set temp to hi div 10
else
set temp to hi
end if
repeat until (temp is 0)
set pal to pal * 10 + temp mod 10
set temp to temp div 10
end repeat
-- Check the result and the following 9 palindromes (derived by incrementing the middle digit(s))
-- and store as text any which are both gapful and the ones required.
repeat 10 times
if (pal mod outerNumber is 0) then
set counter to counter + 1
if (counter ≤ 20) then
set end of collector1 to intText(pal)
else if (counter < 86) then
else if (counter ≤ 100) then
set end of collector2 to intText(pal)
else if (counter < 991) then
else --if (counter ≤ 1000) then
set end of collector3 to intText(pal)
set done to (counter = maxNeeded)
if (done) then exit repeat
end if
end if
set pal to pal + inc
end repeat
-- Increment the high end number's penultimate digit after every 10th palindrome.
-- If a carry changes its first digit, reset for longer palindromes.
set hi to hi + 10
if (hi = carryCheck) then
set oddDigitCount to (not oddDigitCount)
if (oddDigitCount) then
set baseHi to baseHi * 10
set carryCheck to carryCheck * 10
set inc to inc div 11 * 10
else
set inc to inc * 11
end if
set hi to baseHi
end if
end repeat
set {end of part1, end of part2, end of part3} to {collector1 as text, collector2 as text, collector3 as text}
end repeat
set AppleScript's text item delimiters to linefeed
set output to {part1, "", part2, "", part3} as text
set AppleScript's text item delimiters to astid
return output
end doTask
on intText(n)
if (n < 100000000) then return n as text
set txt to text 2 thru end of ((100000000 + (n mod 100000000 as integer)) as text)
set n to n div 100000000
repeat
set lo to n mod 100000000 as integer
set n to n div 100000000
if (n is 0) then return (lo as text) & txt
set txt to (text 2 thru end of ((100000000 + lo) as text)) & txt
end repeat
end intText
return doTask()
- Output:
"First 20 palindromic gapful numbers > 100 ending with each digit from 1 to 9: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 86th to 100th such: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 991st to 1000th: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869"
Translation of Phix "Ludicrously fast …"
See the original's comments for an explanation of the logic. While this translation was developed directly from the Phix, comparing the two may be difficult as I've pulled things around a bit for AppleScript efficiency and have relabelled some of the variables for consistency and to help me understand the process myself. On my machine, this version takes 0.12 seconds to carry out the set tasks — only a tad slower than the hard-wired script above. The batch of extreme tests in the Phix demo takes around 1.6 seconds.
-- Return a script object containing the main handlers.
-- It could be loaded as a library instead if there were any point in having such a library.
on getWorks()
script theWorks
property outerX11 : missing value
property countLimit : missing value
property to_skip : missing value
property palcount : missing value
property skipd : {{}, {}, {}, {}, {}, {}, {}, {}, {}}
property skipdOuter : missing value
property pals : missing value
-- Work out the remainder from the division of the positive decimal integer value which is
-- one or two instances of digit 'digit' separated by 'gap' zeros and followed by 'shift' zeros
-- (which may not be realisable as an AppleScript number) by 'outerX11', a multiple of 11.
on rmdr(digit, gap, shift)
-- Remainders from the division of left-shifted decimals by multiples of 11 reliably repeat
-- every six places shifted > 2, so use a dividend with the equivalent digit shifts < 9.
set coefficient to 10 ^ ((shift - 3) mod 6 + 3)
if (gap > -1) then set coefficient to coefficient + 10 ^ ((gap + shift - 2) mod 6 + 3)
return (digit * coefficient mod outerX11) as integer
end rmdr
-- Recursively infer from remainder arithmetic any palindromic gapful numbers with
-- ((count lhs) * 2 + gap) digits whose outer digit is the first value in lhs.
-- Append text versions of any falling in the current keep range to the 'pals' list.
on palindromicGapfuls(lhs, gap, remainder)
-- lhs: eg {9, 4, 5} of a potential 945…549 result.
-- gap: length of inner to be filled in
-- remainder: remainder of outer, eg 9400049 mod 11, but derived from rmdr() results.
set shift to (count lhs) -- left shift of inner (same as its right shift).
-- This translation's 'skipd' is a four-deep AppleScript list structure indexed with the elements
-- of the original dictionary's keys: (skipd) -> outermost digit -> shift -> gap -> remainder (+ 1).
-- The outermost digit element doesn't change during a search based on it, so the script property
-- 'skipdOuter' has been preset to skipd's outer-th sublist in the set-up for the current search.
-- Populate it just enough here to ensure that the slot about to be checked for a 'skip' value exists.
repeat (shift - (count my skipdOuter)) times
set end of my skipdOuter to {}
end repeat
repeat (gap - (count item shift of my skipdOuter)) times
set end of item shift of my skipdOuter to {}
end repeat
repeat (remainder + 1 - (count item gap of item shift of my skipdOuter)) times
set end of item gap of item shift of my skipdOuter to missing value
end repeat
set skip to item (remainder + 1) of item gap of item shift of my skipdOuter
if ((skip is missing value) or (palcount + skip > to_skip)) then
set skip to 0
set nextGap to gap - 2
repeat with d from 0 to 9
set nextRem to (remainder + rmdr(d, nextGap, shift)) mod outerX11
if (gap > 2) then
set skip to skip + palindromicGapfuls(lhs & d, nextGap, nextRem)
else if (nextRem is 0) then
-- A palindrome of lhs's contents around gap ds would be … gapful.
set palcount to palcount + 1
if (palcount > to_skip) then
-- This one would be in the current keep range, so realise it as text and store it.
if (gap is 2) then set d to {d, d} -- Not d * 11 as d could be 0.
set end of my pals to (lhs & d & reverse of lhs) as text
else
set skip to skip + 1
end if
end if
if (palcount = countLimit) then exit repeat
end repeat
if (palcount < to_skip) then set item (remainder + 1) of item gap of item shift of my skipdOuter to skip
else
set palcount to palcount + skip
end if
return skip
end palindromicGapfuls
-- Set up a search for the last 'keep' of the first 'countLimit' PGNs > 100 whose outer digit is 'outer',
-- call the recursive process for each palindrome width, and eventually return the stored numeric texts.
on collect(outer, countLimit, keep)
-- Initialise script object properties for the current search.
set outerX11 to outer * 11
set my countLimit to countLimit
set to_skip to countLimit - keep
set palcount to 0
set skipdOuter to item outer of my skipd
set pals to {}
-- Also locals and TIDs.
set lhs to {outer}
set gap to 1 -- Number of digits between outer pair.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "" -- For list-to-text coercions.
repeat until (palcount = countLimit)
set remainder to rmdr(outer, gap, 0)
palindromicGapfuls(lhs, gap, remainder)
set gap to gap + 1
end repeat
set AppleScript's text item delimiters to astid
return pals
end collect
end script
return theWorks
end getWorks
(* Test code *)
-- Return an integer as text with the appropriate English ordinal suffix
on ordinalise(n)
-- Adapted from Victor Yee (adapted from NG (adapted from Jason Bourque) & Paul Skinner)
set units to n mod 10
if ((units > 3) or ((n - units) mod 100 is 10) or (units < 1) or (units mod 1 > 0)) then return (n as text) & "th"
return (n as text) & item units of {"st", "nd", "rd"}
end ordinalise
on doTask()
set tests to {{20, 20, 1, 9}, {100, 15, 1, 9}, {1000, 10, 1, 9}, {10000, 5, 1, 9}, ¬
{100000, 1, 1, 9}, {1000000, 1, 1, 9}, {10000000, 1, 1, 9}, ¬
{100000000, 1, 9, 9}, {1.0E+9, 1, 9, 9}, {1.0E+10, 1, 9, 9}, ¬
{1.0E+11, 1, 9, 9}, {1.0E+12, 1, 9, 9}, ¬
{1.0E+13, 1, 9, 9}, {1.0E+14, 1, 9, 9}, ¬
{1.0E+15, 1, 2, 4}}
-- set tests to {{20, 20, 1, 9}, {100, 15, 1, 9}, {1000, 10, 1, 9}} -- The RC task.
set output to {}
set theWorks to getWorks()
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " "
repeat with i from 1 to (count tests)
set {countLimit, keep, firstOuter, lastOuter} to item i of tests
if (countLimit = keep) then
set h to "First " & countLimit
else if (keep > 1) then
set h to "Last " & keep & (" of first " & countLimit)
else
set h to ordinalise(countLimit)
end if
if ((keep = 1) and (firstOuter = lastOuter)) then
set h to h & " palindromic gapful number > 100 ending with " & firstOuter & ":"
else if (firstOuter = lastOuter) then
set h to h & " palindromic gapful numbers > 100 ending with " & firstOuter & ":"
else
set h to h & " palindromic gapful numbers > 100 ending with digits from " & firstOuter & (" to " & lastOuter & ":")
end if
if (i > 1) then set end of output to ""
set end of output to h
repeat with outer from firstOuter to lastOuter
set end of output to theWorks's (collect(outer, countLimit, keep)) as text
end repeat
end repeat
set AppleScript's text item delimiters to linefeed
set output to output as text
set AppleScript's text item delimiters to astid
return output
end doTask
doTask()
- Output:
First 20 palindromic gapful numbers > 100 ending with digits from 1 to 9: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of first 100 palindromic gapful numbers > 100 ending with digits from 1 to 9: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of first 1000 palindromic gapful numbers > 100 ending with digits from 1 to 9: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 Last 5 of first 10000 palindromic gapful numbers > 100 ending with digits from 1 to 9: 1787557871 1787667871 1787777871 1787887871 1787997871 2787557872 2787667872 2787777872 2787887872 2787997872 308760067803 308763367803 308766667803 308769967803 308772277803 48327872384 48329192384 48330303384 48331513384 48332723384 5787557875 5787667875 5787777875 5787887875 5787997875 608763367806 608766667806 608769967806 608772277806 608775577806 746958859647 746961169647 746968869647 746971179647 746978879647 808691196808 808692296808 808693396808 808694496808 808695596808 968697796869 968706607869 968715517869 968724427869 968733337869 100000th palindromic gapful numbers > 100 ending with digits from 1 to 9: 178788887871 278788887872 30878611687803 4833326233384 578789987875 60878611687806 74826144162847 80869688696808 96878077087869 1000000th palindromic gapful numbers > 100 ending with digits from 1 to 9: 17878799787871 27878799787872 3087876666787803 483333272333384 57878799787875 6087876996787806 7487226666227847 8086969559696808 9687870990787869 10000000th palindromic gapful numbers > 100 ending with digits from 1 to 9: 1787878888787871 2787878888787872 308787855558787803 48333332623333384 5787878998787875 608787855558787806 748867523325768847 808696968869696808 968787783387787869 100000000th palindromic gapful number > 100 ending with 9: 96878786855868787869 1.0E+9th palindromic gapful number > 100 ending with 9: 9687878775995778787869 1.0E+10th palindromic gapful number > 100 ending with 9: 968787878661166878787869 1.0E+11th palindromic gapful number > 100 ending with 9: 96878787877355377878787869 1.0E+12th palindromic gapful number > 100 ending with 9: 9687878787863773687878787869 1.0E+13th palindromic gapful number > 100 ending with 9: 968787878787711117787878787869 1.0E+14th palindromic gapful number > 100 ending with 9: 96878787878786133168787878787869 1.0E+15th palindromic gapful numbers > 100 ending with digits from 2 to 4: 27878787878787888878787878787872 3087878787878783113878787878787803 483333333333333262333333333333384
C
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
typedef uint64_t integer;
integer reverse(integer n) {
integer rev = 0;
while (n > 0) {
rev = rev * 10 + (n % 10);
n /= 10;
}
return rev;
}
typedef struct palgen_tag {
integer power;
integer next;
int digit;
bool even;
} palgen_t;
void init_palgen(palgen_t* palgen, int digit) {
palgen->power = 10;
palgen->next = digit * palgen->power - 1;
palgen->digit = digit;
palgen->even = false;
}
integer next_palindrome(palgen_t* p) {
++p->next;
if (p->next == p->power * (p->digit + 1)) {
if (p->even)
p->power *= 10;
p->next = p->digit * p->power;
p->even = !p->even;
}
return p->next * (p->even ? 10 * p->power : p->power)
+ reverse(p->even ? p->next : p->next/10);
}
bool gapful(integer n) {
integer m = n;
while (m >= 10)
m /= 10;
return n % (n % 10 + 10 * m) == 0;
}
void print(int len, integer array[][len]) {
for (int digit = 1; digit < 10; ++digit) {
printf("%d: ", digit);
for (int i = 0; i < len; ++i)
printf(" %llu", array[digit - 1][i]);
printf("\n");
}
}
int main() {
const int n1 = 20, n2 = 15, n3 = 10;
const int m1 = 100, m2 = 1000;
integer pg1[9][n1];
integer pg2[9][n2];
integer pg3[9][n3];
for (int digit = 1; digit < 10; ++digit) {
palgen_t pgen;
init_palgen(&pgen, digit);
for (int i = 0; i < m2; ) {
integer n = next_palindrome(&pgen);
if (!gapful(n))
continue;
if (i < n1)
pg1[digit - 1][i] = n;
else if (i < m1 && i >= m1 - n2)
pg2[digit - 1][i - (m1 - n2)] = n;
else if (i >= m2 - n3)
pg3[digit - 1][i - (m2 - n3)] = n;
++i;
}
}
printf("First %d palindromic gapful numbers ending in:\n", n1);
print(n1, pg1);
printf("\nLast %d of first %d palindromic gapful numbers ending in:\n", n2, m1);
print(n2, pg2);
printf("\nLast %d of first %d palindromic gapful numbers ending in:\n", n3, m2);
print(n3, pg3);
return 0;
}
- Output:
First 20 palindromic gapful numbers ending in: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of first 100 palindromic gapful numbers ending in: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of first 1000 palindromic gapful numbers ending in: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
C++
The idea of generating palindromes first then testing for gapfulness was borrowed from other solutions.
#include <iostream>
#include <cstdint>
typedef uint64_t integer;
integer reverse(integer n) {
integer rev = 0;
while (n > 0) {
rev = rev * 10 + (n % 10);
n /= 10;
}
return rev;
}
// generates base 10 palindromes greater than 100 starting
// with the specified digit
class palindrome_generator {
public:
palindrome_generator(int digit) : power_(10), next_(digit * power_ - 1),
digit_(digit), even_(false) {}
integer next_palindrome() {
++next_;
if (next_ == power_ * (digit_ + 1)) {
if (even_)
power_ *= 10;
next_ = digit_ * power_;
even_ = !even_;
}
return next_ * (even_ ? 10 * power_ : power_)
+ reverse(even_ ? next_ : next_/10);
}
private:
integer power_;
integer next_;
int digit_;
bool even_;
};
bool gapful(integer n) {
integer m = n;
while (m >= 10)
m /= 10;
return n % (n % 10 + 10 * m) == 0;
}
template<size_t len>
void print(integer (&array)[9][len]) {
for (int digit = 1; digit < 10; ++digit) {
std::cout << digit << ":";
for (int i = 0; i < len; ++i)
std::cout << ' ' << array[digit - 1][i];
std::cout << '\n';
}
}
int main() {
const int n1 = 20, n2 = 15, n3 = 10;
const int m1 = 100, m2 = 1000;
integer pg1[9][n1];
integer pg2[9][n2];
integer pg3[9][n3];
for (int digit = 1; digit < 10; ++digit) {
palindrome_generator pgen(digit);
for (int i = 0; i < m2; ) {
integer n = pgen.next_palindrome();
if (!gapful(n))
continue;
if (i < n1)
pg1[digit - 1][i] = n;
else if (i < m1 && i >= m1 - n2)
pg2[digit - 1][i - (m1 - n2)] = n;
else if (i >= m2 - n3)
pg3[digit - 1][i - (m2 - n3)] = n;
++i;
}
}
std::cout << "First " << n1 << " palindromic gapful numbers ending in:\n";
print(pg1);
std::cout << "\nLast " << n2 << " of first " << m1 << " palindromic gapful numbers ending in:\n";
print(pg2);
std::cout << "\nLast " << n3 << " of first " << m2 << " palindromic gapful numbers ending in:\n";
print(pg3);
return 0;
}
- Output:
First 20 palindromic gapful numbers ending in: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of first 100 palindromic gapful numbers ending in: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of first 1000 palindromic gapful numbers ending in: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
Crystal
Brute force and slow
def palindromesgapful(digit, pow)
r1 = (10_u64**pow + 1) * digit
r2 = 10_u64**pow * (digit + 1)
nn = digit * 11
(r1...r2).select { |i| n = i.to_s; n == n.reverse && i.divisible_by?(nn) }
end
def digitscount(digit, count)
pow = 2
nums = [] of UInt64
while nums.size < count
nums += palindromesgapful(digit, pow)
pow += 1
end
nums[0...count]
end
count = 20
puts "First 20 palindromic gapful numbers ending with:"
(1..9).each { |digit| print "#{digit} : #{digitscount(digit, count)}\n" }
count = 100
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
(1..9).each { |digit| print "#{digit} : #{digitscount(digit, count).last(15)}\n" }
count = 1000
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
(1..9).each { |digit| print "#{digit} : #{digitscount(digit, count).last(10)}\n" }
Orders of Magnitude Faster: Direct Generation of Numbers
Crystal is a statically typed and a compiled language.
The code as implemented has been tested to produce optimum performance.
System: I7-6700HQ, 3.5GHz, Linux Kernel 5.6.17, Crystal 0.35 Run as: $ crystal run --release palindromicgapfuls.cr
Optimized version using number<->string conversion: 21.5 secs
def palindromicgapfuls(digit, count)
gapfuls = [] of UInt64 # array of palindromic gapfuls
dd = 11_u64 * digit # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_u64
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd)
return gapfuls if gapfuls.size == count
palindrome += base11
end
else
palindrome = (left_half.rchop + right_half).to_u64
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd)
return gapfuls if gapfuls.size == count
palindrome += base
end
end
end
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
puts (Time.monotonic - start).total_seconds
Compact version: 22.0 secs
def palindromicgapfuls(digit, count)
gapfuls = [] of UInt64 # array of palindromic gapfuls
dd = 11_u64 * digit # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
palindrome, left_half = 0_u64, front_half.to_s
basep, right_half = base11, left_half.reverse
(basep = base; left_half = left_half.rchop) if power.even?
palindrome = (left_half + right_half).to_u64
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd)
return gapfuls if gapfuls.size == count
palindrome += basep
end
end
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
puts (Time.monotonic - start).total_seconds
Object Oriented implementation: same speed - 21.8 seconds
Here using a Struct (allocated on stack) is faster than using a Class (allocated on heap)
struct PalindromicGapfuls
include Enumerable(UInt64)
@dd : Int32
def initialize(@digit : Int32)
@dd = 11 * @digit # digit gapful divisor: 11, 22,...88, 99
end
def each
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * @digit # starting half for this digit: 10.. to 90..
next_lo = base * (@digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_u64
10.times do
yield palindrome if palindrome.divisible_by?(@dd)
palindrome += base11
end
else
palindrome = (left_half.rchop + right_half).to_u64
10.times do
yield palindrome if palindrome.divisible_by?(@dd)
palindrome += base
end
end
end
end
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
puts (Time.monotonic - start).total_seconds
Original version optimized for minimal memory use: 24.6 secs
def palindromicgapfuls(digit, count, keep)
palcnt = 0 # count of gapful palindromes
to_skip = count - keep # count of unwanted values to skip
gapfuls = [] of UInt64 # array of palindromic gapfuls
dd = 11_u64 * digit # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_u64
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd) && (palcnt += 1) > to_skip
palindrome += base11
end
else
palindrome = (left_half.rchop + right_half).to_u64
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd) && (palcnt += 1) > to_skip
palindrome += base
end
end
return gapfuls[0...keep] unless gapfuls.size < keep
end
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
puts (Time.monotonic - start).total_seconds
Compact version optimized for minimal memory use: 24.5 secs
def palindromicgapfuls(digit, count, keep)
palcnt = 0 # count of gapful palindromes
to_skip = count - keep # count of unwanted values to skip
gapfuls = [] of UInt64 # array of palindromic gapfuls
dd, base = 11_u64 * digit, 1_u64 # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
base *= 10 if power.even? # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
palindrome, left_half = 0_u64, front_half.to_s
basep, right_half = base11, left_half.reverse
(basep = base; left_half = left_half.rchop) if power.even?
palindrome = (left_half + right_half).to_u64
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd) && (palcnt += 1) > to_skip
palindrome += basep
end
return gapfuls[0...keep] unless palcnt < count
end
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
puts (Time.monotonic - start).total_seconds
OOP version optimized for minimal memory use - 25.4 secs
It creates an output method that skips the unwanted values and only keeps/stores the desired ones.
struct PalindromicGapfuls
include Enumerable(UInt64)
@dd : Int32
def initialize(@digit : Int32)
@dd = 11 * @digit # digit gapful divisor: 11, 22,...88, 99
end
def each
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * @digit # starting half for this digit: 10.. to 90..
next_lo = base * (@digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_u64
10.times do
yield palindrome if palindrome.divisible_by?(@dd)
palindrome += base11
end
else
palindrome = (left_half.rchop + right_half).to_u64
10.times do
yield palindrome if palindrome.divisible_by?(@dd)
palindrome += base
end
end
end
end
end
# Optimized output method: only keep desired values.
def keep_from(count, keep)
to_skip = (count - keep)
kept = [] of UInt64
each_with_index do |value, i|
i < to_skip ? next : kept << value
return kept if kept.size == keep
end
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
puts (Time.monotonic - start).total_seconds
Compact minimized memory version that numerically create palindromes: 9.2 secs
def palindromicgapfuls(digit, count, keep)
palcnt = 0 # count of gapful palindromes
to_skip = count - keep # count of unwanted values to skip
gapfuls = [] of UInt64 # array of palindromic gapfuls
dd, base = 11_u64 * digit, 1_u64 # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
base *= 10 if power.even? # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
basep = power.odd? ? base11 : base
palindrome = make_palindrome(front_half, power)
10.times do
gapfuls << palindrome if palindrome.divisible_by?(dd) && (palcnt += 1) > to_skip
palindrome += basep
end
return gapfuls[0...keep] unless palcnt < count
end
end
end
def make_palindrome(front_half, power)
result = front_half
result //= 10 if power.even?
while front_half > 0
result = result * 10 + front_half.remainder(10)
front_half //= 10
end
result
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
puts (Time.monotonic - start).total_seconds
OOP version optimized for minimal memory use, palindromes created numerically - 9.59 secs
struct PalindromicGapfuls
include Enumerable(UInt64)
@dd : Int32
def initialize(@digit : Int32)
@dd = 11 * @digit # digit gapful divisor: 11, 22,...88, 99
end
def each
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * @digit # starting half for this digit: 10.. to 90..
next_lo = base * (@digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
basep = power.odd? ? base11 : base
palindrome = make_palindrome(front_half, power)
10.times do
yield palindrome if palindrome.divisible_by?(@dd)
palindrome += basep
end
end
end
end
# Optimized output method: only keep desired values.
def keep_from(count, keep)
to_skip = (count - keep)
kept = [] of UInt64
each_with_index do |value, i|
i < to_skip ? next : kept << value
return kept if kept.size == keep
end
end
def make_palindrome(front_half, power)
result = front_half
result //= 10 if power.even?
while front_half > 0
result = result * 10 + front_half.remainder(10)
front_half //= 10
end
result
end
end
start = Time.monotonic
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
puts (Time.monotonic - start).total_seconds
- Output:
First 20 palindromic gapful numbers 100 ending with: 1 : [121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] 2 : [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] 3 : [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] 4 : [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] 5 : [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] 6 : [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] 7 : [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] 8 : [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] 9 : [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] Last 15 of first 100 palindromic gapful numbers ending in: 1 : [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] 2 : [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] 3 : [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] 4 : [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] 5 : [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] 6 : [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] 7 : [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] 8 : [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] 9 : [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] Last 10 of first 1000 palindromic gapful numbers ending in: 1 : [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] 2 : [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] 3 : [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] 4 : [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] 5 : [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] 6 : [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] 7 : [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] 8 : [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] 9 : [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] 100,000th palindromic gapful number ending with: 1 : [178788887871] 2 : [278788887872] 3 : [30878611687803] 4 : [4833326233384] 5 : [578789987875] 6 : [60878611687806] 7 : [74826144162847] 8 : [80869688696808] 9 : [96878077087869] 1,000,000th palindromic gapful number ending with: 1 : [17878799787871] 2 : [27878799787872] 3 : [3087876666787803] 4 : [483333272333384] 5 : [57878799787875] 6 : [6087876996787806] 7 : [7487226666227847] 8 : [8086969559696808] 9 : [9687870990787869] 10,000,000th palindromic gapful number ending with: 1 : [1787878888787871] 2 : [2787878888787872] 3 : [308787855558787803] 4 : [48333332623333384] 5 : [5787878998787875] 6 : [608787855558787806] 7 : [748867523325768847] 8 : [808696968869696808] 9 : [968787783387787869]
Translation of F#
Recursive version; max memory consumption hits ~22%; comment out necessary outputs to run.
May produce: "GC Warning: Repeated allocation of very large block (appr. size xxxxxx):" messages in output.
For Crystal >= 0.34, the operations &+, &*, and &** turnoff default compiler overflow checks.
System: I7-6700HQ, 3.5GHz, 16GB, Linux Kernel 5.9.10, Crystal 0.35.1 Run as: $ crystal run --release fsharp2crystal.cr Best Time: 29.455717914 secs
class PalNo
@digit : UInt64
@dd : UInt64
def initialize(digit : Int32)
@digit, @l, @dd = digit.to_u64, 3, 11u64 * digit
end
def fN(n : Int32)
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] of UInt64 if n == 1
return [0, 11, 22, 33, 44, 55, 66, 77, 88, 99] of UInt64 if n == 2
a = [] of UInt64
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9] of UInt64).product(fN(n - 2)) do |g0, g1|
a << g0.to_u64 &* 10u64 &** (n - 1) &+ g0.to_u64 &+ 10u64 &* g1.to_u64
end
return a
end
def show(count, keep)
to_skip, palcnt, pals = count - keep, 0, [] of UInt64
while palcnt < count
fN(@l - 2).each do |g|
pal = @digit * 10u64 &** (@l - 1) + @digit + 10u64 &* g
pals << pal if pal % @dd == 0 && (palcnt += 1) > to_skip
break if palcnt - to_skip == keep
end
@l += 1
end
print pals; puts
end
end
start = Time.monotonic
(1..9).each { |digit| PalNo.new(digit).show(20, 20) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(100, 15) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(1000, 10) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(100_000, 1) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(1_000_000, 1) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(10_000_000, 1) }; puts "####"
puts (Time.monotonic - start).total_seconds
- Output:
[121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] #### [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] #### [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] #### [178788887871] [278788887872] [30878611687803] [4833326233384] [578789987875] [60878611687806] [74826144162847] [80869688696808] [96878077087869] #### [17878799787871] [27878799787872] [3087876666787803] [483333272333384] [57878799787875] [6087876996787806] [7487226666227847] [8086969559696808] [9687870990787869] #### [1787878888787871] [2787878888787872] [308787855558787803] [48333332623333384] [5787878998787875] [608787855558787806] [748867523325768847] [808696968869696808] [968787783387787869] ####
Delphi
This is among the faster versions of the problem. It solves the standard and optional tasks in 0.7 seconds.
{-------------Library Routines ----------------------------------------------------------------}
procedure GetDigits(N: integer; var IA: TIntegerDynArray);
{Get an array of the integers in a number}
{Numbers returned from least to most significant}
var T,I,DC: integer;
begin
DC:=Trunc(Log10(N))+1;
SetLength(IA,DC);
for I:=0 to DC-1 do
begin
T:=N mod 10;
N:=N div 10;
IA[I]:=T;
end;
end;
function GetNKPalindrome(N,K: int64): int64;
{Get Nth Palindrome with K-number of digits}
{N = Left half, Right = Reversed(left) a }
var Temp,H1,H2,I: int64;
begin
{Get left digit count - depends on K being odd/even}
if (K and 1)<>0 then Temp:=K div 2 else Temp:=K div 2 - 1;
{Get power of 10 digits}
H1:=trunc(Power(10, Temp));
{Add in N}
H1:=H1 + N - 1;
H2:=H1;
{ If K is odd, truncate the last digit}
if (k and 1)<>0 then H2:=H2 div 10;
{Reverse H2 and add to H1}
while H2>0 do
begin
H1:=H1 * 10 + (H2 mod 10);
H2:=H2 div 10;
end;
Result:=H1;
end;
function GetPalDigits(N: int64; var Offset: int64): integer;
{Get number of digits and offset for Nth Palindrome}
{Used to feed GetNKPalindrome to find Nth Palindrome}
var R1,R2,Step: int64;
begin
R1:=0;
{Step through number of digits}
for Result:=1 to 36 do
begin
{Calculate new Range step: 9,9,90,90,90,900,900...}
if (Result and 1)<>0 then Step:=9 * Trunc(Power(10,Result div 2));
{Calculate R2}
R2:=(R1 + Step)-1;
{See if N falls between R1 and R2}
if (N>=R1) and (N<=R2) then
begin
{Calculate offset and exit}
Offset:=(N - R1)+1;
exit;
end;
R1:=R2+1;
end;
end;
function GetNthPalindrome(N: integer): int64;
{Get the Nth Palindrome number}
var D,Off: int64;
begin
D:=GetPalDigits(N,Off);
Result:=GetNKPalindrome(Off,D);
end;
procedure GetPalindromeList(Count: integer; var Pals: TInt64DynArray);
{Get a list of the first "Count"-number of palinedromes (Fast)}
var D,I,Inx,Max: integer;
begin
{Set array length}
SetLength(Pals,Count);
Inx:=0;
{Handle palindromes up to 18 digits}
for D:=1 to 18 do
begin
{Get maximum count for palindrom of D digits}
if (D and 1)=1 then Max:=Trunc(Power(10,(D + 1) div 2))
else Max:=Trunc(Power(10,D div 2));
{Step through all the numbers half the size of the number of digits}
for I:=1 to Max-Max div 10 do
begin
{Store palindrome}
Pals[Inx]:=GetNKPalindrome(I,D);
Inc(Inx);
{Exit when array is full}
if Inx>=Count then break;
end;
end;
end;
{------------------------------------------------------------------------------------------------}
function IsGapful(N: int64): boolean;
{Return true if number is "GapFul"}
{GapFul = combined first/last}
{ digits divide evenly into N}
var Digits: TIntegerDynArray;
var I: int64;
begin
Result:=False;
{Must be 3 digit number}
if N<100 then exit;
{Put digits in array}
GetDigits(N,Digits);
{Form number from first and last digit}
I:=Digits[0] + 10 * Digits[High(Digits)];
{Does it divide evenly into N}
Result:=(N mod I)=0;
end;
function HasEndDigit(N: int64; Digit: integer): boolean;
{Return true if last digit match specified "Digit"}
var LD: integer;
begin
LD:=N mod 10;
Result:=LD=Digit;
end;
function GetGapfulPalinEndSet(Max, EndDigit: integer): string;
{Get first Max number of Gapful Palindromes with specified EndDigit}
var I,Cnt,P: integer;
begin
Result:='Ending in: '+IntToStr(EndDigit)+CRLF;
Cnt:=0;
{Get palindromes and test them}
for I:=0 to high(Integer) do
begin
{Get next palinedrome}
P:=GetNthPalindrome(I);
{Is Gapful and has specified EndDigit}
if IsGapFul(P) and HasEndDigit(P,EndDigit) then
begin
Inc(Cnt);
{Display it}
Result:=Result+Format('%8d',[P]);
if (Cnt mod 5)=0 then Result:=Result+CRLF;
{Break when finished}
if Cnt>=Max then break;
end;
end;
end;
function LastGapfulPalinEndSet(Count,Last,EndDigit: integer): string;
{Get Gapful Palindromes with specified EndDigit}
{Get "Last" number of items out of a total "Count" }
var I,Inx: integer;
var P: int64;
var IA: TInt64DynArray;
begin
SetLength(IA,Count);
Result:='Ending in: '+IntToStr(EndDigit)+CRLF;
{Get count number of items}
Inx:=0;
for I:=0 to Count-1 do
begin
{Keep getting palindromes until}
{they Gapful and have specified last digit}
repeat
begin
P:=GetNthPalindrome(Inx);
Inc(Inx);
end
until IsGapFul(P) and HasEndDigit(P,EndDigit);
{Save item}
IA[I]:=P;
end;
{Get last items}
for I:=Count-Last to Count-1 do
begin
Result:=Result+Format('%12d',[IA[I]]);
if (I mod 5)=4 then Result:=Result+CRLF;
end;
end;
procedure ShowPalindromicGapfuls(Memo: TMemo);
var S: string;
begin
Memo.Lines.Add('First 20 palindromic gapful numbers');
Memo.Lines.Add(GetGapFulPalinEndSet(20,1));
Memo.Lines.Add(GetGapFulPalinEndSet(20,2));
Memo.Lines.Add(GetGapFulPalinEndSet(20,3));
Memo.Lines.Add(GetGapFulPalinEndSet(20,4));
Memo.Lines.Add(GetGapFulPalinEndSet(20,5));
Memo.Lines.Add(GetGapFulPalinEndSet(20,6));
Memo.Lines.Add(GetGapFulPalinEndSet(20,7));
Memo.Lines.Add(GetGapFulPalinEndSet(20,8));
Memo.Lines.Add(GetGapFulPalinEndSet(20,9));
Memo.Lines.Add('86th to 100th');
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,1));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,2));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,3));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,4));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,5));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,6));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,7));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,8));
Memo.Lines.Add(LastGapFulPalinEndSet(100,15,9));
Memo.Lines.Add('991st to 1000th:');
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,1));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,2));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,3));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,4));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,5));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,6));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,7));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,8));
Memo.Lines.Add(LastGapFulPalinEndSet(1000,10,9));
end;
- Output:
First 20 palindromic gapful numbers Ending in: 1 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 Ending in: 2 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 Ending in: 3 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 Ending in: 4 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 Ending in: 5 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 Ending in: 6 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 Ending in: 7 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 Ending in: 8 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 Ending in: 9 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 86th to 100th Ending in: 1 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 Ending in: 2 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 Ending in: 3 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 Ending in: 4 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 Ending in: 5 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 Ending in: 6 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 Ending in: 7 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 Ending in: 8 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 Ending in: 9 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 991st to 1000th: Ending in: 1 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 Ending in: 2 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 Ending in: 3 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 Ending in: 4 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 Ending in: 5 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 Ending in: 6 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 Ending in: 7 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 Ending in: 8 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 Ending in: 9 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 Elapsed Time: 763.788 ms.
F#
// Palindromic Gapful Numbers . Nigel Galloway: December 3rd., 2020
let rec fN g l=seq{match l with 3->yield! seq{for n in 0L..9L->g*100L+g+n*10L}
|4->yield! seq{for n in 0L..9L->g*1000L+g+n*110L}
|_->yield! seq{for n in 0L..9L do for i in fN n (l-2)->i*10L+g+g*(pown 10L (l-1))}}
let rcGf n=let rec rcGf g=seq{yield! fN n g|>Seq.filter(fun g->g%(10L*n+n)=0L); yield! rcGf(g+1)} in rcGf 3
[1L..9L]|>Seq.iter(fun n->rcGf n|>Seq.take 20|>Seq.iter(printf "%d ");printfn "");printfn "#####"
[1L..9L]|>Seq.iter(fun n->rcGf n|>Seq.skip 85|>Seq.take 15|>Seq.iter(printf "%d ");printfn "");printfn "#####"
[1L..9L]|>Seq.iter(fun n->rcGf n|>Seq.skip 990|>Seq.take 10|>Seq.iter(printf "%d ");printfn "");printfn "#####"
- Output:
121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 ##### 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 ##### 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 #####
Factor
USING: formatting fry io kernel lists lists.lazy locals math
math.functions math.ranges math.text.utils prettyprint sequences ;
IN: rosetta-code.palindromic-gapful-numbers
! Palindromic numbers are relatively rare compared to gapful
! numbers, so our strategy for finding palindromic gapful
! numbers is to filter gapful numbers from palindromic numbers.
! Palindromic numbers can be generated directly rather than
! filtered or identified from the natural numbers. This is a
! significant speedup since palindromic numbers are relatively
! rare in the natural numbers.
! Here I have used a generation method similar to
! https://www.geeksforgeeks.org/generate-palindromic-numbers-less-n/
! Create a palindrome from its base natural number.
! e.g. 321 t -> 32123
! 321 f -> 321123
: create-palindrome ( n odd? -- m )
dupd [ 10 /i ] when swap [ over 0 > ]
[ 10 * [ 10 /mod ] [ + ] bi* ] while nip ;
! Create an infinite lazy list of palindromic numbers starting
! at 100.
: palindromes ( -- l )
1 lfrom [
10 swap ^ dup 10 * [a,b)
[ [ t create-palindrome ] map ]
[ [ f create-palindrome ] map ] bi
[ sequence>list ] bi@ lappend
] lmap-lazy lconcat ;
! Is an integer gapful?
: gapful? ( n -- ? )
dup 1 digit-groups [ first ] [ last 10 * + ] bi divisor? ;
! Create an infinite lazy list of gapful palindromes.
: gapful-palindromes ( -- l ) palindromes [ gapful? ] lfilter ;
:: show-palindromic-gapfuls ( last of -- )
gapful-palindromes :> nums
last of
"~~==[ Last %d of %d palindromic gapful numbers starting at 100 ]==~~\n"
printf 9 [1,b] [| d |
of nums [ 10 mod d = ] lfilter ltake list>array
last tail* d pprint ": " write [ pprint bl ] each nl
] each nl ;
20 20 ! part 1
15 100 ! part 2
10 1000 ! part 3 (Optional)
[ show-palindromic-gapfuls ] 2tri@
- Output:
~~==[ Last 20 of 20 palindromic gapful numbers starting at 100 ]==~~ 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 ~~==[ Last 15 of 100 palindromic gapful numbers starting at 100 ]==~~ 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 ~~==[ Last 10 of 1000 palindromic gapful numbers starting at 100 ]==~~ 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
FreeBASIC
Time-consuming brute-force solution with only a few speedups...
function is_gapful( n as uinteger ) as boolean
if n<100 then return false
dim as string ns = str(n)
dim as uinteger gap = 10*val(mid(ns,1,1)) + val(mid(ns,len(ns),1))
if n mod gap = 0 then return true else return false
end function
function is_palindrome( n as uinteger ) as boolean
dim as string ns = str(n)
for i as uinteger = 1 to len(ns)\2
if mid(ns,i,1) <> mid(ns,len(ns)+1-i,1) then return false
next i
return true
end function
function padto( n as uinteger, s as integer ) as string
dim as string outstr=""
dim as integer k = len(str(n))
for i as integer = 1 to s-k
outstr = " " + outstr
next i
return outstr + str(n)
end function
sub print_range( yays() as uinteger, first as uinteger, last as uinteger)
dim as string outstr
for i as uinteger = first to last
outstr = padto(i,4)+" : "
for d as uinteger = 1 to 9
outstr += padto(yays(d,i), 11)
next d
print outstr
next i
end sub
#define is_yay(n) (is_gapful(n) and is_palindrome(n))
#define log10(n) log(n)*0.43429448190325182765112891891660508229
dim as uinteger yays(1 to 9, 1 to 1000), nyays(1 to 9), num = 99, fd
do
num += 1 : fd = val(left(str(num),1))
if fd = 0 then continue do 'no paligap will have 0 as leading digit
if nyays(fd) = 1000 then
num = (fd+1)*10^int(log10(num))
end if
if is_yay(num) then
nyays(fd) += 1
yays(fd, nyays(fd)) = num
end if
for y as uinteger = 1 to 9
if nyays(y) < 1000 then continue do
next y
exit do
loop
'excessive output requirements for such a simple task
print_range(yays(), 1, 20)
print_range(yays(), 86, 100)
print_range(yays(), 991, 1000)
- Output:
1 : 121 242 363 484 5005 6006 7007 8008 9009 2 : 1001 2002 3003 4004 5115 6336 7777 8448 9999 3 : 1111 2112 3333 4224 5225 6666 77077 8888 94149 4 : 1221 2222 3663 4444 5335 6996 700007 80608 99099 5 : 1331 2332 3993 4664 5445 61116 707707 86768 900009 6 : 1441 2442 31713 4884 5555 64746 710017 88088 909909 7 : 1551 2552 33033 40304 5665 66066 717717 800008 918819 8 : 1661 2662 36663 42724 5775 69696 720027 802208 927729 9 : 1771 2772 300003 44044 5885 600006 727727 804408 936639 10 : 1881 2882 303303 46464 5995 603306 730037 806608 945549 11 : 1991 2992 306603 48884 50105 606606 737737 808808 954459 12 : 10901 20702 309903 400004 51315 609906 740047 821128 963369 13 : 11011 21912 312213 401104 52525 612216 747747 823328 972279 14 : 12221 22022 315513 402204 53735 615516 750057 825528 981189 15 : 13431 23232 318813 403304 54945 618816 757757 827728 990099 16 : 14641 24442 321123 404404 55055 621126 760067 829928 999999 17 : 15851 25652 324423 405504 56265 624426 767767 840048 9459549 18 : 17171 26862 327723 406604 57475 627726 770077 842248 9508059 19 : 18381 28182 330033 407704 58685 630036 777777 844448 9557559 20 : 19591 29392 333333 408804 59895 633336 780087 846648 9606069 86 : 165561 265562 30366303 4473744 565565 60399306 72299227 80611608 95311359 87 : 166661 266662 30399303 4485844 566665 60422406 72322327 80622608 95400459 88 : 167761 267762 30422403 4497944 567765 60455406 72399327 80633608 95499459 89 : 168861 268862 30455403 4607064 568865 60488406 72422427 80644608 95588559 90 : 169961 269962 30488403 4619164 569965 60511506 72499427 80655608 95677659 91 : 170071 270072 30511503 4620264 570075 60544506 72522527 80666608 95766759 92 : 171171 271172 30544503 4632364 571175 60577506 72599527 80677608 95855859 93 : 172271 272272 30577503 4644464 572275 60600606 72622627 80688608 95944959 94 : 173371 273372 30600603 4656564 573375 60633606 72699627 80699608 96033069 95 : 174471 274472 30633603 4668664 574475 60666606 72722727 80800808 96122169 96 : 175571 275572 30666603 4681864 575575 60699606 72799727 80811808 96211269 97 : 176671 276672 30699603 4693964 576675 60722706 72822827 80822808 96300369 98 : 177771 277772 30722703 4803084 577775 60755706 72899827 80833808 96399369 99 : 178871 278872 30755703 4815184 578875 60788706 72922927 80844808 96488469 100 : 179971 279972 30788703 4827284 579975 60811806 72999927 80855808 96577569 991 : 17799771 27799772 3084004803 482282284 57800875 6084004806 7452992547 8085995808 9675005769 992 : 17800871 27800872 3084334803 482414284 57811875 6084334806 7453223547 8086006808 9675995769 993 : 17811871 27811872 3084664803 482535284 57822875 6084664806 7453993547 8086116808 9676886769 994 : 17822871 27822872 3084994803 482656284 57833875 6084994806 7454224547 8086226808 9677777769 995 : 17833871 27833872 3085225803 482777284 57844875 6085225806 7454994547 8086336808 9678668769 996 : 17844871 27844872 3085555803 482898284 57855875 6085555806 7455225547 8086446808 9679559769 997 : 17855871 27855872 3085885803 482909284 57866875 6085885806 7455995547 8086556808 9680440869 998 : 17866871 27866872 3086116803 483020384 57877875 6086116806 7456226547 8086666808 9681331869 999 : 17877871 27877872 3086446803 483141384 57888875 6086446806 7456996547 8086776808 9682222869 1000 : 17888871 27888872 3086776803 483262384 57899875 6086776806 7457227547 8086886808 9683113869
Fōrmulæ
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.
Programs in Fōrmulæ are created/edited online in its website.
In this page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.
Go
This uses the same strategy as the Factor entry i.e. to generate all palindromic numbers in order and then test whether they're gapful or not.
To keep the Pascal entry company, I've extended the search to the first 10 million such numbers for each of the nine sets.
package main
import "fmt"
func reverse(s uint64) uint64 {
e := uint64(0)
for s > 0 {
e = e*10 + (s % 10)
s /= 10
}
return e
}
func commatize(n uint) string {
s := fmt.Sprintf("%d", n)
le := len(s)
for i := le - 3; i >= 1; i -= 3 {
s = s[0:i] + "," + s[i:]
}
return s
}
func ord(n uint) string {
var suffix string
if n > 10 && ((n-11)%100 == 0 || (n-12)%100 == 0 || (n-13)%100 == 0) {
suffix = "th"
} else {
switch n % 10 {
case 1:
suffix = "st"
case 2:
suffix = "nd"
case 3:
suffix = "rd"
default:
suffix = "th"
}
}
return fmt.Sprintf("%s%s", commatize(n), suffix)
}
func main() {
const max = 10_000_000
data := [][3]uint{{1, 20, 7}, {86, 100, 8}, {991, 1000, 10}, {9995, 10000, 12}, {1e5, 1e5, 14},
{1e6, 1e6, 16}, {1e7, 1e7, 18}}
results := make(map[uint][]uint64)
for _, d := range data {
for i := d[0]; i <= d[1]; i++ {
results[i] = make([]uint64, 9)
}
}
var p uint64
outer:
for d := uint64(1); d < 10; d++ {
count := uint(0)
pow := uint64(1)
fl := d * 11
for nd := 3; nd < 20; nd++ {
slim := (d + 1) * pow
for s := d * pow; s < slim; s++ {
e := reverse(s)
mlim := uint64(1)
if nd%2 == 1 {
mlim = 10
}
for m := uint64(0); m < mlim; m++ {
if nd%2 == 0 {
p = s*pow*10 + e
} else {
p = s*pow*100 + m*pow*10 + e
}
if p%fl == 0 {
count++
if _, ok := results[count]; ok {
results[count][d-1] = p
}
if count == max {
continue outer
}
}
}
}
if nd%2 == 1 {
pow *= 10
}
}
}
for _, d := range data {
if d[0] != d[1] {
fmt.Printf("%s to %s palindromic gapful numbers (> 100) ending with:\n", ord(d[0]), ord(d[1]))
} else {
fmt.Printf("%s palindromic gapful number (> 100) ending with:\n", ord(d[0]))
}
for i := 1; i <= 9; i++ {
fmt.Printf("%d: ", i)
for j := d[0]; j <= d[1]; j++ {
fmt.Printf("%*d ", d[2], results[j][i-1])
}
fmt.Println()
}
fmt.Println()
}
}
- Output:
1st to 20th palindromic gapful numbers (> 100) ending with: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 86th to 100th palindromic gapful numbers (> 100) ending with: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 991st to 1,000th palindromic gapful numbers (> 100) ending with: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 9,995th to 10,000th palindromic gapful numbers (> 100) ending with: 1: 1787447871 1787557871 1787667871 1787777871 1787887871 1787997871 2: 2787447872 2787557872 2787667872 2787777872 2787887872 2787997872 3: 308757757803 308760067803 308763367803 308766667803 308769967803 308772277803 4: 48326662384 48327872384 48329192384 48330303384 48331513384 48332723384 5: 5787447875 5787557875 5787667875 5787777875 5787887875 5787997875 6: 608760067806 608763367806 608766667806 608769967806 608772277806 608775577806 7: 746951159647 746958859647 746961169647 746968869647 746971179647 746978879647 8: 808690096808 808691196808 808692296808 808693396808 808694496808 808695596808 9: 968688886869 968697796869 968706607869 968715517869 968724427869 968733337869 100,000th palindromic gapful number (> 100) ending with: 1: 178788887871 2: 278788887872 3: 30878611687803 4: 4833326233384 5: 578789987875 6: 60878611687806 7: 74826144162847 8: 80869688696808 9: 96878077087869 1,000,000th palindromic gapful number (> 100) ending with: 1: 17878799787871 2: 27878799787872 3: 3087876666787803 4: 483333272333384 5: 57878799787875 6: 6087876996787806 7: 7487226666227847 8: 8086969559696808 9: 9687870990787869 10,000,000th palindromic gapful number (> 100) ending with: 1: 1787878888787871 2: 2787878888787872 3: 308787855558787803 4: 48333332623333384 5: 5787878998787875 6: 608787855558787806 7: 748867523325768847 8: 808696968869696808 9: 968787783387787869
Haskell
Brute Force
import Control.Monad (guard)
palindromic :: Int -> Bool
palindromic n = d == reverse d
where
d = show n
gapful :: Int -> Bool
gapful n = n `rem` firstLastDigit == 0
where
firstLastDigit = read [head asDigits, last asDigits]
asDigits = show n
result :: Int -> [Int]
result d = do
x <- [(d+100),(d+110)..]
guard $ palindromic x && gapful x
pure x
showSets :: (Int -> String) -> IO ()
showSets r = go 1
where
go n = if n <= 9 then do
putStrLn (show n ++ ": " ++ r n)
go (succ n)
else pure ()
main :: IO ()
main = do
putStrLn "\nFirst 20 palindromic gapful numbers ending in:"
showSets (show . take 20 . result)
putStrLn "\nLast 15 of first 100 palindromic gapful numbers ending in:"
showSets (show . drop 85 . take 100 . result)
putStrLn "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
showSets (show . drop 990 . take 1000 . result)
putStrLn "\ndone."
Optimized
Here the approach is to generate a series of palindromes.
import Data.List (sort, unfoldr)
import Control.Monad (guard)
gapful :: Int -> Bool
gapful n = n `rem` firstLastDigit n == 0
where
firstLastDigit = (\xs -> head xs * 10 + last xs) . reverse
. unfoldr (\n -> guard (n /= 0) >> pure (n `mod` 10, n `div` 10))
toPalinDrome :: Int -> [Int]
toPalinDrome n = filter ((&&) . (> 100) <*> gapful) [go n n, go n (n `div` 10)]
where
go p 0 = p
go p n'' = go (p * 10 + (n'' `mod` 10)) (n'' `div` 10)
gapfulPalindromes :: [Int]
gapfulPalindromes = (sort . (=<<) toPalinDrome) [1 .. 99999]
endsWith :: Int -> [Int]
endsWith n = filter ((n ==) . (`mod` 10)) gapfulPalindromes
showSets :: (String, [Int] -> [Int]) -> String
showSets (k, r) =
k ++
" palindromic gapful numbers ending in:\n" ++
unlines ((<*>) ((++) . show) ((": " ++) . show . r . endsWith) <$> [1 .. 9])
main :: IO ()
main =
mapM_
(putStrLn . showSets)
[ ("First 20", take 20)
, ("Last 15 of first 100", drop 85 . take 100)
, ("Last 10 of first 1000", drop 990 . take 1000)
]
- Output:
First 20 palindromic gapful numbers ending in: 1: [121,1001,1111,1221,1331,1441,1551,1661,1771,1881,1991,10901,11011,12221,13431,14641,15851,17171,18381,19591] 2: [242,2002,2112,2222,2332,2442,2552,2662,2772,2882,2992,20702,21912,22022,23232,24442,25652,26862,28182,29392] 3: [363,3003,3333,3663,3993,31713,33033,36663,300003,303303,306603,309903,312213,315513,318813,321123,324423,327723,330033,333333] 4: [484,4004,4224,4444,4664,4884,40304,42724,44044,46464,48884,400004,401104,402204,403304,404404,405504,406604,407704,408804] 5: [5005,5115,5225,5335,5445,5555,5665,5775,5885,5995,50105,51315,52525,53735,54945,55055,56265,57475,58685,59895] 6: [6006,6336,6666,6996,61116,64746,66066,69696,600006,603306,606606,609906,612216,615516,618816,621126,624426,627726,630036,633336] 7: [7007,7777,77077,700007,707707,710017,717717,720027,727727,730037,737737,740047,747747,750057,757757,760067,767767,770077,777777,780087] 8: [8008,8448,8888,80608,86768,88088,800008,802208,804408,806608,808808,821128,823328,825528,827728,829928,840048,842248,844448,846648] 9: [9009,9999,94149,99099,900009,909909,918819,927729,936639,945549,954459,963369,972279,981189,990099,999999,9459549,9508059,9557559,9606069] Last 15 of first 100 palindromic gapful numbers ending in: 1: [165561,166661,167761,168861,169961,170071,171171,172271,173371,174471,175571,176671,177771,178871,179971] 2: [265562,266662,267762,268862,269962,270072,271172,272272,273372,274472,275572,276672,277772,278872,279972] 3: [30366303,30399303,30422403,30455403,30488403,30511503,30544503,30577503,30600603,30633603,30666603,30699603,30722703,30755703,30788703] 4: [4473744,4485844,4497944,4607064,4619164,4620264,4632364,4644464,4656564,4668664,4681864,4693964,4803084,4815184,4827284] 5: [565565,566665,567765,568865,569965,570075,571175,572275,573375,574475,575575,576675,577775,578875,579975] 6: [60399306,60422406,60455406,60488406,60511506,60544506,60577506,60600606,60633606,60666606,60699606,60722706,60755706,60788706,60811806] 7: [72299227,72322327,72399327,72422427,72499427,72522527,72599527,72622627,72699627,72722727,72799727,72822827,72899827,72922927,72999927] 8: [80611608,80622608,80633608,80644608,80655608,80666608,80677608,80688608,80699608,80800808,80811808,80822808,80833808,80844808,80855808] 9: [95311359,95400459,95499459,95588559,95677659,95766759,95855859,95944959,96033069,96122169,96211269,96300369,96399369,96488469,96577569] Last 10 of first 1000 palindromic gapful numbers ending in: 1: [17799771,17800871,17811871,17822871,17833871,17844871,17855871,17866871,17877871,17888871] 2: [27799772,27800872,27811872,27822872,27833872,27844872,27855872,27866872,27877872,27888872] 3: [3084004803,3084334803,3084664803,3084994803,3085225803,3085555803,3085885803,3086116803,3086446803,3086776803] 4: [482282284,482414284,482535284,482656284,482777284,482898284,482909284,483020384,483141384,483262384] 5: [57800875,57811875,57822875,57833875,57844875,57855875,57866875,57877875,57888875,57899875] 6: [6084004806,6084334806,6084664806,6084994806,6085225806,6085555806,6085885806,6086116806,6086446806,6086776806] 7: [7452992547,7453223547,7453993547,7454224547,7454994547,7455225547,7455995547,7456226547,7456996547,7457227547] 8: [8085995808,8086006808,8086116808,8086226808,8086336808,8086446808,8086556808,8086666808,8086776808,8086886808] 9: [9675005769,9675995769,9676886769,9677777769,9678668769,9679559769,9680440869,9681331869,9682222869,9683113869] done.
J
Part 1:
task1 =: {. (((= 10&#:) # ]) palindromic_multiples_of_eleven) palindromic_multiples_of_eleven =: [: (#~ (99&< *. palindrome&>)) (11*i.100001)&* palindrome =: (-: |.)@:": 20 task1&> >:i.9 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069
Part 2:
palindromify=: [: , ((,~ |.@}.) ; (,~ |.))&>
gapful=: (0 = (|~ ({.,{:)&.(10&#.inv)))&>
task2_cartesian_products=: [: , [: { ((i. 10) ; (>: i. 9)) #~ ,&1
task2_palindromes=: [: 10&#.&> [: palindromify task2_cartesian_products
task2_gapfuls=: [: /:~ [: ; [: (#~ gapful)@task2_palindromes&.> >:@i.
palindromify { ;: 'abc XY' NB. demonstration +---+----+---+----+---+----+---+----+---+----+---+----+ |XaX|XaaX|YaY|YaaY|XbX|XbbX|YbY|YbbY|XcX|XccX|YcY|YccY| +---+----+---+----+---+----+---+----+---+----+---+----+ NB. task2 solution A=: task2_gapfuls 4 NB. A is an ordered vector of the 3 to 10 digit gapful palindromes B=: (</.~ 10&#:) A NB. B are A grouped by last (first) digit (# , {:)&> B NB. tally and tail of each group 12120 1999999991 12120 2999999992 4044 3999999993 6061 4899999984 12120 5999999995 4044 6999999996 1785 7999449997 3031 8889999888 1352 9999999999 (_15 {. 100&{.)&> B NB. the last 15 of the first hundred 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 (_10 {. 1000&{.)&> B NB. the last 10 of the first 1000 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 NB. timing NB. B matches the rearranged expression timespacex'assert B -: (</.~ 10&#:) task2_gapfuls 4' NB. approximate timing for the substantial part of the effort 0.551638 7.2343e7 NB. full memory, Thinkpad W540 JVERSION Engine: j901/j64avx2/windows Release-c: commercial/2020-01-11T13:29:14 Library: 9.01.20 Platform: Win 64 Installer: J901 install InstallPath: c:/program files/j901 Contact: www.jsoftware.com
Java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PalindromicGapfulNumbers {
public static void main(String[] args) {
System.out.println("First 20 palindromic gapful numbers ending in:");
displayMap(getPalindromicGapfulEnding(20, 20));
System.out.printf("%nLast 15 of first 100 palindromic gapful numbers ending in:%n");
displayMap(getPalindromicGapfulEnding(15, 100));
System.out.printf("%nLast 10 of first 1000 palindromic gapful numbers ending in:%n");
displayMap(getPalindromicGapfulEnding(10, 1000));
}
private static void displayMap(Map<Integer,List<Long>> map) {
for ( int key = 1 ; key <= 9 ; key++ ) {
System.out.println(key + " : " + map.get(key));
}
}
public static Map<Integer,List<Long>> getPalindromicGapfulEnding(int countReturned, int firstHowMany) {
Map<Integer,List<Long>> map = new HashMap<>();
Map<Integer,Integer> mapCount = new HashMap<>();
for ( int i = 1 ; i <= 9 ; i++ ) {
map.put(i, new ArrayList<>());
mapCount.put(i, 0);
}
boolean notPopulated = true;
for ( long n = 101 ; notPopulated ; n = nextPalindrome(n) ) {
if ( isGapful(n) ) {
int index = (int) (n % 10);
if ( mapCount.get(index) < firstHowMany ) {
map.get(index).add(n);
mapCount.put(index, mapCount.get(index) + 1);
if ( map.get(index).size() > countReturned ) {
map.get(index).remove(0);
}
}
boolean finished = true;
for ( int i = 1 ; i <= 9 ; i++ ) {
if ( mapCount.get(i) < firstHowMany ) {
finished = false;
break;
}
}
if ( finished ) {
notPopulated = false;
}
}
}
return map;
}
public static boolean isGapful(long n) {
String s = Long.toString(n);
return n % Long.parseLong("" + s.charAt(0) + s.charAt(s.length()-1)) == 0;
}
public static int length(long n) {
int length = 0;
while ( n > 0 ) {
length += 1;
n /= 10;
}
return length;
}
public static long nextPalindrome(long n) {
int length = length(n);
if ( length % 2 == 0 ) {
length /= 2;
while ( length > 0 ) {
n /= 10;
length--;
}
n += 1;
if ( powerTen(n) ) {
return Long.parseLong(n + reverse(n/10));
}
return Long.parseLong(n + reverse(n));
}
length = (length - 1) / 2;
while ( length > 0 ) {
n /= 10;
length--;
}
n += 1;
if ( powerTen(n) ) {
return Long.parseLong(n + reverse(n/100));
}
return Long.parseLong(n + reverse(n/10));
}
private static boolean powerTen(long n) {
while ( n > 9 && n % 10 == 0 ) {
n /= 10;
}
return n == 1;
}
private static String reverse(long n) {
return (new StringBuilder(n + "")).reverse().toString();
}
}
- Output:
First 20 palindromic gapful numbers ending in: 1 : [121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] 2 : [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] 3 : [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] 4 : [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] 5 : [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] 6 : [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] 7 : [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] 8 : [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] 9 : [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] Last 15 of first 100 palindromic gapful numbers ending in: 1 : [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] 2 : [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] 3 : [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] 4 : [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] 5 : [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] 6 : [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] 7 : [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] 8 : [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] 9 : [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] Last 10 of first 1000 palindromic gapful numbers ending in: 1 : [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] 2 : [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] 3 : [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] 4 : [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] 5 : [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] 6 : [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] 7 : [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] 8 : [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] 9 : [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869]
jq
Adapted from Crystal ("Direct Generation of Numbers")
Works with jq, the C implementation of jq
Works with gojq, the Go implementation of jq
The task as defined here (see "def task:") highlights the relative strengths and weakness of the C and Go implementations of jq.
In general, jq supports the efficient processing of streams, and the program presented below is accordingly based on a function that generates a stream of the numbers of interest.
The C implementation of jq is careful about memory management and has no problem completing the task. However this implementation relies on IEEE 754 arithmetic and thus the accuracy of results for integers with more than 15 digits cannot be relied on, and indeed the last line in the transcript is erroneous, as indicated by the annotation.
The Go implementation of jq, by contrast, though offering support for unbounded-precision integer arithmetic, is not so careful about memory management, and the program exhausts memory fairly quickly, as also indicated in the annotated transcript below.
### Generic functions
def power($a;$b): reduce range(0;$b) as $i (1; . * $a);
# Emit the reverse of the string $s
def reverse($s):
$s | tostring | split("") | reverse | join("");
def skip($n; stream):
foreach stream as $s (-1;
if . == $n then . else .+1 end;
select(. == $n) | $s);
### Palindromic gapful numbers
# Output: a stream of non-trivial palindromic gapful numbers ending in the specified digit
def palindromicgapfuls($digit):
{emit: null,
dd: (11 * $digit), # digit gapful divisor: 11, 22,...88, 99
power: 1}
| foreach range(0; infinite) as $_ (.;
.power += 1
| (power(10; .power / 2 | floor)) as $base # value of middle digit position: 10..
| ($base * 11) as $base11 # value of middle two digits positions: 110..
| ($base * $digit) as $this_lo # starting half for this digit: 10.. to 90..
| ($base * ($digit + 1)) as $next_lo # starting half for next digit: 20.. to 100..
| foreach range($this_lo; $next_lo; 10) as $front_half (.; # d_00; d_10; d_20; ...
($front_half|tostring) as $left_half
| reverse($left_half) as $right_half
| if .power%2 == 1
then .palindrome = (($left_half + $right_half) | tonumber)
| foreach range(0;10) as $i (.;
.emit = if .palindrome % .dd == 0
then .palindrome
else null
end
| .palindrome += $base11 )
else .palindrome = ((($left_half[:-1]) + $right_half) | tonumber)
| foreach range(0;10) as $i (.;
.emit = if .palindrome % .dd == 0
then .palindrome
else null
end
| .palindrome += $base )
end ) )
| select(.emit).emit ;
def palindromicgapfuls($count; $keep):
range(1; 10) as $digit
| "\($digit) : \([limit($keep; skip($count - $keep; palindromicgapfuls($digit)))])" ;
def task:
"First 20 non-trivial palindromic gapful numbers ending with:",
palindromicgapfuls(20; 20),
"\nLast 15 of first 100 non-trivial palindromic gapful numbers ending in:",
palindromicgapfuls(100; 15),
"\nLast 10 of first 1000 non-trivial palindromic gapful numbers ending in:",
palindromicgapfuls(1000; 10),
"\n100,000th non-trivial palindromic gapful number ending with:",
palindromicgapfuls(100000; 1),
"\n1,000,000th non-trivial palindromic gapful number ending with:",
palindromicgapfuls(1000000; 1);
task
- Output:
The output has been annotated, as explained above.
First 20 non-trivial palindromic gapful numbers ending with: 1 : [121,1001,1111,1221,1331,1441,1551,1661,1771,1881,1991,10901,11011,12221,13431,14641,15851,17171,18381,19591] 2 : [242,2002,2112,2222,2332,2442,2552,2662,2772,2882,2992,20702,21912,22022,23232,24442,25652,26862,28182,29392] 3 : [363,3003,3333,3663,3993,31713,33033,36663,300003,303303,306603,309903,312213,315513,318813,321123,324423,327723,330033,333333] 4 : [484,4004,4224,4444,4664,4884,40304,42724,44044,46464,48884,400004,401104,402204,403304,404404,405504,406604,407704,408804] 5 : [5005,5115,5225,5335,5445,5555,5665,5775,5885,5995,50105,51315,52525,53735,54945,55055,56265,57475,58685,59895] 6 : [6006,6336,6666,6996,61116,64746,66066,69696,600006,603306,606606,609906,612216,615516,618816,621126,624426,627726,630036,633336] 7 : [7007,7777,77077,700007,707707,710017,717717,720027,727727,730037,737737,740047,747747,750057,757757,760067,767767,770077,777777,780087] 8 : [8008,8448,8888,80608,86768,88088,800008,802208,804408,806608,808808,821128,823328,825528,827728,829928,840048,842248,844448,846648] 9 : [9009,9999,94149,99099,900009,909909,918819,927729,936639,945549,954459,963369,972279,981189,990099,999999,9459549,9508059,9557559,9606069] Last 15 of first 100 non-trivial palindromic gapful numbers ending in: 1 : [165561,166661,167761,168861,169961,170071,171171,172271,173371,174471,175571,176671,177771,178871,179971] 2 : [265562,266662,267762,268862,269962,270072,271172,272272,273372,274472,275572,276672,277772,278872,279972] 3 : [30366303,30399303,30422403,30455403,30488403,30511503,30544503,30577503,30600603,30633603,30666603,30699603,30722703,30755703,30788703] 4 : [4473744,4485844,4497944,4607064,4619164,4620264,4632364,4644464,4656564,4668664,4681864,4693964,4803084,4815184,4827284] 5 : [565565,566665,567765,568865,569965,570075,571175,572275,573375,574475,575575,576675,577775,578875,579975] 6 : [60399306,60422406,60455406,60488406,60511506,60544506,60577506,60600606,60633606,60666606,60699606,60722706,60755706,60788706,60811806] 7 : [72299227,72322327,72399327,72422427,72499427,72522527,72599527,72622627,72699627,72722727,72799727,72822827,72899827,72922927,72999927] 8 : [80611608,80622608,80633608,80644608,80655608,80666608,80677608,80688608,80699608,80800808,80811808,80822808,80833808,80844808,80855808] 9 : [95311359,95400459,95499459,95588559,95677659,95766759,95855859,95944959,96033069,96122169,96211269,96300369,96399369,96488469,96577569] Last 10 of first 1000 non-trivial palindromic gapful numbers ending in: 1 : [17799771,17800871,17811871,17822871,17833871,17844871,17855871,17866871,17877871,17888871] 2 : [27799772,27800872,27811872,27822872,27833872,27844872,27855872,27866872,27877872,27888872] 3 : [3084004803,3084334803,3084664803,3084994803,3085225803,3085555803,3085885803,3086116803,3086446803,3086776803] 4 : [482282284,482414284,482535284,482656284,482777284,482898284,482909284,483020384,483141384,483262384] 5 : [57800875,57811875,57822875,57833875,57844875,57855875,57866875,57877875,57888875,57899875] 6 : [6084004806,6084334806,6084664806,6084994806,6085225806,6085555806,6085885806,6086116806,6086446806,6086776806] 7 : [7452992547,7453223547,7453993547,7454224547,7454994547,7455225547,7455995547,7456226547,7456996547,7457227547] 8 : [8085995808,8086006808,8086116808,8086226808,8086336808,8086446808,8086556808,8086666808,8086776808,8086886808] 9 : [9675005769,9675995769,9676886769,9677777769,9678668769,9679559769,9680440869,9681331869,9682222869,9683113869] 100,000th non-trivial palindromic gapful number ending with: 1 : [178788887871] 2 : [278788887872] 3 : [30878611687803] 4 : [4833326233384] 5 : [578789987875] 6 : [60878611687806] 7 : [74826144162847] 8 : [80869688696808] 9 : [96878077087869] 1,000,000th palindromic gapful number ending with: 1 : [17878799787871] 2 : [27878799787872] 3 : [3087876666787803] 4 : [483333272333384] 5 : [57878799787875] 6 : [6087876996787806] #### gojq program terminated #### 7 : [7487226666227847] 8 : [8086969559696808] 9 : [97487364246378480] #### wrong
Julia
import Base.iterate, Base.IteratorSize, Base.IteratorEltype
struct Palindrome x1::UInt8; x2::UInt8; outer::UInt8; end
Base.IteratorSize(p::Palindrome) = Base.IsInfinite()
Base.IteratorEltype(g::Palindrome) = Vector{Int8}
function Base.iterate(p::Palindrome, state=(UInt8[p.x1]))
arr, len = [p.outer; state; p.outer], length(state)
if all(c -> c == p.x2, state)
return arr, fill(p.x1, len + 1)
end
for i in (len+1)÷2:-1:1
if state[i] < p.x2
state[len - i + 1] = state[i] = state[i] + one(UInt8)
return arr, state
else
state[len - i + 1] = state[i] = p.x1
end
end
state[1] += one(UInt8)
push!(state, state[1])
return arr, state
end
asint(s) = foldl((i, j) -> 10i + j, s)
isgapful(a) = mod(asint(a), a[1] * 11) == 0
GapfulPalindrome(i) = Iterators.filter(isgapful, Iterators.take(Palindrome(0, 9, i), 100000000000))
function testpal()
for (lastones, outof) in [(20, 20), (15, 100), (10, 1000), (10, 10000), (10, 100000), (10, 1000000), (10, 10000000)]
@time begin
println("\nLast digit | Last $lastones of $outof palindromic gapful numbers from 100\n",
"-----------|----------------------------------------------------------------------------------------------------------------")
output = fill("", 9)
Threads.@threads for i in 1:9
gplist = sort!(asint.(collect(Iterators.take(GapfulPalindrome(i), outof))))
output[i] = " $i " * string(gplist[end-lastones+1:end]) * "\n"
end
foreach(print, output)
end
end
end
testpal()
- Output:
Last digit | Last 20 of 20 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] 2 [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] 3 [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] 4 [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] 5 [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] 6 [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] 7 [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] 8 [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] 9 [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] 0.623229 seconds (1.68 M allocations: 85.926 MiB, 2.02% gc time) Last digit | Last 15 of 100 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] 2 [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] 3 [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] 4 [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] 5 [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] 6 [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] 7 [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] 8 [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] 9 [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] 0.011659 seconds (125.64 k allocations: 4.389 MiB) Last digit | Last 10 of 1000 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] 2 [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] 3 [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] 4 [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] 5 [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] 6 [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] 7 [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] 8 [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] 9 [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] 0.121723 seconds (1.31 M allocations: 45.342 MiB, 23.28% gc time) Last digit | Last 10 of 10000 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [1787007871, 1787117871, 1787227871, 1787337871, 1787447871, 1787557871, 1787667871, 1787777871, 1787887871, 1787997871] 2 [2787007872, 2787117872, 2787227872, 2787337872, 2787447872, 2787557872, 2787667872, 2787777872, 2787887872, 2787997872] 3 [308745547803, 308748847803, 308751157803, 308754457803, 308757757803, 308760067803, 308763367803, 308766667803, 308769967803, 308772277803] 4 [48322922384, 48323032384, 48324242384, 48325452384, 48326662384, 48327872384, 48329192384, 48330303384, 48331513384, 48332723384] 5 [5787007875, 5787117875, 5787227875, 5787337875, 5787447875, 5787557875, 5787667875, 5787777875, 5787887875, 5787997875] 6 [608748847806, 608751157806, 608754457806, 608757757806, 608760067806, 608763367806, 608766667806, 608769967806, 608772277806, 608775577806] 7 [746931139647, 746938839647, 746941149647, 746948849647, 746951159647, 746958859647, 746961169647, 746968869647, 746971179647, 746978879647] 8 [808686686808, 808687786808, 808688886808, 808689986808, 808690096808, 808691196808, 808692296808, 808693396808, 808694496808, 808695596808] 9 [968652256869, 968661166869, 968670076869, 968679976869, 968688886869, 968697796869, 968706607869, 968715517869, 968724427869, 968733337869] 1.194631 seconds (13.03 M allocations: 452.216 MiB, 19.09% gc time) Last digit | Last 10 of 100000 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [178779977871, 178780087871, 178781187871, 178782287871, 178783387871, 178784487871, 178785587871, 178786687871, 178787787871, 178788887871] 2 [278779977872, 278780087872, 278781187872, 278782287872, 278783387872, 278784487872, 278785587872, 278786687872, 278787787872, 278788887872] 3 [30878344387803, 30878377387803, 30878400487803, 30878433487803, 30878466487803, 30878499487803, 30878522587803, 30878555587803, 30878588587803, 30878611687803] 4 [4833228223384, 4833241423384, 4833253523384, 4833265623384, 4833277723384, 4833289823384, 4833290923384, 4833302033384, 4833314133384, 4833326233384] 5 [578780087875, 578781187875, 578782287875, 578783387875, 578784487875, 578785587875, 578786687875, 578787787875, 578788887875, 578789987875] 6 [60878344387806, 60878377387806, 60878400487806, 60878433487806, 60878466487806, 60878499487806, 60878522587806, 60878555587806, 60878588587806, 60878611687806] 7 [74825233252847, 74825333352847, 74825433452847, 74825533552847, 74825633652847, 74825733752847, 74825833852847, 74825933952847, 74826044062847, 74826144162847] 8 [80869599596808, 80869600696808, 80869611696808, 80869622696808, 80869633696808, 80869644696808, 80869655696808, 80869666696808, 80869677696808, 80869688696808] 9 [96877266277869, 96877355377869, 96877444477869, 96877533577869, 96877622677869, 96877711777869, 96877800877869, 96877899877869, 96877988977869, 96878077087869] 10.614688 seconds (129.23 M allocations: 4.349 GiB, 14.81% gc time) Last digit | Last 10 of 1000000 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [17878700787871, 17878711787871, 17878722787871, 17878733787871, 17878744787871, 17878755787871, 17878766787871, 17878777787871, 17878788787871, 17878799787871] 2 [27878700787872, 27878711787872, 27878722787872, 27878733787872, 27878744787872, 27878755787872, 27878766787872, 27878777787872, 27878788787872, 27878799787872] 3 [3087873993787803, 3087874224787803, 3087874554787803, 3087874884787803, 3087875115787803, 3087875445787803, 3087875775787803, 3087876006787803, 3087876336787803, 3087876666787803] 4 [483332292233384, 483332303233384, 483332424233384, 483332545233384, 483332666233384, 483332787233384, 483332919233384, 483333030333384, 483333151333384, 483333272333384] 5 [57878700787875, 57878711787875, 57878722787875, 57878733787875, 57878744787875, 57878755787875, 57878766787875, 57878777787875, 57878788787875, 57878799787875] 6 [6087874224787806, 6087874554787806, 6087874884787806, 6087875115787806, 6087875445787806, 6087875775787806, 6087876006787806, 6087876336787806, 6087876666787806, 6087876996787806] 7 [7487217557127847, 7487218558127847, 7487219559127847, 7487220660227847, 7487221661227847, 7487222662227847, 7487223663227847, 7487224664227847, 7487225665227847, 7487226666227847] 8 [8086968668696808, 8086968778696808, 8086968888696808, 8086968998696808, 8086969009696808, 8086969119696808, 8086969229696808, 8086969339696808, 8086969449696808, 8086969559696808] 9 [9687862882687869, 9687863773687869, 9687864664687869, 9687865555687869, 9687866446687869, 9687867337687869, 9687868228687869, 9687869119687869, 9687870000787869, 9687870990787869] 114.847779 seconds (1.28 G allocations: 43.170 GiB, 19.29% gc time) Last digit | Last 10 of 10000000 palindromic gapful numbers from 100 -----------|------------------------------------------------------------------------------------------------------------------------ 1 [1787877997787871, 1787878008787871, 1787878118787871, 1787878228787871, 1787878338787871, 1787878448787871, 1787878558787871, 1787878668787871, 1787878778787871, 1787878888787871] 2 [2787877997787872, 2787878008787872, 2787878118787872, 2787878228787872, 2787878338787872, 2787878448787872, 2787878558787872, 2787878668787872, 2787878778787872, 2787878888787872] 3 [308787828828787803, 308787831138787803, 308787834438787803, 308787837738787803, 308787840048787803, 308787843348787803, 308787846648787803, 308787849948787803, 308787852258787803, 308787855558787803] 4 [48333322822333384, 48333324142333384, 48333325352333384, 48333326562333384, 48333327772333384, 48333328982333384, 48333329092333384, 48333330203333384, 48333331413333384, 48333332623333384] 5 [5787878008787875, 5787878118787875, 5787878228787875, 5787878338787875, 5787878448787875, 5787878558787875, 5787878668787875, 5787878778787875, 5787878888787875, 5787878998787875] 6 [608787828828787806, 608787831138787806, 608787834438787806, 608787837738787806, 608787840048787806, 608787843348787806, 608787846648787806, 608787849948787806, 608787852258787806, 608787855558787806] 7 [748867469964768847, 748867472274768847, 748867479974768847, 748867482284768847, 748867489984768847, 748867492294768847, 748867499994768847, 748867503305768847, 748867513315768847, 748867523325768847] 8 [808696959959696808, 808696960069696808, 808696961169696808, 808696962269696808, 808696963369696808, 808696964469696808, 808696965569696808, 808696966669696808, 808696967769696808, 808696968869696808] 9 [968787702207787869, 968787711117787869, 968787720027787869, 968787729927787869, 968787738837787869, 968787747747787869, 968787756657787869, 968787765567787869, 968787774477787869, 968787783387787869] 1770.411549 seconds (13.02 G allocations: 443.799 GiB, 40.12% gc time)
Mathematica /Wolfram Language
ClearAll[GapfulQ, GetFirstPalindromicGapfulNumbers]
GapfulQ[n_Integer] := Divisible[n, FromDigits[IntegerDigits[n][[{1, -1}]]]]
GetFirstPalindromicGapfulNumbers[startend_, n_Integer] :=
Module[{out = {}, i, new, digs, id},
digs = 1;
While[Length[out] < n,
Do[
id = IntegerDigits[i, 10, Ceiling[digs/2]];
If[OddQ[digs],
new = Join[{startend}, id, Rest@Reverse[id], {startend}]
,
new = Join[{startend}, id, Reverse[id], {startend}]
];
new //= FromDigits;
If[GapfulQ[new],
AppendTo[out, new]
];
i++;
,
{i, 0, 10^Ceiling[digs/2] - 1}
];
digs += 1;
];
Take[out, n]
]
Print["First 20 palindromic gapful numbers >100 ending with each digit from 1 to 9:"]
Print[GetFirstPalindromicGapfulNumbers[#, 20]] & /@ Range[9];
Print["86th to 100th:"]
Print[GetFirstPalindromicGapfulNumbers[#, 100][[86 ;; 100]]] & /@ Range[9];
Print["991st to 1000th:"]
Print[GetFirstPalindromicGapfulNumbers[#, 1000][[991 ;; 1000]]] & /@ Range[9];
- Output:
First 20 palindromic gapful numbers >100 ending with each digit from 1 to 9: {121,1001,1111,1221,1331,1441,1551,1661,1771,1881,1991,10901,11011,12221,13431,14641,15851,17171,18381,19591} {242,2002,2112,2222,2332,2442,2552,2662,2772,2882,2992,20702,21912,22022,23232,24442,25652,26862,28182,29392} {363,3003,3333,3663,3993,31713,33033,36663,300003,303303,306603,309903,312213,315513,318813,321123,324423,327723,330033,333333} {484,4004,4224,4444,4664,4884,40304,42724,44044,46464,48884,400004,401104,402204,403304,404404,405504,406604,407704,408804} {5005,5115,5225,5335,5445,5555,5665,5775,5885,5995,50105,51315,52525,53735,54945,55055,56265,57475,58685,59895} {6006,6336,6666,6996,61116,64746,66066,69696,600006,603306,606606,609906,612216,615516,618816,621126,624426,627726,630036,633336} {7007,7777,77077,700007,707707,710017,717717,720027,727727,730037,737737,740047,747747,750057,757757,760067,767767,770077,777777,780087} {8008,8448,8888,80608,86768,88088,800008,802208,804408,806608,808808,821128,823328,825528,827728,829928,840048,842248,844448,846648} {9009,9999,94149,99099,900009,909909,918819,927729,936639,945549,954459,963369,972279,981189,990099,999999,9459549,9508059,9557559,9606069} 86th to 100th: {165561,166661,167761,168861,169961,170071,171171,172271,173371,174471,175571,176671,177771,178871,179971} {265562,266662,267762,268862,269962,270072,271172,272272,273372,274472,275572,276672,277772,278872,279972} {30366303,30399303,30422403,30455403,30488403,30511503,30544503,30577503,30600603,30633603,30666603,30699603,30722703,30755703,30788703} {4473744,4485844,4497944,4607064,4619164,4620264,4632364,4644464,4656564,4668664,4681864,4693964,4803084,4815184,4827284} {565565,566665,567765,568865,569965,570075,571175,572275,573375,574475,575575,576675,577775,578875,579975} {60399306,60422406,60455406,60488406,60511506,60544506,60577506,60600606,60633606,60666606,60699606,60722706,60755706,60788706,60811806} {72299227,72322327,72399327,72422427,72499427,72522527,72599527,72622627,72699627,72722727,72799727,72822827,72899827,72922927,72999927} {80611608,80622608,80633608,80644608,80655608,80666608,80677608,80688608,80699608,80800808,80811808,80822808,80833808,80844808,80855808} {95311359,95400459,95499459,95588559,95677659,95766759,95855859,95944959,96033069,96122169,96211269,96300369,96399369,96488469,96577569} 991st to 1000th: {17799771,17800871,17811871,17822871,17833871,17844871,17855871,17866871,17877871,17888871} {27799772,27800872,27811872,27822872,27833872,27844872,27855872,27866872,27877872,27888872} {3084004803,3084334803,3084664803,3084994803,3085225803,3085555803,3085885803,3086116803,3086446803,3086776803} {482282284,482414284,482535284,482656284,482777284,482898284,482909284,483020384,483141384,483262384} {57800875,57811875,57822875,57833875,57844875,57855875,57866875,57877875,57888875,57899875} {6084004806,6084334806,6084664806,6084994806,6085225806,6085555806,6085885806,6086116806,6086446806,6086776806} {7452992547,7453223547,7453993547,7454224547,7454994547,7455225547,7455995547,7456226547,7456996547,7457227547} {8085995808,8086006808,8086116808,8086226808,8086336808,8086446808,8086556808,8086666808,8086776808,8086886808} {9675005769,9675995769,9676886769,9677777769,9678668769,9679559769,9680440869,9681331869,9682222869,9683113869}
Nim
Forms palindromes using number<->string conversions.
import strutils # for number input
import times # for timing code execution
import unicode # for reversed
proc palindromicgapfuls(digit, count, keep: int): seq[uint64] =
var palcnt = 0 # count of gapful palindromes
let to_skip = count - keep # count of unwanted values to skip
var gapfuls = newSeq[uint64]() # array of palindromic gapfuls
let nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
var (power, base, basep) = (1, 1, 0)
while true:
if (power.inc; power and 1) == 0: base = base * 10
var base11 = base * 11 # value of middle two digits positions: 110..
var this_lo = base * digit # starting half for this digit: 10.. to 90..
var next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
while this_lo < next_lo - 1:
var (palindrome, palindrome_base, left_half) = (0'u64, 0'u64, this_lo.intToStr)
let right_half = left_half.reversed
if (power and 1) == 1: basep = base11; palindrome_base = (left_half & right_half).parseUInt
else: basep = base; left_half.removeSuffix("0"); palindrome_base = (left_half & right_half).parseUInt
for i in 0..9:
palindrome = palindrome_base + (basep * i).uint
if (palindrome mod nn.uint) == 0:
if palcnt < to_skip: (palcnt += 1; continue)
gapfuls.add(palindrome)
if gapfuls.len == keep: return gapfuls
this_lo += 10
let start = epochTime()
var (count, keep) = (20, 20)
echo("First 20 palindromic gapful numbers ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (100, 15)
echo("\nLast 15 of first 100 palindromic gapful numbers ending in:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (1_000, 10)
echo("\nLast 10 of first 1000 palindromic gapful numbers ending in:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (100_000, 1)
echo("\n100,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (1_000_000, 1)
echo("\n1,000,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (10_000_000, 1)
echo("\n10,000,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
echo (epochTime() - start)
System: I7-6700HQ, 3.5GHz, Linux Kernel 5.9.10, GCC 10.2.0, Nim 1.4.0 Compil: $ nim c --cc:gcc --d:danger palindromicgapfuls.nim Run as: $ ./palindromicgapfuls Time: 25.42800664901733 secs
Faster version performing number<->string conversions for palindromes.
import strutils # for number input
import times # for timing code execution
import unicode # for reversed
proc palindromicgapfuls(digit, count, keep: int): seq[uint64] =
var palcnt = 0 # count of gapful palindromes
let to_skip = count - keep # count of unwanted values to skip
let nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
var (power, base, digit) = (1, 1u64, digit.uint64)
while true:
if (power.inc; power and 1) == 0: base *= 10
let base11 = base * 11 # value of middle two digits positions: 110..
let this_lo = base * digit # starting half for this digit: 10.. to 90..
let next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
for front_half in countup(this_lo, next_lo - 2, 10):
var
basep = base11
left_half = $front_half
let right_half = left_half.reversed
if (power and 1) == 0: basep = base; left_half.setLen left_half.len - 1
var palindrome = (left_half.add right_half; left_half).parseUInt.uint64
for _ in 0..9:
if palindrome mod nn.uint == 0: (palcnt.inc; if palcnt > to_skip: result.add palindrome)
palindrome += basep
if result.len >= keep: result.setLen(keep); return
let start = epochTime()
var (count, keep) = (20, 20)
echo("First 20 palindromic gapful numbers ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (100, 15)
echo("\nLast 15 of first 100 palindromic gapful numbers ending in:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (1_000, 10)
echo("\nLast 10 of first 1000 palindromic gapful numbers ending in:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (100_000, 1)
echo("\n100,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (1_000_000, 1)
echo("\n1,000,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (10_000_000, 1)
echo("\n10,000,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
echo (epochTime() - start)
System: I7-6700HQ, 3.5GHz, Linux Kernel 5.9.10, GCC 10.2.0, Nim 1.4.0 Compil: $ nim c -d:danger -d:lto --passC:-march=native palindromicgapfuls.nim Run as: $ ./palindromicgapfuls Time: 18.29568219184875 secs
Fastest: make palindromes directly numerically.
import times
proc make_palindrome(front_half: uint64, power: int): uint64 =
var res, front_half = front_half
if (power and 1) == 0: res = res div 10
while front_half > 0:
res = res * 10 + front_half mod 10
front_half = front_half div 10
res
proc palindromicgapfuls(digit, count, keep: int): seq[uint64] =
var (palcnt, digit) = (0, digit.uint64) # count of gapful palindromes
let to_skip = count - keep # count of unwanted values to skip
var gapfuls = newSeq[uint64]() # array of palindromic gapfuls
let dd = digit * 11 # digit gapful divisor: 11, 22,...88, 99
var (power, base) = (1, 1u64)
while true:
if (power.inc; power and 1) == 0: base = base * 10
var base11 = base * 11 # value of middle two digits positions: 110..
var this_lo = base * digit # starting half for this digit: 10.. to 90..
var next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
for front_half in countup(this_lo, next_lo - 2, 10):
let basep = if (power and 1) == 1: base11 else: base
var palindrome = make_palindrome(front_half, power)
for _ in 0..9:
if palindrome mod dd == 0: (palcnt.inc; if palcnt > to_skip: gapfuls.add(palindrome))
palindrome += basep
if gapfuls.len >= keep: return gapfuls[0..keep-1]
let start = epochTime()
var (count, keep) = (20, 20)
echo("First 20 palindromic gapful numbers ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (100, 15)
echo("\nLast 15 of first 100 palindromic gapful numbers ending in:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (1_000, 10)
echo("\nLast 10 of first 1000 palindromic gapful numbers ending in:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (100_000, 1)
echo("\n100,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (1_000_000, 1)
echo("\n1,000,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
(count, keep) = (10_000_000, 1)
echo("\n10,000,000th palindromic gapful number ending with:")
for digit in 1..9: echo(digit, " : ", palindromicgapfuls(digit, count, keep) )
echo (epochTime() - start)
System: I7-6700HQ, 3.5GHz, Linux Kernel 5.9.14, GCC 10.2.0, Nim 1.4.2 Compil: $ nim c --cc:gcc --d:danger palindromicgapfuls.nim Run as: $ ./palindromicgapfuls Time: 8.304139614105225 secs
- Output:
First 20 palindromic gapful numbers ending with: 1 : @[121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] 2 : @[242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] 3 : @[363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] 4 : @[484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] 5 : @[5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] 6 : @[6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] 7 : @[7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] 8 : @[8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] 9 : @[9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] Last 15 of first 100 palindromic gapful numbers ending in: 1 : @[165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] 2 : @[265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] 3 : @[30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] 4 : @[4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] 5 : @[565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] 6 : @[60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] 7 : @[72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] 8 : @[80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] 9 : @[95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] Last 10 of first 1000 palindromic gapful numbers ending in: 1 : @[17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] 2 : @[27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] 3 : @[3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] 4 : @[482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] 5 : @[57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] 6 : @[6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] 7 : @[7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] 8 : @[8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] 9 : @[9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] 100,000th palindromic gapful number ending with: 1 : @[178788887871] 2 : @[278788887872] 3 : @[30878611687803] 4 : @[4833326233384] 5 : @[578789987875] 6 : @[60878611687806] 7 : @[74826144162847] 8 : @[80869688696808] 9 : @[96878077087869] 1,000,000th palindromic gapful number ending with: 1 : @[17878799787871] 2 : @[27878799787872] 3 : @[3087876666787803] 4 : @[483333272333384] 5 : @[57878799787875] 6 : @[6087876996787806] 7 : @[7487226666227847] 8 : @[8086969559696808] 9 : @[9687870990787869] 10,000,000th palindromic gapful number ending with: 1 : @[1787878888787871] 2 : @[2787878888787872] 3 : @[308787855558787803] 4 : @[48333332623333384] 5 : @[5787878998787875] 6 : @[608787855558787806] 7 : @[748867523325768847] 8 : @[808696968869696808] 9 : @[968787783387787869]
Pascal
Creating palindromes by adding the right numbers one by one and the precalculated modulus of that numbers
So the numbers to check stays small in bitsize modsum ~16 Bit , n ~ 64 Bit.Dividing is therefore faster
Thinking about it, you don't need n = Uint64, only the value of the digit in that place is enough.
Of course this task has no relevance see digit 9 from 100,000 to 10,000,000
9 : 96878077087869 9 : 9687870990787869 9 : 968787783387787869
program PalinGap;
{$IFDEF FPC}
{$MODE DELPHI}{$OPTIMIZATION ON,ALL}{$CODEALIGN proc=16}{$ALIGN 16}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
//example 5 digits, digit d
// d000d
// +00100 10 -times delta[0] aka middle digit
//->d010d d020d d030d d040d d050d d060d d070d d080d d090d and
// d100d -> not palindromatic
//correct by -10x00100 and use the next delta for the next digitplaces
// d000d
//+ 01010 -> delta[1]
// d101d
// starting over again with delta[0] until delta[1] is used 10 times
type
tLimits = record
LoLmt,HiLmt:Uint64;
end;
const
base = 10;
var
delta : Array[0..9] of Uint64;
deltaBase: Array[0..9] of Uint64;
deltaMod : Array[0..9] of Uint32;
deltaModBase : Array[0..9] of Uint32;
IdxCnt : Array[0..9] of Uint32;
ModSum : UInt64;
dgtMod : UInt32;
procedure InitDelta(dgt:Byte;dgtCnt:Byte);
var
n : Uint64;
i,k,mid : NativeInt;
Begin
mid := (dgtCnt-1) DIV 2;
//create Add masks
For i := 0 to mid do
Begin
IF ODD(dgtCnt) then
//first 1,101,10001,1000001,100000001,10000000001
Begin
n := 1;
IF i> 0 then
Begin
For k := 1 to i do
n := n*(Base*Base);
inc(n);
end
end
Else //even
// first 11,1001,100001,10000001...
Begin
n := Base;
For k := 1 to i do
n := n*(Base*Base);
inc(n);
end;
// second move to the right place
// 1000000,10100000,10001000,10000010,100000001
dgtMod := (dgt*(Base+1));
For k := mid-1 DOWNTO i do
n := n*Base;
delta[i] := n;
deltaMod[i]:= n MOD dgtMod;
deltaBase[i] := base*n;
deltaModBase[i]:= (base*n) MOD dgtMod;
end;
//counter for digit position
For k := 0 to 9 do
IdxCnt[k] := Base;
end;
function NextPalin(n : Uint64;dgtcnt:NativeInt):Uint64;inline;
var
k,b: NativeInt;
begin
k := 0;
repeat
n := n+delta[k];
inc(ModSum,deltaMod[k]);
b := IdxCnt[k]-1;
IdxCnt[k]:= b;
IF b <> 0 then
break
else
Begin
n := n-deltaBase[k];
dec(ModSum,deltaModBase[k]);
IdxCnt[k]:= Base;
inc(k);
IF k = dgtCnt then
Begin
n := 0;
BREAK;
end;
end;
until false;
NextPalin := n;
end;
procedure OutPalinGap(lowLmt,HiLmt,dgt:NativeInt);
var
n : Uint64;
i,dgtcnt,mid :NativeInt;
begin
i:=1;
write(dgt,' :');
For dgtcnt := 3 to 20 do
Begin
mid := (dgtcnt-1) shr 1;
initDelta(dgt,dgtcnt);
n := dgt*delta[mid];// '10...01' -> 'd0...0d'
ModSum := n MOD dgtMod;
while (n <>0) AND (i< LowLmt) do
Begin
IF (ModSum MOD dgtMod) = 0 then
Begin
inc(i);
ModSum :=0;//reduce Modsum
end;
n := NextPalin(n,mid);
end;
while (n <>0) AND (i<= HiLmt) do
Begin
IF (ModSum MOD dgtMod) = 0 then
Begin
inc(i);
write(n:dgtcnt+1);
ModSum :=0;//reduce Modsum
end;
n := NextPalin(n,mid);
end;
IF (i > HiLmt) then
BREAK;
end;
writeln;
end;
var
dgt : NativeInt;
begin
writeln('palindromic gapful numbers from 1 to 20');
For dgt := 1 to 9 do
OutPalinGap(1,20,dgt);
writeln;
writeln('palindromic gapful numbers from 86 to 100');
For dgt := 1 to 9 do
OutPalinGap(86,100,dgt);
writeln;
writeln('palindromic gapful numbers from 991 to 1000');
For dgt := 1 to 9 do
OutPalinGap(991,1000,dgt);
writeln;
writeln('palindromic gapful number 100,000');
For dgt := 1 to 9 do
OutPalinGap(100000,100000,dgt);
writeln;
writeln('palindromic gapful number 1,000,000');
For dgt := 1 to 9 do
OutPalinGap(1000000,1000000,dgt);
writeln;
writeln('palindromic gapful number 10,000,000');
For dgt := 1 to 9 do
OutPalinGap(10000000,10000000,dgt);
writeln;
end.
- Output:
palindromic gapful numbers from 1 to 20 1 : 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2 : 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3 : 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4 : 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5 : 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6 : 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7 : 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8 : 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9 : 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069
palindromic gapful numbers from 86 to 100 1 : 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2 : 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3 : 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4 : 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5 : 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6 : 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7 : 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8 : 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9 : 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569
palindromic gapful numbers from 991 to 1000 1 : 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2 : 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3 : 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4 : 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5 : 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6 : 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7 : 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8 : 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9 : 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
palindromic gapful number 100,000 1 : 178788887871 2 : 278788887872 3 : 30878611687803 4 : 4833326233384 5 : 578789987875 6 : 60878611687806 7 : 74826144162847 8 : 80869688696808 9 : 96878077087869
palindromic gapful number 1,000,000 1 : 17878799787871 2 : 27878799787872 3 : 3087876666787803 4 : 483333272333384 5 : 57878799787875 6 : 6087876996787806 7 : 7487226666227847 8 : 8086969559696808 9 : 9687870990787869
palindromic gapful number 10,000,000 1 : 1787878888787871 2 : 2787878888787872 3 : 308787855558787803 4 : 48333332623333384 5 : 5787878998787875 6 : 608787855558787806 7 : 748867523325768847 8 : 808696968869696808 9 : 968787783387787869
real 0m4,503s
Perl
Minor (and inefficient) tweak on the Gapful numbers task.
use strict;
use warnings;
use feature 'say';
use constant Inf => 1e10;
sub is_p_gapful {
my($d,$n) = @_;
return '' unless 0 == $n % 11;
my @digits = split //, $n;
$d eq $digits[0] and (0 == $n % ($digits[0].$digits[-1])) and $n eq join '', reverse @digits;
}
for ([1, 20], [86, 15]) {
my($offset, $count) = @$_;
say "Palindromic gapful numbers starting at $offset:";
for my $d ('1'..'9') {
my $n = 0; my $out = "$d: ";
$out .= do { $n+1 < $count+$offset ? (is_p_gapful($d,$_) and ++$n and $n >= $offset and "$_ ") : last } for 100 .. Inf;
say $out
}
say ''
}
- Output:
Palindromic gapful numbers starting at 1: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Palindromic gapful numbers starting at 86: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569
Phix
Translation of Go, but trimmed back to bare minimum: you should not expect this to fare particularly well at the 10_000_000-level against the likes of Go/Pascal, though it should fare reasonably well against lesser beings... The version below beats 'em all, though, for now.
with javascript_semantics function reverse_n(atom s) atom e = 0 while s>0 do e = e*10 + remainder(s,10) s = floor(s/10) end while return e end function constant mx = 1000, data = {{1, 20, "%7d "}, {86, 100, "%8d "}, {991, 1000, "%10d "}} include builtins\ordinal.e function digit(sequence results, integer d) integer count = 0, pow = 1, fl = d*11 for nd=3 to 15 do -- (number of digits, usually quits early) -- (obvs. 64-bit phix is fine with 19 digits, but 32-bit ain't) bool odd = (remainder(nd,2)==1) for s=d*pow to (d+1)*pow-1 do -- (eg 300 to 399) integer e = reverse_n(s) for m=0 to iff(odd?9:0) do -- (1 or 10 iterations) atom p = e + iff(odd ? s*pow*100+m*pow*10 : s*pow*10) if remainder(p,fl)==0 then -- gapful! count += 1 results[count][d] = p if count==mx then return results end if end if end for end for if odd then pow *= 10 end if end for if count<mx then ?9/0 end if -- oh dear... return results end function procedure main() sequence results = repeat(repeat({},9),mx) for d=1 to 9 do -- (the start/end digit) results = digit(results,d) end for for i=1 to length(data) do {integer s, integer e, string fmt} = data[i] printf(1,"%,d%s to %,d%s palindromic gapful numbers (> 100) ending with:\n", {s,ord(s),e,ord(e)}) for d=1 to 9 do printf(1,"%d: ",d) for j=s to e do printf(1,fmt,results[j][d]) end for printf(1,"\n") end for printf(1,"\n") end for end procedure main()
- Output:
1st to 20th palindromic gapful numbers (> 100) ending with: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 86th to 100th palindromic gapful numbers (> 100) ending with: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 991st to 1,000th palindromic gapful numbers (> 100) ending with: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
Ludicrously fast to 10,000,000,000,000,000,000th
You can run this online here.
-- -- demo\rosetta\Palindromic_gapful_numbers.exw -- =========================================== -- -- Astonishingly this is all done with standard precision numbers, <2^53. -- I will credit Self_numbers#AppleScript and comment by Nigel Galloway -- on the talk page for ideas that inspired me. -- -- A palindrome such as 9459549 can be constructed/broken down into -- 9000009 -- 400040 -- 50500 -- 9000 -- -- Further, 9459549 rem 99 is the same as -- (the sum of rem 99 on all of those pieces) rem 99 -- -- Finding eg 400040 rem 99 can also be simplified, it is of course the -- same as (400000 rem 99 + 40 rem 99) rem 99, and further 40 rem 99 -- is the same as (4 rem 99[already known])*10 rem 99 [smaller nos]. -- -- Also, when filling a "hole", such as the final 9, we find -- v -- 9450549 rem 99 = 9 -- 9451549 rem 99 = 19, -- 9452549 rem 99 = 29, -- 9453549 rem 99 = 39, -- 9454549 rem 99 = 49, -- 9455549 rem 99 = 59, -- 9456549 rem 99 = 69, -- 9457549 rem 99 = 79, -- 9458549 rem 99 = 89, and -- 9459549 rem 99 = 0, -- ^ -- in this case only the '9' fits. -- -- But actually we can predict what will fit from the partial sum of -- prior pieces rem 99, ie 9000009..50500, and the same can be said -- when filling the 505-sized hole - what will "fit" depends not on -- what the "outer" actually are, but what their sum rem 99 is, and -- likewise for larger and larger holes. -- If we later find ourselves looking at the same size hole, with -- the same outer rem and the same rem 99 outmost requirement, we -- would know instantly how many things are going to fit. -- True, keeping full lists as the holes got bigger would probably -- consume memory almost as fast as an SR-71, but a single count, -- albeit one keyed on 4 conditions, we can cope. It turns out that -- even by the 10^15th scan, we only hit 17,579 variations anyway. -- As we stumble across larger and larger holes, what we learn can -- be used to skip more and more similar, such that finding the -- ten millionth item is almost as fast as the first millionth, as -- opposed to the times 10 that you'd normally expect. -- -- Note that if I stumble across a hole that will fit more than I'm -- prepared to fully skip, I start going through things one-by-one, -- but that's ok because many smaller but still quite big holes -- will probably be skipped. -- with javascript_semantics sequence cache = columnize(repeat(columnize({tagset(9)}),9)) -- ie {{{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}}, -- {{2}, {2}, {2}, {2}, {2}, {2}, {2}, {2}, {2}}, -- {{3}, {3}, {3}, {3}, {3}, {3}, {3}, {3}, {3}}, -- {{4}, {4}, {4}, {4}, {4}, {4}, {4}, {4}, {4}}, -- {{5}, {5}, {5}, {5}, {5}, {5}, {5}, {5}, {5}}, -- {{6}, {6}, {6}, {6}, {6}, {6}, {6}, {6}, {6}}, -- {{7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}, {7}}, -- {{8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}, {8}}, -- {{9}, {9}, {9}, {9}, {9}, {9}, {9}, {9}, {9}}} -- aka 1 rem 11 .. 1 rem 99 are all 1, -- .. 9 rem 11 .. 9 rem 99 are all 9. -- each gets extended with 10 rem 11 .. 10 rem 99, -- 100 rem 11 .. 100 rem 99, -- ... .. 900 rem 99, etc. -- (not really worth trying to take advantage of any cycles -- that might appear in such a relatively small table, as -- it will be at most (on 64-bit) 9 * 9 * 42.) -- function rmdrn(integer digit, gap, pow, n) -- -- digit is the outer 0..9 (obvs 0 always yields 0), -- gap is zeroes between (-1,0,1,2,.. for eg 1,11,101,1001), -- pow is trailing zeros (0,1,2,.. for eg 101,1010,10100), -- n is 1..9 for 11..99 -- eg rmdrn(4,3,2,1) yields remainder(4000400,11), but -- that === remainder(remainder(4000000,11)+ -- remainder( 400,11),11), and -- if k = remainder(4*10^(m-1),11) [already known] then -- remainder(4*10^m,11) === remainder(k*10,11), so -- we only need to keep a small table for each [digit][n]. -- Thus we avoid maths on 10^42-ish numbers/needing gmp. -- if digit=0 then return 0 end if integer nn = n*11, g sequence cdn = cache[digit][n] while length(cdn)<gap+pow+2 do cache[digit][n] = 0 -- (kill refcount) cdn &= remainder(cdn[$]*10,nn) cache[digit][n] = cdn end while g = iff(gap=-1 ? 0 : cdn[gap+pow+2]) return remainder(g + cdn[pow+1],nn) end function integer skipd = new_dict() function palindromicgapfuls(sequence pals, string lhs, atom palcount, to_skip, count, integer l, r, p, dd) -- -- pals: results (passing it up grants it automatic pass-by-reference status, which may help speedwise) -- lhs: eg "945" of a potential 9459549 result -- palcount, to_skip, count: self explanatory (aka got/ignore/target) -- l: length of inner to be filled in -- r: remainder of outer, eg remainder(9400049,11), built from rmdrn() -- p: left shift (should in fact always equal length(lhs), I think) -- dd: outermost 1..9 (despite the name, it's a single digit) -- sequence key = {l,r,p,dd} integer node = getd_index(key,skipd) atom skip = iff(node==null?count:getd_by_index(node,skipd)), skipn if node!=null and (palcount+skip)<to_skip then palcount += skip else skip = 0 for d=0 to 9 do integer r2 = remainder(r+rmdrn(d,l-2,p,dd),dd*11) if l<=2 then if r2=0 then palcount += 1 if palcount<=to_skip then skip += 1 else pals = append(deep_copy(pals),lhs&repeat(d+'0',l)&reverse(lhs)) end if end if else {pals,palcount,skipn} = palindromicgapfuls(pals,lhs&(d+'0'),palcount,to_skip,count,l-2,r2,p+1,dd) skip += skipn end if if palcount==count then exit end if end for if palcount<to_skip then setd(key,skip,skipd) end if end if return {pals,palcount,skip} end function function collect(integer digit, atom count, keep) atom to_skip = count - keep, palcount = 0, l = 3 sequence pals = {} string lhs = ""&(digit+'0') -- ie "1" or "2" .. or "9" while palcount < count do integer r = rmdrn(digit,l-2,0,digit) {pals,palcount} = palindromicgapfuls(pals,lhs,palcount,to_skip,count,l-2,r,1,digit) l += 1 end while return pals end function constant tests = {{20,20,1,9},{100,15,1,9},{1000,10,1,9},{10_000,5,1,9}, {100_000,1,1,9},{1_000_000,1,1,9},{10_000_000,1,1,9}, {100_000_000,1,9,9},{1000_000_000,1,9,9},{10_000_000_000,1,9,9}, {100_000_000_000,1,9,9},{1000_000_000_000,1,9,9}, {10_000_000_000_000,1,9,9},{100_000_000_000_000,1,9,9}, {1_000_000_000_000_000,1,9,9}, -- {1_000_000_000_000_000,1,2,4}, -- (matches AppleScript) {10_000_000_000_000_000_000,1,9,9}} -- 64 bit only -- (any further and you'd need mpfr just to hold counts) atom t0 = time(), count, keep, start, finish for i=1 to length(tests)-(machine_bits()!=64) do {count, keep, start, finish} = tests[i] string r = iff(count==keep?sprintf("First %d",{count}): iff(keep>1?sprintf("Last %d of first %,d",{keep,count}) :sprintf("%,dth",{count}))), s = iff(keep=1?"":"s") printf(1,"%s palindromic gapful number%s ending with:\n", {r,s}) sequence tags = tagset(finish,start), res = apply(true,collect,{tags,count,keep}) string fmt = sprintf("%%%ds",max(apply(join(res,{}),length))) for j=1 to length(res) do printf(1,"%d: %s\n",{tags[j],join(apply(true,sprintf,{{fmt},res[j]})," ")}) end for puts(1,"\n") end for printf(1,"Completed in %s\n",elapsed(time()-t0))
- Output:
First 20 palindromic gapful numbers ending with: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of first 100 palindromic gapful numbers ending with: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of first 1,000 palindromic gapful numbers ending with: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 Last 5 of first 10,000 palindromic gapful numbers ending with: 1: 1787557871 1787667871 1787777871 1787887871 1787997871 2: 2787557872 2787667872 2787777872 2787887872 2787997872 3: 308760067803 308763367803 308766667803 308769967803 308772277803 4: 48327872384 48329192384 48330303384 48331513384 48332723384 5: 5787557875 5787667875 5787777875 5787887875 5787997875 6: 608763367806 608766667806 608769967806 608772277806 608775577806 7: 746958859647 746961169647 746968869647 746971179647 746978879647 8: 808691196808 808692296808 808693396808 808694496808 808695596808 9: 968697796869 968706607869 968715517869 968724427869 968733337869 100,000th palindromic gapful number ending with: 1: 178788887871 2: 278788887872 3: 30878611687803 4: 4833326233384 5: 578789987875 6: 60878611687806 7: 74826144162847 8: 80869688696808 9: 96878077087869 1,000,000th palindromic gapful number ending with: 1: 17878799787871 2: 27878799787872 3: 3087876666787803 4: 483333272333384 5: 57878799787875 6: 6087876996787806 7: 7487226666227847 8: 8086969559696808 9: 9687870990787869 10,000,000th palindromic gapful number ending with: 1: 1787878888787871 2: 2787878888787872 3: 308787855558787803 4: 48333332623333384 5: 5787878998787875 6: 608787855558787806 7: 748867523325768847 8: 808696968869696808 9: 968787783387787869 100,000,000th palindromic gapful number ending with: 9: 96878786855868787869 1,000,000,000th palindromic gapful number ending with: 9: 9687878775995778787869 10,000,000,000th palindromic gapful number ending with: 9: 968787878661166878787869 100,000,000,000th palindromic gapful number ending with: 9: 96878787877355377878787869 1,000,000,000,000th palindromic gapful number ending with: 9: 9687878787863773687878787869 10,000,000,000,000th palindromic gapful number ending with: 9: 968787878787711117787878787869 100,000,000,000,000th palindromic gapful number ending with: 9: 96878787878786133168787878787869 1,000,000,000,000,000th palindromic gapful number ending with: 9: 9687878787878768778678787878787869 Completed in 0.7s
On 64bit you'll also get (in 0.8s)
10,000,000,000,000,000,000th palindromic gapful number ending with: 9: 968787878787878787639936787878787878787869
I might agree that the last entry does not feel very convincing. Depending on how much spare time you have, leave this running and it'll look better, uncomment the reset of count, to something that'll actually finish, and you'll start to believe. :-)
--count = 100000
while count do
count -= 1
?collect(9,count,1)
end while
Prolog
init_palindrome(Digit, p(10, Next, 0)):-
Next is Digit * 10 - 1.
next_palindrome(Digit, p(Power, Next, Even), p(Power1, Next2, Even1), Palindrome):-
Next1 is Next + 1,
(Next1 is Power * (Digit + 1) ->
(Even == 1 -> Power1 is Power * 10 ; Power1 = Power),
Next2 is Digit * Power1,
Even1 is 1 - Even
;
Power1 = Power,
Next2 = Next1,
Even1 = Even
),
(Even1 == 1 ->
X is 10 * Power1, Y = Next2
;
X = Power1, Y is Next2 // 10
),
reverse_number(Y, Z),
Palindrome is Next2 * X + Z.
reverse_number(N, R):-
reverse_number(N, 0, R).
reverse_number(0, Result, Result):-
!.
reverse_number(N, R, Result):-
R1 is R * 10 + N mod 10,
N1 is N // 10,
reverse_number(N1, R1, Result).
is_gapful(N):-
is_gapful(N, N).
is_gapful(N, M):-
M < 10,
!,
0 is N mod (N mod 10 + 10 * (M mod 10)).
is_gapful(N, M):-
M1 is M // 10,
is_gapful(N, M1).
find_palindromic_gapful_numbers(N, List):-
find_palindromic_gapful_numbers(N, 1, List).
find_palindromic_gapful_numbers(_, 10, []):-
!.
find_palindromic_gapful_numbers(N, Digit, [Numbers|Rest]):-
find_palindromic_gapful_numbers1(Digit, N, Numbers),
Next_digit is Digit + 1,
find_palindromic_gapful_numbers(N, Next_digit, Rest).
find_palindromic_gapful_numbers1(Digit, N, List):-
init_palindrome(Digit, P),
find_palindromic_gapful_numbers1(Digit, P, N, 0, List).
find_palindromic_gapful_numbers1(_, _, N, N, []):-
!.
find_palindromic_gapful_numbers1(Digit, P, N, Count, List):-
next_palindrome(Digit, P, P_next, Palindrome),
(is_gapful(Palindrome) ->
Count1 is Count + 1,
List = [Palindrome|Rest]
;
Count1 = Count,
List = Rest
),
find_palindromic_gapful_numbers1(Digit, P_next, N, Count1, Rest).
print_numbers(First, Last, Numbers):-
(First == 1 ->
writef("First %w palindromic gapful numbers ending in:\n", [Last])
;
Count is Last - First + 1,
writef("Last %w of first %w palindromic gapful numbers ending in:\n", [Count, Last])
),
print_numbers(First, Last, 1, Numbers),
nl.
print_numbers(_, _, 10, _):-
!.
print_numbers(First, Last, Digit, [N|Numbers]):-
writef("%w:", [Digit]),
print_numbers1(First, Last, 1, N),
Next_digit is Digit + 1,
print_numbers(First, Last, Next_digit, Numbers).
print_numbers1(_, Last, I, _):-
I > Last,
nl,
!.
print_numbers1(First, Last, I, [_|Numbers]):-
I < First,
!,
J is I + 1,
print_numbers1(First, Last, J, Numbers).
print_numbers1(First, Last, I, [N|Numbers]):-
writef(" %w", [N]),
J is I + 1,
print_numbers1(First, Last, J, Numbers).
main:-
find_palindromic_gapful_numbers(1000, Numbers),
print_numbers(1, 20, Numbers),
print_numbers(86, 100, Numbers),
print_numbers(991, 1000, Numbers).
- Output:
First 20 palindromic gapful numbers ending in: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of first 100 palindromic gapful numbers ending in: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of first 1000 palindromic gapful numbers ending in: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
Python
Generators
Uses the technique of:
- generating all odd number of digits palindromes, in order.
- generating all even number of digits palindromes, in order.
- merge sorting those (unbounded) generators.
- then filtering the palindromes for gapful palindromic numbers >= 100
With the number generator the binning was straight-forward.
Runtime is short.
Note: Although this uses the idea of generating palindromes from the Geeks4geeks reference mentioned in the Factor entry, none of their code was used.
from itertools import count
from pprint import pformat
import re
import heapq
def pal_part_gen(odd=True):
for i in count(1):
fwd = str(i)
rev = fwd[::-1][1:] if odd else fwd[::-1]
yield int(fwd + rev)
def pal_ordered_gen():
yield from heapq.merge(pal_part_gen(odd=True), pal_part_gen(odd=False))
def is_gapful(x):
return (x % (int(str(x)[0]) * 10 + (x % 10)) == 0)
if __name__ == '__main__':
start = 100
for mx, last in [(20, 20), (100, 15), (1_000, 10)]:
print(f"\nLast {last} of the first {mx} binned-by-last digit "
f"gapful numbers >= {start}")
bin = {i: [] for i in range(1, 10)}
gen = (i for i in pal_ordered_gen() if i >= start and is_gapful(i))
while any(len(val) < mx for val in bin.values()):
g = next(gen)
val = bin[g % 10]
if len(val) < mx:
val.append(g)
b = {k:v[-last:] for k, v in bin.items()}
txt = pformat(b, width=220)
print('', re.sub(r"[{},\[\]]", '', txt))
- Output:
Last 20 of the first 20 binned-by-last digit gapful numbers >= 100 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of the first 100 binned-by-last digit gapful numbers >= 100 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of the first 1000 binned-by-last digit gapful numbers >= 100 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
Functional
'''Palindromic gapful numbers'''
from itertools import chain, count, islice, tee
from functools import reduce
# palindromicGapfuls :: () -> [Int]
def palindromicGapfuls():
'''A non-finite series of gapful palindromic numbers.
'''
def derived(digitsEven):
'''A palindrome of an even or odd number of digits,
obtained by appending either all or just the tail
of the reversed digits of n.
'''
def go(x):
s = str(x)
r = s[::-1]
return int((s + r) if digitsEven else (s + r[1:]))
return go
return filter(
lambda n: 0 == n % (int(str(n)[0]) * 10 + (n % 10)),
mergeInOrder(
map(derived(False), count(10))
)(map(derived(True), count(10)))
)
# --------------------------TESTS--------------------------
# main :: IO ()
def main():
'''Various samples of gapful palindromes grouped by final digit.'''
tpl = tee(palindromicGapfuls(), 9)
# sample :: (String, Int, Int) -> String
def sample(label, dropped, taken):
return fTable(label)(compose(cons(' '), str))(
compose(unwords, map_(str))
)(
compose(
take(taken),
drop(dropped),
lambda i: filter(
lambda x: i == x % 10,
tpl[i - 1]
)
)
)(enumFromTo(1)(9))
print(
'\n\n'.join(map(lambda x: sample(*x), [
('First 20 samples of gapful palindromes ' +
'(> 100) by last digit:', 0, 20),
('Last 15 of first 100 gapful palindromes ' +
'(> 100) by last digit:', 65, 15),
('Last 10 of first 1000 gapful palindromes ' +
'(> 100) by last digit:', 890, 10)
]))
)
# ------------------------DISPLAY -------------------------
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function -> fx display function ->
f -> xs -> tabular string.
'''
def go(xShow, fxShow, f, xs):
ys = [xShow(x) for x in xs]
w = max(map(len, ys))
return s + '\n' + '\n'.join(map(
lambda x, y: y.rjust(w, ' ') + ': ' + fxShow(f(x)),
xs, ys
))
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
xShow, fxShow, f, xs
)
# ------------------------GENERIC--------------------------
# Just :: a -> Maybe a
def Just(x):
'''Constructor for an inhabited Maybe (option type) value.
Wrapper containing the result of a computation.
'''
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
# Nothing :: Maybe a
def Nothing():
'''Constructor for an empty Maybe (option type) value.
Empty wrapper returned where a computation is not possible.
'''
return {'type': 'Maybe', 'Nothing': True}
# compose :: ((a -> a), ...) -> (a -> a)
def compose(*fs):
'''Composition, from right to left,
of a series of functions.
'''
def go(f, g):
return lambda x: f(g(x))
return reduce(go, fs, lambda x: x)
# cons :: a -> [a] -> [a]
def cons(x):
'''A list string or iterator constructed
from x as head, and xs as tail.
'''
return lambda xs: [x] + xs if (
isinstance(xs, list)
) else x + xs if (
isinstance(xs, str)
) else chain([x], xs)
# drop :: Int -> [a] -> [a]
def drop(n):
'''The sublist of xs beginning at
(zero-based) index n.
'''
def go(xs):
take(n)(xs)
return xs
return go
# enumFromTo :: Int -> Int -> [Int]
def enumFromTo(m):
'''Enumeration of integer values [m..n]'''
def go(n):
return list(range(m, 1 + n))
return go
# map :: (a -> b) -> [a] -> [b]
def map_(f):
'''The list obtained by applying f
to each element of xs.
'''
return lambda xs: [f(x) for x in xs]
# mergeInOrder :: Gen [Int] -> Gen [Int] -> Gen [Int]
def mergeInOrder(ga):
'''An ordered, non-finite, stream of integers
obtained by merging two other such streams.
'''
def go(ma, mb):
a = ma
b = mb
while not a['Nothing'] and not b['Nothing']:
(a1, a2) = a['Just']
(b1, b2) = b['Just']
if a1 < b1:
yield a1
a = uncons(a2)
else:
yield b1
b = uncons(b2)
return lambda gb: go(uncons(ga), uncons(gb))
# take :: Int -> [a] -> [a]
def take(n):
'''The prefix of xs of length n,
or xs itself if n > length xs.
'''
return lambda xs: list(islice(xs, n))
# uncons :: [a] -> Maybe (a, [a])
def uncons(xs):
'''The deconstruction of a non-empty list
(or generator stream) into two parts:
a head value, and the remaining values.
'''
nxt = take(1)(xs)
return Just((nxt[0], xs)) if nxt else Nothing()
# unwords :: [String] -> String
def unwords(xs):
'''A space-separated string derived
from a list of words.
'''
return ' '.join(xs)
# MAIN ---
if __name__ == '__main__':
main()
- Output:
First 20 samples of gapful palindromes (> 100) by last digit: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 Last 15 of first 100 gapful palindromes (> 100) by last digit: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 Last 10 of first 1000 gapful palindromes (> 100) by last digit: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
Raku
(formerly Perl 6)
constant @digits = '0','1','2','3','4','5','6','7','8','9';
# Infinite lazy iterator to generate palindromic "gap" numbers
my @npal = flat [ @digits ], [ '00','11','22','33','44','55','66','77','88','99' ],
{
sink @^previous, @^penultimate;
[ flat @digits.map: -> \digit { @penultimate.map: digit ~ * ~ digit } ]
} … *;
# Individual lazy palindromic gapful number iterators for each start/end digit
my @gappal = (1..9).map: -> \digit {
my \divisor = digit + 10 * digit;
@npal.map: -> \this { next unless (my \test = digit ~ this ~ digit) %% divisor; test }
}
# Display
( "(Required) First 20 gapful palindromes:", ^20, 7
,"\n(Required) 86th through 100th:", 85..99, 8
,"\n(Optional) 991st through 1,000th:", 990..999, 10
,"\n(Extra stretchy) 9,995th through 10,000th:", 9994..9999, 12
,"\n(Meh) 100,000th:", 99999, 14
).hyper(:1batch).map: -> $caption, $range, $fmt {
my $now = now;
say $caption;
put "$_: " ~ @gappal[$_-1][|$range].fmt("%{$fmt}s") for 1..9;
say round( now - $now, .001 ), " seconds";
}
- Output:
(Required) First 20 gapful palindromes: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 0.111 seconds (Required) 86th through 100th: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 0.046 seconds (Optional) 991st through 1,000th: 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 0.282 seconds (Extra stretchy) 9,995th through 10,000th: 1: 1787447871 1787557871 1787667871 1787777871 1787887871 1787997871 2: 2787447872 2787557872 2787667872 2787777872 2787887872 2787997872 3: 308757757803 308760067803 308763367803 308766667803 308769967803 308772277803 4: 48326662384 48327872384 48329192384 48330303384 48331513384 48332723384 5: 5787447875 5787557875 5787667875 5787777875 5787887875 5787997875 6: 608760067806 608763367806 608766667806 608769967806 608772277806 608775577806 7: 746951159647 746958859647 746961169647 746968869647 746971179647 746978879647 8: 808690096808 808691196808 808692296808 808693396808 808694496808 808695596808 9: 968688886869 968697796869 968706607869 968715517869 968724427869 968733337869 3.114 seconds (Meh) 100,000th: 1: 178788887871 2: 278788887872 3: 30878611687803 4: 4833326233384 5: 578789987875 6: 60878611687806 7: 74826144162847 8: 80869688696808 9: 96878077087869 32.603 seconds
REXX
/*REXX program computes and displays palindromic gapful numbers, it also can show those */
/*─────────────────────── palindromic gapful numbers listed by their last decimal digit.*/
numeric digits 20 /*ensure enough decimal digits gapfuls.*/
parse arg palGaps /*obtain optional arguments from the CL*/
if palGaps='' then palGaps= 20 100@@15 1000@@10 /*Not specified? Then use the defaults*/
do until palGaps=''; parse var palGaps stuff palGaps; call palGap stuff
end /*until*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
palGap: procedure; parse arg n '@' sp "@" z; #= 0; if sp=='' then sp= 100
@ending= ' (ending in a specific digit) '; if z=='' then z= n
@which= ' last '; if z==n then @which= " first "
@palGap#Start= ' palindromic gapful numbers starting at: '
say center(@which z ' of ' n @palGap#Start sp" " @ending, 140, "═")
#.= 0 /*array of result counts for each digit*/
newSP= max(110, sp%11*11) /*calculate the new starting point. */
tot= n * 9 /*total # of results that are wanted. */
$.=; sum= 0 /*blank lists; digit results (so far).*/
do j=newSP by 11 until sum==tot /*loop 'til all digit counters filled. */
if reverse(j) \==j then iterate /*Not a palindrome? Then skip it.*/
parse var j a 2 '' -1 b /*obtain the first and last dec. digit.*/
if #.b ==n then iterate /*Digit quota filled? Then skip it.*/
if j // (a||b) \==0 then iterate /*Not divisible by A||B? " " " */
sum= sum + 1; #.b= #.b + 1 /*bump the sum counter & digit counter.*/
$.b= $.b j /*append J to the correct list. */
end /*j*/
/* [↓] just show the last Z numbers.*/
do k=1 for 9; say k':' strip( subword($.k, 1 + n - z) )
end /*k*/; say
return
- output when using the internal default inputs:
(Shown at 5/6 size.)
═════════════════════ first 20 of 20 palindromic gapful numbers starting at: 100 (ending in a specific digit) ══════════════════════ 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 ═════════════════════ last 15 of 100 palindromic gapful numbers starting at: 100 (ending in a specific digit) ══════════════════════ 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 3: 30366303 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 4: 4473744 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 5: 565565 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 6: 60399306 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 7: 72299227 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 8: 80611608 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 9: 95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 ═════════════════════ last 10 of 1000 palindromic gapful numbers starting at: 100 (ending in a specific digit) ═════════════════════ 1: 17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 2: 27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 3: 3084004803 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 4: 482282284 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 5: 57800875 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 6: 6084004806 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 7: 7452992547 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 8: 8085995808 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 9: 9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869
Ring
load "stdlib.ring"
see "First 20 palindromic gapful numbers > 100 ending with each digit from 1 to 9:" + nl
limit = 9606069
for n = 1 to 9
sum = 0
for x = 101 to limit
flag = 0
strx = string(x)
xbegin = left(strx,1)
xend = right(strx,1)
xnew = number(xbegin+xend)
for y = 2 to ceil(x/2)+1
if ispalindrome(strx)
if y != xnew and x % y != 0
if x % xnew = 0 and number(xend) = n
flag = 1
else
flag = 0
exit
ok
ok
ok
next
if flag = 1
sum = sum + 1
if sum < 21
see "x = " + x + nl
else
exit
ok
ok
next
see nl
next
see "done..." + nl
Output:
First 20 palindromic gapful numbers > 100 ending with each digit from 1 to 9: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069
Ruby
Brute force and slow
def palindromesgapful(digit, pow)
r1 = digit * (10**pow + 1)
r2 = 10**pow * (digit + 1)
nn = digit * 11
(r1...r2).select { |i| n = i.to_s; n == n.reverse && i % nn == 0 }
end
def digitscount(digit, count)
pow = 2
nums = []
while nums.size < count
nums += palindromesgapful(digit, pow)
pow += 1
end
nums[0...count]
end
count = 20
puts "First 20 palindromic gapful numbers ending with:"
(1..9).each { |digit| print "#{digit} : #{digitscount(digit, count)}\n" }
count = 100
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
(1..9).each { |digit| print "#{digit} : #{digitscount(digit, count).last(15)}\n" }
count = 1000
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
(1..9).each { |digit| print "#{digit} : #{digitscount(digit, count).last(10)}\n" }
Orders of Magnitude Faster: Direct Generation of Numbers
Ruby is a dynamic language evaluated at runtime.
The code as implemented has been tested to produce optimum performance.
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.13 Run as: $ ruby palindromicgapfuls.rb
Optimized version, the ultimate fastest: Ruby 2.7.1 - 112.5 secs
def palindromicgapfuls(digit, count)
gapfuls = [] # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
power = 1 # these two lines will work
while power += 1 # for all Ruby VMs|versions
#(2..).each do |power| # Ruby => 2.6; can replace above 2 lines
base = 10**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_i
10.times do
gapfuls << palindrome if palindrome % nn == 0
palindrome += base11
end
else
palindrome = (left_half.chop + right_half).to_i
10.times do
gapfuls << palindrome if palindrome % nn == 0
palindrome += base
end
end
return gapfuls[0...count] unless gapfuls.size < count
end
end
end
start = Time.now
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
puts (Time.now - start)
Compact version: Ruby-2.7.1 - 113.0 secs
def palindromicgapfuls(digit, count)
gapfuls = [] # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
power = 1 # these two lines will work
while power += 1 # for all Ruby VMs|versions
#(2..).each do |power| # Ruby => 2.6; can replace above 2 lines
base = 10**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half, basep = front_half.to_s, base11; right_half = left_half.reverse
(basep = base; left_half = left_half.chop) if power.even?
palindrome = (left_half + right_half).to_i
10.times do
gapfuls << palindrome if palindrome % nn == 0
palindrome += basep
end
return gapfuls[0...count] unless gapfuls.size < count
end
end
end
start = Time.now
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count).last(keep)}" }
puts (Time.now - start)
Object Oriented implementation: Ruby 2.7.1 - 113.0 secs
class PalindromicGapfuls
include Enumerable
def initialize(digit)
@digit = digit
@nn = @digit * 11 # digit gapful divisor: 11, 22,...88, 99
end
def each
power = 1 # these two lines will work
while power += 1 # for all Ruby VMs|versions
#(2..).each do |power| # Ruby => 2.6; can replace above 2 lines
base = 10**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * @digit # starting half for this digit: 10.. to 90..
next_lo = base * (@digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_i
10.times do
yield palindrome if palindrome % @nn == 0
palindrome += base11
end
else
palindrome = (left_half.chop + right_half).to_i
10.times do
yield palindrome if palindrome % @nn == 0
palindrome += base
end
end
end
end
end
end
start = Time.now
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).first(count).last(keep)}" }
puts (Time.now - start)
Versions optimized for minimal memory use: Ruby 2.7.1 - 110.0 secs
def palindromicgapfuls(digit, count, keep)
palcnt = 0 # count of gapful palindromes
to_skip = count - keep # count of unwanted values to skip
gapfuls = [] # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
power = 1 # these two lines will work
while power += 1 # for all Ruby VMs|versions
#(2..).each do |power| # Ruby => 2.6; can replace above 2 lines
base = 10**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_i
10.times do
(gapfuls << palindrome if (palcnt += 1) > to_skip) if palindrome % nn == 0
palindrome += base11
end
else
palindrome = (left_half.chop + right_half).to_i
10.times do
(gapfuls << palindrome if (palcnt += 1) > to_skip) if palindrome % nn == 0
palindrome += base
end
end
return gapfuls[0...keep] unless gapfuls.size < keep
end
end
end
start = Time.now
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
puts (Time.now - start)
Compact version optimized for minimal memory use: Ruby 2.7.1 - 111.5 secs
def palindromicgapfuls(digit, count, keep)
palcnt = 0 # count of gapful palindromes
to_skip = count - keep # count of unwanted values to skip
gapfuls = [] # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
power = 1 # these two lines will work
while power += 1 # for all Ruby VMs|versions
#(2..).each do |power| # Ruby => 2.6; can replace above 2 lines
base = 10 ** (power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half, basep = front_half.to_s, base11; right_half = left_half.reverse
(basep = base; left_half = left_half.chop) if power.even?
palindrome = (left_half + right_half).to_i
10.times do
(gapfuls << palindrome if (palcnt += 1) > to_skip) if palindrome % nn == 0
palindrome += basep
end
return gapfuls[0...keep] unless gapfuls.size < keep
end
end
end
start = Time.now
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{palindromicgapfuls(digit, count, keep)}" }
puts (Time.now - start)
OOP version optimized for minimal memory use: Ruby 2.7.1 - 116.0 secs
It creates an output method that skips the unwanted values and only keeps/stores the desired ones.
class PalindromicGapfuls
include Enumerable
def initialize(digit)
@digit = digit
@nn = @digit * 11 # digit gapful divisor: 11, 22,...88, 99
end
def each
power = 1 # these two lines will work
while power += 1 # for all Ruby VMs|versions
#(2..).each do |power| # Ruby => 2.6; can replace above 2 lines
base = 10**(power >> 1) # value of middle digit position: 10..
base11 = base * 11 # value of middle two digits positions: 110..
this_lo = base * @digit # starting half for this digit: 10.. to 90..
next_lo = base * (@digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
left_half = front_half.to_s; right_half = left_half.reverse
if power.odd?
palindrome = (left_half + right_half).to_i
10.times do
yield palindrome if palindrome % @nn == 0
palindrome += base11
end
else
palindrome = (left_half.chop + right_half).to_i
10.times do
yield palindrome if palindrome % @nn == 0
palindrome += base
end
end
end
end
end
# Optimized output method: only keep desired values.
def keep_from(count, keep)
to_skip = (count - keep)
kept = []
each_with_index do |value, i|
i < to_skip ? next : kept << value
return kept if kept.size == keep
end
end
end
start = Time.now
count, keep = 20, 20
puts "First 20 palindromic gapful numbers ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 100, 15
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 1_000, 10
puts "\nLast 10 of first 1000 palindromic gapful numbers ending in:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 100_000, 1
puts "\n100,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 1_000_000, 1
puts "\n1,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
count, keep = 10_000_000, 1
puts "\n10,000,000th palindromic gapful number ending with:"
1.upto(9) { |digit| puts "#{digit} : #{PalindromicGapfuls.new(digit).keep_from(count, keep)}" }
puts (Time.now - start)
- Output:
First 20 palindromic gapful numbers 100 ending with: 1 : [121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] 2 : [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] 3 : [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] 4 : [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] 5 : [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] 6 : [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] 7 : [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] 8 : [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] 9 : [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] Last 15 of first 100 palindromic gapful numbers ending in: 1 : [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] 2 : [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] 3 : [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] 4 : [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] 5 : [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] 6 : [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] 7 : [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] 8 : [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] 9 : [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] Last 10 of first 1000 palindromic gapful numbers ending in: 1 : [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] 2 : [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] 3 : [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] 4 : [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] 5 : [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] 6 : [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] 7 : [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] 8 : [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] 9 : [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] 100,000th palindromic gapful number ending with: 1 : [178788887871] 2 : [278788887872] 3 : [30878611687803] 4 : [4833326233384] 5 : [578789987875] 6 : [60878611687806] 7 : [74826144162847] 8 : [80869688696808] 9 : [96878077087869] 1,000,000th palindromic gapful number ending with: 1 : [17878799787871] 2 : [27878799787872] 3 : [3087876666787803] 4 : [483333272333384] 5 : [57878799787875] 6 : [6087876996787806] 7 : [7487226666227847] 8 : [8086969559696808] 9 : [9687870990787869] 10,000,000th palindromic gapful number ending with: 1 : [1787878888787871] 2 : [2787878888787872] 3 : [308787855558787803] 4 : [48333332623333384] 5 : [5787878998787875] 6 : [608787855558787806] 7 : [748867523325768847] 8 : [808696968869696808] 9 : [968787783387787869]
Translation of F#
0.186s on Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz
class PalNo
def initialize(set)
@set, @l=set, 3
end
def fN(n)
return [0,1,2,3,4,5,6,7,8,9] if n==1
return [0,11,22,33,44,55,66,77,88,99] if n==2
a=[]; [0,1,2,3,4,5,6,7,8,9].product(fN(n-2)).each{|g| a.push(g[0]*10**(n-1)+g[0]+10*g[1])}; return a
end
def each
while true do fN(@l-2).each{|g| a=@set*10**(@l-1)+@set+10*g; yield a if a%(11*@set)==0}; @l+=1 end
end
end
for n in 1..9 do palNo=PalNo.new(n); g=1; palNo.each{|n| print "#{n} "; g+=1; break unless g<21}; puts "" end; puts "####"
for n in 1..9 do palNo=PalNo.new(n); g=1; palNo.each{|n| print "#{n} " if g>85; g+=1; break unless g<101}; puts "" end; puts "####"
for n in 1..9 do palNo=PalNo.new(n); g=1; palNo.each{|n| print "#{n} " if g>990; g+=1; break unless g<1001}; puts "" end; puts "####"
- Output:
121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 #### 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 180081 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 280082 30399303 30422403 30455403 30488403 30511503 30544503 30577503 30600603 30633603 30666603 30699603 30722703 30755703 30788703 30811803 4485844 4497944 4607064 4619164 4620264 4632364 4644464 4656564 4668664 4681864 4693964 4803084 4815184 4827284 4839384 566665 567765 568865 569965 570075 571175 572275 573375 574475 575575 576675 577775 578875 579975 580085 60422406 60455406 60488406 60511506 60544506 60577506 60600606 60633606 60666606 60699606 60722706 60755706 60788706 60811806 60844806 72322327 72399327 72422427 72499427 72522527 72599527 72622627 72699627 72722727 72799727 72822827 72899827 72922927 72999927 73033037 80622608 80633608 80644608 80655608 80666608 80677608 80688608 80699608 80800808 80811808 80822808 80833808 80844808 80855808 80866808 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 96666669 #### 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 17899871 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 27899872 3084334803 3084664803 3084994803 3085225803 3085555803 3085885803 3086116803 3086446803 3086776803 3087007803 482414284 482535284 482656284 482777284 482898284 482909284 483020384 483141384 483262384 483383384 57811875 57822875 57833875 57844875 57855875 57866875 57877875 57888875 57899875 57900975 6084334806 6084664806 6084994806 6085225806 6085555806 6085885806 6086116806 6086446806 6086776806 6087007806 7453223547 7453993547 7454224547 7454994547 7455225547 7455995547 7456226547 7456996547 7457227547 7457997547 8086006808 8086116808 8086226808 8086336808 8086446808 8086556808 8086666808 8086776808 8086886808 8086996808 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 9684004869 ####
More user friendly|simpler implementation; max memory consumption hits ~50%.
System: I7-6700HQ, 3.5 GHz, 16GB, Linux Kernel 5.9.10, Ruby 2.7.2 Run as: $ ruby fsharp2ruby.rb Best Time: 437.566515299 secs
class PalNo
def initialize(digit)
@digit, @l, @dd = digit, 3, 11*digit
end
def fN(n)
return [0,1,2,3,4,5,6,7,8,9] if n==1
return [0,11,22,33,44,55,66,77,88,99] if n==2
a=[]; [0,1,2,3,4,5,6,7,8,9].product(fN(n-2)).each{ |g0,g1| a << g0*10**(n-1)+g0+10*g1 }; return a
end
def show(count, keep)
to_skip, palcnt, pals = count - keep, 0, []
while palcnt < count
fN(@l-2).each{ |g| pal=@digit*10**(@l-1)+@digit+10*g;
pals << pal if pal%(@dd)==0 && (palcnt += 1) > to_skip; break if palcnt - to_skip == keep }; @l+=1
end
print pals; puts
end
end
start = Time.now
(1..9).each { |digit| PalNo.new(digit).show(20, 20) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(100, 15) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(1000, 10) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(100_000, 1) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(1_000_000, 1) }; puts "####"
(1..9).each { |digit| PalNo.new(digit).show(10_000_000, 1) }; puts "####"
puts (Time.now - start)
- Output:
[121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] #### [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] #### [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] #### [178788887871] [278788887872] [30878611687803] [4833326233384] [578789987875] [60878611687806] [74826144162847] [80869688696808] [96878077087869] #### [17878799787871] [27878799787872] [3087876666787803] [483333272333384] [57878799787875] [6087876996787806] [7487226666227847] [8086969559696808] [9687870990787869] #### [1787878888787871] [2787878888787872] [308787855558787803] [48333332623333384] [5787878998787875] [608787855558787806] [748867523325768847] [808696968869696808] [968787783387787869] #### 437.566515299
Rust
This version uses number->string then string->number conversions to create palindromes.
fn palindromicgapfuls(digit: u64, count: u64, keep: usize) -> Vec<u64> {
let mut palcnt = 0u64; // count of gapful palindromes
let to_skip = count - keep as u64; // count of unwanted values to skip
let mut gapfuls: Vec<u64> = vec![]; // array of palindromic gapfuls
let nn = digit * 11; // digit gapful divisor: 11, 22,...88, 99
let (mut power, mut base) = (1, 1u64);
loop { power += 1;
if power & 1 == 0 { base *= 10 }; // value of middle digit position: 10..
let base11 = base * 11; // value of middle two digits positions: 110..
let this_lo = base * digit; // starting half for this digit: 10.. to 90..
let next_lo = base * (digit + 1); // starting half for next digit: 20.. to 100..
for front_half in (this_lo..next_lo-1).step_by(10) { // d_00; d_10; d_20; ...
let (mut left_half, mut basep) = (front_half.to_string(), 0);
let right_half = left_half.chars().rev().collect::<String>();
if power & 1 == 1 { basep = base11; left_half.push_str(&right_half) }
else { basep = base; left_half.pop(); left_half.push_str(&right_half) };
let mut palindrome = left_half.parse::<u64>().unwrap();
for _ in 0..10 {
if palindrome % nn == 0 { palcnt += 1; if palcnt > to_skip { gapfuls.push(palindrome) } };
palindrome += basep;
}
if gapfuls.len() >= keep { return gapfuls[0..keep].to_vec() };
}
}
}
fn main() {
let t = std::time::Instant::now();
let (count, keep) = (20, 20);
println!("First 20 palindromic gapful numbers ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (100, 15);
println!("\nLast 15 of first 100 palindromic gapful numbers ending in:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (1_000, 10);
println!("\nLast 10 of first 1000 palindromic gapful numbers ending in:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (100_000, 1);
println!("\n100,000th palindromic gapful number ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (1_000_000, 1);
println!("\n1,000,000th palindromic gapful number ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (10_000_000, 1);
println!("\n10,000,000th palindromic gapful number ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
println!("{:?}", t.elapsed())
}
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.9.10, Rust 1.48 Compil: $ rustc -C opt-level=3 -C target-cpu=native -C codegen-units=1 -C lto palindromicgapfuls.rs Run as: ./palindromicgapfuls Time: 19.973894976s
This version creates palindromes numerically instead of using number<->string conversions. About 2.5x faster.
fn palindromicgapfuls(digit: u64, count: u64, keep: usize) -> Vec<u64> {
let mut palcnt = 0u64; // count of gapful palindromes
let to_skip = count - keep as u64; // count of unwanted values to skip
let mut gapfuls: Vec<u64> = vec![]; // array of palindromic gapfuls
let nn = digit * 11; // digit gapful divisor: 11, 22,...88, 99
let (mut power, mut base) = (1, 1u64);
loop { power += 1;
if power & 1 == 0 { base *= 10 } // value of middle digit position: 10..
let base11 = base * 11; // value of middle two digits positions: 110..
let this_lo = base * digit; // starting half for this digit: 10.. to 90..
let next_lo = base * (digit + 1); // starting half for next digit: 20.. to 100..
for front_half in (this_lo..next_lo).step_by(10) { // d_00; d_10; d_20; ...
let basep = if power & 1 == 1 { base11 } else { base };
let mut palindrome = make_palindrome(front_half, power);
for _ in 0..10 {
if palindrome % nn == 0 { palcnt += 1; if palcnt > to_skip { gapfuls.push(palindrome) } };
palindrome += basep;
}
if gapfuls.len() >= keep { return gapfuls[0..keep].to_vec() };
} } }
fn make_palindrome(mut front_half: u64, power: u64) -> u64 {
let mut result = front_half;
if power & 1 == 0 { result /= 10; }
while front_half > 0 {
result *= 10;
result += front_half % 10;
front_half /= 10;
}
result
}
fn main() {
let t = std::time::Instant::now();
let (count, keep) = (20, 20);
println!("First 20 palindromic gapful numbers ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (100, 15);
println!("\nLast 15 of first 100 palindromic gapful numbers ending in:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (1_000, 10);
println!("\nLast 10 of first 1000 palindromic gapful numbers ending in:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (100_000, 1);
println!("\n100,000th palindromic gapful number ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (1_000_000, 1);
println!("\n1,000,000th palindromic gapful number ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
let (count, keep) = (10_000_000, 1);
println!("\n10,000,000th palindromic gapful number ending with:");
for digit in 1..10 { println!("{} : {:?}", digit, palindromicgapfuls(digit, count, keep)); }
println!("{:?}", t.elapsed())
}
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.9.10, Rust 1.48 Compil: $ rustc -C opt-level=3 -C target-cpu=native -C codegen-units=1 -C lto palindromicgapfuls.rs Run as: ./palindromicgapfuls Time: 8.768842134s
- Output:
First 20 palindromic gapful numbers 100 ending with: 1 : [121, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991, 10901, 11011, 12221, 13431, 14641, 15851, 17171, 18381, 19591] 2 : [242, 2002, 2112, 2222, 2332, 2442, 2552, 2662, 2772, 2882, 2992, 20702, 21912, 22022, 23232, 24442, 25652, 26862, 28182, 29392] 3 : [363, 3003, 3333, 3663, 3993, 31713, 33033, 36663, 300003, 303303, 306603, 309903, 312213, 315513, 318813, 321123, 324423, 327723, 330033, 333333] 4 : [484, 4004, 4224, 4444, 4664, 4884, 40304, 42724, 44044, 46464, 48884, 400004, 401104, 402204, 403304, 404404, 405504, 406604, 407704, 408804] 5 : [5005, 5115, 5225, 5335, 5445, 5555, 5665, 5775, 5885, 5995, 50105, 51315, 52525, 53735, 54945, 55055, 56265, 57475, 58685, 59895] 6 : [6006, 6336, 6666, 6996, 61116, 64746, 66066, 69696, 600006, 603306, 606606, 609906, 612216, 615516, 618816, 621126, 624426, 627726, 630036, 633336] 7 : [7007, 7777, 77077, 700007, 707707, 710017, 717717, 720027, 727727, 730037, 737737, 740047, 747747, 750057, 757757, 760067, 767767, 770077, 777777, 780087] 8 : [8008, 8448, 8888, 80608, 86768, 88088, 800008, 802208, 804408, 806608, 808808, 821128, 823328, 825528, 827728, 829928, 840048, 842248, 844448, 846648] 9 : [9009, 9999, 94149, 99099, 900009, 909909, 918819, 927729, 936639, 945549, 954459, 963369, 972279, 981189, 990099, 999999, 9459549, 9508059, 9557559, 9606069] Last 15 of first 100 palindromic gapful numbers ending in: 1 : [165561, 166661, 167761, 168861, 169961, 170071, 171171, 172271, 173371, 174471, 175571, 176671, 177771, 178871, 179971] 2 : [265562, 266662, 267762, 268862, 269962, 270072, 271172, 272272, 273372, 274472, 275572, 276672, 277772, 278872, 279972] 3 : [30366303, 30399303, 30422403, 30455403, 30488403, 30511503, 30544503, 30577503, 30600603, 30633603, 30666603, 30699603, 30722703, 30755703, 30788703] 4 : [4473744, 4485844, 4497944, 4607064, 4619164, 4620264, 4632364, 4644464, 4656564, 4668664, 4681864, 4693964, 4803084, 4815184, 4827284] 5 : [565565, 566665, 567765, 568865, 569965, 570075, 571175, 572275, 573375, 574475, 575575, 576675, 577775, 578875, 579975] 6 : [60399306, 60422406, 60455406, 60488406, 60511506, 60544506, 60577506, 60600606, 60633606, 60666606, 60699606, 60722706, 60755706, 60788706, 60811806] 7 : [72299227, 72322327, 72399327, 72422427, 72499427, 72522527, 72599527, 72622627, 72699627, 72722727, 72799727, 72822827, 72899827, 72922927, 72999927] 8 : [80611608, 80622608, 80633608, 80644608, 80655608, 80666608, 80677608, 80688608, 80699608, 80800808, 80811808, 80822808, 80833808, 80844808, 80855808] 9 : [95311359, 95400459, 95499459, 95588559, 95677659, 95766759, 95855859, 95944959, 96033069, 96122169, 96211269, 96300369, 96399369, 96488469, 96577569] Last 10 of first 1000 palindromic gapful numbers ending in: 1 : [17799771, 17800871, 17811871, 17822871, 17833871, 17844871, 17855871, 17866871, 17877871, 17888871] 2 : [27799772, 27800872, 27811872, 27822872, 27833872, 27844872, 27855872, 27866872, 27877872, 27888872] 3 : [3084004803, 3084334803, 3084664803, 3084994803, 3085225803, 3085555803, 3085885803, 3086116803, 3086446803, 3086776803] 4 : [482282284, 482414284, 482535284, 482656284, 482777284, 482898284, 482909284, 483020384, 483141384, 483262384] 5 : [57800875, 57811875, 57822875, 57833875, 57844875, 57855875, 57866875, 57877875, 57888875, 57899875] 6 : [6084004806, 6084334806, 6084664806, 6084994806, 6085225806, 6085555806, 6085885806, 6086116806, 6086446806, 6086776806] 7 : [7452992547, 7453223547, 7453993547, 7454224547, 7454994547, 7455225547, 7455995547, 7456226547, 7456996547, 7457227547] 8 : [8085995808, 8086006808, 8086116808, 8086226808, 8086336808, 8086446808, 8086556808, 8086666808, 8086776808, 8086886808] 9 : [9675005769, 9675995769, 9676886769, 9677777769, 9678668769, 9679559769, 9680440869, 9681331869, 9682222869, 9683113869] 100,000th palindromic gapful number ending with: 1 : [178788887871] 2 : [278788887872] 3 : [30878611687803] 4 : [4833326233384] 5 : [578789987875] 6 : [60878611687806] 7 : [74826144162847] 8 : [80869688696808] 9 : [96878077087869] 1,000,000th palindromic gapful number ending with: 1 : [17878799787871] 2 : [27878799787872] 3 : [3087876666787803] 4 : [483333272333384] 5 : [57878799787875] 6 : [6087876996787806] 7 : [7487226666227847] 8 : [8086969559696808] 9 : [9687870990787869] 10,000,000th palindromic gapful number ending with: 1 : [1787878888787871] 2 : [2787878888787872] 3 : [308787855558787803] 4 : [48333332623333384] 5 : [5787878998787875] 6 : [608787855558787806] 7 : [748867523325768847] 8 : [808696968869696808] 9 : [968787783387787869]
Sidef
Inspired from the C++ and Raku entries.
class PalindromeGenerator (digit, base=10) {
has power = base
has after = (digit*power - 1)
has even = false
method next {
if (++after == power*(digit+1)) {
power *= base if even
after = digit*power
even.not!
}
even ? (after*power*base + reverse(after, base))
: (after*power + reverse(after/base, base))
}
}
var task = [
"(Required) First 20 gapful palindromes:", { .first(20) }, 7,
,"\n(Required) 86th through 100th:", { .first(1e2).last(15) }, 8,
,"\n(Optional) 991st through 1,000th:", { .first(1e3).last(10) }, 10,
,"\n(Extra stretchy) 9,995th through 10,000th:", { .first(1e4).last(6) }, 12,
]
task.each_slice(3, {|title, f, w|
say title
for d in (1..9) {
var k = 11*d
var iter = PalindromeGenerator(d)
var arr = f(^Inf->lazy.map { iter.next }.grep {|n| k `divides` n })
say ("#{d}: ", arr.map{ "%*s" % (w, _) }.join(' '))
}
})
- Output:
(Required) First 20 gapful palindromes: 1: 121 1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 10901 11011 12221 13431 14641 15851 17171 18381 19591 2: 242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 3: 363 3003 3333 3663 3993 31713 33033 36663 300003 303303 306603 309903 312213 315513 318813 321123 324423 327723 330033 333333 4: 484 4004 4224 4444 4664 4884 40304 42724 44044 46464 48884 400004 401104 402204 403304 404404 405504 406604 407704 408804 5: 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 50105 51315 52525 53735 54945 55055 56265 57475 58685 59895 6: 6006 6336 6666 6996 61116 64746 66066 69696 600006 603306 606606 609906 612216 615516 618816 621126 624426 627726 630036 633336 7: 7007 7777 77077 700007 707707 710017 717717 720027 727727 730037 737737 740047 747747 750057 757757 760067 767767 770077 777777 780087 8: 8008 8448 8888 80608 86768 88088 800008 802208 804408 806608 808808 821128 823328 825528 827728 829928 840048 842248 844448 846648 9: 9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 (Required) 86th through 100th: 1: 165561 166661 167761 168861 169961 170071 171171 172271 173371 174471 175571 176671 177771 178871 179971 2: 265562 266662 267762