Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
4
Task/Lychrel-numbers/00-META.yaml
Normal file
4
Task/Lychrel-numbers/00-META.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Palindromes
|
||||
from: http://rosettacode.org/wiki/Lychrel_numbers
|
||||
72
Task/Lychrel-numbers/00-TASK.txt
Normal file
72
Task/Lychrel-numbers/00-TASK.txt
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
::# Take an integer n, greater than zero.
|
||||
::# Form the next n of its series by reversing the digits of the current n and adding the result to the current n.
|
||||
::# Stop when n becomes palindromic - i.e. the digits of n in reverse order == n.
|
||||
|
||||
<br>
|
||||
The above recurrence relation when applied to most starting numbers n = 1, 2, ... terminates in a palindrome quite quickly.
|
||||
|
||||
|
||||
;Example:
|
||||
If n<sub>0</sub> = 12 we get
|
||||
<pre>
|
||||
12
|
||||
12 + 21 = 33, a palindrome!
|
||||
</pre>
|
||||
|
||||
And if n<sub>0</sub> = 55 we get
|
||||
<pre>
|
||||
55
|
||||
55 + 55 = 110
|
||||
110 + 011 = 121, a palindrome!
|
||||
</pre>
|
||||
|
||||
Notice that the check for a palindrome happens ''after'' an addition.
|
||||
|
||||
|
||||
Some starting numbers seem to go on forever; the recurrence relation for 196 has been calculated for millions of repetitions forming numbers with millions of digits, without forming a palindrome.
|
||||
|
||||
These numbers that do not end in a palindrome are called '''Lychrel numbers'''.
|
||||
|
||||
For the purposes of this task a Lychrel number is any starting number that does not form a palindrome within 500 (or more) iterations.
|
||||
|
||||
|
||||
;Seed and related Lychrel numbers:
|
||||
Any integer produced in the sequence of a Lychrel number is also a Lychrel number.
|
||||
|
||||
In general, any sequence from one Lychrel number ''might'' converge to join the sequence from a prior Lychrel number candidate; for example the sequences for the numbers 196 and then 689 begin:
|
||||
<pre>
|
||||
196
|
||||
196 + 691 = 887
|
||||
887 + 788 = 1675
|
||||
1675 + 5761 = 7436
|
||||
7436 + 6347 = 13783
|
||||
13783 + 38731 = 52514
|
||||
52514 + 41525 = 94039
|
||||
...
|
||||
|
||||
|
||||
689
|
||||
689 + 986 = 1675
|
||||
1675 + 5761 = 7436
|
||||
...
|
||||
</pre>
|
||||
So we see that the sequence starting with 689 converges to, and continues with the same numbers as that for 196.
|
||||
|
||||
Because of this we can further split the Lychrel numbers into true '''Seed''' Lychrel number candidates, and '''Related''' numbers that produce no palindromes but have integers in their sequence seen as part of the sequence generated from a lower Lychrel number.
|
||||
|
||||
|
||||
;Task:
|
||||
* Find the number of seed Lychrel number candidates and related numbers for n in the range 1..10000 inclusive. (With that iteration limit of 500).
|
||||
* Print the number of seed Lychrels found; the actual seed Lychrels; and just the ''number'' of relateds found.
|
||||
* Print any seed Lychrel or related number that is itself a palindrome.
|
||||
|
||||
<br>
|
||||
Show all output here.
|
||||
|
||||
|
||||
;References:
|
||||
* [https://www.youtube.com/watch?v=bN8PE3eljdA What's special about 196?] Numberphile video.
|
||||
* [http://oeis.org/A023108 A023108] Positive integers which apparently never result in a palindrome under repeated applications of the function f(x) = x + (x with digits reversed).
|
||||
* [http://mathoverflow.net/questions/117104/status-of-the-196-conjecture/117277#117277 Status of the 196 conjecture?] Mathoverflow.
|
||||
<br><br>
|
||||
|
||||
43
Task/Lychrel-numbers/11l/lychrel-numbers.11l
Normal file
43
Task/Lychrel-numbers/11l/lychrel-numbers.11l
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
F rev(n)
|
||||
R BigInt(reversed(String(n)))
|
||||
|
||||
[BigInt = (Bool, BigInt)] cache
|
||||
|
||||
F lychrel(BigInt =n)
|
||||
I n C :cache
|
||||
R :cache[n]
|
||||
|
||||
V r = rev(n)
|
||||
V res = (1B, n)
|
||||
[BigInt] seen
|
||||
L(i) 1000
|
||||
n += r
|
||||
r = rev(n)
|
||||
I n == r
|
||||
res = (0B, BigInt(0))
|
||||
L.break
|
||||
I n C :cache
|
||||
res = :cache[n]
|
||||
L.break
|
||||
seen [+]= n
|
||||
|
||||
L(x) seen
|
||||
:cache[x] = res
|
||||
R res
|
||||
|
||||
[Int] seeds, related, palin
|
||||
|
||||
L(i) 1..9999
|
||||
V tf_s = lychrel(i)
|
||||
I !tf_s[0]
|
||||
L.continue
|
||||
I BigInt(i) == tf_s[1]
|
||||
seeds [+]= i
|
||||
E
|
||||
related [+]= i
|
||||
I BigInt(i) == rev(i)
|
||||
palin [+]= i
|
||||
|
||||
print(seeds.len‘ Lychrel seeds: ’seeds)
|
||||
print(related.len‘ Lychrel related’)
|
||||
print(palin.len‘ Lychrel palindromes: ’palin)
|
||||
167
Task/Lychrel-numbers/ALGOL-68/lychrel-numbers.alg
Normal file
167
Task/Lychrel-numbers/ALGOL-68/lychrel-numbers.alg
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
PR read "aArray.a68" PR
|
||||
|
||||
# number of additions to attempt before deciding the number is Lychrel #
|
||||
INT max additions = 500;
|
||||
|
||||
# buffer to hold number during testing #
|
||||
# addition of two equal sized numbers can produce a number of at most #
|
||||
# one additional digit, so for 500 additions of numbers up to 10 000 #
|
||||
# we need a bit over 500 digits... #
|
||||
[ 512 ]CHAR number;
|
||||
FOR c TO UPB number DO number[ c ] := "0" OD;
|
||||
# count of used digits in number #
|
||||
INT digits := 0;
|
||||
|
||||
# sets the number buffer to the specified positive value #
|
||||
PROC set number = ( INT value )VOID:
|
||||
BEGIN
|
||||
digits := 0;
|
||||
INT v := ABS value;
|
||||
WHILE digits +:= 1;
|
||||
number[ digits ] := REPR ( ABS "0" + v MOD 10 );
|
||||
v OVERAB 10;
|
||||
v > 0
|
||||
DO SKIP OD
|
||||
END # set number # ;
|
||||
|
||||
# adds the reverse of number to itself #
|
||||
PROC add reverse = VOID:
|
||||
BEGIN
|
||||
[ digits + 1 ]CHAR result;
|
||||
INT carry := 0;
|
||||
INT r pos := digits;
|
||||
FOR d pos TO digits DO
|
||||
INT sum = ( ( ABS number[ d pos ] + ABS number[ r pos ] + carry )
|
||||
- ( 2 * ABS "0" )
|
||||
);
|
||||
IF sum < 10 THEN
|
||||
# no carry required #
|
||||
result[ d pos ] := REPR( sum + ABS "0" );
|
||||
carry := 0
|
||||
ELSE
|
||||
# need to carry #
|
||||
result[ d pos ] := REPR ( ( sum - 10 ) + ABS "0" );
|
||||
carry := 1
|
||||
FI;
|
||||
r pos -:= 1
|
||||
OD;
|
||||
IF carry /= 0 THEN
|
||||
# need another digit #
|
||||
digits +:= 1;
|
||||
result[ digits ] := REPR ( ABS "0" + carry )
|
||||
FI;
|
||||
number[ : digits ] := result[ : digits ]
|
||||
END # add reverse # ;
|
||||
|
||||
# returns TRUE if number is a palindrome, FALSE otherwise #
|
||||
PROC is palindromic = BOOL:
|
||||
BEGIN
|
||||
BOOL result := TRUE;
|
||||
INT d pos := 1;
|
||||
INT r pos := digits;
|
||||
WHILE IF d pos >= r pos
|
||||
THEN FALSE
|
||||
ELSE result := ( number[ d pos ] = number[ r pos ] )
|
||||
FI
|
||||
DO
|
||||
d pos +:= 1;
|
||||
r pos -:= 1
|
||||
OD;
|
||||
result
|
||||
END # is palindromic # ;
|
||||
|
||||
# associative array of numbers that are not palindromic after 500 #
|
||||
# iterations #
|
||||
REF AARRAY related := INIT HEAP AARRAY;
|
||||
|
||||
# adds the elements of the specified path to the related numbers #
|
||||
PROC add related numbers = ( REF AARRAY path )VOID:
|
||||
BEGIN
|
||||
REF AAELEMENT r := FIRST path;
|
||||
WHILE r ISNT nil element DO
|
||||
related // key OF r := "Y";
|
||||
r := NEXT path
|
||||
OD
|
||||
END # add related numbers # ;
|
||||
|
||||
# Lychrel number results #
|
||||
# lychrel[n] is: #
|
||||
# not lychrel if n becomes palidromic before 500 additions #
|
||||
# lychrel seed if n is a seed lychrel number #
|
||||
# lychrel related if n is a related lychrel number #
|
||||
# untested if n hasn't been tested yet #
|
||||
INT not lychrel = 0;
|
||||
INT lychrel seed = 1;
|
||||
INT lychrel related = 2;
|
||||
INT untested = 3;
|
||||
INT max number = 10 000;
|
||||
[ max number ]INT lychrel;
|
||||
FOR n TO UPB lychrel DO lychrel[ n ] := untested OD;
|
||||
[ UPB lychrel ]BOOL palindromic;
|
||||
FOR n TO UPB palindromic DO palindromic[ n ] := FALSE OD;
|
||||
INT seed count := 0;
|
||||
INT related count := 0;
|
||||
INT palindrome count := 0;
|
||||
|
||||
# set the lychrel array to the values listed above #
|
||||
FOR n TO UPB lychrel DO
|
||||
# classify this number #
|
||||
set number( n );
|
||||
palindromic[ n ] := is palindromic;
|
||||
add reverse;
|
||||
REF AARRAY path := INIT HEAP AARRAY;
|
||||
BOOL continue searching := TRUE;
|
||||
TO max additions WHILE continue searching :=
|
||||
IF related CONTAINSKEY number[ : digits ] THEN
|
||||
# this number is already known to be lychrel #
|
||||
lychrel[ n ] := lychrel related;
|
||||
add related numbers( path );
|
||||
related count +:= 1;
|
||||
FALSE
|
||||
ELIF is palindromic THEN
|
||||
# have reached a palindrome #
|
||||
lychrel[ n ] := not lychrel;
|
||||
FALSE
|
||||
ELSE
|
||||
# not palindromic - try another iteration #
|
||||
path // number[ : digits ] := "Y";
|
||||
add reverse;
|
||||
TRUE
|
||||
FI
|
||||
DO SKIP OD;
|
||||
IF continue searching THEN
|
||||
# we have a lychrel seed #
|
||||
add related numbers( path );
|
||||
lychrel[ n ] := lychrel seed;
|
||||
seed count +:= 1
|
||||
FI;
|
||||
IF palindromic[ n ] AND ( lychrel[ n ] = lychrel seed OR lychrel[ n ] = lychrel related ) THEN
|
||||
# have a palindromic related or seed lychrel number #
|
||||
palindrome count +:= 1
|
||||
FI
|
||||
OD;
|
||||
|
||||
# print the lychrel numbers up to max number #
|
||||
print( ( "There are "
|
||||
, whole( seed count, 0 ), " seed Lychrel numbers and "
|
||||
, whole( related count, 0 ), " related Lychrel numbers up to "
|
||||
, whole( UPB lychrel, 0 )
|
||||
, newline
|
||||
)
|
||||
);
|
||||
# shpw the seeds #
|
||||
print( ( "Seed Lychrel numbers up to ", whole( UPB lychrel, 0 ), ":" ) );
|
||||
FOR n TO UPB lychrel DO IF lychrel[ n ] = lychrel seed THEN print( ( " ", whole( n, 0 ) ) ) FI OD;
|
||||
print( ( newline ) );
|
||||
# show the Lychrel numbers that are palindromic #
|
||||
print( ( "There are "
|
||||
, whole( palindrome count, 0 )
|
||||
, " palindromic Lychrel numbers up to "
|
||||
, whole( UPB lychrel, 0 )
|
||||
, ":"
|
||||
)
|
||||
);
|
||||
FOR n TO UPB lychrel DO
|
||||
IF ( lychrel[ n ] = lychrel seed OR lychrel[ n ] = lychrel related ) AND palindromic[ n ] THEN print( ( " ", whole( n, 0 ) ) ) FI
|
||||
OD;
|
||||
print( ( newline ) )
|
||||
133
Task/Lychrel-numbers/AppleScript/lychrel-numbers-1.applescript
Normal file
133
Task/Lychrel-numbers/AppleScript/lychrel-numbers-1.applescript
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
on Lychrels(numberLimit, iterationLimit)
|
||||
script o
|
||||
property digits : missing value -- Digits of the current startNumber or a derived sum.
|
||||
property stigid : missing value -- Reverse thereof.
|
||||
property digitLists : missing value -- Copies of the digit lists in the current sequence.
|
||||
-- The digit lists from earlier Lychrel sequences, grouped into 1000 sublists
|
||||
-- indexed by their last three digits (+ 1) to speed up searches for them.
|
||||
property earlierDigitLists : listOfLists(1000)
|
||||
property subgroup : missing value -- Sublist picked from earlierDigitLists.
|
||||
-- Lychrel output.
|
||||
property seeds : {}
|
||||
property relateds : {}
|
||||
property palindromics : {}
|
||||
|
||||
-- Subhandler: Has the current list of digits come up in the sequence for an earlier Lychrel?
|
||||
on isRelated()
|
||||
-- Unless it only has one digit, look for it in the appropriate subgroup of earlierDigitLists.
|
||||
set digitCount to (count my digits)
|
||||
if (digitCount > 1) then
|
||||
set i to (item -2 of my digits) * 10 + (end of my digits) + 1
|
||||
if (digitCount > 2) then set i to i + (item -3 of my digits) * 100
|
||||
set subgroup to item i of my earlierDigitLists
|
||||
-- It's faster to test this using a repeat than with 'is in'!
|
||||
repeat with i from 1 to (count my subgroup)
|
||||
if (item i of my subgroup = digits) then return true
|
||||
end repeat
|
||||
end if
|
||||
return false
|
||||
end isRelated
|
||||
end script
|
||||
|
||||
repeat with startNumber from 1 to numberLimit
|
||||
-- Get the number's digits and their reverse.
|
||||
set o's digits to {}
|
||||
set temp to startNumber
|
||||
repeat until (temp = 0)
|
||||
set beginning of o's digits to temp mod 10
|
||||
set temp to temp div 10
|
||||
end repeat
|
||||
set o's stigid to reverse of o's digits
|
||||
-- Note if the number itself is palindromic.
|
||||
set startNumberIsPalindrome to (o's digits = o's stigid)
|
||||
|
||||
if (o's isRelated()) then
|
||||
-- It(s digits) occurred in the sequence for an earlier Lychrel, so it's a related Lychrel.
|
||||
set end of o's relateds to startNumber
|
||||
else
|
||||
-- Otherwise run its sequence.
|
||||
set o's digitLists to {}
|
||||
set digitCount to (count o's digits)
|
||||
|
||||
-- Sequence loop.
|
||||
repeat iterationLimit times
|
||||
-- Add the reversed digits to those of the current number.
|
||||
set carry to 0
|
||||
repeat with i from digitCount to 1 by -1
|
||||
set d to (item i of o's digits) + (item i of o's stigid) + carry
|
||||
set item i of o's digits to d mod 10
|
||||
set carry to d div 10
|
||||
end repeat
|
||||
if (carry > 0) then
|
||||
set beginning of o's digits to carry
|
||||
set digitCount to digitCount + 1
|
||||
end if
|
||||
|
||||
-- If the sum's digits are palindromic, the start number's not a Lychrel.
|
||||
set o's stigid to reverse of o's digits
|
||||
set sumIsPalindrome to (o's digits = o's stigid)
|
||||
if (sumIsPalindrome) then exit repeat
|
||||
-- Otherwise, if the digits occurred in an earlier Lychrel sequence, the start number's a related Lychrel.
|
||||
set startNumberIsRelated to (o's isRelated())
|
||||
if (startNumberIsRelated) then
|
||||
set sumIsPalindrome to false
|
||||
exit repeat
|
||||
end if
|
||||
-- Otherwise keep a copy of the digits and go for the next number in the sequence.
|
||||
copy o's digits to end of o's digitLists
|
||||
end repeat
|
||||
|
||||
if (not sumIsPalindrome) then
|
||||
-- No palindrome other than the start number occurred in the sequence,
|
||||
-- so the number's a Lychrel. Store it as the relevant type.
|
||||
if (startNumberIsRelated) then
|
||||
set end of o's relateds to startNumber
|
||||
else
|
||||
set end of o's seeds to startNumber
|
||||
end if
|
||||
if (startNumberIsPalindrome) then set end of o's palindromics to startNumber
|
||||
-- Store this sequence's digit lists based on their last three digits. There won't be any
|
||||
-- single-digit lists (they're palindromes), but there may be some with only two digits.
|
||||
repeat with thisList in o's digitLists
|
||||
set i to (item -2 of thisList) * 10 + (end of thisList) + 1
|
||||
set digitCount to (count thisList)
|
||||
if (digitCount > 2) then set i to i + (item -3 of thisList) * 100
|
||||
set end of item i of o's earlierDigitLists to thisList's contents
|
||||
end repeat
|
||||
end if
|
||||
end if
|
||||
end repeat
|
||||
|
||||
return {seeds:o's seeds, relateds:o's relateds, palindromics:o's palindromics}
|
||||
end Lychrels
|
||||
|
||||
on listOfLists(len)
|
||||
script o
|
||||
property lst : {}
|
||||
end script
|
||||
repeat len times
|
||||
set end of o's lst to {}
|
||||
end repeat
|
||||
return o's lst
|
||||
end listOfLists
|
||||
|
||||
on join(lst, delim)
|
||||
set astid to AppleScript's text item delimiters
|
||||
set AppleScript's text item delimiters to delim
|
||||
set txt to lst as text
|
||||
set AppleScript's text item delimiters to astid
|
||||
return txt
|
||||
end join
|
||||
|
||||
on task()
|
||||
set numberLimit to 10000
|
||||
set iterationLimit to 500
|
||||
set {seeds:seeds, relateds:relateds, palindromics:palindromics} to Lychrels(numberLimit, iterationLimit)
|
||||
set output to {"Lychrel numbers between 1 and " & numberLimit & ":", ""}
|
||||
set end of output to ((count seeds) as text) & " seed Lychrels: " & join(seeds, ", ")
|
||||
set end of output to ((count relateds) as text) & " related Lychrels"
|
||||
set end of output to ((count palindromics) as text) & " palindromic Lychrels: " & join(palindromics, ", ")
|
||||
return join(output, linefeed)
|
||||
end task
|
||||
|
||||
task()
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
"Lychrel numbers between 1 and 10000:
|
||||
|
||||
5 seed Lychrels: 196, 879, 1997, 7059, 9999
|
||||
244 related Lychrels
|
||||
3 palindromic Lychrels: 4994, 8778, 9999"
|
||||
325
Task/Lychrel-numbers/BASIC/lychrel-numbers.basic
Normal file
325
Task/Lychrel-numbers/BASIC/lychrel-numbers.basic
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||
' Lychrel Numbers V1.0 '
|
||||
' '
|
||||
' Developed by A. David Garza Marín in QB64 for '
|
||||
' RosettaCode. December 2, 2016. '
|
||||
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||
|
||||
OPTION _EXPLICIT ' Change to OPTION EXPLICIT in VB-DOS or PDS 7.1. Remove in QB and QBASIC
|
||||
|
||||
' SUBs and FUNCTIONs
|
||||
DECLARE SUB doAddLychrel (WhichNumber AS LONG)
|
||||
DECLARE SUB doAddRelated (WhichNumber AS LONG)
|
||||
DECLARE SUB doFindLychrelPalyndromes ()
|
||||
DECLARE FUNCTION CalculateMaxRes& (WhichNumber AS LONG)
|
||||
DECLARE FUNCTION IsLychrel% (WhichNumber AS LONG)
|
||||
DECLARE FUNCTION Reverse$ (WhatToReverse AS STRING)
|
||||
DECLARE FUNCTION Sum$ (N1 AS STRING, N2 AS STRING)
|
||||
|
||||
' Var
|
||||
DIM sN1 AS STRING, sN2 AS STRING, sLychrel AS STRING
|
||||
DIM i AS LONG, iLychrel AS INTEGER, iCount AS INTEGER, l AS INTEGER
|
||||
DIM c1 AS INTEGER, l1 AS INTEGER, c2 AS INTEGER, l2 AS INTEGER
|
||||
DIM lMC AS LONG, lT AS LONG
|
||||
DIM lLC AS LONG, lRL AS LONG, lPN AS LONG
|
||||
CONST MaxNumbers = 10000, MaxIterations = 500, False = 0, True = NOT False
|
||||
|
||||
' Init
|
||||
REDIM lLC(1, 0) AS LONG, lRL(0) AS LONG, lPN(0) AS LONG
|
||||
lMC = CalculateMaxRes&(MaxNumbers)
|
||||
lT = TIMER
|
||||
|
||||
' ------------------ Main program -----------------------------------------
|
||||
CLS
|
||||
PRINT "Lychrel Numbers 1.0"
|
||||
PRINT
|
||||
PRINT "Calculating numbers from 1 to"; MaxNumbers;
|
||||
c1 = POS(1)
|
||||
l1 = CSRLIN
|
||||
COLOR 7 + 16: PRINT "...": PRINT
|
||||
COLOR 7
|
||||
c2 = POS(1)
|
||||
l2 = CSRLIN
|
||||
FOR i = 1 TO MaxNumbers
|
||||
sN1 = LTRIM$(STR$(i))
|
||||
sN2 = Reverse$(sN1)
|
||||
iCount = 0
|
||||
LOCATE l2, 1: PRINT "Analyzing number"; i;
|
||||
COLOR 7 + 16: PRINT "...": COLOR 7
|
||||
DO
|
||||
iCount = iCount + 1
|
||||
sN1 = Sum$(sN1, sN2)
|
||||
sN2 = Reverse$(sN1)
|
||||
LOOP UNTIL iCount >= MaxIterations OR sN1 = sN2
|
||||
|
||||
IF sN1 <> sN2 THEN
|
||||
IF IsLychrel%(i) THEN
|
||||
doAddLychrel i
|
||||
ELSE
|
||||
doAddRelated i
|
||||
END IF
|
||||
PRINT "Potential Lychrel numbers:"; UBOUND(lLC, 2); "{";
|
||||
FOR l = 1 TO UBOUND(lLC, 2)
|
||||
PRINT lLC(1, l);
|
||||
NEXT
|
||||
PRINT "}"
|
||||
|
||||
IF UBOUND(lRL) > 0 THEN
|
||||
PRINT "Kin Lychrel numbers found:"; UBOUND(lRL)
|
||||
END IF
|
||||
END IF
|
||||
NEXT i
|
||||
|
||||
' Look for palyndromes
|
||||
IF UBOUND(lLC, 2) > 0 THEN
|
||||
doFindLychrelPalyndromes
|
||||
END IF
|
||||
|
||||
' Shows the results
|
||||
CLS
|
||||
PRINT "Lychrel numbers 1.0 in QB64"
|
||||
PRINT
|
||||
PRINT "Lychrel numbers found: "; UBOUND(lLC, 2)
|
||||
PRINT "Lychrel numbers: {";
|
||||
FOR i = 1 TO UBOUND(lLC, 2)
|
||||
PRINT lLC(1, i);
|
||||
NEXT
|
||||
PRINT "}"
|
||||
PRINT
|
||||
PRINT "Kin numbers found: "; UBOUND(lRL)
|
||||
' You can uncomment the following lines if you want to see the
|
||||
' Kin or Related numbers found.
|
||||
'PRINT "Kin numbers: {";
|
||||
'FOR i = 1 TO UBOUND(lRL)
|
||||
' PRINT lRL(i);
|
||||
'NEXT i
|
||||
'PRINT "}"
|
||||
PRINT
|
||||
PRINT "Palyndrome Lychrel numbers found:"; UBOUND(lPN); "{";
|
||||
FOR i = 1 TO UBOUND(lPN)
|
||||
PRINT lPN(i);
|
||||
NEXT i
|
||||
PRINT "}"
|
||||
lT = TIMER - lT
|
||||
PRINT
|
||||
PRINT USING "Calculation took ##:## seconds."; FIX(lT / 60), (lT MOD 60)
|
||||
PRINT "End of program."
|
||||
' ------------------ End of Main program --------------------------------------
|
||||
END
|
||||
|
||||
FUNCTION CalculateMaxRes& (WhichNumber AS LONG)
|
||||
' Var
|
||||
IF (WhichNumber MOD 10) <> 0 THEN
|
||||
CalculateMaxRes& = WhichNumber + VAL(Reverse$(LTRIM$(STR$(WhichNumber))))
|
||||
ELSE
|
||||
CalculateMaxRes& = (WhichNumber - 1) + VAL(Reverse$(LTRIM$(STR$(WhichNumber - 1))))
|
||||
END IF
|
||||
END FUNCTION
|
||||
|
||||
SUB doAddLychrel (WhichNumber AS LONG)
|
||||
' Var
|
||||
DIM iMaxC AS INTEGER, iMaxR AS INTEGER
|
||||
DIM lRes AS LONG, iRow AS INTEGER
|
||||
DIM sN1 AS STRING, sN2 AS STRING
|
||||
DIM lNum(1 TO 10) AS LONG
|
||||
SHARED lLC() AS LONG, lMC AS LONG
|
||||
|
||||
'
|
||||
lNum(1) = WhichNumber
|
||||
iRow = 1
|
||||
iMaxR = 10
|
||||
lRes = WhichNumber
|
||||
DO
|
||||
iRow = iRow + 1
|
||||
IF iRow > iMaxR THEN
|
||||
' Change to REDIM PRESERVE for VB-DOS, QB, QBASIC and PDS 7.1
|
||||
REDIM _PRESERVE lNum(1 TO iMaxR + 10) AS LONG
|
||||
END IF
|
||||
sN1 = LTRIM$(STR$(lRes))
|
||||
sN2 = Reverse$(sN1)
|
||||
lRes = VAL(Sum$(sN1, sN2))
|
||||
lNum(iRow) = lRes
|
||||
LOOP UNTIL lRes > lMC
|
||||
|
||||
' Change to REDIM PRESERVE for VB-DOS, QB, QBASIC and PDS 7.1
|
||||
REDIM _PRESERVE lNum(1 TO iRow) AS LONG
|
||||
|
||||
' Now, Gathers the size of the lLC table
|
||||
iMaxC = UBOUND(lLC, 2) + 1
|
||||
IF iMaxC = 1 THEN
|
||||
ERASE lLC
|
||||
iMaxR = iRow
|
||||
ELSE
|
||||
iMaxR = UBOUND(lLC, 1)
|
||||
END IF
|
||||
|
||||
IF iMaxC = 1 THEN
|
||||
REDIM lLC(1 TO iMaxR, 1 TO iMaxC) AS LONG
|
||||
ELSE
|
||||
' Change to REDIM PRESERVE for VB-DOS, QB, QBASIC and PDS 7.1
|
||||
REDIM _PRESERVE lLC(1 TO iMaxR, 1 TO iMaxC) AS LONG
|
||||
END IF
|
||||
|
||||
' Assigns the result to the table
|
||||
FOR lRes = 1 TO iRow
|
||||
lLC(lRes, iMaxC) = lNum(lRes)
|
||||
NEXT lRes
|
||||
|
||||
ERASE lNum
|
||||
END SUB
|
||||
|
||||
SUB doAddRelated (WhichNumber AS LONG)
|
||||
' Var
|
||||
DIM iMax AS INTEGER
|
||||
SHARED lRL() AS LONG
|
||||
|
||||
iMax = UBOUND(lRL) + 1
|
||||
IF iMax = 1 THEN
|
||||
ERASE lRL
|
||||
END IF
|
||||
' Change to REDIM PRESERVE for VB-DOS, QB, QBASIC and PDS 7.1
|
||||
REDIM _PRESERVE lRL(1 TO iMax) AS LONG
|
||||
lRL(iMax) = WhichNumber
|
||||
END SUB
|
||||
|
||||
SUB doFindLychrelPalyndromes ()
|
||||
' Var
|
||||
DIM iMaxC AS INTEGER, i AS INTEGER, iCount AS INTEGER
|
||||
DIM sN1 AS STRING, sN2 AS STRING
|
||||
SHARED lLC() AS LONG, lRL() AS LONG, lPN() AS LONG
|
||||
|
||||
' Verify seeds
|
||||
iMaxC = UBOUND(lLC, 2)
|
||||
FOR i = 1 TO iMaxC
|
||||
IF lLC(1, i) > 0 THEN
|
||||
sN1 = LTRIM$(STR$(lLC(1, i)))
|
||||
sN2 = Reverse$(sN1)
|
||||
IF sN1 = sN2 THEN
|
||||
iCount = iCount + 1
|
||||
GOSUB AddSpaceForItem
|
||||
lPN(iCount) = VAL(sN1)
|
||||
END IF
|
||||
END IF
|
||||
NEXT i
|
||||
|
||||
' Verify Kins
|
||||
iMaxC = UBOUND(lRL)
|
||||
FOR i = 1 TO iMaxC
|
||||
IF lRL(i) > 0 THEN
|
||||
sN1 = LTRIM$(STR$(lRL(i)))
|
||||
sN2 = Reverse$(sN1)
|
||||
IF sN1 = sN2 THEN
|
||||
iCount = iCount + 1
|
||||
GOSUB AddSpaceForItem
|
||||
lPN(iCount) = VAL(sN1)
|
||||
END IF
|
||||
END IF
|
||||
NEXT i
|
||||
|
||||
' Change to REDIM PRESERVE for VB-DOS, QB, QBASIC and PDS 7.1
|
||||
REDIM _PRESERVE lPN(1 TO iCount) AS LONG
|
||||
|
||||
EXIT SUB
|
||||
|
||||
AddSpaceForItem:
|
||||
IF UBOUND(lPN) < iCount THEN
|
||||
IF UBOUND(lPN) = 0 THEN
|
||||
ERASE lPN
|
||||
END IF
|
||||
' Change to REDIM PRESERVE for VB-DOS, QB, QBASIC and PDS 7.1
|
||||
REDIM _PRESERVE lPN(1 TO iCount + 9) AS LONG
|
||||
END IF
|
||||
RETURN
|
||||
|
||||
|
||||
END SUB
|
||||
|
||||
FUNCTION IsLychrel% (WhichNumber AS LONG)
|
||||
' Var
|
||||
DIM iMaxC AS INTEGER, iMaxR AS INTEGER
|
||||
DIM iCol AS INTEGER, iRow AS INTEGER
|
||||
DIM lToCompare AS LONG
|
||||
DIM YesItIs AS INTEGER
|
||||
DIM sN1 AS STRING, sN2 AS STRING
|
||||
SHARED lLC() AS LONG, lMC AS LONG
|
||||
|
||||
iMaxC = UBOUND(lLC, 2)
|
||||
iMaxR = UBOUND(lLC, 1)
|
||||
lToCompare = WhichNumber
|
||||
IF iMaxC > 0 THEN
|
||||
DO
|
||||
sN1 = LTRIM$(STR$(lToCompare))
|
||||
sN2 = Reverse$(sN1)
|
||||
lToCompare = VAL(Sum$(sN1, sN2))
|
||||
iCol = 0
|
||||
DO
|
||||
iCol = iCol + 1
|
||||
iRow = 0
|
||||
DO
|
||||
iRow = iRow + 1
|
||||
LOOP UNTIL iRow = iMaxR OR lToCompare = lLC(iRow, iCol)
|
||||
LOOP UNTIL iCol = iMaxC OR lToCompare = lLC(iRow, iCol)
|
||||
LOOP UNTIL lToCompare >= lMC OR lToCompare = lLC(iRow, iCol)
|
||||
YesItIs = (lToCompare <> lLC(iRow, iCol))
|
||||
ELSE
|
||||
YesItIs = True
|
||||
END IF
|
||||
|
||||
IsLychrel = YesItIs
|
||||
|
||||
END FUNCTION
|
||||
|
||||
FUNCTION Reverse$ (WhatToReverse AS STRING)
|
||||
' Var
|
||||
DIM sChar AS STRING
|
||||
DIM sRes AS STRING
|
||||
DIM i AS INTEGER, l AS INTEGER
|
||||
|
||||
l = LEN(WhatToReverse)
|
||||
sRes = ""
|
||||
FOR i = 1 TO l
|
||||
sRes = MID$(WhatToReverse, i, 1) + sRes
|
||||
NEXT i
|
||||
|
||||
Reverse$ = sRes
|
||||
END FUNCTION
|
||||
|
||||
FUNCTION Sum$ (N1 AS STRING, N2 AS STRING)
|
||||
' Var
|
||||
DIM iN1 AS INTEGER, iN2 AS INTEGER, iSum AS INTEGER
|
||||
DIM i AS INTEGER, l AS INTEGER, iCarry AS INTEGER, lM AS LONG
|
||||
DIM sRes AS STRING
|
||||
|
||||
IF LEN(N1) > LEN(N2) THEN
|
||||
l = LEN(N1)
|
||||
ELSE
|
||||
l = LEN(N2)
|
||||
END IF
|
||||
lM = 2147483647 / 2
|
||||
|
||||
' Add trailing zeroes (uncomment in case strings have not equal number of digits)
|
||||
' N1 = STRING$(l - LEN(N1), 48) + N1
|
||||
' N2 = STRING$(l - LEN(N2), 48) + N2
|
||||
|
||||
' Hace la suma
|
||||
IF VAL(N1) < lM THEN
|
||||
sRes = LTRIM$(STR$(VAL(N1) + VAL(N2)))
|
||||
ELSE
|
||||
|
||||
FOR i = l TO 1 STEP -1
|
||||
iN1 = VAL(MID$(N1, i, 1))
|
||||
iN2 = VAL(MID$(N2, i, 1))
|
||||
|
||||
iSum = iN1 + iN2 + iCarry
|
||||
|
||||
iCarry = FIX(iSum / 10)
|
||||
iSum = iSum MOD 10
|
||||
|
||||
sRes = LTRIM$(STR$(iSum)) + sRes
|
||||
NEXT i
|
||||
IF iCarry > 0 THEN sRes = LTRIM$(STR$(iCarry)) + sRes
|
||||
END IF
|
||||
|
||||
Sum$ = sRes
|
||||
|
||||
END FUNCTION
|
||||
68
Task/Lychrel-numbers/C++/lychrel-numbers.cpp
Normal file
68
Task/Lychrel-numbers/C++/lychrel-numbers.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <gmpxx.h>
|
||||
|
||||
using integer = mpz_class;
|
||||
|
||||
integer reverse(integer n) {
|
||||
integer rev = 0;
|
||||
while (n > 0) {
|
||||
rev = rev * 10 + (n % 10);
|
||||
n /= 10;
|
||||
}
|
||||
return rev;
|
||||
}
|
||||
|
||||
void print_vector(const std::vector<integer>& vec) {
|
||||
if (vec.empty())
|
||||
return;
|
||||
auto i = vec.begin();
|
||||
std::cout << *i++;
|
||||
for (; i != vec.end(); ++i)
|
||||
std::cout << ", " << *i;
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::map<integer, std::pair<bool, integer>> cache;
|
||||
std::vector<integer> seeds, related, palindromes;
|
||||
for (integer n = 1; n <= 10000; ++n) {
|
||||
std::pair<bool, integer> p(true, n);
|
||||
std::vector<integer> seen;
|
||||
integer rev = reverse(n);
|
||||
integer sum = n;
|
||||
for (int i = 0; i < 500; ++i) {
|
||||
sum += rev;
|
||||
rev = reverse(sum);
|
||||
if (rev == sum) {
|
||||
p.first = false;
|
||||
p.second = 0;
|
||||
break;
|
||||
}
|
||||
auto iter = cache.find(sum);
|
||||
if (iter != cache.end()) {
|
||||
p = iter->second;
|
||||
break;
|
||||
}
|
||||
seen.push_back(sum);
|
||||
}
|
||||
for (integer s : seen)
|
||||
cache.emplace(s, p);
|
||||
if (!p.first)
|
||||
continue;
|
||||
if (p.second == n)
|
||||
seeds.push_back(n);
|
||||
else
|
||||
related.push_back(n);
|
||||
if (n == reverse(n))
|
||||
palindromes.push_back(n);
|
||||
}
|
||||
std::cout << "number of seeds: " << seeds.size() << '\n';
|
||||
std::cout << "seeds: ";
|
||||
print_vector(seeds);
|
||||
std::cout << "number of related: " << related.size() << '\n';
|
||||
std::cout << "palindromes: ";
|
||||
print_vector(palindromes);
|
||||
return 0;
|
||||
}
|
||||
75
Task/Lychrel-numbers/Clojure/lychrel-numbers.clj
Normal file
75
Task/Lychrel-numbers/Clojure/lychrel-numbers.clj
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
(ns lychrel.core
|
||||
(require [clojure.string :as s])
|
||||
(require [clojure.set :as set-op])
|
||||
(:gen-class))
|
||||
|
||||
(defn palindrome? "Returns true if given number is a palindrome (number on base 10)"
|
||||
[number]
|
||||
(let [number-str (str number)]
|
||||
(= number-str (s/reverse number-str))))
|
||||
|
||||
(defn delete-leading-zeros
|
||||
"Delete leading zeros so that you can read the string"
|
||||
[number-str]
|
||||
(read-string (re-find (re-pattern "[1-9]\\d*") number-str))
|
||||
)
|
||||
|
||||
(defn lychrel "Returns T if number is a candidate Lychrel (up to max iterations), and a second value with the sequence of sums"
|
||||
([number] (lychrel number 500))
|
||||
([number depth]
|
||||
(let [next-number (+' number (delete-leading-zeros (s/reverse (str number))))
|
||||
depth (- depth 1)]
|
||||
(if (palindrome? next-number) (conj [next-number] number)
|
||||
(if (not= depth 0) (conj (lychrel next-number depth) number) (conj [] nil))
|
||||
)
|
||||
)))
|
||||
|
||||
(defn lychrel? "Test if number is a possible lychrel number"
|
||||
[number]
|
||||
(= nil (first (lychrel number 500))))
|
||||
|
||||
(defn lychrel-up-to-n "Get all lychrels up to N"
|
||||
[N]
|
||||
(filter lychrel? (range 1 N)))
|
||||
|
||||
(defn make-kin "Removes the starting number of the list, the starting number"
|
||||
[kin]
|
||||
(rest (butlast kin)))
|
||||
|
||||
(defn calc-seed "The seeding" []
|
||||
(let [kin-set (atom #{})
|
||||
seed-set (atom #{})]
|
||||
(fn [n] (let [lychrel-seed (set #{(last n)})
|
||||
kins (set (butlast n))]
|
||||
(if (= kins (clojure.set/difference kins @kin-set))
|
||||
(do (swap! kin-set clojure.set/union kins)
|
||||
(swap! seed-set clojure.set/union lychrel-seed)
|
||||
@kin-set))
|
||||
@seed-set
|
||||
))))
|
||||
|
||||
(defn filter-seeds "Filtering the seed through the paths"
|
||||
[]
|
||||
(let [calc-f (calc-seed)
|
||||
all-lychrels (for [lychrel-list (filter lychrel? (range 1 10000))]
|
||||
(filter (fn [x] (> 1000001 x)) (rest (lychrel lychrel-list))))]
|
||||
(last (for [ll all-lychrels]
|
||||
(do (calc-f ll))))))
|
||||
|
||||
(defn -main
|
||||
"Here we do the three tasks:
|
||||
Get all possible Lychrel numbers up to 10000
|
||||
Count them
|
||||
Reduce all possible numbers to seed"
|
||||
|
||||
[& args]
|
||||
(let [lychrels-n (filter-seeds)
|
||||
count-lychrels (count lychrels-n)
|
||||
related-n (- (count (filter lychrel? (range 1 10000))) count-lychrels)
|
||||
palindrom-n (filter palindrome? (filter lychrel? (range 1 10000)))
|
||||
count-palindromes (count palindrom-n)
|
||||
]
|
||||
(println count-lychrels "Lychrel seeds:" lychrels-n)
|
||||
(println related-n "Lychrel related.")
|
||||
(println count-palindromes "Lychrel palindromes found:" palindrom-n))
|
||||
)
|
||||
26
Task/Lychrel-numbers/Common-Lisp/lychrel-numbers.lisp
Normal file
26
Task/Lychrel-numbers/Common-Lisp/lychrel-numbers.lisp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
(defun Lychrel (number &optional (max 500))
|
||||
"Returns T if number is a candidate Lychrel (up to max iterations), and a second value with the sequence of sums"
|
||||
(do* ((n number (+ n (parse-integer rev-str)))
|
||||
(n-str (write-to-string n) (write-to-string n))
|
||||
(rev-str (reverse n-str) (reverse n-str))
|
||||
(i 0 (1+ i))
|
||||
(list (list n) (cons n list)) )
|
||||
((or (> i max) (and (string= n-str rev-str) (> i 0))) (values (not (string= n-str rev-str)) (nreverse list)))))
|
||||
|
||||
|
||||
(defun Lychrel-test (n &optional (max 500))
|
||||
"Tests the first n numbers up to max number of iterations"
|
||||
(let ((seeds nil)
|
||||
(related 0)
|
||||
(palyndromes nil) )
|
||||
(dotimes (i (1+ n))
|
||||
(multiple-value-bind (Lychrel-p seq) (Lychrel i max)
|
||||
(when Lychrel-p
|
||||
(if (find seq seeds :test #'intersection :key #'cdr)
|
||||
(incf related)
|
||||
(push (cons i seq) seeds) )
|
||||
(when (= i (parse-integer (reverse (write-to-string i))))
|
||||
(push i palyndromes) ))))
|
||||
(format T "Testing numbers: 1 to ~D~%Iteration maximum: ~D~%~%Number of Lychrel seeds found: ~d => ~a~%~
|
||||
Number of related found: ~D~%Palyndrome Lychrel numbers: ~D => ~a~%"
|
||||
n max (length seeds) (nreverse (mapcar #'car seeds)) related (length palyndromes) (nreverse palyndromes)) ))
|
||||
53
Task/Lychrel-numbers/Crystal/lychrel-numbers.crystal
Normal file
53
Task/Lychrel-numbers/Crystal/lychrel-numbers.crystal
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
require "set"
|
||||
require "big"
|
||||
|
||||
def add_reverse(num, max_iter=1000)
|
||||
num = num.to_big_i
|
||||
nums = [] of BigInt
|
||||
(1..max_iter).each_with_object(Set.new([num])) do |_, nums|
|
||||
num += reverse_int(num)
|
||||
nums << num
|
||||
return nums if palindrome?(num)
|
||||
end
|
||||
end
|
||||
|
||||
def palindrome?(num)
|
||||
num == reverse_int(num)
|
||||
end
|
||||
|
||||
def reverse_int(num)
|
||||
num.to_s.reverse.to_big_i
|
||||
end
|
||||
|
||||
def split_roots_from_relateds(roots_and_relateds)
|
||||
roots = roots_and_relateds.dup
|
||||
i = 1
|
||||
while i < roots.size
|
||||
this = roots[i]
|
||||
if roots[0...i].any?{ |prev| this.intersects?(prev) }
|
||||
roots.delete_at(i)
|
||||
else
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
root = roots.map{ |each_set| each_set.min }
|
||||
related = roots_and_relateds.map{ |each_set| each_set.min }
|
||||
related = related.reject{ |n| root.includes?(n) }
|
||||
return root, related
|
||||
end
|
||||
|
||||
def find_lychrel(maxn, max_reversions)
|
||||
series = (1..maxn).map{ |n| add_reverse(n, max_reversions*2) }
|
||||
roots_and_relateds = series.select{ |s| s.size > max_reversions }
|
||||
split_roots_from_relateds(roots_and_relateds)
|
||||
end
|
||||
|
||||
maxn, reversion_limit = 10000, 500
|
||||
puts "Calculations using n = 1..#{maxn} and limiting each search to 2*#{reversion_limit} reverse-digits-and-adds"
|
||||
lychrel, l_related = find_lychrel(maxn, reversion_limit)
|
||||
puts " Number of Lychrel numbers: #{lychrel.size}"
|
||||
puts " Lychrel numbers: #{lychrel}"
|
||||
puts " Number of Lychrel related: #{l_related.size}"
|
||||
pals = (lychrel + l_related).select{|x| palindrome?(x)}.sort
|
||||
puts " Number of Lychrel palindromes: #{pals.size}"
|
||||
puts " Lychrel palindromes: #{pals}"
|
||||
51
Task/Lychrel-numbers/D/lychrel-numbers.d
Normal file
51
Task/Lychrel-numbers/D/lychrel-numbers.d
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import std.stdio, std.conv, std.range, std.typecons, std.bigInt;
|
||||
|
||||
auto rev(in BigInt n) {
|
||||
return n.text.retro.text.BigInt;
|
||||
}
|
||||
|
||||
alias Res = Tuple!(bool, BigInt);
|
||||
|
||||
Res lychrel(BigInt n) {
|
||||
static Res[BigInt] cache;
|
||||
if (n in cache)
|
||||
return cache[n];
|
||||
|
||||
auto r = n.rev;
|
||||
auto res = Res(true, n);
|
||||
immutable(BigInt)[] seen;
|
||||
foreach (immutable i; 0 .. 1_000) {
|
||||
n += r;
|
||||
r = n.rev;
|
||||
if (n == r) {
|
||||
res = Res(false, BigInt(0));
|
||||
break;
|
||||
}
|
||||
if (n in cache) {
|
||||
res = cache[n];
|
||||
break;
|
||||
}
|
||||
seen ~= n;
|
||||
}
|
||||
|
||||
foreach (x; seen)
|
||||
cache[x] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
void main() {
|
||||
BigInt[] seeds, related, palin;
|
||||
|
||||
foreach (immutable i; BigInt(1) .. BigInt(10_000)) { // 1_000_000
|
||||
const tf_s = i.lychrel;
|
||||
if (!tf_s[0])
|
||||
continue;
|
||||
(i == tf_s[1] ? seeds : related) ~= i;
|
||||
if (i == i.rev)
|
||||
palin ~= i;
|
||||
}
|
||||
|
||||
writeln(seeds.length, " Lychrel seeds: ", seeds);
|
||||
writeln(related.length, " Lychrel related");
|
||||
writeln(palin.length, " Lychrel palindromes: ", palin);
|
||||
}
|
||||
391
Task/Lychrel-numbers/Fortran/lychrel-numbers.f
Normal file
391
Task/Lychrel-numbers/Fortran/lychrel-numbers.f
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
SUBROUTINE CROAK(GASP) !A dying message.
|
||||
CHARACTER*(*) GASP !The message.
|
||||
WRITE (6,*) "Oh dear! ",GASP !The gasp.
|
||||
STOP "Alas." !The death.
|
||||
END !Goodbye, cruel world.
|
||||
|
||||
MODULE LYCHREL SEARCH !Assistants for the pursuit of Lychrel numbers.
|
||||
INTEGER LOTSADIGITS,BASE !Parameters.
|
||||
PARAMETER (LOTSADIGITS = 1000, BASE = 10) !This should do.
|
||||
TYPE BIGINT !Can't use an element zero as the count, as lots of digits are needed.
|
||||
INTEGER LDIGIT !Count in use.
|
||||
INTEGER*1 DIGIT(LOTSADIGITS) !Stored in increasing powers of BASE.
|
||||
END TYPE BIGINT !No fractional parts.
|
||||
INTEGER MSTASH !Now for my stash.
|
||||
PARAMETER (MSTASH = 66666) !This should be enough.
|
||||
TYPE(BIGINT) STASH(MSTASH) !The work area.
|
||||
INTEGER AVAILS(0:MSTASH) !A list of available STASH entries.
|
||||
INTEGER PLIST(0:MSTASH) !These strings of fingers
|
||||
INTEGER LLIST(0:MSTASH) !Each starting with a count
|
||||
INTEGER LYCHREL(0:MSTASH)!Finger BIGINTs in the STASH
|
||||
INTEGER L0P(0:MSTASH) !Without the body of the BIGINT being copied.
|
||||
INTEGER LONGESTNUMBER !Keep track out of curiosity.
|
||||
DATA LONGESTNUMBER/0/ !No digits so far.
|
||||
CONTAINS !A miscellany.
|
||||
Commence with some STASH service. If problems were to arise, better error messages would be in order.
|
||||
SUBROUTINE PREPARESTASH !Since fancy usage is involved, fancy initialisation is needed.
|
||||
INTEGER I !A stepper.
|
||||
AVAILS(0) = MSTASH !All are available.
|
||||
FORALL (I = 1:MSTASH) AVAILS(I) = MSTASH + 1 - I !Will be used stack style.
|
||||
STASH.LDIGIT = -666 !This will cause trouble!
|
||||
END SUBROUTINE PREPARESTASH !Simple enough.
|
||||
SUBROUTINE GRABSTASH(X) !Finger an available STASH.
|
||||
INTEGER X !The finger.
|
||||
INTEGER L !The last.
|
||||
L = AVAILS(0) !Pick on the last in the list.
|
||||
IF (L .LE. 0) CALL CROAK("Run out of stashes!") !Hopefully not.
|
||||
X = AVAILS(L) !Select some element or other.
|
||||
AVAILS(L) = 0 !Might as well unfinger.
|
||||
AVAILS(0) = L - 1 !As well as drop off the list.
|
||||
END SUBROUTINE GRABSTASH!Can't be bothered making this a function. Sudden death instead.
|
||||
SUBROUTINE FREESTASH(X) !Unhand a STASH.
|
||||
INTEGER X !The finger.
|
||||
IF (X.EQ.0) RETURN !A non-finger.
|
||||
IF (X.LT.0) CALL CROAK("Unhanding a non-stash!") !Paranoia.
|
||||
IF (X.GT.MSTASH) CALL CROAK("Not a stash!") !I don't expect any of these.
|
||||
IF (AVAILS(0).GE.MSTASH) CALL CROAK("Over subscribed!") !But on principle...
|
||||
AVAILS(0) = AVAILS(0) + 1 !So, append to the list of available entries.
|
||||
AVAILS(AVAILS(0)) = X !Thus.
|
||||
X = 0 !The finger is amputated.
|
||||
END SUBROUTINE FREESTASH !Last out, first in. Etc.
|
||||
|
||||
SUBROUTINE BIGWRITE(T,N)!Reveal an annotated bignumber.
|
||||
CHARACTER*(*) T !The text of its name.
|
||||
TYPE(BIGINT) N !The value of its name.
|
||||
WRITE (6,1) T,N.LDIGIT,N.DIGIT(N.LDIGIT:1:-1) !Roll!
|
||||
1 FORMAT (A,"(1:",I0,") = ",(300I1)) !This should do.
|
||||
END SUBROUTINE BIGWRITE !Perhaps bigger than Integer*8.
|
||||
|
||||
SUBROUTINE SHOWLIST(BLAH,LIST) !One can become confused.
|
||||
INTEGER LIST(0:MSTASH) !Explicit bounds prevents confusion.
|
||||
CHARACTER*(*) BLAH !An identifying message.
|
||||
CHARACTER*4 ZOT !Scratchpad.
|
||||
INTEGER I,IT !Stepper.
|
||||
c REAL*8 V,P !For logarithmic output.
|
||||
c INTEGER J !Another stepper needed.
|
||||
WRITE (6,1) BLAH,LIST(0) !A heading.
|
||||
1 FORMAT ("The count for ",A," is ",I0) !Ah, layout.
|
||||
DO I = 1,LIST(0) !Work through the list.
|
||||
WRITE(ZOT,"('#',I3)") I !Prepare an annotation.
|
||||
IT = LIST(I) !Finger the stash.
|
||||
CALL BIGWRITE(ZOT,STASH(IT)) !Show.
|
||||
c V = 0 !Convert the BIGINT to a floating-point number.
|
||||
c P = 1 !Tracking the powers of BASE, presumed ten.
|
||||
c PP:DO J = STASH(IT).LDIGIT,1,-1 !Start with the highest power.
|
||||
c V = V + STASH(IT).DIGIT(J)/P !Deem it a units digit.
|
||||
c P = P*10 !The next digit will have a lesser power.
|
||||
c IF (P.GT.1000000) EXIT PP !This will do.
|
||||
c END DO PP !On to the next digit.
|
||||
c V = STASH(IT).LDIGIT - 1 + LOG10(V) !Convert. LOG10(196) = 2.29225607135648
|
||||
c WRITE (6,*) I,V !Reveal.
|
||||
END DO !On to the next.
|
||||
END SUBROUTINE SHOWLIST !Adrift in indirection.
|
||||
|
||||
SUBROUTINE BIGLOAD(A,NUM) !Shatters a proper number into its digits.
|
||||
Can't overflow, because the biggest normal integer has far fewer than LOTSADIGITS digits.
|
||||
TYPE(BIGINT) A !The bignumber.
|
||||
INTEGER NUM !The normal integer to put in it.
|
||||
INTEGER L,N !Assistants.
|
||||
N = NUM !A copy that I can damage.
|
||||
A.DIGIT = 0 !Scrub, against a future carry..
|
||||
L = 0 !No digits so far.
|
||||
DO WHILE(N .GT. 0) !Some number remaining?
|
||||
L = L + 1 !Yes. Count another digit.
|
||||
A.DIGIT(L) = MOD(N,BASE) !Place it.
|
||||
N = N/BASE !Reduce the number.
|
||||
END DO !And try again.
|
||||
A.LDIGIT = MAX(1,L) !Zero will have one digit, a zero.
|
||||
END SUBROUTINE BIGLOAD !A small service.
|
||||
|
||||
Continue with routines for doing the work.
|
||||
SUBROUTINE ADVANCE(A,B) !Advance A, giving B.
|
||||
C Experiment shows that for 196, log10(v) = 0·43328*step + 2·1616, or, each advance increases by a factor of ~2·7.
|
||||
TYPE(BIGINT) A,B !To be twiddled.
|
||||
INTEGER D !An assistant for carrying.
|
||||
INTEGER I !A stepper.
|
||||
B.LDIGIT = A.LDIGIT !Same size, so far.
|
||||
FORALL(I = 1:A.LDIGIT) !Do these in any order, even in parallel!
|
||||
1 B.DIGIT(I) = A.DIGIT(I) !Add each digit
|
||||
2 + A.DIGIT(A.LDIGIT - I + 1) ! to its other-end partner.
|
||||
B.DIGIT(B.LDIGIT + 1) = 0 !Perhaps another digit will be needed shortly.
|
||||
DO I = 1,B.LDIGIT !Now slow down and taste the carry.
|
||||
D = B.DIGIT(I) - BASE !Allowable digits are 0:BASE - 1.
|
||||
IF (D.GE.0) THEN !So, has this digit overflowed?
|
||||
B.DIGIT(I) = D !Yes. Only addition, so no div and mod stuff.
|
||||
B.DIGIT(I + 1) = B.DIGIT(I + 1) + 1 !Carry one up, corresponding to subtracting one BASE down.
|
||||
END IF !So much for that digit.
|
||||
END DO !On to the next digit, of higher power.
|
||||
IF (D.GE.0) THEN !A carry from the highest digit?
|
||||
IF (B.LDIGIT .GE. LOTSADIGITS) CALL CROAK("Overflow!") !Oh dear.
|
||||
B.LDIGIT = B.LDIGIT + 1 !NB! Always there is room left for ONE more digit.
|
||||
LONGESTNUMBER = MAX(B.LDIGIT,LONGESTNUMBER) !Perhaps a surprise awaits.
|
||||
END IF !Avoids overflow testing for every carry above.
|
||||
END SUBROUTINE ADVANCE !That was fun!
|
||||
|
||||
LOGICAL FUNCTION PALINDROME(N) !Perhaps a surprise property?
|
||||
Calls a one-digit number palindromic through the execution of vacuous logic.
|
||||
TYPE(BIGINT) N !The big number to inspect.
|
||||
PALINDROME = ALL(N.DIGIT(1:N.LDIGIT/2) !Compare each digit in the first half...
|
||||
1 .EQ.N.DIGIT(N.LDIGIT:N.LDIGIT/2 + 1:-1)) !To its opposite digit in the second. Whee!
|
||||
END FUNCTION PALINDROME !If an odd number of digits, ignores the middle digit.
|
||||
|
||||
INTEGER FUNCTION ORDER(A,B) !Does B follow A?
|
||||
TYPE(BIGINT) A,B !The two numbers.
|
||||
INTEGER I !A stepper.
|
||||
IF (A.LDIGIT - B.LDIGIT) 1,10,2 !First, compare the lengths.
|
||||
1 ORDER = +1 !B has more digits.
|
||||
RETURN !So, A must be smaller: in order.
|
||||
2 ORDER = -1 !A has more digits.
|
||||
RETURN !So B must be smaller: reverse order.
|
||||
Compare the digits of the two numbers, known to be of equal length.
|
||||
10 DO 11 I = A.LDIGIT,1,-1 !The last digit has the highest power.
|
||||
IF (A.DIGIT(I) - B.DIGIT(I)) 1,11,2 !Compare the digits.
|
||||
11 CONTINUE !If they match, continue with the next digit.
|
||||
ORDER = 0 !If all match, A = B.
|
||||
END FUNCTION ORDER !Ah, three-way tests...
|
||||
|
||||
SUBROUTINE COMBSORT(XNDX) !Sort according to STASH(XNDX)) by reordering XNDX.
|
||||
Crank up a Comb sort of array STASH as indexed by XNDX.
|
||||
INTEGER XNDX(0:),T !The index to be rearranged.
|
||||
INTEGER I,H !Tools. H ought not be a small integer.
|
||||
LOGICAL CURSE !Annoyance.
|
||||
H = XNDX(0) - 1 !Last - First, and not +1.
|
||||
IF (H.LE.0) GO TO 999 !Ha ha.
|
||||
1 H = MAX(1,H*10/13) !The special feature.
|
||||
IF (H.EQ.9 .OR. H.EQ.10) H = 11 !A twiddle.
|
||||
CURSE = .FALSE. !So far, so good.
|
||||
DO I = XNDX(0) - H,1,-1 !If H = 1, this is a BubbleSort.
|
||||
IF (ORDER(STASH(XNDX(I)),STASH(XNDX(I + H))) .LT. 0) THEN !One compare.
|
||||
T=XNDX(I); XNDX(I)=XNDX(I+H); XNDX(I+H)=T !One swap.
|
||||
CURSE = .TRUE. !One curse.
|
||||
END IF !One test.
|
||||
END DO !One loop.
|
||||
IF (CURSE .OR. H.GT.1) GO TO 1!Work remains?
|
||||
999 RETURN !If not, we're done.
|
||||
END SUBROUTINE COMBSORT !Good performance, and simple.
|
||||
|
||||
SUBROUTINE INSERTIONSORT(XNDX) !Adjust XNDX according to STASH(XNDX)
|
||||
Crank up an Insertion sort of array STASH as indexed by XNDX.
|
||||
INTEGER XNDX(0:),IT !The index to be prepared, and a safe place.
|
||||
INTEGER I,L !Fingers.
|
||||
DO L = 2,XNDX(0) !Step along the array.
|
||||
IF (ORDER(STASH(XNDX(L - 1)),STASH(XNDX(L))) .LT. 0) THEN !Disorder?
|
||||
I = L !Yes. Element L belongs earlier.
|
||||
IT = XNDX(L) !Save it so that others can be shifted up one.
|
||||
1 XNDX(I) = XNDX(I - 1) !Shift one.
|
||||
I = I - 1 !The next candidate back.
|
||||
IF (I.GT.1 .AND. ORDER(STASH(XNDX(I - 1)), !Do I have to go further back?
|
||||
1 STASH(IT)).LT.0) GO TO 1 !Yes.
|
||||
XNDX(I) = IT !Done. Place it in the space created.
|
||||
END IF !So much for that comparison.
|
||||
END DO !On to the next.
|
||||
END SUBROUTINE INSERTIONSORT !Swift only if the array is nearly in order.
|
||||
|
||||
INTEGER FUNCTION FOUNDIN(XNDX,X) !Search STASH(XNDX) for X.
|
||||
Crank up a binary serach. This uses EXCLUSIVE bounds.
|
||||
INTEGER XNDX(0:) !The list of elements.
|
||||
TYPE(BIGINT) X !The value to be sought.
|
||||
INTEGER L,P,R !Fingers for the binary search.
|
||||
L = 0 !Establish outer bounds.
|
||||
R = XNDX(0) + 1 !One before, and one after, the first and last.
|
||||
1 P = (R - L)/2 !Probe point offset. Beware integer overflow with (L + R)/2.
|
||||
IF (P.LE.0) THEN !Is the search span exhausted?
|
||||
FOUNDIN = -L !Alas. X should follow position L but doesn't.
|
||||
RETURN !Nothing more to search.
|
||||
END IF !Otherwise, STASH(XNDX(L + 1)) <= X <= STASH(XNDX(R - 1))
|
||||
P = L + P !Convert from offset to probe point.
|
||||
IF (ORDER(X,STASH(XNDX(P)))) 2,4,3 !Compare X to the probe point's value.
|
||||
2 L = P !STASH(XNDX(P)) < X: advance L to P.
|
||||
GO TO 1 !Try again.
|
||||
3 R = P !X < STASH(XNDX(P)): retract R to P.
|
||||
GO TO 1 !Try again.
|
||||
Caught it! X = STASH(XNDX(P)) - the result indexes XNDX, not STASH.
|
||||
4 FOUNDIN = P !So, X is found, here! *Not* at P, but at XNDX(P).
|
||||
END FUNCTION FOUNDIN !Hopefully, without array copy-in, copy-out.
|
||||
|
||||
SUBROUTINE INSPECT(S1,S2,ENUFF) !Follow the Lychrel protocol.
|
||||
Careful! A march is stopped on encountering a palindrome, BUT, the starting value is not itself checked.
|
||||
INTEGER S1,S2 !Start and stop values.
|
||||
INTEGER ENUFF !An infinite trail can't be followed.
|
||||
INTEGER STEP,SEED !Counts the advances along the long march.
|
||||
INTEGER START !The first value of a march has special treatment.
|
||||
INTEGER MARCH(0:ENUFF) !The waypoints of a long march.
|
||||
INTEGER DEJAVU !Some may prove to be junctions.
|
||||
INTEGER LP,NP,LL,NL !Counters for various odd outcomes.
|
||||
NP = 0 !No palindromic stops.
|
||||
LP = 0 !Nor any that head for one.
|
||||
NL = 0 !No neverending sequences seen.
|
||||
LL = 0 !Nor any that head for one.
|
||||
WRITE (6,10) S1,S2,ENUFF !Announce the plan.
|
||||
10 FORMAT ("Starting values ",I0," to ",I0,"; step limit ",I0)
|
||||
C For each try, steps (but not the START) are saved in MARCH, and those steps end up in one list or another.
|
||||
C Thus, there is no removal of their entries from the working STASH. If a plaindrome is found, or a step's value is
|
||||
c noticed in the PLIST or LYCHREL list, the last STEP is not saved (being in that list, as a different entry in STASH)
|
||||
c and its redundant value in STASH is unhanded via CALL FREESTASH(MARCH(STEP)).
|
||||
c But if instead the MARCH is to be added to the LYCHREL list, the last value is included.
|
||||
c Since tries are made in increasing order, and ADVANCE always produces a bigger number, there is no point
|
||||
c in saving the START value in STASH, except, some START values turn out to be notable and being saved in L0P
|
||||
c or LLIST, their entry in STASH must not be rugpulled, thus the START = 0 to note this and prevent FREESTASH.
|
||||
TRY:DO SEED = S1,S2 !Here we go.
|
||||
CALL GRABSTASH(START) !Ask for a starting space.
|
||||
CALL BIGLOAD(STASH(START),SEED) !The starting value.
|
||||
c CALL BIGWRITE("N0",STASH(START)) !Show it.
|
||||
c IF (FOUNDIN(LYCHREL,STASH(START)) .GT. 0) THEN! Have we been here during a long march?
|
||||
c WRITE (6,*) SEED,"Falls in!" !Yes!
|
||||
c CYCLE TRY !Nothing will be learnt by continuing.
|
||||
c END IF !Otherwise, we're not discouraged.
|
||||
STEP = 1 !Even the longest journey stars with its first step.
|
||||
MARCH(0) = STEP !And I'm remembering every step.
|
||||
CALL GRABSTASH(MARCH(STEP)) !A place for my first footfall.
|
||||
CALL ADVANCE(STASH(START),STASH(MARCH(STEP))) !Start the stomping.
|
||||
Contemplate the current step.
|
||||
100 CONTINUE !Can't label a blank line...
|
||||
c CALL BIGWRITE("N1",STASH(MARCH(STEP))) !Progress may be of interest.
|
||||
DEJAVU = FOUNDIN(PLIST,STASH(MARCH(STEP))) !A value known to later become a palindrome?
|
||||
IF (DEJAVU .GT. 0) THEN !It being amongst those stashed for that cause.
|
||||
c WRITE (6,*) SEED,STEP,"Deja vu! List#",DEJAVU
|
||||
LP = LP + 1 !Count a late starter.
|
||||
CALL FREESTASH(MARCH(STEP)) !The last step is already known.
|
||||
CALL SLURP(PLIST) !Add the MARCH to the palindrome starters.
|
||||
GO TO 110 !And we're finished with this try.
|
||||
END IF !So much for prospective palindromes.
|
||||
IF (PALINDROME(STASH(MARCH(STEP)))) THEN !Attained an actual palindrome?
|
||||
c WRITE (6,*) SEED,STEP,"Palindrome!" !Yes!
|
||||
NP = NP + 1 !Count a proper palendrome.
|
||||
CALL FREESTASH(MARCH(STEP)) !The last step is a palindrome.
|
||||
CALL SLURP(PLIST) !So remember only those non-palindromes before it.
|
||||
GO TO 110 !This is a pretext for ending.
|
||||
END IF !Since one could advance past a palindrome, and then find another.
|
||||
DEJAVU = FOUNDIN(LYCHREL,STASH(MARCH(STEP))) !A value known to later pass ENUFF?
|
||||
IF (DEJAVU .GT. 0) THEN !If so, there is no need to follow that march again.
|
||||
c WRITE (6,*) SEED,STEP,"Latecomer! List#",DEJAVU !So this starter has been preempted.
|
||||
c CALL BIGWRITE("Latecomer!",STASH(LYCHREL(DEJAVU))) !Or, STASH(MARCH(STEP)), they being equal.
|
||||
LLIST(0) = LLIST(0) + 1 !Count another latecomer.
|
||||
LLIST(LLIST(0)) = START !This was its starting value's finger.
|
||||
IF (PALINDROME(STASH(START))) THEN !Perhaps its starting value was also already a palindrome?
|
||||
L0P(0) = L0P(0) + 1 !Yes! Count another such.
|
||||
L0P(L0P(0)) = START !Using a finger, rather than copying a BIGINT.
|
||||
END IF !A Lychrel number whose zeroth step is palindromic.
|
||||
START = 0 !This is not to be unfingered!
|
||||
LL = LL + 1 !Anyway, this path has joined a known long march.
|
||||
CALL FREESTASH(MARCH(STEP)) !This value is already fingered in a list.
|
||||
CALL SLURP(LYCHREL) !So, all its steps do so also, including the last.
|
||||
GO TO 110 !Even though its later start might find a palindrome within ENUFF steps.
|
||||
END IF !So much for discoveries at each step.
|
||||
IF (STEP.LT.ENUFF) THEN !Are we there yet?
|
||||
STEP = STEP + 1 !It seems there is no reason to stop.
|
||||
MARCH(0) = STEP !So, the long march extends.
|
||||
CALL GRABSTASH(MARCH(STEP)) !Another step.
|
||||
CALL ADVANCE(STASH(MARCH(STEP - 1)),STASH(MARCH(STEP))) !Lurch forwards.
|
||||
GO TO 100 !And see what happens here.
|
||||
END IF !The end of the loop.
|
||||
Chase completed, having reached STEP = ENUFF with no decision.
|
||||
WRITE (6,*) SEED,"retains Lychrel potential." !Since a palindrome has not been reached.
|
||||
IF (PALINDROME(STASH(START))) THEN !Perhaps it started as a palindrome?
|
||||
L0P(0) = L0P(0) + 1 !It did!
|
||||
L0P(L0P(0)) = START !So remember it.
|
||||
START = 0 !And don't unhand this entry, a finger to it being saved.
|
||||
END IF !Enough shades of classification.
|
||||
NL = NL + 1 !Count another at the end of a long march.
|
||||
CALL SLURP(LYCHREL) !And save the lot, including the final value.
|
||||
110 IF (START.GT.0) CALL FREESTASH(START) !The starting value was not held as a part of the MARCH.
|
||||
END DO TRY !Start another.
|
||||
Cast forth a summary.
|
||||
WRITE (6,*)
|
||||
WRITE (6,11) NL,ENUFF,LL,LYCHREL(0)
|
||||
11 FORMAT (I8," starters attained step ",I0," and ",
|
||||
1 I0," joined a long march. "
|
||||
2 I0," waypoints stashed.")
|
||||
c CALL SHOWLIST("starters that joined a Long March",LLIST)
|
||||
CALL SHOWLIST("Long Marchers starting as palindromes",L0P)
|
||||
WRITE (6,12) NP,LP,PLIST(0)
|
||||
12 FORMAT (I8," starters ended as a palindrome, ",
|
||||
1 I0," joined a route leading to a palindrome. ",
|
||||
2 I0," waypoints stashed.")
|
||||
CONTAINS !An assistant.
|
||||
SUBROUTINE SLURP(LIST) !Adds the elements in MARCH to LIST.
|
||||
C Entries in LIST are such that STASH(LIST(~)) is ordered. Because I arrange this.
|
||||
C Entries MARCH are also in increasing order as they are successive values from ADVANCE.
|
||||
C Accordingly, if only a few entries are to be added, a binary search can be used to find the
|
||||
C location for insertion, and then existing entries can be shifted up to make room for the new entry.
|
||||
C This is the basic task of Insertionsort, however, this shift can be conducted without invoking ORDER
|
||||
C to determine its bounds, as is done by Insertionsort, and ORDER takes a lot of time to decide.
|
||||
C In other words, the binary search makes only a few calls to ORDER and then the moves follow, in one go,
|
||||
C whereas the Insertionsort makes as many calls to ORDER as it makes moves, and does so stepwise.
|
||||
C When many entries are to be added, they could be appended to LIST and then COMBSORT invoked.
|
||||
C This is infrequent as few numbers evoke a lengthy march, so that method is adequate.
|
||||
C But since both lists are in order, a merge of the two lists would be more stylish, if encoded clunkily.
|
||||
C It turns out that the incoming set may finger a value that is already in LIST,
|
||||
c so equal values may appear. With the binary search method, such incomers can simply be skipped,
|
||||
c but with the merge it is a bit more messy. In the event, the new value is discarded and the
|
||||
c old one retained.
|
||||
C For instance, 5 -> 10 -> 11 so fingers for 5 and 10 are added to PLIST.
|
||||
C Later on, 10 -> 11 and a finger for 10 is to be added to PLIST, because the starting value is not checked.
|
||||
C However, a later version refrains from adding the (unchecked) starting value, and then, no worries.
|
||||
INTEGER LIST(0:MSTASH) !Some string of numbers.
|
||||
INTEGER MIST(0:MSTASH) !LIST(0) is the upper bound, but risks stack overflow.
|
||||
INTEGER I,S,L !A stepper.
|
||||
Check for annoying nullities.
|
||||
1 IF (MARCH(0).LE.0) RETURN !An empty march already!
|
||||
IF (MARCH(MARCH(0)).LE.0) THEN !Otherwise, look at the last step.
|
||||
MARCH(0) = MARCH(0) - 1 !It was boring.
|
||||
GO TO 1 !So, go back one and look afresh.
|
||||
END IF !Having snipped off trailing nullities, what remains means effort.
|
||||
Can't escape some work.
|
||||
IF (MARCH(0) .LE. 6) THEN !If we have a few only,
|
||||
DO I = 1,MARCH(0) !Work through them one by one,
|
||||
S = MARCH(I) !The finger for this step of the march.
|
||||
IF (S.LE.0) CYCLE !A stump?
|
||||
L = FOUNDIN(LIST,STASH(S)) !Using a binary search to find the proper place.
|
||||
IF (L.GT.0) THEN !If already present,
|
||||
CALL FREESTASH(S) !Its entry is no longer needed.
|
||||
CYCLE !So skip this.
|
||||
END IF !But if not found, a place must be made.
|
||||
L = 1 - L !Finger where the missing element should be.
|
||||
LIST(LIST(0) + 1:L + 1:-1) = LIST(LIST(0):L:-1) !Shift followers up to make space.
|
||||
LIST(0) = LIST(0) + 1 !Count another.
|
||||
LIST(L) = S !Place it.
|
||||
END DO !On to the next.
|
||||
ELSE !But if there are many to add, merge the two lists... Both are ordered.
|
||||
MIST(0:LIST(0)) = LIST(0:LIST(0)) !Copy the source list.
|
||||
LIST(0) = 0 !It is to be reformed by the merge.
|
||||
L = 1 !Start with the first in MIST.
|
||||
DO I = 1,MARCH(0) !And work along the long MARCH.
|
||||
S = MARCH(I) !So, a step from the long march.
|
||||
IF (S.LE.0) CYCLE !And if not an empty step, we have one.
|
||||
11 LIST(0) = LIST(0) + 1 !Count in another for this list.
|
||||
IF (L.LE.MIST(0)) THEN !Still have suppliers from what had been LIST?
|
||||
IF (ORDER(STASH(MIST(L)),STASH(S))) 14,13,12 !Yes, Which is to be selected?
|
||||
12 LIST(LIST(0)) = MIST(L) !STASH(MIST(L)) precedes STASH(S), so take it.
|
||||
L = L + 1 !Advance to the next MIST entry.
|
||||
GO TO 11 !And look again.
|
||||
13 CALL FREESTASH(S) !Equal. Discard the new entry.
|
||||
S = MIST(L) !And pefer the established entry.
|
||||
L = L + 1 !Advance past the MIST(L) entry.
|
||||
END IF !Thus, MIST entries have been rolled until a MARCH entry was due.
|
||||
14 LIST(LIST(0)) = S !Save the finger - which may have come from MIST...
|
||||
END DO !On to the next MARCH.
|
||||
S = MIST(0) - L + 1 !The number of MIST entries still waiting.
|
||||
IF (S .GT. 0) THEN !Are there any?
|
||||
LIST(LIST(0) + 1:LIST(0) + S) = MIST(L:MIST(0)) !Yes. Append them.
|
||||
LIST(0) = LIST(0) + S !And count them in.
|
||||
END IF !So much for the merge.
|
||||
END IF !Otherwise, a COMBSORT would do.
|
||||
END SUBROUTINE SLURP !Can't overflow, because each LIST has room for MSTASH entries.
|
||||
END SUBROUTINE INSPECT !That was fun.
|
||||
END MODULE LYCHREL SEARCH !Enough of that.
|
||||
|
||||
PROGRAM TEST
|
||||
USE LYCHREL SEARCH
|
||||
CALL PREPARESTASH
|
||||
Clear my lists.
|
||||
LYCHREL = 0 !No Lychrel candidates.
|
||||
LLIST = 0 !No latecomers to a Lychrel candidacy sequence.
|
||||
PLIST = 0 !No numbers leading to a palindrome.
|
||||
L0P = 0 !No Lychrel/latecomers starting as a palindrome.
|
||||
|
||||
CALL INSPECT(1,10000,500) !Whee!
|
||||
|
||||
WRITE (6,*) "Longest digit string =",LONGESTNUMBER
|
||||
WRITE (6,*) "Unused STASH entries =",AVAILS(0)
|
||||
END
|
||||
94
Task/Lychrel-numbers/FreeBASIC/lychrel-numbers.basic
Normal file
94
Task/Lychrel-numbers/FreeBASIC/lychrel-numbers.basic
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
' version 13-09-2015
|
||||
' compile with: fbc -s console
|
||||
|
||||
' iteration limit
|
||||
#Define max_it 500
|
||||
' the highest number to be tested
|
||||
#Define max_number_to_test 10000
|
||||
|
||||
Dim As String num, rev
|
||||
Dim As String temp(), store()
|
||||
|
||||
Dim As Integer x, x1, palindrome
|
||||
Dim As UInteger it, s, carry, sum, match, seed, related
|
||||
Dim As UInteger num2test, p_count, lychrel_palindrome()
|
||||
|
||||
For num2test = 1 To max_number_to_test
|
||||
num = Str(num2test)
|
||||
rev = num : s = Len(num) - 1
|
||||
For x = 0 To s
|
||||
rev[s - x] = num[x]
|
||||
Next
|
||||
' if num = rev then palindrome = -1 else palindrome = 0
|
||||
' palindrome is set to the result of the compare of num and rev
|
||||
palindrome = (num = rev)
|
||||
it = 0
|
||||
ReDim temp(1 To max_it)
|
||||
Do
|
||||
carry = 0
|
||||
For x = s To 0 Step -1 'add the two numbers
|
||||
sum = num[x] + rev[x] + carry
|
||||
If sum > (9 + 48 + 48) Then
|
||||
num[x] = sum - 10 - 48
|
||||
carry = 1
|
||||
Else
|
||||
num[x] = sum - 48
|
||||
carry = 0
|
||||
End If
|
||||
Next
|
||||
If carry = 1 Then num = "1" + num
|
||||
it = it + 1 : temp(it) = num
|
||||
rev = num : s = Len(num) - 1
|
||||
For x = 0 To s
|
||||
rev[s - x] = num[x]
|
||||
Next
|
||||
Loop Until num = rev OrElse it = max_it
|
||||
If it = max_it Then
|
||||
match = 0
|
||||
' if it's palindrome then save the number
|
||||
If palindrome <> 0 Then
|
||||
p_count = p_count + 1
|
||||
ReDim Preserve lychrel_palindrome(1 To p_count)
|
||||
lychrel_palindrome(p_count) = num2test
|
||||
End If
|
||||
For x = 1 To seed ' check against previous found seed(s)
|
||||
For x1 = max_it To 1 Step -1
|
||||
If store(x, 1) = temp(x1) Then
|
||||
match = 1
|
||||
related = related + 1
|
||||
Exit For, For
|
||||
Else
|
||||
If Len(store(x,1)) > Len(temp(x1)) Then
|
||||
Exit For
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
' no match found then it's a new seed, store it
|
||||
If match = 0 Then
|
||||
seed = seed + 1
|
||||
ReDim Preserve store(seed, 1)
|
||||
store(seed, 0) = Str(num2test)
|
||||
store(seed, 1) = temp(max_it)
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
|
||||
Print
|
||||
Print " Testing numbers: 1 to "; Str(max_number_to_test)
|
||||
Print " Iteration maximum: ";Str(max_it)
|
||||
Print
|
||||
Print " Number of Lychrel seeds: "; seed
|
||||
Print " Lychrel number: ";
|
||||
For x = 1 To seed : Print store(x,0); " "; : Next : Print
|
||||
Print " Number of relateds found: "; related
|
||||
Print " Lychrel numbers that are palindromes: "; p_count
|
||||
Print " Lychrel palindromes: ";
|
||||
For x = 1 To p_count : Print lychrel_palindrome(x); " "; : Next : Print
|
||||
Print
|
||||
|
||||
' empty keyboard buffer
|
||||
While Inkey <> "" : Wend
|
||||
Print : Print "hit any key to end program"
|
||||
Sleep
|
||||
End
|
||||
131
Task/Lychrel-numbers/Go/lychrel-numbers.go
Normal file
131
Task/Lychrel-numbers/Go/lychrel-numbers.go
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
var maxRev = big.NewInt(math.MaxUint64 / 10) // approximate
|
||||
var ten = big.NewInt(10)
|
||||
|
||||
// Reverse sets `result` to the value of the base ten digits of `v` in
|
||||
// reverse order and returns `result`.
|
||||
// Only handles positive integers.
|
||||
func reverseInt(v *big.Int, result *big.Int) *big.Int {
|
||||
if v.Cmp(maxRev) <= 0 {
|
||||
// optimize small values that fit within uint64
|
||||
result.SetUint64(reverseUint64(v.Uint64()))
|
||||
} else {
|
||||
if true {
|
||||
// Reverse the string representation
|
||||
s := reverseString(v.String())
|
||||
result.SetString(s, 10)
|
||||
} else {
|
||||
// This has fewer allocations but is slower:
|
||||
// Use a copy of `v` since we mutate it.
|
||||
v := new(big.Int).Set(v)
|
||||
digit := new(big.Int)
|
||||
result.SetUint64(0)
|
||||
for v.BitLen() > 0 {
|
||||
v.QuoRem(v, ten, digit)
|
||||
result.Mul(result, ten)
|
||||
result.Add(result, digit)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func reverseUint64(v uint64) uint64 {
|
||||
var r uint64
|
||||
for v > 0 {
|
||||
r *= 10
|
||||
r += v % 10
|
||||
v /= 10
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func reverseString(s string) string {
|
||||
b := make([]byte, len(s))
|
||||
for i, j := 0, len(s)-1; j >= 0; i, j = i+1, j-1 {
|
||||
b[i] = s[j]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
var known = make(map[string]bool)
|
||||
|
||||
func Lychrel(n uint64, iter uint) (isLychrel, isSeed bool) {
|
||||
v, r := new(big.Int).SetUint64(n), new(big.Int)
|
||||
reverseInt(v, r)
|
||||
seen := make(map[string]bool)
|
||||
isLychrel = true
|
||||
isSeed = true
|
||||
for i := iter; i > 0; i-- {
|
||||
str := v.String()
|
||||
if seen[str] {
|
||||
//log.Println("found a loop with", n, "at", str)
|
||||
isLychrel = true
|
||||
break
|
||||
}
|
||||
if ans, ok := known[str]; ok {
|
||||
//log.Println("already know:", str, ans)
|
||||
isLychrel = ans
|
||||
isSeed = false
|
||||
break
|
||||
}
|
||||
seen[str] = true
|
||||
|
||||
v = v.Add(v, r)
|
||||
//log.Printf("%v + %v = %v\n", str, r, v)
|
||||
reverseInt(v, r)
|
||||
if v.Cmp(r) == 0 {
|
||||
//log.Println(v, "is a palindrome,", n, "is not a Lychrel number")
|
||||
isLychrel = false
|
||||
isSeed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
for k := range seen {
|
||||
known[k] = isLychrel
|
||||
}
|
||||
//if isLychrel { log.Printf("%v may be a Lychrel number\n", n) }
|
||||
return isLychrel, isSeed
|
||||
}
|
||||
|
||||
func main() {
|
||||
max := flag.Uint64("max", 10000, "search in the range 1..`N` inclusive")
|
||||
iter := flag.Uint("iter", 500, "limit palindrome search to `N` iterations")
|
||||
flag.Parse()
|
||||
if flag.NArg() != 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
fmt.Printf("Calculating using n = 1..%v and %v iterations:\n", *max, *iter)
|
||||
var seeds []uint64
|
||||
var related int
|
||||
var pals []uint64
|
||||
for i := uint64(1); i <= *max; i++ {
|
||||
if l, s := Lychrel(i, *iter); l {
|
||||
if s {
|
||||
seeds = append(seeds, i)
|
||||
} else {
|
||||
related++
|
||||
}
|
||||
if i == reverseUint64(i) {
|
||||
pals = append(pals, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(" Number of Lychrel seeds:", len(seeds))
|
||||
fmt.Println(" Lychrel seeds:", seeds)
|
||||
fmt.Println(" Number of related:", related)
|
||||
fmt.Println("Number of Lychrel palindromes:", len(pals))
|
||||
fmt.Println(" Lychrel palindromes:", pals)
|
||||
}
|
||||
50
Task/Lychrel-numbers/Haskell/lychrel-numbers.hs
Normal file
50
Task/Lychrel-numbers/Haskell/lychrel-numbers.hs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
module Main where
|
||||
|
||||
import Data.List
|
||||
|
||||
procLychrel :: Integer -> [Integer]
|
||||
procLychrel a = a : pl a
|
||||
where
|
||||
pl n =
|
||||
let s = n + reverseInteger n
|
||||
in if isPalindrome s
|
||||
then [s]
|
||||
else s : pl s
|
||||
|
||||
isPalindrome :: Integer -> Bool
|
||||
isPalindrome n =
|
||||
let s = show n
|
||||
in (s == reverse s)
|
||||
|
||||
isLychrel :: Integer -> Bool
|
||||
isLychrel = not . null . drop 500 . procLychrel
|
||||
|
||||
reverseInteger :: Integer -> Integer
|
||||
reverseInteger = read . reverse . show
|
||||
|
||||
seedAndRelated :: (Int, [Integer], [Integer], Int)
|
||||
seedAndRelated =
|
||||
let (seed, related, _) = foldl sar ([], [], []) [1 .. 10000]
|
||||
lseed = length seed
|
||||
lrelated = length related
|
||||
totalCount = lseed + lrelated
|
||||
pal = filter isPalindrome $ seed ++ related
|
||||
in (totalCount, pal, seed, lrelated)
|
||||
where
|
||||
sar (seed, related, lych) x =
|
||||
let s = procLychrel x
|
||||
sIsLychrel = not . null . drop 500 $ s
|
||||
(isIn, isOut) = partition (`elem` lych) . take 501 $ s
|
||||
newLych = lych ++ isOut
|
||||
in if sIsLychrel
|
||||
then if null isIn -- seed lychrel number
|
||||
then (x : seed, related, newLych)
|
||||
else (seed, x : related, newLych) -- related lychrel number
|
||||
else (seed, related, lych)
|
||||
|
||||
main = do
|
||||
let (totalCount, palindromicLychrel, lychrelSeeds, relatedCount) = seedAndRelated
|
||||
putStrLn $ "[1..10,000] contains " ++ show totalCount ++ " Lychrel numbers."
|
||||
putStrLn $ show palindromicLychrel ++ " are palindromic Lychrel numbers."
|
||||
putStrLn $ show lychrelSeeds ++ " are Lychrel seeds."
|
||||
putStrLn $ "There are " ++ show relatedCount ++ " related Lychrel numbers."
|
||||
1
Task/Lychrel-numbers/J/lychrel-numbers-1.j
Normal file
1
Task/Lychrel-numbers/J/lychrel-numbers-1.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
revdig=:('x',~|.)&.":"0
|
||||
2
Task/Lychrel-numbers/J/lychrel-numbers-10.j
Normal file
2
Task/Lychrel-numbers/J/lychrel-numbers-10.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(#~(=revdig))L
|
||||
4994 8778 9999
|
||||
13
Task/Lychrel-numbers/J/lychrel-numbers-11.j
Normal file
13
Task/Lychrel-numbers/J/lychrel-numbers-11.j
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
revdig=:('x',~|.)&.":"0
|
||||
lychrel500=: (~: revdig)@((+^:~: revdig)^:500)@(+revdig)"0
|
||||
L=:I.lychrel500 i.10001
|
||||
S=:(+revdig)^:(i.501)"0 L
|
||||
owned=: <@~.@,\S
|
||||
#T=: (-. (<"1 S) +./@e.&> a:,}:owned)#L
|
||||
5
|
||||
T
|
||||
196 879 1997 7059 9999
|
||||
L -&# T
|
||||
244
|
||||
(#~(=revdig))L
|
||||
4994 8778 9999
|
||||
2
Task/Lychrel-numbers/J/lychrel-numbers-2.j
Normal file
2
Task/Lychrel-numbers/J/lychrel-numbers-2.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(+revdig)^:500(12)
|
||||
989330226271793404132120335101444022368928728236373385750622261099268167362912850818170039990942038798808908830140199820181718948328173760873880172226156484473632718819962221534191534021132404387162721132989
|
||||
1
Task/Lychrel-numbers/J/lychrel-numbers-3.j
Normal file
1
Task/Lychrel-numbers/J/lychrel-numbers-3.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
lychrel500=: (~: revdig)@((+^:~: revdig)^:500)@(+revdig)"0
|
||||
2
Task/Lychrel-numbers/J/lychrel-numbers-4.j
Normal file
2
Task/Lychrel-numbers/J/lychrel-numbers-4.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#L=:I.lychrel500 i.10001
|
||||
249
|
||||
4
Task/Lychrel-numbers/J/lychrel-numbers-5.j
Normal file
4
Task/Lychrel-numbers/J/lychrel-numbers-5.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
3 83$L
|
||||
196 295 394 493 592 689 691 788 790 879 887 978 986 1495 1497 1585 1587 1675 1677 1765 1767 1855 1857 1945 1947 1997 2494 2496 2584 2586 2674 2676 2764 2766 2854 2856 2944 2946 2996 3493 3495 3583 3585 3673 3675 3763 3765 3853 3855 3943 3945 3995 4079 4169 4259 4349 4439 4492 4494 4529 4582 4584 4619 4672 4674 4709 4762 4764 4799 4852 4854 4889 4942 4944 4979 4994 5078 5168 5258 5348 5438 5491 5493
|
||||
5528 5581 5583 5618 5671 5673 5708 5761 5763 5798 5851 5853 5888 5941 5943 5978 5993 6077 6167 6257 6347 6437 6490 6492 6527 6580 6582 6617 6670 6672 6707 6760 6762 6797 6850 6852 6887 6940 6942 6977 6992 7059 7076 7149 7166 7239 7256 7329 7346 7419 7436 7491 7509 7526 7581 7599 7616 7671 7689 7706 7761 7779 7796 7851 7869 7886 7941 7959 7976 7991 8058 8075 8079 8089 8148 8165 8169 8179 8238 8255 8259 8269 8328
|
||||
8345 8349 8359 8418 8435 8439 8449 8490 8508 8525 8529 8539 8580 8598 8615 8619 8629 8670 8688 8705 8709 8719 8760 8778 8795 8799 8809 8850 8868 8885 8889 8899 8940 8958 8975 8979 8989 8990 9057 9074 9078 9088 9147 9164 9168 9178 9237 9254 9258 9268 9327 9344 9348 9358 9417 9434 9438 9448 9507 9524 9528 9538 9597 9614 9618 9628 9687 9704 9708 9718 9777 9794 9798 9808 9867 9884 9888 9898 9957 9974 9978 9988 9999
|
||||
1
Task/Lychrel-numbers/J/lychrel-numbers-6.j
Normal file
1
Task/Lychrel-numbers/J/lychrel-numbers-6.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
S=:(+revdig)^:(i.501)"0 L
|
||||
11
Task/Lychrel-numbers/J/lychrel-numbers-7.j
Normal file
11
Task/Lychrel-numbers/J/lychrel-numbers-7.j
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
10 10 {.S
|
||||
196 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
295 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
394 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
493 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
592 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
689 1675 7436 13783 52514 94039 187088 1067869 10755470 18211171
|
||||
691 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
788 1675 7436 13783 52514 94039 187088 1067869 10755470 18211171
|
||||
790 887 1675 7436 13783 52514 94039 187088 1067869 10755470
|
||||
879 1857 9438 17787 96558 182127 903408 1707717 8884788 17759676
|
||||
5
Task/Lychrel-numbers/J/lychrel-numbers-8.j
Normal file
5
Task/Lychrel-numbers/J/lychrel-numbers-8.j
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
owned=: <@~.@,\S
|
||||
#T=: (-. (<"1 S) +./@e.&> a:,}:owned)#L
|
||||
5
|
||||
T
|
||||
196 879 1997 7059 9999
|
||||
2
Task/Lychrel-numbers/J/lychrel-numbers-9.j
Normal file
2
Task/Lychrel-numbers/J/lychrel-numbers-9.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
L -&# T
|
||||
244
|
||||
82
Task/Lychrel-numbers/Java/lychrel-numbers.java
Normal file
82
Task/Lychrel-numbers/Java/lychrel-numbers.java
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
public class Lychrel {
|
||||
|
||||
static Map<BigInteger, Tuple> cache = new HashMap<>();
|
||||
|
||||
static class Tuple {
|
||||
final Boolean flag;
|
||||
final BigInteger bi;
|
||||
|
||||
Tuple(boolean f, BigInteger b) {
|
||||
flag = f;
|
||||
bi = b;
|
||||
}
|
||||
}
|
||||
|
||||
static BigInteger rev(BigInteger bi) {
|
||||
String s = new StringBuilder(bi.toString()).reverse().toString();
|
||||
return new BigInteger(s);
|
||||
}
|
||||
|
||||
static Tuple lychrel(BigInteger n) {
|
||||
Tuple res;
|
||||
if ((res = cache.get(n)) != null)
|
||||
return res;
|
||||
|
||||
BigInteger r = rev(n);
|
||||
res = new Tuple(true, n);
|
||||
List<BigInteger> seen = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 500; i++) {
|
||||
n = n.add(r);
|
||||
r = rev(n);
|
||||
|
||||
if (n.equals(r)) {
|
||||
res = new Tuple(false, BigInteger.ZERO);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cache.containsKey(n)) {
|
||||
res = cache.get(n);
|
||||
break;
|
||||
}
|
||||
|
||||
seen.add(n);
|
||||
}
|
||||
|
||||
for (BigInteger bi : seen)
|
||||
cache.put(bi, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
List<BigInteger> seeds = new ArrayList<>();
|
||||
List<BigInteger> related = new ArrayList<>();
|
||||
List<BigInteger> palin = new ArrayList<>();
|
||||
|
||||
for (int i = 1; i <= 10_000; i++) {
|
||||
BigInteger n = BigInteger.valueOf(i);
|
||||
|
||||
Tuple t = lychrel(n);
|
||||
|
||||
if (!t.flag)
|
||||
continue;
|
||||
|
||||
if (n.equals(t.bi))
|
||||
seeds.add(t.bi);
|
||||
else
|
||||
related.add(t.bi);
|
||||
|
||||
if (n.equals(t.bi))
|
||||
palin.add(t.bi);
|
||||
}
|
||||
|
||||
System.out.printf("%d Lychrel seeds: %s%n", seeds.size(), seeds);
|
||||
System.out.printf("%d Lychrel related%n", related.size());
|
||||
System.out.printf("%d Lychrel palindromes: %s%n", palin.size(), palin);
|
||||
}
|
||||
}
|
||||
63
Task/Lychrel-numbers/Jq/lychrel-numbers-1.jq
Normal file
63
Task/Lychrel-numbers/Jq/lychrel-numbers-1.jq
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# This workhorse function assumes its arguments are
|
||||
# non-negative integers represented as decimal strings:
|
||||
def add(num1;num2):
|
||||
if (num1|length) < (num2|length) then add(num2;num1)
|
||||
else (num1 | explode | map(.-48) | reverse) as $a1
|
||||
| (num2 | explode | map(.-48) | reverse) as $a2
|
||||
| reduce range(0; num1|length) as $ix
|
||||
($a2; # result
|
||||
( $a1[$ix] + .[$ix] ) as $r
|
||||
| if $r > 9 # carrying
|
||||
then
|
||||
.[$ix + 1] = ($r / 10 | floor) + (if $ix + 1 >= length then 0 else .[$ix + 1] end )
|
||||
| .[$ix] = $r - ( $r / 10 | floor ) * 10
|
||||
else
|
||||
.[$ix] = $r
|
||||
end )
|
||||
| reverse | map(.+48) | implode
|
||||
end ;
|
||||
|
||||
# Input: an array
|
||||
def is_palindrome:
|
||||
. as $in
|
||||
| (length -1) as $n
|
||||
| all( range(0; length/2); $in[.] == $in[$n - .]);
|
||||
|
||||
# Input: a string representing a decimal number.
|
||||
# Output: a stream of such strings generated in accordance with the Lychrel rule,
|
||||
# subject to the limitation imposed by "limit", and ending in true if the previous item in the stream is a palindrome
|
||||
def next_palindromes(limit):
|
||||
def toa: explode | map(.-48);
|
||||
def tos: map(.+48) | implode;
|
||||
def myadd(x;y): add(x|tos; y|tos) | toa;
|
||||
# input: [limit, n]
|
||||
def next:
|
||||
.[0] as $limit
|
||||
| .[1] as $n
|
||||
| if $limit <= 0 then empty
|
||||
else myadd($n ; $n|reverse) as $sum
|
||||
| ($sum,
|
||||
if ($sum | is_palindrome) then true else [$limit - 1, $sum] | next end)
|
||||
end;
|
||||
[limit, toa] | next | if type == "boolean" then . else tos end;
|
||||
|
||||
# Consider integers in range(0;n) using maxiter as the maximum number
|
||||
# of iterations in the search for palindromes.
|
||||
# Emit a dictionary:
|
||||
# { seed: _, palindromic_seed: _, related: _} + {($n): $n} for all related $n
|
||||
# where .seed is an array of integers holding the potential Lychrel seeds, etc
|
||||
def lychrel_dictionary(n; maxiter):
|
||||
reduce range(0; n) as $i ({};
|
||||
($i | tostring) as $is
|
||||
| if .[$is] then .related += [$i]
|
||||
else [$is | next_palindromes(maxiter)] as $seq
|
||||
| . as $dict
|
||||
# | ([$i, $seq] | debug) as $debug
|
||||
| if $seq[-1] == true then .
|
||||
else if ($is | explode | is_palindrome) then .palindromic_seed += [$i] else . end
|
||||
| if any($seq[]; $dict[.]) then .related += [$i]
|
||||
else .seed += [$i]
|
||||
end
|
||||
| reduce $seq[] as $n (.; if .[$n] then . else .[$n] = $n end)
|
||||
end
|
||||
end ) ;
|
||||
2
Task/Lychrel-numbers/Jq/lychrel-numbers-2.jq
Normal file
2
Task/Lychrel-numbers/Jq/lychrel-numbers-2.jq
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
lychrel_dictionary(10001; 500)
|
||||
| {seed, palindromic_seed, related: (.related | length) }
|
||||
54
Task/Lychrel-numbers/Julia/lychrel-numbers.julia
Normal file
54
Task/Lychrel-numbers/Julia/lychrel-numbers.julia
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
const cache = Dict{BigInt, Tuple{Bool, BigInt}}()
|
||||
|
||||
Base.reverse(n::Integer) = parse(BigInt, string(n) |> reverse)
|
||||
function lychrel(n::BigInt)::Tuple{Bool, BigInt}
|
||||
if haskey(cache, n)
|
||||
return cache[n]
|
||||
end
|
||||
|
||||
r = reverse(n)
|
||||
rst = (true, n)
|
||||
seen = Set{BigInt}()
|
||||
for i in 0:500
|
||||
n += r
|
||||
r = reverse(n)
|
||||
if n == r
|
||||
rst = (false, big(0))
|
||||
break
|
||||
end
|
||||
if haskey(cache, n)
|
||||
rst = cache[n]
|
||||
break
|
||||
end
|
||||
push!(seen, n)
|
||||
end
|
||||
|
||||
for bi in seen
|
||||
cache[bi] = rst
|
||||
end
|
||||
return rst
|
||||
end
|
||||
|
||||
seeds = BigInt[]
|
||||
related = BigInt[]
|
||||
palin = BigInt[]
|
||||
|
||||
for n in big.(1:10000)
|
||||
t = lychrel(n)
|
||||
if ! t[1]
|
||||
continue
|
||||
end
|
||||
if n == t[2]
|
||||
push!(seeds, n)
|
||||
else
|
||||
push!(related, n)
|
||||
end
|
||||
|
||||
if n == t[2]
|
||||
push!(palin, t[2])
|
||||
end
|
||||
end
|
||||
|
||||
println(length(seeds), " lychrel seeds: ", join(seeds, ", "))
|
||||
println(length(related), " lychrel related")
|
||||
println(length(palin), " lychrel palindromes: ", join(palin, ", "))
|
||||
62
Task/Lychrel-numbers/Kotlin/lychrel-numbers.kotlin
Normal file
62
Task/Lychrel-numbers/Kotlin/lychrel-numbers.kotlin
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// version 1.0.6
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
const val ITERATIONS = 500
|
||||
const val LIMIT = 10000
|
||||
|
||||
val bigLimit = BigInteger.valueOf(LIMIT.toLong())
|
||||
|
||||
// In the sieve, 0 = not Lychrel, 1 = Seed Lychrel, 2 = Related Lychrel
|
||||
val lychrelSieve = IntArray(LIMIT + 1) // all zero by default
|
||||
val seedLychrels = mutableListOf<Int>()
|
||||
val relatedLychrels = mutableSetOf<BigInteger>()
|
||||
|
||||
fun isPalindrome(bi: BigInteger): Boolean {
|
||||
val s = bi.toString()
|
||||
return s == s.reversed()
|
||||
}
|
||||
|
||||
fun lychrelTest(i: Int, seq: MutableList<BigInteger>){
|
||||
if (i < 1) return
|
||||
var bi = BigInteger.valueOf(i.toLong())
|
||||
(1 .. ITERATIONS).forEach {
|
||||
bi += BigInteger(bi.toString().reversed())
|
||||
seq.add(bi)
|
||||
if (isPalindrome(bi)) return
|
||||
}
|
||||
for (j in 0 until seq.size) {
|
||||
if (seq[j] <= bigLimit) lychrelSieve[seq[j].toInt()] = 2
|
||||
else break
|
||||
}
|
||||
val sizeBefore = relatedLychrels.size
|
||||
relatedLychrels.addAll(seq) // if all of these can be added 'i' must be a seed Lychrel
|
||||
if (relatedLychrels.size - sizeBefore == seq.size) {
|
||||
seedLychrels.add(i)
|
||||
lychrelSieve[i] = 1
|
||||
}
|
||||
else {
|
||||
relatedLychrels.add(BigInteger.valueOf(i.toLong()))
|
||||
lychrelSieve[i] = 2
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val seq = mutableListOf<BigInteger>()
|
||||
for (i in 1 .. LIMIT)
|
||||
if (lychrelSieve[i] == 0) {
|
||||
seq.clear()
|
||||
lychrelTest(i, seq)
|
||||
}
|
||||
var related = lychrelSieve.count { it == 2 }
|
||||
println("Lychrel numbers in the range [1, $LIMIT]")
|
||||
println("Maximum iterations = $ITERATIONS")
|
||||
println("\nThere are ${seedLychrels.size} seed Lychrel numbers, namely")
|
||||
println(seedLychrels)
|
||||
println("\nThere are also $related related Lychrel numbers in this range")
|
||||
val palindromes = mutableListOf<Int>()
|
||||
for (i in 1 .. LIMIT)
|
||||
if (lychrelSieve[i] > 0 && isPalindrome(BigInteger.valueOf(i.toLong()))) palindromes.add(i)
|
||||
println("\nThere are ${palindromes.size} palindromic Lychrel numbers, namely")
|
||||
println(palindromes)
|
||||
}
|
||||
9
Task/Lychrel-numbers/Mathematica/lychrel-numbers-1.math
Normal file
9
Task/Lychrel-numbers/Mathematica/lychrel-numbers-1.math
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
palindromeQ[n_Integer] :=
|
||||
Block[{digits = IntegerDigits[n]}, digits == Reverse@digits]
|
||||
|
||||
nextNumber[n_Integer] := n + FromDigits[Reverse@IntegerDigits@n]
|
||||
|
||||
lychrelQ[n_Integer] := !
|
||||
palindromeQ@
|
||||
Catch[Nest[If[palindromeQ[#], Throw[#], nextNumber[#]] &,
|
||||
nextNumber[n], 500]]
|
||||
1
Task/Lychrel-numbers/Mathematica/lychrel-numbers-2.math
Normal file
1
Task/Lychrel-numbers/Mathematica/lychrel-numbers-2.math
Normal file
|
|
@ -0,0 +1 @@
|
|||
candidates = Cases[Range[10000], _?(lychrelQ@# &)];
|
||||
7
Task/Lychrel-numbers/Mathematica/lychrel-numbers-3.math
Normal file
7
Task/Lychrel-numbers/Mathematica/lychrel-numbers-3.math
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
seeds = {};
|
||||
NestWhile[(seeds = {seeds, First@#};
|
||||
test = NestList[nextNumber, First@#, 10];
|
||||
DeleteCases[
|
||||
Rest[#], _?(IntersectingQ[test,
|
||||
NestList[nextNumber, #, 10]] &)]) &, candidates,
|
||||
Length@# > 0 &]; seeds = Flatten@seeds
|
||||
1
Task/Lychrel-numbers/Mathematica/lychrel-numbers-4.math
Normal file
1
Task/Lychrel-numbers/Mathematica/lychrel-numbers-4.math
Normal file
|
|
@ -0,0 +1 @@
|
|||
Length@candidates - Length@seeds
|
||||
1
Task/Lychrel-numbers/Mathematica/lychrel-numbers-5.math
Normal file
1
Task/Lychrel-numbers/Mathematica/lychrel-numbers-5.math
Normal file
|
|
@ -0,0 +1 @@
|
|||
Cases[candidates, _?(palindromeQ@# &)]
|
||||
132
Task/Lychrel-numbers/Nim/lychrel-numbers.nim
Normal file
132
Task/Lychrel-numbers/Nim/lychrel-numbers.nim
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
import algorithm, sequtils, strformat, strutils, tables
|
||||
|
||||
type
|
||||
|
||||
Digit = range[0..9]
|
||||
Number = seq[Digit] # Number as a sequence of digits (unit at index 0).
|
||||
|
||||
# Structure used to find the candidates for Lychrel numbers.
|
||||
Candidates = object
|
||||
seeds: seq[Number] # List of possible seeds.
|
||||
linked: Table[Number, Number] # Maps a number to a smallest number in a sequence.
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Conversions.
|
||||
|
||||
func toInt(n: Number): Natural =
|
||||
## Convert a Number to an int. No check is done for overflow.
|
||||
for i in countdown(n.high, 0):
|
||||
result = 10 * result + n[i]
|
||||
|
||||
func `$`(n: Number): string =
|
||||
## Return the string representation of a Number.
|
||||
reversed(n).join()
|
||||
|
||||
func `$`(s: seq[Number]): string =
|
||||
## Return the string representation of a sequence of Numbers.
|
||||
s.mapIt($it).join(" ")
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Operations on Numbers.
|
||||
|
||||
func addReverse(n: var Number) =
|
||||
## Add a Number to its reverse.
|
||||
var carry = 0
|
||||
var high = n.high
|
||||
var r = reversed(n)
|
||||
for i in 0..high:
|
||||
var sum = n[i] + r[i] + carry
|
||||
if sum >= 10:
|
||||
n[i] = sum - 10
|
||||
carry = 1
|
||||
else:
|
||||
n[i] = sum
|
||||
carry = 0
|
||||
if carry != 0: n.add carry
|
||||
|
||||
func inc(a: var Number) =
|
||||
## Increment a Number by one.
|
||||
for item in a.mitems:
|
||||
let sum = item + 1
|
||||
if sum >= 10:
|
||||
item = sum - 10
|
||||
else:
|
||||
item = sum
|
||||
return # No carry: stop adding.
|
||||
a.add 1 # Add last carry.
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Operations related to Lychrel numbers.
|
||||
|
||||
func isPalindromic(n: Number): bool =
|
||||
## Check if a Number is palindromic.
|
||||
for i in 0..(n.high div 2):
|
||||
if n[i] != n[n.high - i]: return false
|
||||
result = true
|
||||
|
||||
|
||||
func isRelatedLychrel(candidates: Candidates; n: Number): bool =
|
||||
## Check if a Number is a Lychrel related number.
|
||||
|
||||
var val = candidates.linked[n]
|
||||
# Search for the first value in a list of linked values.
|
||||
while val in candidates.linked: val = candidates.linked[val]
|
||||
# If the first value is a seed, "n" is related to it.
|
||||
result = val in candidates.seeds
|
||||
|
||||
|
||||
func relatedCount(candidates: Candidates; maxlen: Positive): int =
|
||||
## Return the number of related Lychrel numbers with length <= maxlen.
|
||||
|
||||
# Loop on values which are linked to a smallest value.
|
||||
for n in candidates.linked.keys:
|
||||
if n.len <= maxlen and candidates.isRelatedLychrel(n): inc result
|
||||
|
||||
|
||||
func palindromicLychrel(candidates: Candidates; maxlen: Positive): seq[int] =
|
||||
## Return the list of palindromic Lychrel numbers with length <= maxlen.
|
||||
|
||||
# Search among seed Lychrel numbers.
|
||||
for n in candidates.seeds:
|
||||
if n.len <= maxlen and n.isPalindromic:
|
||||
result.add n.toInt
|
||||
# Search among related Lychrel numbers.
|
||||
for n in candidates.linked.keys:
|
||||
if n.len <= maxlen and n.isPalindromic and candidates.isRelatedLychrel(n):
|
||||
result.add n.toInt
|
||||
# Sort the whole list.
|
||||
result.sort()
|
||||
|
||||
|
||||
proc check(candidates: var Candidates; num: Number) =
|
||||
## Check if a Number is a possible Lychrel number.
|
||||
|
||||
if num in candidates.linked: return # Already encountered: nothing to do.
|
||||
var val = num
|
||||
for _ in 1..500:
|
||||
val.addReverse()
|
||||
if val in candidates.linked:
|
||||
# Set the linked value of "num" to that of "val".
|
||||
candidates.linked[num] = candidates.linked[val]
|
||||
return
|
||||
if val.isPalindromic(): return # Don't store palindromic values as they may be seeds.
|
||||
candidates.linked[val] = num
|
||||
candidates.seeds.add num
|
||||
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
var cand: Candidates
|
||||
|
||||
var num: Number = @[Digit(0)] # The Number to test.
|
||||
for n in 1..10_000:
|
||||
inc num
|
||||
cand.check(num)
|
||||
|
||||
echo &"Found {cand.seeds.len} candidate seed Lychrel numbers between 1 and 10000."
|
||||
echo "These candidate seed Lychrel numbers are: ", cand.seeds
|
||||
echo &"Found {cand.relatedCount(4)} candidate related Lychrel numbers between 1 and 10000."
|
||||
echo "Palindromic candidate Lychrel numbers between 1 and 10000 are: ", cand.palindromicLychrel(4)
|
||||
297
Task/Lychrel-numbers/Pascal/lychrel-numbers.pas
Normal file
297
Task/Lychrel-numbers/Pascal/lychrel-numbers.pas
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
program p196;
|
||||
{$IFDEF FPC}
|
||||
{$R-}
|
||||
{$MODE DELPHI}
|
||||
{$Optimization ON}
|
||||
{$Else}
|
||||
{$APPTYPE console}
|
||||
{$Endif}
|
||||
{
|
||||
nativeUint = LongWord;//Uint64
|
||||
nativeInt = LongInt;//Int64
|
||||
}
|
||||
|
||||
uses
|
||||
SysUtils,classes;
|
||||
|
||||
const
|
||||
cMAXNUM = 100*1000*1000;//100*1000*1000;
|
||||
cMaxCycle = 1500;
|
||||
cChkDigit = 10;//first check lychrel found
|
||||
MaxLen = 256;//maximal count of digits
|
||||
cMaxDigit = MAXLEN-1;
|
||||
|
||||
type
|
||||
TDigit = byte;
|
||||
tpDigit =^TDigit;
|
||||
tDigitArr = array[0..0] of tDigit;
|
||||
tpDigitArr = ^tDigitArr;
|
||||
//LSB at position 0
|
||||
TNumber = record
|
||||
nNum : array [0..cMaxDigit] of TDigit;
|
||||
nMaxPos : LongInt;
|
||||
end;
|
||||
tRelated = array[0..cMAXNUM] of byte;
|
||||
|
||||
procedure NumberFromString(var Number: TNumber; S: string);
|
||||
var
|
||||
i,le: integer;
|
||||
begin
|
||||
le := Length(s);
|
||||
IF le > cMaxDigit then
|
||||
le := cMaxDigit;
|
||||
Number.nMaxPos:= le-1;
|
||||
for i:= 0 to le-1 do
|
||||
Number.nNum[i]:= Ord(s[le- i]) - Ord('0');
|
||||
end;
|
||||
|
||||
function NumberToString(var Number: TNumber): string;
|
||||
var
|
||||
i,l: integer;
|
||||
begin
|
||||
i := Number.nMaxPos;
|
||||
If i <= MAXLEN then
|
||||
begin
|
||||
SetLength(Result, i+1);
|
||||
l := i+1;
|
||||
i := 0;
|
||||
repeat
|
||||
Result[l]:= Chr(Ord('0') + Number.nNum[i]);
|
||||
inc(i);
|
||||
dec(l);
|
||||
until l <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
SetLength(Result, MAXLEN);
|
||||
fillchar(Result[1],MAXLEN,'.');
|
||||
For l := 1 to MAXLEN DIV 2-1 do
|
||||
Begin
|
||||
Result[l] := Chr(Ord('0') + Number.nNum[i-l+1]);
|
||||
Result[l+MAXLEN DIV 2+1] := Chr(Ord('0') + Number.nNum[24-l]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CorrectCarry(var Number : TNumber);
|
||||
//correct sum of digit to digit and carry
|
||||
//without IF d>10 then...
|
||||
var
|
||||
d,i,carry: nativeInt;
|
||||
p: tpDigitArr;
|
||||
begin
|
||||
carry := 0;
|
||||
i := Number.nMaxPos;
|
||||
p := @Number.nNum[i];
|
||||
i := -i;
|
||||
For i := i to 0 do
|
||||
Begin
|
||||
d := p^[i]+carry;
|
||||
carry := ord(d>=10);//0, 1-> (-10 AND(-carry) = 0 ,-10
|
||||
p^[i] := d+(-10 AND(-carry));
|
||||
end;
|
||||
//correct length
|
||||
IF carry >0 then
|
||||
begin
|
||||
i := Number.nMaxPos+1;
|
||||
Number.nNum[i] :=1;
|
||||
NUmber.nMaxPos := i;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure NumberAdd(var Number : TNumber);
|
||||
// first add than correct carry
|
||||
var
|
||||
//pointer, for fpc is a little bit slow with dynamic array
|
||||
loIdx,hiIdx: integer;
|
||||
sum: nativeUint;
|
||||
begin
|
||||
loIdx := 0;
|
||||
hiIdx := Number.nMaxPos;
|
||||
while loIdx< hiIdx do
|
||||
Begin
|
||||
sum := Number.nNum[loIdx]+Number.nNum[hiIdx];
|
||||
Number.nNum[loIdx] := sum;
|
||||
Number.nNum[hiIdx] := sum;
|
||||
inc(loIdx);
|
||||
dec(HiIdx);
|
||||
end;
|
||||
|
||||
IF loIdx = hiIdx then
|
||||
Number.nNum[loIdx] := 2*Number.nNum[loIdx];
|
||||
|
||||
CorrectCarry(Number);
|
||||
end;
|
||||
|
||||
function PalinCheck(var A: TNumber): boolean;
|
||||
var
|
||||
loIdx,hiIdx: integer;
|
||||
begin
|
||||
loIdx := 0;
|
||||
hiIdx := A.nMaxPos;
|
||||
repeat
|
||||
Result:= A.nNum[loIdx]=A.nNum[hiIdx];
|
||||
inc(loIdx);
|
||||
dec(hiIdx);
|
||||
until Not(Result) OR (hiIdx<loIdx);
|
||||
end;
|
||||
|
||||
procedure ShowPalinLychrel(var Related:tRelated);
|
||||
var
|
||||
i : NativeInt;
|
||||
s : string;
|
||||
slRes : TStringList;
|
||||
Work: TNumber;
|
||||
Begin
|
||||
slRes := TStringList.create;
|
||||
|
||||
For i := 0 to High(Related) do
|
||||
begin
|
||||
IF Related[i] <> 0 then
|
||||
Begin
|
||||
s := IntToSTr(i);
|
||||
NumberFromString(Work,s);
|
||||
If PalinCheck(Work) then
|
||||
slRes.Add(s);
|
||||
end;
|
||||
end;
|
||||
|
||||
Writeln('number of palindromatic lychrel ',slRes.count:8);
|
||||
IF slRes.Count < 10 then
|
||||
Begin
|
||||
For i := 0 to slRes.count-2 do
|
||||
write(slRes[i]:8,',');
|
||||
writeln(slRes[slRes.count-1]:8);
|
||||
end;
|
||||
slRes.free;
|
||||
end;
|
||||
|
||||
var
|
||||
Related : tRelated;
|
||||
slSeedCache,
|
||||
slFirstChkCache : TStringList;
|
||||
|
||||
Seeds : array of LongInt;
|
||||
Work: TNumber;
|
||||
num,findpos,InsPos : LongInt;
|
||||
relCount : NativeUint;
|
||||
s,f: string;
|
||||
|
||||
procedure FirstCheckCache;
|
||||
//Test if Work is already in Cache
|
||||
//if not it will be inserted
|
||||
//Inspos saves the position
|
||||
var
|
||||
i : LongInt;
|
||||
Begin
|
||||
f:= NumberToString(Work);
|
||||
IF slFirstChkCache.find(f,i) then
|
||||
Begin
|
||||
IF slFirstChkCache.Objects[i]<> NIL then
|
||||
Begin
|
||||
Related[num] := 2;
|
||||
inc(RelCount);
|
||||
end;
|
||||
end
|
||||
else
|
||||
Begin
|
||||
//memorize the number as Object
|
||||
InsPos := slFirstChkCache.addObject(f,TObject(num));
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
fillchar(Related[1],Length(Related),#0);
|
||||
relCount := 0;
|
||||
|
||||
slSeedCache := TStringList.create;
|
||||
slSeedCache.sorted := true;
|
||||
slSeedCache.duplicates := dupIgnore;
|
||||
|
||||
slFirstChkCache := TStringList.create;
|
||||
slFirstChkCache.sorted := true;
|
||||
slFirstChkCache.duplicates := dupIgnore;
|
||||
|
||||
setlength(Seeds,0);
|
||||
|
||||
num := 1;
|
||||
repeat
|
||||
s := IntToStr(num);
|
||||
NumberFromString(Work, s);
|
||||
|
||||
findPos := -1;
|
||||
InsPos := -1;
|
||||
|
||||
//early test if already in Cache
|
||||
repeat
|
||||
NumberAdd(Work);
|
||||
IF (Work.nMaxPos = cChkDigit) then
|
||||
Begin
|
||||
FirstCheckCache;
|
||||
BREAK;
|
||||
end;
|
||||
until PalinCheck(Work);
|
||||
|
||||
//IF new number of cChkDigit length inserted in Cache
|
||||
IF (InsPos >= 0) AND NOT (PalinCheck(Work)) then
|
||||
Begin
|
||||
//check for lychrel
|
||||
while Work.nMaxPos < cMaxDigit do
|
||||
Begin
|
||||
NumberAdd(Work);
|
||||
if PalinCheck(Work) then
|
||||
BREAK;
|
||||
end;
|
||||
|
||||
if Work.nMaxPos >= cMaxDigit then
|
||||
Begin
|
||||
f := NumberToString(Work);
|
||||
//new lychrel seed found
|
||||
IF NOT(slSeedCache.find(f,findPos)) then
|
||||
Begin
|
||||
//memorize the number by misusing of Object
|
||||
slSeedCache.addObject(f,TObject(num));
|
||||
setlength(Seeds,length(Seeds)+1);
|
||||
Seeds[High(Seeds)] := num;
|
||||
Related[num] := 1;
|
||||
end
|
||||
else
|
||||
Begin
|
||||
//a new way to known lycrel seed found, so memorize it
|
||||
Related[num] := 2;
|
||||
inc(RelCount)
|
||||
end
|
||||
end
|
||||
else
|
||||
//mark slFirstChkCache[InsPos] as not_lychrel
|
||||
slFirstChkCache.Objects[InsPos] := NIL;
|
||||
end;
|
||||
inc(num);
|
||||
until num > cMAXNUM;
|
||||
writeln ('Lychrel from 1 to ',cMAXNUM);
|
||||
writeln('number of cached ',cChkDigit,' digit ',slFirstChkCache.Count);
|
||||
writeln('number of lychrel seed ',length(Seeds):8);
|
||||
IF length(Seeds) < 10 then
|
||||
Begin
|
||||
For InsPos:= 0 to High(Seeds)-1 do
|
||||
write(Seeds[InsPos],',');
|
||||
writeln(Seeds[High(seeds)]);
|
||||
end;
|
||||
writeln('number of lychrel related ',RelCount:8);
|
||||
ShowPalinLychrel(Related);
|
||||
slFirstChkCache.free;
|
||||
slSeedCache.free;
|
||||
setlength(Seeds,0);
|
||||
end.
|
||||
{
|
||||
...
|
||||
Lychrel from 1 to 100000000
|
||||
number of cached 10 digit 7008
|
||||
number of lychrel seed 3552
|
||||
number of lychrel related 28802508
|
||||
number of palindromatic lychrel 5074
|
||||
|
||||
real 0m48.634s
|
||||
user 0m48.579s
|
||||
sys 0m0.012s
|
||||
}
|
||||
52
Task/Lychrel-numbers/Perl/lychrel-numbers.pl
Normal file
52
Task/Lychrel-numbers/Perl/lychrel-numbers.pl
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use English;
|
||||
use Const::Fast;
|
||||
use Math::AnyNum qw(:overload);
|
||||
|
||||
const my $n_max => 10_000;
|
||||
const my $iter_cutoff => 500;
|
||||
my(@seq_dump, @seed_lychrels, @related_lychrels);
|
||||
|
||||
for (my $n=1; $n<=$n_max; $n++) {
|
||||
my @seq = lychrel_sequence($n);
|
||||
if ($iter_cutoff == scalar @seq) {
|
||||
if (has_overlap(\@seq, \@seq_dump)) { push @related_lychrels, $n }
|
||||
else { push @seed_lychrels, $n }
|
||||
@seq_dump = set_union(\@seq_dump, \@seq);
|
||||
}
|
||||
}
|
||||
|
||||
printf "%45s %s\n", "Number of seed Lychrels <= $n_max:", scalar @seed_lychrels;
|
||||
printf "%45s %s\n", "Seed Lychrels <= $n_max:", join ', ', @seed_lychrels;
|
||||
printf "%45s %s\n", "Number of related Lychrels <= $n_max:", scalar @related_lychrels;
|
||||
printf "%45s %s\n", "Palindromes among seed and related <= $n_max:",
|
||||
join ', ', sort {$a <=> $b} grep { is_palindrome($ARG) } @seed_lychrels, @related_lychrels;
|
||||
|
||||
sub lychrel_sequence {
|
||||
my $n = shift;
|
||||
my @seq;
|
||||
for (1 .. $iter_cutoff) {
|
||||
return if is_palindrome($n = next_n($n));
|
||||
push @seq, $n;
|
||||
}
|
||||
@seq;
|
||||
}
|
||||
|
||||
sub next_n { my $n = shift; $n + reverse($n) }
|
||||
sub is_palindrome { my $n = shift; $n eq reverse($n) }
|
||||
|
||||
sub has_overlap {
|
||||
my ($a, $b) = @ARG;
|
||||
my %h;
|
||||
$h{$_}++ for @{$a};
|
||||
exists $h{$_} and return 1 for @{$b};
|
||||
0;
|
||||
}
|
||||
|
||||
sub set_union {
|
||||
my ($a, $b) = @ARG;
|
||||
my %h;
|
||||
$h{$_}++ for @{$a}, @{$b};
|
||||
keys %h;
|
||||
}
|
||||
60
Task/Lychrel-numbers/Phix/lychrel-numbers.phix
Normal file
60
Task/Lychrel-numbers/Phix/lychrel-numbers.phix
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">iterations</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">500</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">limit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10000</span>
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">seeds</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
|
||||
<span style="color: #000000;">cache</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">temp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">iterations</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">palin</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">related</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">limit</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">rev</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">bool</span> <span style="color: #000000;">palindrome</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">=</span><span style="color: #000000;">rev</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">iterations</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">rev</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
|
||||
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">></span><span style="color: #008000;">'9'</span>
|
||||
<span style="color: #000000;">num</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">-</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span> <span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"1"</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">num</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span>
|
||||
<span style="color: #000000;">rev</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">=</span><span style="color: #000000;">rev</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">rev</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">bool</span> <span style="color: #000000;">no_match</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
|
||||
<span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">palindrome</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">palin</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">palin</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">seed</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000080;font-style:italic;">-- check against previous found seeds</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">iterations</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seed</span><span style="color: #0000FF;">)></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">seed</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ti</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">no_match</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
|
||||
<span style="color: #000000;">related</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">no_match</span><span style="color: #0000FF;">=</span><span style="color: #004600;">false</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">no_match</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">seeds</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seeds</span><span style="color: #0000FF;">,</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cache</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">,</span><span style="color: #000000;">temp</span><span style="color: #0000FF;">[$])</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d lychrel seeds: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seeds</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seeds</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">", "</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"related lychrel: %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">related</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d lychrel palindromes: %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">palin</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">palin</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">", "</span><span style="color: #0000FF;">)})</span>
|
||||
<!--
|
||||
47
Task/Lychrel-numbers/Picat/lychrel-numbers.picat
Normal file
47
Task/Lychrel-numbers/Picat/lychrel-numbers.picat
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
go =>
|
||||
Limit = 500,
|
||||
Lychrel = [],
|
||||
Cache = new_set(), % caching the found Lychrel numbers
|
||||
Seeds = [],
|
||||
Palindromes = [],
|
||||
foreach(N in 1..10_000)
|
||||
if lychrel(N,Cache,Limit,Seed) then
|
||||
Lychrel := Lychrel ++ [N],
|
||||
if Seed then Seeds := Seeds ++ [N] end,
|
||||
if rev(N) == N then Palindromes := Palindromes ++ [N] end
|
||||
end
|
||||
end,
|
||||
|
||||
println(num_lychrel_numbers=Seeds.len),
|
||||
println(seeds=Seeds),
|
||||
println(palindromes=Palindromes),
|
||||
println(num_palindromes=Palindromes.len),
|
||||
println(num_related=(Lychrel.len-Seeds.len)),
|
||||
nl.
|
||||
|
||||
table
|
||||
rev(N) = N.to_string().reverse().to_int().
|
||||
|
||||
lychrel(N,Cache,Limit,Seed) =>
|
||||
Found = false, % true if we found a non Lychrel number
|
||||
Seq = [N],
|
||||
Seed1 = false,
|
||||
OldHit = cond(Cache.has_key(N),true,false), % found a Lychrel number from cache
|
||||
I = 0,
|
||||
while (OldHit == false,Found == false,I <= Limit)
|
||||
I := I+1,
|
||||
N := N + rev(N),
|
||||
if Cache.has_key(N) then
|
||||
OldHit := true
|
||||
else
|
||||
Seq := Seq ++ [N],
|
||||
if N == rev(N) then Found := true end
|
||||
end
|
||||
end,
|
||||
if Found == false, OldHit == false then
|
||||
Seed1 := true, % this is a seed, so add all elements to the cache
|
||||
foreach(S in Seq) Cache.put(S) end
|
||||
end,
|
||||
Seed = Seed1,
|
||||
% The check: have we found a Lyncrel number
|
||||
(OldHit == true ; Found == false).
|
||||
55
Task/Lychrel-numbers/PicoLisp/lychrel-numbers.l
Normal file
55
Task/Lychrel-numbers/PicoLisp/lychrel-numbers.l
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
(de pali? (N)
|
||||
(let N (chop N)
|
||||
(= N (reverse N)) ) )
|
||||
(de lychrel (A)
|
||||
(let
|
||||
(R NIL
|
||||
Lst
|
||||
(make
|
||||
(for X A
|
||||
(let (N X C 500)
|
||||
(while
|
||||
(and
|
||||
(inc 'N (format (flip (chop N))))
|
||||
(gt0 (dec 'C))
|
||||
(not (pali? N)) ) )
|
||||
(and (=0 C) (link X) ) ) ) )
|
||||
Lst22
|
||||
(by
|
||||
'((N)
|
||||
(let (X N C 3)
|
||||
(prog1
|
||||
(bool
|
||||
(or
|
||||
(member (+ N (format (flip (chop N)))) R)
|
||||
(find
|
||||
'((N) (member N R))
|
||||
(make
|
||||
(do C
|
||||
(link (inc 'X (format (flip (chop X))))) ) ) ) ) )
|
||||
(do C
|
||||
(push1
|
||||
'R
|
||||
(inc 'N (format (flip (chop N)))) ) ) ) ) )
|
||||
group
|
||||
Lst )
|
||||
P (filter pali? Lst) )
|
||||
(prinl
|
||||
"Using n = 1..10000 and limiting each search to 500 reverse-digits-and-adds" )
|
||||
(prinl
|
||||
" Number of Lychrel numbers: "
|
||||
(length (car Lst22)) )
|
||||
(prin " Lychrel numbers: ")
|
||||
(println (car Lst22))
|
||||
(prinl
|
||||
" Number of Lychrel related: "
|
||||
(length (cadr Lst22)) )
|
||||
(prinl
|
||||
" Number of Lychrel palindroms: "
|
||||
(length P) )
|
||||
(prin " Lychrel palindromes: ")
|
||||
(println P) ) )
|
||||
|
||||
(lychrel 10000)
|
||||
|
||||
(bye)
|
||||
102
Task/Lychrel-numbers/PowerShell/lychrel-numbers-1.psh
Normal file
102
Task/Lychrel-numbers/PowerShell/lychrel-numbers-1.psh
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
function Test-Palindrome ( [String]$String )
|
||||
{
|
||||
# Default value
|
||||
$IsPalindrome = $True
|
||||
|
||||
# For each position in the string from the start to the middle
|
||||
ForEach ( $Index in ( 0..($String.Length -shr 1 ) ) )
|
||||
{
|
||||
# Check if the character at this position matches the corresponding character at the other end
|
||||
$IsPalindrome = $IsPalindrome -and $String[$Index] -eq $String[$String.Length - $Index - 1]
|
||||
}
|
||||
|
||||
return $IsPalindrome
|
||||
}
|
||||
|
||||
function Get-LychrelNumbers ( [int]$Upto, [int]$IterationLimit = 500 )
|
||||
{
|
||||
# Initialize empty collections
|
||||
# (More typically, PowerShell will use Arrays, but we are using
|
||||
# ArrayLists here to optimize speed and memory usage.)
|
||||
$Seeds = New-Object System.Collections.ArrayList
|
||||
$Related = New-Object System.Collections.ArrayList
|
||||
$Palindromes = New-Object System.Collections.ArrayList
|
||||
|
||||
# For each integer in the test range...
|
||||
ForEach ( $N in [bigint]1..[bigint]$Upto )
|
||||
{
|
||||
# If N was already identified as a related Lychrel in another
|
||||
# Lychrel series, we don't need to test it
|
||||
If ( $N -notin $Related )
|
||||
{
|
||||
# Default value
|
||||
$IsRelated = $False
|
||||
|
||||
# Initialize empty collection
|
||||
$NSeries = New-Object System.Collections.ArrayList
|
||||
|
||||
# Starting at N
|
||||
$S = $N
|
||||
|
||||
# Convert S to a string for testing and processing
|
||||
$SString = $S.ToString()
|
||||
|
||||
# For each iteration up to the maximum...
|
||||
# (Generally we would not use ForEach with Break for a loop with
|
||||
# these requirements, but this script is optimized for speed
|
||||
# and ForEach ( $x in $y ) is the fastest loop in PowerShell.)
|
||||
ForEach ( $i in 1..$IterationLimit )
|
||||
{
|
||||
# Add the reverse of S to S
|
||||
$S += [bigint]($SString[($SString.Length)..0] -join '' )
|
||||
|
||||
# If S appears in the series of a smaller seed Lychrel
|
||||
If ( $S -in $Related )
|
||||
{
|
||||
# S is a related Lychrel; exit processing loop
|
||||
$IsRelated = $True
|
||||
Break
|
||||
}
|
||||
|
||||
# Convert S to a string for testing and processing
|
||||
$SString = $S.ToString()
|
||||
|
||||
If ( Test-Palindrome $SString )
|
||||
{
|
||||
Break
|
||||
}
|
||||
|
||||
# Add S to the series we are testing
|
||||
# (for possible inclusion as a related number if N turns out to be a seed)
|
||||
$NSeries.Add( $S )
|
||||
}
|
||||
|
||||
# If series did not terminate before the iteration limit...
|
||||
# (Including if we stopped early because it join up with an earlier non-terminating series)
|
||||
If ( $IsRelated -or $i -eq $IterationLimit )
|
||||
{
|
||||
# Add everything in the series above N to the list of related Lychrel numbers
|
||||
$Related.AddRange( $NSeries )
|
||||
|
||||
# If N is a related Lychrel number, add it to the list
|
||||
If ( $IsRelated ) { $Related. Add( $N ) }
|
||||
|
||||
# Otherwise add it to the list of Seed Lychrel numbers
|
||||
Else { $Seeds. Add( $N ) }
|
||||
|
||||
# If N is a palindrome, add it to the list of palindrome Lychrel numbers
|
||||
If ( Test-Palindrome $N ) { $Palindromes.Add( $N ) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Convert the various arraylists of big integers to arrays of integers and assign
|
||||
# them as properties of a custom return object. Filter out those Related Lychrel
|
||||
# numbers which exceed our search range.
|
||||
$LychrelNumbers = [pscustomobject]@{
|
||||
Seeds = [int[]]$Seeds
|
||||
Related = [int[]]$Related.Where{ $_ -le $Upto }
|
||||
Palindromes = [int[]]$Palindromes }
|
||||
|
||||
return $LychrelNumbers
|
||||
}
|
||||
10
Task/Lychrel-numbers/PowerShell/lychrel-numbers-2.psh
Normal file
10
Task/Lychrel-numbers/PowerShell/lychrel-numbers-2.psh
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
$Upto = 10000
|
||||
$IterationLimit = 500
|
||||
$LychrelNumbers = Get-LychrelNumbers -Upto $Upto -IterationLimit $IterationLimit
|
||||
|
||||
"Searching N = 1 through $Upto with a maximum of $IterationLimit iterations"
|
||||
" Number of seed Lychrel numbers: " + $LychrelNumbers.Seeds.Count
|
||||
" Seed Lychrel numbers: " + ( $LychrelNumbers.Seeds -join ", " )
|
||||
" Number of related Lychrel numbers: " + $LychrelNumbers.Related.Count
|
||||
"Number of palindrome Lychrel numbers: " + $LychrelNumbers.Palindromes.Count
|
||||
" Palindrome Lychrel numbers: " + ( $LychrelNumbers.Palindromes -join ", " )
|
||||
57
Task/Lychrel-numbers/Prolog/lychrel-numbers.pro
Normal file
57
Task/Lychrel-numbers/Prolog/lychrel-numbers.pro
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
reverse_number(Number, Rev):-
|
||||
reverse_number(Number, 0, Rev).
|
||||
|
||||
reverse_number(0, Rev, Rev):-!.
|
||||
reverse_number(N, R, Rev):-
|
||||
R1 is R * 10 + N mod 10,
|
||||
N1 is N // 10,
|
||||
reverse_number(N1, R1, Rev).
|
||||
|
||||
lychrel(N, M, _, [], [], []):-
|
||||
M > N,
|
||||
!.
|
||||
lychrel(N, M, Cache, Seeds, Related, Palindromes):-
|
||||
reverse_number(M, R),
|
||||
lychrel_sequence(M, 0, M, R, Cache, Sequence, Result),
|
||||
update_cache(Cache, Sequence, Result, Cache1),
|
||||
M1 is M + 1,
|
||||
(Result == 0 ->
|
||||
S = Seeds, Rel = Related, P = Palindromes
|
||||
;
|
||||
(R == M ->
|
||||
Palindromes = [M|P]
|
||||
;
|
||||
Palindromes = P),
|
||||
(Result == M ->
|
||||
Seeds = [M|S], Related = Rel
|
||||
;
|
||||
Seeds = S, Related = [M|Rel])),
|
||||
lychrel(N, M1, Cache1, S, Rel, P).
|
||||
|
||||
update_cache(Cache, [], _, Cache):-!.
|
||||
update_cache(Cache, [S|Seq], Result, Cache2):-
|
||||
put_assoc(S, Cache, Result, Cache1),
|
||||
update_cache(Cache1, Seq, Result, Cache2).
|
||||
|
||||
lychrel_sequence(N, 500, _, _, _, [], N):-!.
|
||||
lychrel_sequence(N, I, Sum, Rev, Cache, [Sum1|Sequence], Result):-
|
||||
I1 is I + 1,
|
||||
Sum1 is Sum + Rev,
|
||||
reverse_number(Sum1, Rev1),
|
||||
(((Rev1 == Sum1, Result = 0) ; get_assoc(Sum1, Cache, Result)) ->
|
||||
Sequence = []
|
||||
;
|
||||
lychrel_sequence(N, I1, Sum1, Rev1, Cache, Sequence, Result)).
|
||||
|
||||
lychrel(N):-
|
||||
empty_assoc(Cache),
|
||||
lychrel(N, 1, Cache, Seeds, Related, Palindromes),
|
||||
length(Seeds, Num_seeds),
|
||||
length(Related, Num_related),
|
||||
writef('number of seeds: %w\n', [Num_seeds]),
|
||||
writef('seeds: %w\n', [Seeds]),
|
||||
writef('number of related: %w\n', [Num_related]),
|
||||
writef('palindromes: %w\n', [Palindromes]).
|
||||
|
||||
main:-
|
||||
lychrel(10000).
|
||||
48
Task/Lychrel-numbers/Python/lychrel-numbers-1.py
Normal file
48
Task/Lychrel-numbers/Python/lychrel-numbers-1.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
from __future__ import print_function
|
||||
|
||||
def add_reverse(num, max_iter=1000):
|
||||
i, nums = 0, {num}
|
||||
while True:
|
||||
i, num = i+1, num + reverse_int(num)
|
||||
nums.add(num)
|
||||
if reverse_int(num) == num or i >= max_iter:
|
||||
break
|
||||
return nums
|
||||
|
||||
#@functools.lru_cache(maxsize=2**20)
|
||||
def reverse_int(num):
|
||||
return int(str(num)[::-1])
|
||||
|
||||
def split_roots_from_relateds(roots_and_relateds):
|
||||
roots = roots_and_relateds[::]
|
||||
i = 1
|
||||
while i < len(roots):
|
||||
this = roots[i]
|
||||
if any(this.intersection(prev) for prev in roots[:i]):
|
||||
del roots[i]
|
||||
else:
|
||||
i += 1
|
||||
root = [min(each_set) for each_set in roots]
|
||||
related = [min(each_set) for each_set in roots_and_relateds]
|
||||
related = [n for n in related if n not in root]
|
||||
return root, related
|
||||
|
||||
def find_lychrel(maxn, max_reversions):
|
||||
'Lychrel number generator'
|
||||
series = [add_reverse(n, max_reversions*2) for n in range(1, maxn + 1)]
|
||||
roots_and_relateds = [s for s in series if len(s) > max_reversions]
|
||||
return split_roots_from_relateds(roots_and_relateds)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
maxn, reversion_limit = 10000, 500
|
||||
print("Calculations using n = 1..%i and limiting each search to 2*%i reverse-digits-and-adds"
|
||||
% (maxn, reversion_limit))
|
||||
lychrel, l_related = find_lychrel(maxn, reversion_limit)
|
||||
print(' Number of Lychrel numbers:', len(lychrel))
|
||||
print(' Lychrel numbers:', ', '.join(str(n) for n in lychrel))
|
||||
print(' Number of Lychrel related:', len(l_related))
|
||||
#print(' Lychrel related:', ', '.join(str(n) for n in l_related))
|
||||
pals = [x for x in lychrel + l_related if x == reverse_int(x)]
|
||||
print(' Number of Lychrel palindromes:', len(pals))
|
||||
print(' Lychrel palindromes:', ', '.join(str(n) for n in pals))
|
||||
34
Task/Lychrel-numbers/Python/lychrel-numbers-2.py
Normal file
34
Task/Lychrel-numbers/Python/lychrel-numbers-2.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
from __future__ import print_function
|
||||
|
||||
def rev(n): return int(str(n)[::-1])
|
||||
|
||||
def lychel(n, cache = {}):
|
||||
if n in cache: return cache[n]
|
||||
|
||||
n0, r = n, rev(n)
|
||||
res, seen = (True, n), []
|
||||
for i in range(1000):
|
||||
n += r
|
||||
r = rev(n)
|
||||
if n == r:
|
||||
res = (False, 0)
|
||||
break
|
||||
if n in cache:
|
||||
res = cache[n]
|
||||
break
|
||||
seen.append(n)
|
||||
|
||||
for x in seen: cache[x] = res
|
||||
return res
|
||||
|
||||
seeds, related, palin = [], [], []
|
||||
|
||||
for i in range(1, 1000000):
|
||||
tf, s = lychel(i)
|
||||
if not tf: continue
|
||||
(seeds if i == s else related).append(i)
|
||||
if i == rev(i): palin.append(i)
|
||||
|
||||
print("%d Lychel seeds:"%len(seeds), seeds)
|
||||
print("%d Lychel related" % len(related))
|
||||
print("%d Lychel palindromes:" % len(palin), palin)
|
||||
71
Task/Lychrel-numbers/R/lychrel-numbers.r
Normal file
71
Task/Lychrel-numbers/R/lychrel-numbers.r
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
library(gmp)
|
||||
library(magrittr)
|
||||
|
||||
cache <- NULL
|
||||
|
||||
cache_reset <- function() { cache <<- new.env(TRUE, emptyenv()) }
|
||||
cache_set <- function(key, value) { assign(key, value, envir = cache) }
|
||||
cache_get <- function(key) { get(key, envir = cache, inherits = FALSE) }
|
||||
cache_has_key <- function(key) { exists(key, envir = cache, inherits = FALSE) }
|
||||
|
||||
# Initialize the cache
|
||||
cache_reset()
|
||||
|
||||
isPalindromic <- function(num) {
|
||||
paste0(unlist(strsplit(num,"")), collapse = "") ==
|
||||
paste0(rev(unlist(strsplit(num,""))),collapse = "")
|
||||
}
|
||||
|
||||
|
||||
aStep <- function(num) {
|
||||
num %>%
|
||||
strsplit("") %>%
|
||||
unlist() %>%
|
||||
rev() %>%
|
||||
paste0(collapse = "") %>%
|
||||
sub("^0+","",.) %>%
|
||||
as.bigz() %>%
|
||||
'+'(num) %>%
|
||||
as.character
|
||||
}
|
||||
|
||||
max_search <- 10000
|
||||
limit <- 500
|
||||
related <- 0
|
||||
lychrel <- vector("numeric")
|
||||
palindrome_lychrel <- vector("numeric")
|
||||
|
||||
for (candidate in 1:max_search) {
|
||||
n <- as.character(candidate)
|
||||
found <- TRUE
|
||||
for (iteration in 1:limit) {
|
||||
n <- aStep(n)
|
||||
if (cache_has_key(n)) {
|
||||
related <- related + 1
|
||||
found <- FALSE
|
||||
if (isPalindromic(as.character(candidate))) palindrome_lychrel <- append(palindrome_lychrel, candidate)
|
||||
break
|
||||
}
|
||||
if (isPalindromic(n)) {
|
||||
found <- FALSE
|
||||
break
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (isPalindromic(as.character(candidate))) palindrome_lychrel <- append(palindrome_lychrel, candidate)
|
||||
lychrel <- append(lychrel,candidate)
|
||||
seeds <- seeds + 1
|
||||
n <- as.character(candidate)
|
||||
for (iteration in 1:limit) {
|
||||
cache_set(n,"seen")
|
||||
n <- aStep(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
cat("Lychrel numbers in the range [1, ",max_search,"]\n", sep = "")
|
||||
cat("Maximum iterations =",limit,"\n")
|
||||
cat("Number of Lychrel seeds:",length(lychrel),"\n")
|
||||
cat("Lychrel numbers:",lychrel,"\n")
|
||||
cat("Number of related Lychrel numbers found:",related,"\n")
|
||||
cat("Number of palindromic Lychrel numbers:",length(palindrome_lychrel),"\n")
|
||||
cat("Palindromic Lychrel numbers:",palindrome_lychrel,"\n")
|
||||
36
Task/Lychrel-numbers/REXX/lychrel-numbers.rexx
Normal file
36
Task/Lychrel-numbers/REXX/lychrel-numbers.rexx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*REXX program finds and displays Lychrel numbers, related numbers, and palindromes. */
|
||||
parse arg high limit . /*obtain optional argument from the CL.*/
|
||||
if high='' | high=="," then high= 10000 /*Not specified? Then use the default.*/
|
||||
if limit='' | limit=="," then limit= 500 /* " " " " " " */
|
||||
numeric digits limit % 2 /*ensure enough decimal digits for adds*/
|
||||
T.= 0; @.= T.; #.=@.; w= length(high) /*W: is used for formatting numbers. */
|
||||
$= /*the list of Lychrel numbers. */
|
||||
do j=1 for high; call Lychrel j /*find the Lychrel numbers. */
|
||||
end /*j*/
|
||||
p=; R= /*P: list of palindromes; R: related #s*/
|
||||
do k=1 for high
|
||||
if #.k then $= $ k /*build a list of Lychrel numbers. */
|
||||
if T.k then R= R k /* " " " " " related nums.*/
|
||||
if T.k & k==reverse(k) then p= p k /* " " " " " palindromes. */
|
||||
end /*k*/
|
||||
|
||||
say 'Found in the range 1 to ' high " (limiting searches to " limit ' steps):'
|
||||
say
|
||||
say right( words($) , w) 'Lychrel numbers:' $
|
||||
say right( words(R) - words($), w) 'Lychrel related numbers.'
|
||||
say right( words(p) , w) 'Lychrel palindromes:' p
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
Lychrel: procedure expose limit @. #. T.; parse arg x 1 z /*set X and Z to argument 1.*/
|
||||
rels= 0 /*# related numbers (so far)*/
|
||||
do limit; z= z + reverse(z) /*add the reverse of Z ··· */
|
||||
if z==reverse(z) then return /*is the new Z a palindrome?*/
|
||||
rels= rels + 1; !.rels= z /*add to the related numbers*/
|
||||
end /*limit*/ /* [↑] only DO limit times.*/
|
||||
#.x= 1 /*mark number as a Lychrel.*/
|
||||
T.x= 1; do a=1 for rels; _= !.a /*process "related" numbers.*/
|
||||
if @._ then #.x= 0 /*unmark number as Lychrel.*/
|
||||
else @._= 1 /* mark " " " */
|
||||
T._= 1 /*mark number as "related".*/
|
||||
end /*a*/
|
||||
return
|
||||
60
Task/Lychrel-numbers/Racket/lychrel-numbers.rkt
Normal file
60
Task/Lychrel-numbers/Racket/lychrel-numbers.rkt
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#lang racket
|
||||
(require racket/splicing)
|
||||
|
||||
(define (reverse-digits_10 N)
|
||||
(let inr ((n N) (m 0))
|
||||
(match n
|
||||
[0 m]
|
||||
[(app (curryr quotient/remainder 10) q r)
|
||||
(inr q (+ r (* 10 m)))])))
|
||||
|
||||
(define (palindrome?_10 n)
|
||||
(= n (reverse-digits_10 n)))
|
||||
|
||||
;; hash of integer? -> one of 'seed 'related #f
|
||||
(splicing-let ((memo# (make-hash)))
|
||||
(define (generate-lychrel?-chain i i-rev n acc)
|
||||
(cond
|
||||
[(zero? n) ; out of steam
|
||||
(cons 'seed acc)]
|
||||
[else
|
||||
(let* ((i+ (+ i i-rev)) (i+-rev (reverse-digits_10 i+)))
|
||||
(cond
|
||||
[(= i+ i+-rev) ; palindrome breaks the chain
|
||||
(cons #f acc)]
|
||||
[(eq? 'related (hash-ref memo# i+ #f)) ; deja vu
|
||||
(cons 'related acc)]
|
||||
[else ; search some more
|
||||
(generate-lychrel?-chain i+ i+-rev (sub1 n) (cons i+ acc))]))]))
|
||||
|
||||
;; returns 'seed, 'related or #f depending of the Lychrel-ness of a number
|
||||
(define (lychrel-number? i #:n (n 500))
|
||||
(match (hash-ref memo# i 'unfound)
|
||||
['unfound
|
||||
(match (generate-lychrel?-chain i (reverse-digits_10 i) n null)
|
||||
[(cons 'related chain) 'related]
|
||||
[(cons (and seed (or (and 'seed (app (λ (_) 'related) related?))
|
||||
(and #f (app (λ (_) #f) related?))))
|
||||
chain)
|
||||
(for ((c (in-list chain))) (hash-set! memo# c related?))
|
||||
(hash-set! memo# i seed)
|
||||
seed])]
|
||||
[seed/related/false seed/related/false])))
|
||||
|
||||
(module+ main
|
||||
(define-values (seeds/r n-relateds palindromes/r)
|
||||
(for/fold ((s/r null) (r 0) (p/r null))
|
||||
((i (in-range 1 (add1 10000))))
|
||||
(define lych? (lychrel-number? i))
|
||||
(define p/r+ (if (and lych? (palindrome?_10 i)) (cons (list i (list lych?)) p/r) p/r))
|
||||
(match lych?
|
||||
['seed (values (cons i s/r) r p/r+)]
|
||||
['related (values s/r (add1 r) p/r+)]
|
||||
[#f (values s/r r p/r+)])))
|
||||
|
||||
(printf #<<EOS
|
||||
Seed Lychrel numbers: ~a count:~a
|
||||
Related Lychrel numbers: count:~a
|
||||
Palindromic Lychrel numbers: ~a~%
|
||||
EOS
|
||||
(reverse seeds/r) (length seeds/r) n-relateds (reverse palindromes/r)))
|
||||
46
Task/Lychrel-numbers/Raku/lychrel-numbers.raku
Normal file
46
Task/Lychrel-numbers/Raku/lychrel-numbers.raku
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
my %lychrels;
|
||||
my @seeds;
|
||||
my @palindromes;
|
||||
my $count;
|
||||
my $max = 500;
|
||||
my $limit = '10_000';
|
||||
my %seen;
|
||||
|
||||
for 1 .. $limit -> $int {
|
||||
my @test;
|
||||
my $index = 0;
|
||||
if $int.&is-lychrel {
|
||||
%lychrels.push: ($int => @test).invert;
|
||||
@palindromes.push: $int if $int == $int.flip;
|
||||
$count++;
|
||||
}
|
||||
|
||||
sub is-lychrel (Int $l) {
|
||||
if %seen{$l} or $index++ > $max {
|
||||
%seen{$_} = True for @test;
|
||||
return True;
|
||||
}
|
||||
@test.push: my $m = $l + $l.flip;
|
||||
return False if $m == $m.flip;
|
||||
$m.&is-lychrel;
|
||||
}
|
||||
}
|
||||
|
||||
for %lychrels{*}»[0].unique.sort -> $ly {
|
||||
my $next = False;
|
||||
for %lychrels -> $l {
|
||||
for $l.value[1..*] -> $lt {
|
||||
$next = True and last if $ly == $lt;
|
||||
last if $ly < $lt;
|
||||
}
|
||||
last if $next;
|
||||
}
|
||||
next if $next;
|
||||
@seeds.push: $ly;
|
||||
}
|
||||
|
||||
say " Number of Lychrel seed numbers < $limit: ", +@seeds;
|
||||
say " Lychrel seed numbers < $limit: ", join ", ", @seeds;
|
||||
say "Number of Lychrel related numbers < $limit: ", +$count - @seeds;
|
||||
say " Number of Lychrel palindromes < $limit: ", +@palindromes;
|
||||
say " Lychrel palindromes < $limit: ", join ", ", @palindromes;
|
||||
50
Task/Lychrel-numbers/Ruby/lychrel-numbers.rb
Normal file
50
Task/Lychrel-numbers/Ruby/lychrel-numbers.rb
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
require 'set'
|
||||
|
||||
def add_reverse(num, max_iter=1000)
|
||||
(1..max_iter).each_with_object(Set.new([num])) do |_,nums|
|
||||
num += reverse_int(num)
|
||||
nums << num
|
||||
return nums if palindrome?(num)
|
||||
end
|
||||
end
|
||||
|
||||
def palindrome?(num)
|
||||
num == reverse_int(num)
|
||||
end
|
||||
|
||||
def reverse_int(num)
|
||||
num.to_s.reverse.to_i
|
||||
end
|
||||
|
||||
def split_roots_from_relateds(roots_and_relateds)
|
||||
roots = roots_and_relateds.dup
|
||||
i = 1
|
||||
while i < roots.length
|
||||
this = roots[i]
|
||||
if roots[0...i].any?{|prev| this.intersect?(prev)}
|
||||
roots.delete_at(i)
|
||||
else
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
root = roots.map{|each_set| each_set.min}
|
||||
related = roots_and_relateds.map{|each_set| each_set.min}
|
||||
related = related.reject{|n| root.include?(n)}
|
||||
return root, related
|
||||
end
|
||||
|
||||
def find_lychrel(maxn, max_reversions)
|
||||
series = (1..maxn).map{|n| add_reverse(n, max_reversions*2)}
|
||||
roots_and_relateds = series.select{|s| s.length > max_reversions}
|
||||
split_roots_from_relateds(roots_and_relateds)
|
||||
end
|
||||
|
||||
maxn, reversion_limit = 10000, 500
|
||||
puts "Calculations using n = 1..#{maxn} and limiting each search to 2*#{reversion_limit} reverse-digits-and-adds"
|
||||
lychrel, l_related = find_lychrel(maxn, reversion_limit)
|
||||
puts " Number of Lychrel numbers: #{lychrel.length}"
|
||||
puts " Lychrel numbers: #{lychrel}"
|
||||
puts " Number of Lychrel related: #{l_related.length}"
|
||||
pals = (lychrel + l_related).select{|x| palindrome?(x)}.sort
|
||||
puts " Number of Lychrel palindromes: #{pals.length}"
|
||||
puts " Lychrel palindromes: #{pals}"
|
||||
118
Task/Lychrel-numbers/Rust/lychrel-numbers.rust
Normal file
118
Task/Lychrel-numbers/Rust/lychrel-numbers.rust
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
extern crate num;
|
||||
use num::FromPrimitive;
|
||||
use num::bigint::BigInt;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// Reverse a number then add it to the original.
|
||||
fn rev_add(num: &BigInt) -> BigInt {
|
||||
let rev_string: String = num.to_string().chars().rev().collect();
|
||||
// should be safe, our string is guaranteed to be a number
|
||||
let rev_val: BigInt = rev_string.parse().unwrap();
|
||||
num + rev_val
|
||||
}
|
||||
|
||||
/// Check if a number is a palindrome when written in base 10.
|
||||
fn is_palindrome(num: &BigInt) -> bool {
|
||||
let num_string = num.to_string();
|
||||
let rev_string: String = num_string.chars().rev().collect();
|
||||
let comp_len = num_string.len() / 2;
|
||||
num_string[0..comp_len] == rev_string[0..comp_len]
|
||||
}
|
||||
|
||||
/// Perform a lychrel test on a number, stopping after max_tests
|
||||
/// Returns the sequence of numbers if this number is a lychrel, None otherwise.
|
||||
fn test_lychrel(num: &BigInt, max_tests: usize) -> Option<Vec<BigInt>> {
|
||||
let mut sequence = Vec::<BigInt>::new();
|
||||
|
||||
let is_lychrel = (0..max_tests)
|
||||
.scan(num.clone(), |current, _| {
|
||||
*current = rev_add(current);
|
||||
Some(current.clone())
|
||||
})
|
||||
.inspect(|current| sequence.push(current.clone()))
|
||||
.filter(|curent| is_palindrome(curent))
|
||||
.next()
|
||||
.is_none();
|
||||
|
||||
if is_lychrel {
|
||||
Some(sequence)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine if the sequence for a lychrel number is related to a previously seen sequence
|
||||
fn is_related(seq: &Vec<BigInt>, lychrel_seq_numbers: &HashSet<BigInt>) -> bool {
|
||||
seq.iter().filter(|num| lychrel_seq_numbers.contains(num)).next().is_some()
|
||||
}
|
||||
|
||||
/// Find the lychrel numbers up to max_num (inclusive).
|
||||
/// Returns a tuple (lychrel numbers, related numbers, palindrome lychrel/related numbers)
|
||||
fn find_lychrels(max_num: u64, max_tests: usize) -> (Vec<BigInt>, Vec<BigInt>, Vec<BigInt>) {
|
||||
// storage for various outputs
|
||||
let mut lychrels = Vec::<BigInt>::new();
|
||||
let mut relateds = Vec::<BigInt>::new();
|
||||
let mut palindrome_lychrels = Vec::<BigInt>::new();
|
||||
|
||||
let mut lychrel_seq_numbers: HashSet<BigInt> = HashSet::new();
|
||||
|
||||
for i in (1..(max_num + 1)) {
|
||||
let num = FromPrimitive::from_u64(i).unwrap();
|
||||
let maybe_lychrel = test_lychrel(&num, max_tests);
|
||||
|
||||
if let Some(lychrel_seq) = maybe_lychrel {
|
||||
// it's a lychrel - check if it's a related number
|
||||
let related = is_related(&lychrel_seq, &lychrel_seq_numbers);
|
||||
|
||||
// update our sequences
|
||||
for seq_num in lychrel_seq.into_iter() {
|
||||
lychrel_seq_numbers.insert(seq_num);
|
||||
}
|
||||
|
||||
if !related {
|
||||
// the number has a new lychrel sequence, store it
|
||||
lychrels.push(num.clone());
|
||||
}
|
||||
else {
|
||||
// just count it as a related number
|
||||
relateds.push(num.clone());
|
||||
}
|
||||
|
||||
if is_palindrome(&num) {
|
||||
// doesn't matter if palindromes are related or not
|
||||
palindrome_lychrels.push(num.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(lychrels, relateds, palindrome_lychrels)
|
||||
}
|
||||
|
||||
fn print_nums(before: &str, numbers: &Vec<BigInt>) {
|
||||
print!("{}", before);
|
||||
for (i, current) in numbers.iter().enumerate() {
|
||||
print!("{}", current);
|
||||
if i + 1 < numbers.len() {
|
||||
print!(", ");
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let max_num: u64 = 10_000;
|
||||
let max_tests: usize = 500;
|
||||
|
||||
println!("Calculations using n = 1..{} and limiting each search to {} reverse-digits-and-adds",
|
||||
max_num, max_tests);
|
||||
|
||||
let (lychrels, relateds, palindrome_lychrels) = find_lychrels(max_num, max_tests);
|
||||
|
||||
println!("Number of Lychrel numbers: {}", lychrels.len());
|
||||
print_nums("Lychrel numbers: ", &lychrels);
|
||||
println!("Number of Lychrel related: {}", relateds.len());
|
||||
println!("Number of Lychrel palindromes: {}", palindrome_lychrels.len());
|
||||
print_nums("Lychrel palindromes: ", &palindrome_lychrels);
|
||||
}
|
||||
60
Task/Lychrel-numbers/Scala/lychrel-numbers.scala
Normal file
60
Task/Lychrel-numbers/Scala/lychrel-numbers.scala
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import scala.collection.mutable.LinkedHashMap
|
||||
|
||||
val range = 1 to 10000
|
||||
val maxIter = 500;
|
||||
|
||||
def lychrelSeq( seed:BigInt ) : Stream[BigInt] = {
|
||||
def reverse( v:BigInt ) = BigInt(v.toString.reverse)
|
||||
def isPalindromic( v:BigInt ) = { val s = (v + reverse(v)).toString; s == s.reverse }
|
||||
|
||||
def loop( v:BigInt ):Stream[BigInt] = v #:: loop( v + reverse(v) )
|
||||
val seq = loop(seed)
|
||||
|
||||
seq.take( seq.take(maxIter).indexWhere( isPalindromic(_) ) match {
|
||||
case -1 => maxIter
|
||||
case n => n + 1
|
||||
})
|
||||
}
|
||||
|
||||
// A quick test
|
||||
assert( lychrelSeq(56).length == 1 )
|
||||
assert( lychrelSeq(57).length == 2 )
|
||||
assert( lychrelSeq(59).length == 3 )
|
||||
assert( lychrelSeq(89).length == 24 )
|
||||
assert( lychrelSeq(10911).length == 55 )
|
||||
|
||||
val lychrelNums = for( n <- range if lychrelSeq(n).length == maxIter ) yield n
|
||||
|
||||
val (seeds,related) = {
|
||||
val lycs = LinkedHashMap[BigInt,Int]()
|
||||
|
||||
// Fill the Map not allowing duplicate values
|
||||
lychrelNums.foreach{ n => val ll = lychrelSeq(n).map( (_ -> n) ); LinkedHashMap( ll:_* ) ++= lycs }
|
||||
|
||||
for( n <- lychrelNums ) {
|
||||
val ll = lychrelSeq(n).map( (_ -> n) )
|
||||
val mm = LinkedHashMap( ll:_* )
|
||||
lycs ++= (mm ++= lycs)
|
||||
}
|
||||
|
||||
// Group by the Lychrel Number
|
||||
val zz = lycs.groupBy{ _._2 }.map{ case (k,m) => k -> m.keys.toList.sorted }
|
||||
|
||||
// Now, group by size, seeds will have 500 or maxIter
|
||||
val yy = lychrelNums.groupBy( n => zz.filterKeys(_==n).values.flatten.size < maxIter )
|
||||
|
||||
// Results: seeds are false, related true
|
||||
(yy.filterKeys(_ == false).values.toVector.flatten,
|
||||
yy.filterKeys(_ == true).values.toVector.flatten)
|
||||
}
|
||||
|
||||
val lychrelPals = for( n <- lychrelNums; if n.toString == n.toString.reverse ) yield n
|
||||
|
||||
// Show the results
|
||||
{
|
||||
println( s"There are ${lychrelNums.size} Lychrel Numbers between ${range.min} and ${range.max} \n when limited to $maxIter iterations:" )
|
||||
println
|
||||
println( s"\t Seeds: ${seeds.size} (${seeds.mkString(", ")})" )
|
||||
println( s"\tRelated Count: ${related.size}" )
|
||||
println( s"\t Palindromes: (${lychrelPals.mkString(", ")})")
|
||||
}
|
||||
46
Task/Lychrel-numbers/Sidef/lychrel-numbers.sidef
Normal file
46
Task/Lychrel-numbers/Sidef/lychrel-numbers.sidef
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
var (
|
||||
lychrels = [],
|
||||
palindromes = [],
|
||||
seeds = [],
|
||||
max = 500,
|
||||
)
|
||||
|
||||
for i in (1 .. 10_000) {
|
||||
var (test = [], count = 0)
|
||||
|
||||
func lychrel(l) {
|
||||
count++ > max && return true
|
||||
test << (var m = (l + Num(Str(l).flip)))
|
||||
Str(m).is_palindrome && return false
|
||||
lychrel(m)
|
||||
}
|
||||
|
||||
if (lychrel(i)) {
|
||||
lychrels << Pair(Str(i), test)
|
||||
}
|
||||
}
|
||||
|
||||
seeds << lychrels[0]
|
||||
|
||||
for l in lychrels {
|
||||
if (l.key.is_palindrome) {
|
||||
palindromes << l.key
|
||||
}
|
||||
|
||||
var h = Hash()
|
||||
h.set_keys(l.value...)
|
||||
|
||||
var trial = seeds.count_by { |s|
|
||||
s.value.any { |k| h.contains(k) } ? break : true
|
||||
}
|
||||
|
||||
if (trial == seeds.len) {
|
||||
seeds << l
|
||||
}
|
||||
}
|
||||
|
||||
say (" Number of Lychrel seed numbers < 10_000: ", seeds.len)
|
||||
say (" Lychrel seed numbers < 10_000: ", seeds.map{.key}.join(', '))
|
||||
say ("Number of Lychrel related numbers < 10_000: ", lychrels.len - seeds.len)
|
||||
say (" Number of Lychrel palindromes < 10_000: ", palindromes.len)
|
||||
say (" Lychrel palindromes < 10_000: ", palindromes.join(', '))
|
||||
99
Task/Lychrel-numbers/Swift/lychrel-numbers.swift
Normal file
99
Task/Lychrel-numbers/Swift/lychrel-numbers.swift
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import BigInt
|
||||
|
||||
public struct Lychrel<T: ReversibleNumeric & CustomStringConvertible>: Sequence, IteratorProtocol {
|
||||
@usableFromInline
|
||||
let seed: T
|
||||
|
||||
@usableFromInline
|
||||
var done = false
|
||||
|
||||
@usableFromInline
|
||||
var n: T
|
||||
|
||||
@usableFromInline
|
||||
var iterations: T
|
||||
|
||||
@inlinable
|
||||
public init(seed: T, iterations: T = 500) {
|
||||
self.seed = seed
|
||||
self.n = seed
|
||||
self.iterations = iterations
|
||||
}
|
||||
|
||||
@inlinable
|
||||
public mutating func next() -> T? {
|
||||
guard !done && iterations != 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard !isPalindrome(n) || n == seed else {
|
||||
done = true
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
defer {
|
||||
n += n.reversed()
|
||||
iterations -= 1
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
public func isPalindrome<T: CustomStringConvertible>(_ x: T) -> Bool {
|
||||
let asString = String(describing: x)
|
||||
|
||||
for (c, c1) in zip(asString, asString.reversed()) where c != c1 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public protocol ReversibleNumeric: Numeric {
|
||||
func reversed() -> Self
|
||||
}
|
||||
|
||||
extension BigInt: ReversibleNumeric {
|
||||
public func reversed() -> BigInt {
|
||||
return BigInt(String(description.reversed()))!
|
||||
}
|
||||
}
|
||||
|
||||
typealias LychrelReduce = (seen: Set<BigInt>, seeds: Set<BigInt>, related: Set<BigInt>)
|
||||
|
||||
let (seen, seeds, related): LychrelReduce =
|
||||
(1...10_000)
|
||||
.map({ BigInt($0) })
|
||||
.reduce(into: LychrelReduce(seen: Set(), seeds: Set(), related: Set()), {res, cur in
|
||||
guard !res.seen.contains(cur) else {
|
||||
res.related.insert(cur)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var seen = false
|
||||
|
||||
let seq = Lychrel(seed: cur).prefix(while: { seen = res.seen.contains($0); return !seen })
|
||||
let last = seq.last!
|
||||
|
||||
guard !isPalindrome(last) || seen else {
|
||||
return
|
||||
}
|
||||
|
||||
res.seen.formUnion(seq)
|
||||
|
||||
if seq.count == 500 {
|
||||
res.seeds.insert(cur)
|
||||
} else {
|
||||
res.related.insert(cur)
|
||||
}
|
||||
})
|
||||
|
||||
print("Found \(seeds.count + related.count) Lychrel numbers between 1...10_000 when limited to 500 iterations")
|
||||
print("Number of Lychrel seeds found: \(seeds.count)")
|
||||
print("Lychrel seeds found: \(seeds.sorted())")
|
||||
print("Number of related Lychrel nums found: \(related.count)")
|
||||
print("Lychrel palindromes found: \(seeds.union(related).filter(isPalindrome).sorted())")
|
||||
53
Task/Lychrel-numbers/Tcl/lychrel-numbers.tcl
Normal file
53
Task/Lychrel-numbers/Tcl/lychrel-numbers.tcl
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
proc pal? {n} {
|
||||
expr {$n eq [string reverse $n]}
|
||||
}
|
||||
|
||||
proc step {n} {
|
||||
set n_ [string reverse $n]
|
||||
set n_ [string trimleft $n_ 0]
|
||||
expr {$n + $n_}
|
||||
}
|
||||
|
||||
proc lychrels {{max 10000} {iters 500}} {
|
||||
|
||||
set lychrels {} ;# true Lychrels
|
||||
set visited {} ;# visited numbers for Related test
|
||||
set nRelated 0 ;# count of related numbers seen
|
||||
set pals {} ;# palindromic Lychrels and related
|
||||
|
||||
puts "Searching for Lychrel numbers in \[1,$max\]"
|
||||
puts "With a maximum of $iters iterations"
|
||||
|
||||
for {set i 1} {$i <= $max} {incr i} {
|
||||
set n $i ;# seed the sequence
|
||||
set seq {} ;# but don't check the seed, nor remember it for the Related test
|
||||
for {set j 0} {$j < $iters} {incr j} {
|
||||
set n [step $n]
|
||||
dict set seq $n {}
|
||||
if {[dict exists $visited $n]} {
|
||||
incr nRelated
|
||||
if {[pal? $i]} {
|
||||
lappend pals $i
|
||||
}
|
||||
break ;# bail out if it's Related
|
||||
}
|
||||
if {[pal? $n]} {
|
||||
break ;# bail out if it's a palindrome
|
||||
}
|
||||
}
|
||||
if {$j >= $iters} { ;# the loop was exhausted: must be a Lychrel!
|
||||
if {[pal? $i]} {
|
||||
lappend pals $i
|
||||
}
|
||||
lappend lychrels $i
|
||||
set visited [dict merge $visited $seq]
|
||||
}
|
||||
}
|
||||
|
||||
puts "[llength $lychrels] Lychrel numbers found:"
|
||||
puts $lychrels
|
||||
puts "Count of related numbers: $nRelated"
|
||||
puts "Palindromic Lychrel and related numbers: $pals"
|
||||
}
|
||||
|
||||
lychrels
|
||||
63
Task/Lychrel-numbers/Wren/lychrel-numbers.wren
Normal file
63
Task/Lychrel-numbers/Wren/lychrel-numbers.wren
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import "/big" for BigInt
|
||||
import "/set" for Set
|
||||
|
||||
var iterations = 500
|
||||
var limit = 10000
|
||||
var bigLimit = BigInt.new(limit)
|
||||
|
||||
// In the sieve, 0 = not Lychrel, 1 = Seed Lychrel, 2 = Related Lychrel
|
||||
var lychrelSieve = List.filled(limit + 1, 0)
|
||||
var seedLychrels = []
|
||||
var relatedLychrels = Set.new()
|
||||
|
||||
var isPalindrome = Fn.new { |bi|
|
||||
var s = bi.toString
|
||||
return s == s[-1..0]
|
||||
}
|
||||
|
||||
var lychrelTest = Fn.new { |i, seq|
|
||||
if (i < 1) return
|
||||
var bi = BigInt.new(i)
|
||||
for (j in 1..iterations) {
|
||||
bi = bi + BigInt.new(bi.toString[-1..0])
|
||||
seq.add(bi)
|
||||
if (isPalindrome.call(bi)) return
|
||||
}
|
||||
for (j in 0...seq.count) {
|
||||
if (seq[j] <= bigLimit) {
|
||||
lychrelSieve[seq[j].toSmall] = 2
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
var sizeBefore = relatedLychrels.count
|
||||
// if all of these can be added 'i' must be a seed Lychrel
|
||||
relatedLychrels.addAll(seq.map { |i| i.toString }) // can't add BigInts directly to a Set
|
||||
if (relatedLychrels.count - sizeBefore == seq.count) {
|
||||
seedLychrels.add(i)
|
||||
lychrelSieve[i] = 1
|
||||
} else {
|
||||
relatedLychrels.add(i.toString)
|
||||
lychrelSieve[i] = 2
|
||||
}
|
||||
}
|
||||
|
||||
var seq = []
|
||||
for (i in 1..limit) {
|
||||
if (lychrelSieve[i] == 0) {
|
||||
seq.clear()
|
||||
lychrelTest.call(i, seq)
|
||||
}
|
||||
}
|
||||
var related = lychrelSieve.count { |i| i == 2 }
|
||||
System.print("Lychrel numbers in the range [1, %(limit)]")
|
||||
System.print("Maximum iterations = %(iterations)")
|
||||
System.print("\nThere are %(seedLychrels.count) seed Lychrel numbers, namely:")
|
||||
System.print(seedLychrels)
|
||||
System.print("\nThere are also %(related) related Lychrel numbers in this range.")
|
||||
var palindromes = []
|
||||
for (i in 1..limit) {
|
||||
if (lychrelSieve[i] > 0 && isPalindrome.call(BigInt.new(i))) palindromes.add(i)
|
||||
}
|
||||
System.print("\nThere are %(palindromes.count) palindromic Lychrel numbers, namely:")
|
||||
System.print(palindromes)
|
||||
26
Task/Lychrel-numbers/Zkl/lychrel-numbers-1.zkl
Normal file
26
Task/Lychrel-numbers/Zkl/lychrel-numbers-1.zkl
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
var BN=Import("zklBigNum");
|
||||
|
||||
// 192-->"887\01675\07436\013783\0..." ~60k bytes
|
||||
fcn lychrel(n,returnListof=False){ n=BN(n); //-->Bool|Data(==StringBuf)
|
||||
sink:=(if(returnListof) Data(0,String) else Void);
|
||||
nls:=(500).pump(sink,'wrap(){
|
||||
ns:=n.add(BN(n.toString().reverse())).toString();
|
||||
if(ns==ns.reverse()) return(Void.Stop,False); // not a Lychrel number
|
||||
ns
|
||||
});
|
||||
if(nls) if(returnListof) return(sink.mode(Int).howza(2)) else return(True);
|
||||
False;
|
||||
}
|
||||
fcn isPalindrome(n){ n==n.toString().reverse().toInt() }
|
||||
fcn findSeeds(lychrels){
|
||||
seeds:=List(lychrels[0]);
|
||||
foreach n,lnns in ([1..].zip(lychrels[1,*])){ ln,seq:=lnns;
|
||||
foreach _,s2 in (seeds){
|
||||
foreach s3 in (seq){
|
||||
if(Void!=(z:=s2.findString(s3)) and 0==s2[z-1]) break(2);
|
||||
}
|
||||
}
|
||||
fallthrough{ seeds.append(lnns) }
|
||||
}
|
||||
seeds.apply("get",0)
|
||||
}
|
||||
9
Task/Lychrel-numbers/Zkl/lychrel-numbers-2.zkl
Normal file
9
Task/Lychrel-numbers/Zkl/lychrel-numbers-2.zkl
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
lychrels:=[1..0d10_000].filter(lychrel).apply(fcn(n){ T(n,lychrel(n,True)) });
|
||||
println("[1..10,000] contains ",lychrels.len()," Lychrel numbers.");
|
||||
|
||||
lychrels.pump(List,fcn([(n,_)]){ isPalindrome(n) and n or Void.Skip })
|
||||
.println("<-- Palindromic Lychrel numbers");
|
||||
|
||||
(n:=findSeeds(lychrels))
|
||||
.println("<-- Lychrel seeds (%d) ==> %d related"
|
||||
.fmt(n.len(),lychrels.len() - n.len()));
|
||||
Loading…
Add table
Add a link
Reference in a new issue