Skip to content

Commit

Permalink
fixes to run on Python 3.12
Browse files Browse the repository at this point in the history
Added 'change_digits' operator, and made changes to work around some deprecation errors.  tzwhere is no longer being updated, so I switched to timezonefinder.

The version has been bumped to 9.0.beta1.
  • Loading branch information
ConceptJunkie committed Dec 30, 2023
1 parent 9c78c93 commit 1f8d225
Show file tree
Hide file tree
Showing 16 changed files with 140 additions and 64 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ pyreadline3
rpnChiladaData>=1.1.0
setuptools>=65.5.1
skyfield>=1.42
timezonefinder>=6.2.0
tzlocal>=4.2
tzwhere>=3.0.3
wheel>=0.41.2
81 changes: 54 additions & 27 deletions rpn/makeHelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,10 @@ def makeCommandExample( command, indent=0, slow=False ):
The old names were confusing to me, so I thought they would be confusing to
users.

tzwhere has been replaced with timezonefinder.

The 'change_digits' operator was added.

And finally after about 8 years (since version 6.4.0), the Windows binary is
back!

Expand Down Expand Up @@ -2806,7 +2810,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''',
'''
''' + makeCommandExample( 'neptune "Sao Paulo, Brazil" 2019-05-23 previous_rising' ),
[ 'uranus', 'pluto' ] ],
[ 'uranus', 'pluto' ] ],

'pluto' : [
'astronomical_objects', 'the planet Pluto',
Expand Down Expand Up @@ -2924,7 +2928,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''',
'''
''' + makeCommandExample( 'neptune2 "Sao Paulo, Brazil" 2019-05-23 previous_rising' ),
[ 'uranus2', 'pluto2' ] ],
[ 'uranus2', 'pluto2' ] ],

'pluto2' : [
'astronomical_objects', 'the planet Pluto',
Expand Down Expand Up @@ -5020,7 +5024,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''',
'''
''' + makeCommandExample( '3 3 debruijn_sequence' ),
[ 'permutations', 'nth_thue_morse' ] ],
[ 'permutations', 'nth_thue_morse', 'van_eck' ] ],

'count_frobenius' : [
'combinatorics', 'calculates the number of combinations of items on n that add up to k',
Expand Down Expand Up @@ -7194,7 +7198,7 @@ def makeCommandExample( command, indent=0, slow=False ):
Somos\' Quadratic Recurrence Constant
''' + makeCommandExample( '-a20 1 inf lambda x 1 2 x ** / power ranged_product' ) + '''
What percentage of numbers have a factor less than 1000?
''' + makeCommandExample( '1 1 1000 nth_prime lambda 1 x prime 1/x - ranged_product - 100 *' ),
''' + makeCommandExample( '1 1 1000 nth_prime lambda 1 x prime 1/x - ranged_product - 100 *', slow=True ),
[ 'ranged_sum', 'lambda' ] ],

'ranged_sum' : [
Expand Down Expand Up @@ -7952,7 +7956,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''' + makeCommandExample( '12345 67890 add_digits' ) + '''
''',
[ 'build_numbers', 'combine_digits', 'duplicate_digits', 'duplicate_number', 'get_digits',
'rotate_digits_left', 'rotate_digits_right' ] ],
'rotate_digits_left', 'rotate_digits_right' ] ],

'build_numbers' : [
'lexicography', 'constructs numbers lexicographically using a simple language',
Expand Down Expand Up @@ -8007,7 +8011,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''' + makeCommandExample( '[1-4:1:2]e build_numbers' ) + '''
''',
[ 'combine_digits', 'duplicate_digits', 'duplicate_number', 'get_digits',
'rotate_digits_left', 'rotate_digits_right' ] ],
'rotate_digits_left', 'rotate_digits_right', 'change_digits' ] ],

'build_step_numbers' : [
'list_operators', 'builds all step numbers up to n digits in length',
Expand All @@ -8020,14 +8024,27 @@ def makeCommandExample( command, indent=0, slow=False ):
''' + makeCommandExample( '3 build_step_numbers' ),
[ 'is_step_number' ] ],

