Skip to content

Commit 2af2c17

Browse files
authored
Merge pull request #1139 from mathics/IntegerDigits
Bug fix reversed() used on generator
2 parents 1bd8460 + 9d125b8 commit 2af2c17

1 file changed

Lines changed: 89 additions & 62 deletions

File tree

mathics/builtin/integer.py

Lines changed: 89 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
class Floor(SympyFunction):
1919
"""
2020
<dl>
21-
<dt>'Floor[$x$]'
22-
<dd>gives the smallest integer less than or equal to $x$.
23-
<dt>'Floor[$x$, $a$]'
24-
<dd>gives the smallest multiple of $a$ less than or equal to $x$.
21+
<dt>'Floor[$x$]'
22+
<dd>gives the smallest integer less than or equal to $x$.
23+
24+
<dt>'Floor[$x$, $a$]'
25+
<dd>gives the smallest multiple of $a$ less than or equal to $x$.
2526
</dl>
2627
2728
>> Floor[10.4]
@@ -49,12 +50,10 @@ class Floor(SympyFunction):
4950
= -10
5051
"""
5152

52-
rules = {
53-
'Floor[x_, a_]': 'Floor[x / a] * a'
54-
}
53+
rules = {"Floor[x_, a_]": "Floor[x / a] * a"}
5554

5655
def apply_real(self, x, evaluation):
57-
'Floor[x_]'
56+
"Floor[x_]"
5857
x = x.to_sympy()
5958
if x is not None:
6059
return from_sympy(sympy.floor(x))
@@ -63,8 +62,8 @@ def apply_real(self, x, evaluation):
6362
class Ceiling(SympyFunction):
6463
"""
6564
<dl>
66-
<dt>'Ceiling[$x$]'
67-
<dd>gives the first integer greater than $x$.
65+
<dt>'Ceiling[$x$]'
66+
<dd>gives the first integer greater than $x$.
6867
</dl>
6968
7069
>> Ceiling[1.2]
@@ -77,12 +76,10 @@ class Ceiling(SympyFunction):
7776
= 2 + I
7877
"""
7978

80-
rules = {
81-
'Ceiling[x_, a_]': 'Ceiling[x / a] * a'
82-
}
79+
rules = {"Ceiling[x_, a_]": "Ceiling[x / a] * a"}
8380

8481
def apply(self, x, evaluation):
85-
'Ceiling[x_]'
82+
"Ceiling[x_]"
8683
x = x.to_sympy()
8784
if x is None:
8885
return
@@ -124,22 +121,22 @@ class IntegerLength(Builtin):
124121
"""
125122

126123
rules = {
127-
'IntegerLength[n_]': 'IntegerLength[n, 10]',
124+
"IntegerLength[n_]": "IntegerLength[n, 10]",
128125
}
129126

130127
messages = {
131-
'base': "Base `1` is not an integer greater than 1.",
128+
"base": "Base `1` is not an integer greater than 1.",
132129
}
133130

134131
def apply(self, n, b, evaluation):
135-
'IntegerLength[n_, b_]'
132+
"IntegerLength[n_, b_]"
136133

137134
n, b = n.get_int_value(), b.get_int_value()
138135
if n is None or b is None:
139-
evaluation.message('IntegerLength', 'int')
136+
evaluation.message("IntegerLength", "int")
140137
return
141138
if b <= 1:
142-
evaluation.message('IntegerLength', 'base', b)
139+
evaluation.message("IntegerLength", "base", b)
143140
return
144141

145142
if n == 0:
@@ -170,8 +167,8 @@ def apply(self, n, b, evaluation):
170167
class BitLength(Builtin):
171168
"""
172169
<dl>
173-
<dt>'BitLength[$x$]'
174-
<dd>gives the number of bits needed to represent the integer $x$. $x$'s sign is ignored.
170+
<dt>'BitLength[$x$]'
171+
<dd>gives the number of bits needed to represent the integer $x$. $x$'s sign is ignored.
175172
</dl>
176173
177174
>> BitLength[1023]
@@ -185,14 +182,16 @@ class BitLength(Builtin):
185182
"""
186183

187184
def apply(self, n, evaluation):
188-
'BitLength[n_Integer]'
185+
"BitLength[n_Integer]"
189186
n = n.get_int_value()
190187
if n < 0:
191188
n = -1 - n
192189
return Integer(n.bit_length())
193190

194191

195-
def _reversed_digits(number, base): # yield digits for number in base "base" in reverse order
192+
def _reversed_digits(
193+
number, base
194+
): # yield digits for number in base "base" in reverse order
196195
number = abs(number)
197196
if number == 0:
198197
yield 0
@@ -246,11 +245,11 @@ class IntegerString(Builtin):
246245
"""
247246

