Palindromic gapful numbers: Difference between revisions
Content deleted Content added
→{{header|AppleScript}}: →Translation of Phix "Ludicrously fast …": 6.5-fold speed increase by dumping NSMutableDictionary altogether. Several minor tweaks and comment changes. |
|||
Line 178: | Line 178: | ||
===Translation of Phix "Ludicrously fast …"=== |
===Translation of Phix "Ludicrously fast …"=== |
||
See [https://www.rosettacode.org/wiki/Palindromic_gapful_numbers#Ludicrously_fast_to_10.2C000.2C000.2C000.2C000.2C000.2C000th the original's] comments for an explanation of the logic. While this |
See [https://www.rosettacode.org/wiki/Palindromic_gapful_numbers#Ludicrously_fast_to_10.2C000.2C000.2C000.2C000.2C000.2C000th 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. |
||
<lang applescript> |
<lang applescript>-- Return a script object containing the main handlers. |
||
-- 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. |
-- It could be loaded as a library instead if there were any point in having such a library. |
||
on getWorks() |
on getWorks() |
||
script theWorks |
script theWorks |
||
⚫ | |||
use framework "Foundation" -- For its NSMutableDictionary class and methods. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
property outerDigit_x11 : missing value |
|||
⚫ | |||
property to_skip : missing value |
property to_skip : missing value |
||
property palcount : missing value |
property palcount : missing value |
||
property skipd : {{}, {}, {}, {}, {}, {}, {}, {}, {}} |
property skipd : {{}, {}, {}, {}, {}, {}, {}, {}, {}} |
||
property |
property skipdOuter : missing value |
||
property |
property pals : missing value |
||
-- Work out |
-- Work out the remainder from the division of the positive decimal integer value which is |
||
-- instances of |
-- 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( |
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 |
set coefficient to 10 ^ ((shift - 3) mod 6 + 3) |
||
if (gap > -1) then set |
if (gap > -1) then set coefficient to coefficient + 10 ^ ((gap + shift - 2) mod 6 + 3) |
||
return ( |
return (digit * coefficient mod outerX11) as integer |
||
end rmdr |
end rmdr |
||
-- Recursively |
-- 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) |
on palindromicGapfuls(lhs, gap, remainder) |
||
-- lhs: eg {9, 4, 5} of a potential |
-- lhs: eg {9, 4, 5} of a potential 945…549 result. |
||
-- gap: length of inner to be filled in |
-- gap: length of inner to be filled in |
||
-- remainder: remainder |
-- remainder: remainder of outer, eg 9400049 mod 11, but derived from rmdr() results. |
||
set shift to (count lhs) -- left shift |
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). |
|||
-- each containing 99 smaller dictionaries with two-element keys. The values of the original |
|||
-- The outermost digit element doesn't change during a search based on it, so the script property |
|||
-- 'outerDigit' and 'remainder' key elements are used to index this structure. Since 'outerDigit' |
|||
-- has |
-- 'skipdOuter' has been preset to skipd's outer-th sublist in the set-up for the current search. |
||
-- to the |
-- 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 {} |
|||
⚫ | |||
if (skip is missing value) then -- Key not in dictionary. Set 'skip' high for the 'if' test below. |
|||
repeat (gap - (count item shift of my skipdOuter)) times |
|||
⚫ | |||
else |
|||
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 |
|||
⚫ | |||
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 skip to 0 |
||
set template to lhs & missing value & reverse of lhs -- Palindrome template list. |
|||
set mid to shift + 1 -- Index of its middle position. |
|||
set nextGap to gap - 2 |
set nextGap to gap - 2 |
||
repeat with d from 0 to 9 |
repeat with d from 0 to 9 |
||
set nextRem to (remainder + rmdr(d, nextGap, shift)) mod |
set nextRem to (remainder + rmdr(d, nextGap, shift)) mod outerX11 |
||
if (gap > 2) then |
if (gap > 2) then |
||
set skip to skip + palindromicGapfuls(lhs & d, nextGap, nextRem) |
set skip to skip + palindromicGapfuls(lhs & d, nextGap, nextRem) |
||
else if (nextRem is 0) then |
else if (nextRem is 0) then |
||
-- A palindrome of lhs's contents around gap ds would be … gapful. |
|||
set palcount to palcount + 1 |
set palcount to palcount + 1 |
||
if (palcount > to_skip) then |
if (palcount > to_skip) then |
||
-- This one would be in the current keep range, so realise it as text and store it. |
|||
set |
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 if (gap is 0) then |
|||
-- set item mid of template to "" |
|||
-- else |
|||
-- set template to d |
|||
end if |
|||
set end of my output to template as text |
|||
else |
else |
||
set skip to skip + 1 |
set skip to skip + 1 |
||
end if |
end if |
||
end if |
end if |
||
if (palcount = |
if (palcount = countLimit) then exit repeat |
||
end repeat |
end repeat |
||
if (palcount < to_skip) then |
if (palcount < to_skip) then set item (remainder + 1) of item gap of item shift of my skipdOuter to skip |
||
else |
else |
||
set palcount to palcount + skip |
set palcount to palcount + skip |
||
Line 264: | Line 255: | ||
end palindromicGapfuls |
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( |
on collect(outer, countLimit, keep) |
||
-- Initialise |
-- Initialise script object properties for the current search. |
||
set |
set outerX11 to outer * 11 |
||
set |
set my countLimit to countLimit |
||
set |
set to_skip to countLimit - keep |
||
⚫ | |||
set palcount to 0 |
set palcount to 0 |
||
set |
set skipdOuter to item outer of my skipd |
||
set |
set pals to {} |
||
-- |
-- Also locals and TIDs. |
||
set |
set lhs to {outer} |
||
set |
set gap to 1 -- Number of digits between outer pair. |
||
set astid to AppleScript's text item delimiters |
set astid to AppleScript's text item delimiters |
||
set AppleScript's text item delimiters to "" |
set AppleScript's text item delimiters to "" -- For list-to-text coercions. |
||
repeat until (palcount = |
repeat until (palcount = countLimit) |
||
set remainder to rmdr( |
set remainder to rmdr(outer, gap, 0) |
||
palindromicGapfuls(lhs, gap, remainder) |
palindromicGapfuls(lhs, gap, remainder) |
||
set gap to gap + 1 |
set gap to gap + 1 |
||
Line 287: | Line 277: | ||
set AppleScript's text item delimiters to astid |
set AppleScript's text item delimiters to astid |
||
return |
return pals |
||
end collect |
end collect |
||
on initialiseSkipd() |
|||
repeat with thisList in my skipd |
|||
repeat 99 times |
|||
set end of thisList to current application's class "NSMutableDictionary"'s new() |
|||
⚫ | |||
⚫ | |||
end initialiseSkipd |
|||
end script |
end script |
||
tell theWorks to initialiseSkipd() |
|||
return theWorks |
return theWorks |
||
end getWorks |
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() |
on doTask() |
||
Line 310: | Line 301: | ||
{1.0E+13, 1, 9, 9}, {1.0E+14, 1, 9, 9}, ¬ |
{1.0E+13, 1, 9, 9}, {1.0E+14, 1, 9, 9}, ¬ |
||
{1.0E+15, 1, 2, 4}} |
{1.0E+15, 1, 2, 4}} |
||
-- set tests to {{20, 20, 1, 9}, {100, 15, 1, 9}, {1000, 10, 1, 9}} -- The |
-- set tests to {{20, 20, 1, 9}, {100, 15, 1, 9}, {1000, 10, 1, 9}} -- The RC task. |
||
set output to {} |
set output to {} |
||
Line 317: | Line 308: | ||
set AppleScript's text item delimiters to " " |
set AppleScript's text item delimiters to " " |
||
repeat with i from 1 to (count tests) |
repeat with i from 1 to (count tests) |
||
set { |
set {countLimit, keep, firstOuter, lastOuter} to item i of tests |
||
if (countLimit = keep) then |
|||
⚫ | |||
⚫ | |||
⚫ | |||
else if (keep > 1) then |
else if (keep > 1) then |
||
set |
set h to "Last " & keep & (" of first " & countLimit) |
||
⚫ | |||
⚫ | |||
⚫ | |||
if ((keep = 1) and (firstOuter = lastOuter)) then |
|||
⚫ | |||
⚫ | |||
⚫ | |||
else |
else |
||
set |
set h to h & " palindromic gapful numbers > 100 ending with digits from " & firstOuter & (" to " & lastOuter & ":") |
||
end if |
end if |
||
if (i > 1) then set end of output to "" |
|||
set end of output to h |
|||
repeat with outer from firstOuter to lastOuter |
|||
⚫ | |||
if (firstEndDigit is not lastEndDigit) then set t to "digits " & firstEndDigit & " to " & t |
|||
set end of output to "" |
|||
⚫ | |||
repeat with digit from firstEndDigit to lastEndDigit |
|||
⚫ | |||
end repeat |
end repeat |
||
end repeat |
end repeat |
||
set AppleScript's text item delimiters to linefeed |
set AppleScript's text item delimiters to linefeed |
||
set output to |
set output to output as text |
||
set AppleScript's text item delimiters to astid |
set AppleScript's text item delimiters to astid |
||
Line 346: | Line 339: | ||
{{output}} |
{{output}} |
||
<pre style="font-size:80%">First 20 palindromic gapful numbers > 100 ending with digits 1 to 9: |
<pre style="font-size:80%">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 |
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 |
242 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 20702 21912 22022 23232 24442 25652 26862 28182 29392 |
||
Line 357: | Line 350: | ||
9009 9999 94149 99099 900009 909909 918819 927729 936639 945549 954459 963369 972279 981189 990099 999999 9459549 9508059 9557559 9606069 |
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 1 to 9: |
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 |
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 |
265562 266662 267762 268862 269962 270072 271172 272272 273372 274472 275572 276672 277772 278872 279972 |
||
Line 368: | Line 361: | ||
95311359 95400459 95499459 95588559 95677659 95766759 95855859 95944959 96033069 96122169 96211269 96300369 96399369 96488469 96577569 |
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 1 to 9: |
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 |
17799771 17800871 17811871 17822871 17833871 17844871 17855871 17866871 17877871 17888871 |
||
27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 |
27799772 27800872 27811872 27822872 27833872 27844872 27855872 27866872 27877872 27888872 |
||
Line 379: | Line 372: | ||
9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 |
9675005769 9675995769 9676886769 9677777769 9678668769 9679559769 9680440869 9681331869 9682222869 9683113869 |
||
Last 5 of first 10000 palindromic gapful numbers > 100 ending with digits 1 to 9: |
Last 5 of first 10000 palindromic gapful numbers > 100 ending with digits from 1 to 9: |
||
1787557871 1787667871 1787777871 1787887871 1787997871 |
1787557871 1787667871 1787777871 1787887871 1787997871 |
||
2787557872 2787667872 2787777872 2787887872 2787997872 |
2787557872 2787667872 2787777872 2787887872 2787997872 |
||
Line 390: | Line 383: | ||
968697796869 968706607869 968715517869 968724427869 968733337869 |
968697796869 968706607869 968715517869 968724427869 968733337869 |
||
100000th palindromic gapful |
100000th palindromic gapful numbers > 100 ending with digits from 1 to 9: |
||
178788887871 |
178788887871 |
||
278788887872 |
278788887872 |
||
Line 401: | Line 394: | ||
96878077087869 |
96878077087869 |
||
1000000th palindromic gapful |
1000000th palindromic gapful numbers > 100 ending with digits from 1 to 9: |
||
17878799787871 |
17878799787871 |
||
27878799787872 |
27878799787872 |
||
Line 412: | Line 405: | ||
9687870990787869 |
9687870990787869 |
||
10000000th palindromic gapful |
10000000th palindromic gapful numbers > 100 ending with digits from 1 to 9: |
||
1787878888787871 |
1787878888787871 |
||
2787878888787872 |
2787878888787872 |
||
Line 444: | Line 437: | ||
96878787878786133168787878787869 |
96878787878786133168787878787869 |
||
1.0E+15th palindromic gapful |
1.0E+15th palindromic gapful numbers > 100 ending with digits from 2 to 4: |
||
27878787878787888878787878787872 |
27878787878787888878787878787872 |
||
3087878787878783113878787878787803 |
3087878787878783113878787878787803 |