'change_digits' : [
'lexicography', 'changes k digits in number n',
'''
This operator changes k different digits in number n. The digits are replaced
with another digit from 0-9 at random.
''',
'''
''' + makeCommandExample( '111111111111111 1 change_digits' ) + '''
''' + makeCommandExample( '111111111111111 5 change_digits' ) + '''
''' + makeCommandExample( '111111111111111 5 change_digits' ) + '''
''' + makeCommandExample( '111111111111111 12 change_digits' ),
[ 'permute_digits', 'add_digits' ] ],

'combine_digits' : [
'lexicography', 'combines the digits of all elements of list n into a single number',
'''
The individual digits are combined lexicographically to produce a number that
is the equivalent of the concatenation of digits from each item in the argument
list.

This function is the "list version" of 'add_digits'. It does the same thing as
This function is the 'list version" of 'add_digits'. It does the same thing as
'add_digits', but with a list of arguments instead of two arguments.
''',
'''
Expand Down Expand Up @@ -8114,7 +8131,7 @@ def makeCommandExample( command, indent=0, slow=False ):
This operator implements a variation of 'multiplicative persistence' as
described by Martin Gardner.

"A number's persistence is the number of steps required to reduce it to a
A number's persistence is the number of steps required to reduce it to a
single digit by multiplying all its digits to obtain a second number, then
multiplying all the digits of that number to obtain a third number, and so
on until a one-digit number is obtained.
Expand Down Expand Up @@ -8234,7 +8251,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''' + makeCommandExample( '1234567890 5 get_left_digits' ) + '''
''' + makeCommandExample( '1000001 4 get_left_digits' ),
[ 'has_digits', 'get_nonzero_digits', 'get_base_k_digits', 'get_digits', 'get_right_digits',
'rotate_digits_left', 'rotate_digits_right' ] ],
'rotate_digits_left', 'rotate_digits_right' ] ],

'get_left_truncations' : [
'lexicography', 'returns a list of numbers, successively truncated a digit from the left',
Expand Down Expand Up @@ -8276,7 +8293,7 @@ def makeCommandExample( command, indent=0, slow=False ):
''' + makeCommandExample( '1234567890 5 get_right_digits' ) + '''
''' + makeCommandExample( '1000001 4 get_right_digits' ),
[ 'has_digits', 'get_nonzero_digits', 'get_base_k_digits', 'get_left_digits', 'get_digits',
'rotate_digits_left', 'rotate_digits_right' ] ],
'rotate_digits_left', 'rotate_digits_right' ] ],

'get_right_truncations' : [
'lexicography', 'returns a list of numbers, successively truncated a digit from the right',
Expand Down Expand Up @@ -10982,21 +10999,6 @@ def makeCommandExample( command, indent=0, slow=False ):
''' + makeCommandExample( '1 25 range lambda x is_deficient filter' ),
[ 'is_abundant', 'is_perfect' ] ],

'is_sociable_list' : [
'number_theory', 'returns whether list n is a list of sociable numbers',
''';
This operator returns true (1) if the list n is a list of sociable numbers.
Sociable numbers form a looped aliquot chain: The sum of divisors of each
numbers is the next number in the list, with the last number having a divisor
sum that equals the first number.

Therefore, if any of these numbers are used with the 'aliquot' operator, they
will result in early termination because of a loop.
''',
'''
''',
[ 'sigma', 'aliquot' ] ],

'is_harmonic_divisor_number' : [
'number_theory', 'returns whether or not n is a harmonic divisor number',
'''
Expand Down Expand Up @@ -12347,10 +12349,35 @@ def makeCommandExample( command, indent=0, slow=False ):
'van_eck' : [
'number_theory', 'calculates the first n members of the van Eck sequence',
'''
Neil Sloane talks about the Van Eck sequence on Numberphile:

https://www.youtube.com/watch?v=etMJxB-igrc

The first item in the sequence is 0. Compute the next item as follows: If the
previous item has not previously appeared in the sequence, add 0 to the
sequence, otherwise add to the sequence the number of steps back in the sequence
the previous item previously appeared.

For instance, the first item is 0.

Since 0 has not previously appeared in the sequence, the next item is 0.
Now 0 has previously appeared, and the previous 0 was one back in the sequence,
so add 1 to the sequence. Since 1 has not previously appeared, add 0. But 0
appeared previously, two back in the sequence, so add 2. Since 2 has not
previously appeared, add 0. But 0 appeared previously, two items back, so add
2 to the sequence. Since 2 previously appeared in the sequence, two terms back,
add another 2 to the sequence. The next item in the sequence is 1, because 2
also appeared as the previous number. Since 1 appeared in the sequence, count
back to the previous 1, and add 6 to the sequence. And so on.

The sequence begins 0, 0, 1, 0, 2, 0, 2, 2, 1, 6, 0, 5, 0, 2, 6, 5, 4, 0, ...

https://oeis.org/A181391
''',
'''
''',
[ 'root' ] ],
''' + makeCommandExample( '10 van_eck' ) + '''
''' + makeCommandExample( '100 van_eck' ),
[ 'root', 'nth_thue_morse', 'debruijn_sequence' ] ],