248247
rules = {
249-
'IntegerString[n_Integer]': 'IntegerString[n, 10]',
248+
"IntegerString[n_Integer]": "IntegerString[n, 10]",
250249
}
251250

252251
messages = {
253-
'basf': 'Base `` must be an integer in the range from 2 to 36.',
252+
"basf": "Base `` must be an integer in the range from 2 to 36.",
254253
}
255254

256255
list_of_symbols = string.digits + string.ascii_letters
@@ -269,32 +268,33 @@ def _symbols(self, n, b, evaluation):
269268
else:
270269
list_of_symbols = IntegerString.list_of_symbols
271270
if b > len(list_of_symbols) or b < 2:
272-
evaluation.message('IntegerString', 'basf', b)
271+
evaluation.message("IntegerString", "basf", b)
273272
return False
274273
else:
275-
return ''.join(reversed(
276-
[list_of_symbols[r] for r in _reversed_digits(n, b)]))
274+
return "".join(
275+
reversed([list_of_symbols[r] for r in _reversed_digits(n, b)])
276+
)
277277

278278
def apply_n(self, n, b, evaluation):
279-
'IntegerString[n_Integer, b_Integer]'
279+
"IntegerString[n_Integer, b_Integer]"
280280
s = self._symbols(n.get_int_value(), b.get_int_value(), evaluation)
281281
return String(s) if s else None
282282

283283
def apply_n_b_length(self, n, b, length, evaluation):
284-
'IntegerString[n_Integer, b_Integer, length_Integer]'
284+
"IntegerString[n_Integer, b_Integer, length_Integer]"
285285
s = self._symbols(n.get_int_value(), b.get_int_value(), evaluation)
286-
return String(_pad(s, length.get_int_value(), '0')) if s else None
286+
return String(_pad(s, length.get_int_value(), "0")) if s else None
287287

288288

289289
class _IntBaseBuiltin(Builtin):
290290
messages = {
291-
'basf': 'Base `` must be an integer greater than 1.',
291+
"basf": "Base `` must be an integer greater than 1.",
292292
}
293293

294294
def _valid_base(self, b, evaluation):
295295
base = b.get_int_value()
296296
if base < 2:
297-
evaluation.message(self.get_name(), 'basf', base)
297+
evaluation.message(self.get_name(), "basf", base)
298298
return False
299299
else:
300300
return base
@@ -330,22 +330,46 @@ class IntegerDigits(_IntBaseBuiltin):
330330
"""
331331

332332
rules = {
333-
'IntegerDigits[n_Integer]': 'IntegerDigits[n, 10]',
333+
"IntegerDigits[n_Integer]": "IntegerDigits[n, 10]",
334334
}
335335

336336
_padding = [Integer(0)]
337337

338338
def apply_n_b(self, n, b, evaluation):
339-
'IntegerDigits[n_Integer, b_Integer]'
339+
"IntegerDigits[n_Integer, b_Integer]"
340340
base = self._valid_base(b, evaluation)
341-
return Expression('List', *[Integer(d) for d in reversed(
342-
_reversed_digits(n.get_int_value(), base))]) if base else None
341+
return (
342+
Expression(
343+
"List",
344+
*[
345+
Integer(d)
346+
for d in reversed(list(_reversed_digits(n.get_int_value(), base)))
347+
]
348+
)
349+
if base
350+
else None
351+
)
343352

344353
def apply_n_b_length(self, n, b, length, evaluation):
345-
'IntegerDigits[n_Integer, b_Integer, length_Integer]'
354+
"IntegerDigits[n_Integer, b_Integer, length_Integer]"
346355
base = self._valid_base(b, evaluation)
347-
return Expression('List', *_pad([Integer(d) for d in reversed(
348-
_reversed_digits(n.get_int_value(), base))], length.get_int_value(), self._padding)) if base else None
356+
return (
357+
Expression(
358+
"List",
359+
*_pad(
360+
[
361+
Integer(d)
362+
for d in reversed(
363+
list(_reversed_digits(n.get_int_value(), base))
364+
)
365+
],
366+
length.get_int_value(),
367+
self._padding,
368+
)
369+
)
370+
if base
371+
else None
372+
)
349373

350374

351375
class DigitCount(_IntBaseBuiltin):
@@ -370,28 +394,33 @@ class DigitCount(_IntBaseBuiltin):
370394
"""
371395

