Coverage for /usr/lib/python3/dist-packages/sympy/ntheory/digits.py: 21%

28 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1from collections import defaultdict 

2 

3from sympy.utilities.iterables import multiset, is_palindromic as _palindromic 

4from sympy.utilities.misc import as_int 

5 

6 

7def digits(n, b=10, digits=None): 

8 """ 

9 Return a list of the digits of ``n`` in base ``b``. The first 

10 element in the list is ``b`` (or ``-b`` if ``n`` is negative). 

11 

12 Examples 

13 ======== 

14 

15 >>> from sympy.ntheory.digits import digits 

16 >>> digits(35) 

17 [10, 3, 5] 

18 

19 If the number is negative, the negative sign will be placed on the 

20 base (which is the first element in the returned list): 

21 

22 >>> digits(-35) 

23 [-10, 3, 5] 

24 

25 Bases other than 10 (and greater than 1) can be selected with ``b``: 

26 

27 >>> digits(27, b=2) 

28 [2, 1, 1, 0, 1, 1] 

29 

30 Use the ``digits`` keyword if a certain number of digits is desired: 

31 

32 >>> digits(35, digits=4) 

33 [10, 0, 0, 3, 5] 

34 

35 Parameters 

36 ========== 

37 

38 n: integer 

39 The number whose digits are returned. 

40 

41 b: integer 

42 The base in which digits are computed. 

43 

44 digits: integer (or None for all digits) 

45 The number of digits to be returned (padded with zeros, if 

46 necessary). 

47 

48 """ 

49 

50 b = as_int(b) 

51 n = as_int(n) 

52 if b < 2: 

53 raise ValueError("b must be greater than 1") 

54 else: 

55 x, y = abs(n), [] 

56 while x >= b: 

57 x, r = divmod(x, b) 

58 y.append(r) 

59 y.append(x) 

60 y.append(-b if n < 0 else b) 

61 y.reverse() 

62 ndig = len(y) - 1 

63 if digits is not None: 

64 if ndig > digits: 

65 raise ValueError( 

66 "For %s, at least %s digits are needed." % (n, ndig)) 

67 elif ndig < digits: 

68 y[1:1] = [0]*(digits - ndig) 

69 return y 

70 

71 

72def count_digits(n, b=10): 

73 """ 

74 Return a dictionary whose keys are the digits of ``n`` in the 

75 given base, ``b``, with keys indicating the digits appearing in the 

76 number and values indicating how many times that digit appeared. 

77 

78 Examples 

79 ======== 

80 

81 >>> from sympy.ntheory import count_digits 

82 

83 >>> count_digits(1111339) 

84 {1: 4, 3: 2, 9: 1} 

85 

86 The digits returned are always represented in base-10 

87 but the number itself can be entered in any format that is 

88 understood by Python; the base of the number can also be 

89 given if it is different than 10: 

90 

91 >>> n = 0xFA; n 

92 250 

93 >>> count_digits(_) 

94 {0: 1, 2: 1, 5: 1} 

95 >>> count_digits(n, 16) 

96 {10: 1, 15: 1} 

97 

98 The default dictionary will return a 0 for any digit that did 

99 not appear in the number. For example, which digits appear 7 

100 times in ``77!``: 

101 

102 >>> from sympy import factorial 

103 >>> c77 = count_digits(factorial(77)) 

104 >>> [i for i in range(10) if c77[i] == 7] 

105 [1, 3, 7, 9] 

106 """ 

107 rv = defaultdict(int, multiset(digits(n, b)).items()) 

108 rv.pop(b) if b in rv else rv.pop(-b) # b or -b is there 

109 return rv 

110 

111 

112def is_palindromic(n, b=10): 

113 """return True if ``n`` is the same when read from left to right 

114 or right to left in the given base, ``b``. 

115 

116 Examples 

117 ======== 

118 

119 >>> from sympy.ntheory import is_palindromic 

120 

121 >>> all(is_palindromic(i) for i in (-11, 1, 22, 121)) 

122 True 

123 

124 The second argument allows you to test numbers in other 

125 bases. For example, 88 is palindromic in base-10 but not 

126 in base-8: 

127 

128 >>> is_palindromic(88, 8) 

129 False 

130 

131 On the other hand, a number can be palindromic in base-8 but 

132 not in base-10: 

133 

134 >>> 0o121, is_palindromic(0o121) 

135 (81, False) 

136 

137 Or it might be palindromic in both bases: 

138 

139 >>> oct(121), is_palindromic(121, 8) and is_palindromic(121) 

140 ('0o171', True) 

141 

142 """ 

143 return _palindromic(digits(n, b), 1)