'zeta' : [
Expand Down
49 changes: 47 additions & 2 deletions rpn/math/rpnLexicographic.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#******************************************************************************

import itertools
import random
import string

from mpmath import arange, fabs, fadd, ceil, floor, fmod, fmul, fneg, fprod, fsub, fsum, log10, \
Expand Down Expand Up @@ -830,8 +831,8 @@ def buildLimitedDigitNumbers( digits, minLength, maxLength ):
# - "[I[I]...:n:m]" - permutations of any digits I, from a minimum of n,
# up to a maximum of m digits long
# - "s" - the designation for a "step digit", which can be one greater
# or one less than the previous digit. For the purposes of step
#
# or one less than the previous digit. For the purposes of step,
# 0 succeeds 9 and precedes 1.
#
# A digit expression (I) can be a single digit or a range. A single digit is
# anything from "0" through "9". A digit range looks like: "a-b" where a
Expand Down Expand Up @@ -1187,6 +1188,50 @@ def permuteDigitsOperator( n ):
return RPNGenerator.createPermutations( getMPFIntegerAsString( n ) )


#******************************************************************************
#
# changeDigitsOperator
#
#******************************************************************************

@twoArgFunctionEvaluator( )
@argValidator( [ IntValidator( 0 ), IntValidator( 1 ) ] )
def changeDigitsOperator( n, k ):
numbers = '0123456789'
digits = getMPFIntegerAsString( n )
digit_count = len( digits )

if k > digit_count:
raise ValueError( 'change_digits cannot change more digits than exist' )

indices_to_change = [ ]

for _ in arange( k ):
done = False

while not done:
index = random.randrange( digit_count )

if index not in indices_to_change:
indices_to_change.append( index )
done = True

for index in indices_to_change:
digit_to_change = digits[ index ]

done = False

while not done:
new_digit = numbers[ random.randrange( 10 ) ]

if new_digit != digit_to_change:
done = True

digits = digits[ : index ] + new_digit + digits[ index + 1 : ]

return mpmathify( digits )


#******************************************************************************
#
# isIncreasingOperator
Expand Down
4 changes: 2 additions & 2 deletions rpn/math/rpnNumberTheory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3077,7 +3077,7 @@ def getNthKPolygorialOperator( n, k ):
def getRandomPrime( n ):
setAccuracy( n )

base = power( 10, n )
base = int( power( 10, n ) )
result = getNextPrime( randrange( base ) )

if result > base:
Expand Down Expand Up @@ -3155,7 +3155,7 @@ def getReciprocalPeriodOperator( n ):
# if n == 0:
# return 0
#
# a, b = divmod(n.bit_length(), 2)
# a, b = divmod(n.bit_length( ), 2)
# x = 2**(a+b)
#
# while True:
Expand Down
1 change: 1 addition & 0 deletions rpn/rpn.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ def handleOutput( valueList, indent=0, file=sys.stdout ):
if len( valueList ) != 1:
if g.checkForSingleResults:
print( 'valueList', valueList )
formatListOutput( valueList )
raise ValueError( 'unexpected multiple results!' )

valueList = [ valueList ]
Expand Down
5 changes: 3 additions & 2 deletions rpn/rpnOperators.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
from rpn.util.rpnInput import parseInputValue, readListFromFileOperator, readNumberFromFileOperator

from rpn.math.rpnLexicographic import \
addDigitsOperator, buildNumbersOperator, buildStepNumbersOperator, combineDigitsOperator, \
addDigitsOperator, buildNumbersOperator, buildStepNumbersOperator, changeDigitsOperator, combineDigitsOperator, \
containsAnyDigitsOperator, containsDigitsOperator, containsOnlyDigitsOperator, countDifferentDigitsOperator, \
countDigitsOperator, duplicateDigitsOperator, duplicateNumberOperator, findPalindromeOperator, \
generateSquareDigitChainOperator, getCyclicPermutationsOperator, getDigitCountOperator, getDecimalDigitsOperator, \
Expand Down Expand Up @@ -2470,7 +2470,7 @@ def createSizedRangeOperator( a, b, c ):
'crt' : RPNOperator( calculateChineseRemainderTheoremOperator, 2 ),
'frobenius' : RPNOperator( getFrobeniusNumberOperator, 1 ),
'geometric_recurrence' : RPNOperator( getGeometricRecurrenceOperator, 4 ),
'is_sociable_list' : RPNOperator( isSociableListOperator, 1 ),
#'is_sociable_list' : RPNOperator( isSociableListOperator, 1 ),
'linear_recurrence' : RPNOperator( getLinearRecurrenceOperator, 3 ),
'linear_recurrence_with_modulo' : RPNOperator( getLinearRecurrenceWithModuloOperator, 4 ),
'nth_linear_recurrence' : RPNOperator( getNthLinearRecurrenceOperator, 3 ),
Expand Down Expand Up @@ -2928,6 +2928,7 @@ def createSizedRangeOperator( a, b, c ):
'add_digits' : RPNOperator( addDigitsOperator, 2 ),
'build_numbers' : RPNOperator( buildNumbersOperator, 1 ),
'build_step_numbers' : RPNOperator( buildStepNumbersOperator, 1 ),
'change_digits' : RPNOperator( changeDigitsOperator, 2 ),
'count_different_digits' : RPNOperator( countDifferentDigitsOperator, 1 ),
'count_digits' : RPNOperator( countDigitsOperator, 2 ),
'cyclic_permutations' : RPNOperator( getCyclicPermutationsOperator, 1 ),
Expand Down
4 changes: 2 additions & 2 deletions rpn/rpnVersion.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#******************************************************************************

PROGRAM_NAME = 'rpnChilada'
PROGRAM_VERSION = '8.999.991'
PROGRAM_VERSION_NAME = '9.0.alpha1'
PROGRAM_VERSION = '8.999.9991'
PROGRAM_VERSION_NAME = '9.0.beta1'
COPYRIGHT_MESSAGE = 'copyright (c) 2023 (1988), Rick Gutleber ([email protected])'

if PROGRAM_VERSION != PROGRAM_VERSION_NAME:
Expand Down
6 changes: 4 additions & 2 deletions rpn/science/rpnAstronomy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
#from skyfield.api import load, Topos

from rpn.math.rpnMath import subtract
from rpn.special.rpnLocation import getLocation, getTimeZone
from rpn.special.rpnLocation import getTimeZone
from rpn.special.rpnLocation import getLocation
from rpn.time.rpnDateTime import RPNDateTime, convertTimeZone, modifyTimeZone
from rpn.units.rpnMatchUnitTypes import matchUnitTypes
from rpn.units.rpnMeasurementClass import RPNMeasurement
Expand Down Expand Up @@ -719,8 +720,9 @@ def getNextSetting( arg1, arg2, arg3 ):
if not arguments:
raise ValueError( 'unexpected arguments' )

return arguments[ 'body' ].getNextSetting( arguments[ 'location' ], arguments[ 'datetime' ] )
result = arguments[ 'body' ].getNextSetting( arguments[ 'location' ], arguments[ 'datetime' ] )

return result.getLocalTime( getTimeZone( arguments[ 'location' ].name ) )

@twoArgFunctionEvaluator( )
def getNextSunsetOperator( n, k ):
Expand Down
14 changes: 0 additions & 14 deletions rpn/special/rpnLocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,6 @@ def getLocation( name ):
if not isinstance( name, str ):
raise ValueError( '\'location\' expects a string argument' )

if g.locationCache is None:
g.locationCache = loadLocationCache( )

if name in g.locationCache:
locationInfo = g.locationCache[ name ]

observer = ephem.Observer( )
result = RPNLocation( name=name, observer=observer )

result.setLat( locationInfo[ 1 ] )
result.setLong( locationInfo[ 2 ] )

return result

latitude, longitude = lookUpLocation(name)

observer = ephem.Observer( )
Expand Down
Loading

0 comments on commit 1f8d225

Please sign in to comment.