372396
rules = {
373-
'DigitCount[n_Integer]': 'DigitCount[n, 10]',
397+
"DigitCount[n_Integer]": "DigitCount[n, 10]",
374398
}
375399

376400
def apply_n_b_d(self, n, b, d, evaluation):
377-
'DigitCount[n_Integer, b_Integer, d_Integer]'
401+
"DigitCount[n_Integer, b_Integer, d_Integer]"
378402
base = self._valid_base(b, evaluation)
379403
if not base:
380404
return
381405
match = d.get_int_value()
382-
return Integer(sum(1 for digit in _reversed_digits(
383-
n.get_int_value(), base) if digit == match))
406+
return Integer(
407+
sum(
408+
1
409+
for digit in _reversed_digits(n.get_int_value(), base)
410+
if digit == match
411+
)
412+
)
384413

385414
def apply_n_b(self, n, b, evaluation):
386-
'DigitCount[n_Integer, b_Integer]'
415+
"DigitCount[n_Integer, b_Integer]"
387416
base = self._valid_base(b, evaluation)
388417
if not base:
389418
return
390419
occurence_count = [0] * base
391420
for digit in _reversed_digits(n.get_int_value(), base):
392421
occurence_count[digit] += 1
393422
# result list is rotated by one element to the left
394-
return Expression('List', *(occurence_count[1:] + [occurence_count[0]]))
423+
return Expression("List", *(occurence_count[1:] + [occurence_count[0]]))
395424

396425

397426
class IntegerReverse(_IntBaseBuiltin):
@@ -412,11 +441,11 @@ class IntegerReverse(_IntBaseBuiltin):
412441
"""
413442

414443
rules = {
415-
'IntegerReverse[n_Integer]': 'IntegerReverse[n, 10]',
444+
"IntegerReverse[n_Integer]": "IntegerReverse[n, 10]",
416445
}
417446

418447
def apply_n_b(self, n, b, evaluation):
419-
'IntegerReverse[n_Integer, b_Integer]'
448+
"IntegerReverse[n_Integer, b_Integer]"
420449
base = self._valid_base(b, evaluation)
421450
if not base:
422451
return
@@ -465,18 +494,14 @@ class FromDigits(Builtin):
465494
= FromDigits[x, 10]
466495
"""
467496

468-
rules = {
469-
'FromDigits[l_]': 'FromDigits[l, 10]'
470-
}
497+
rules = {"FromDigits[l_]": "FromDigits[l, 10]"}
471498

472-
messages = {
473-
'nlst': 'The input must be a string of digits or a list.'
474-
}
499+
messages = {"nlst": "The input must be a string of digits or a list."}
475500

476501
@staticmethod
477502
def _parse_string(s, b):
478-
code_0 = ord('0')
479-
code_a = ord('a')
503+
code_0 = ord("0")
504+
code_a = ord("a")
480505
assert code_a > code_0
481506

482507
value = Integer(0)
@@ -487,24 +512,26 @@ def _parse_string(s, b):
487512
else:
488513
digit = code - code_0
489514
if 0 <= digit < 36:
490-
value = Expression('Plus', Expression('Times', value, b), Integer(digit))
515+
value = Expression(
516+
"Plus", Expression("Times", value, b), Integer(digit)
517+
)
491518
else:
492519
return None
493520

494521
return value
495522

496523
def apply(self, l, b, evaluation):
497-
'FromDigits[l_, b_]'
498-
if l.get_head_name() == 'System`List':
524+
"FromDigits[l_, b_]"
525+
if l.get_head_name() == "System`List":
499526
value = Integer(0)
500527
for leaf in l.leaves:
501-
value = Expression('Plus', Expression('Times', value, b), leaf)
528+
value = Expression("Plus", Expression("Times", value, b), leaf)
502529
return value
503530
elif isinstance(l, String):
504531
value = FromDigits._parse_string(l.get_string_value(), b)
505532
if value is None:
506-
evaluation.message('FromDigits', 'nlst')
533+
evaluation.message("FromDigits", "nlst")
507534
else:
508535
return value
509536
else:
510-
evaluation.message('FromDigits', 'nlst')
537+
evaluation.message("FromDigits", "nlst")

0 commit comments

Comments
 (0)