Skip to content

Commit 463ff64

Browse files
authored
Merge pull request #1055 from mathics/MapAt
Map at
2 parents 067ffda + 6c063ef commit 463ff64

2 files changed

Lines changed: 57 additions & 27 deletions

File tree

mathics/builtin/structure.py

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ class MapAt(Builtin):
536536
>> MapAt[f, {a, b, c, d}, 2]
537537
= {a, f[b], c, d}
538538
539+
Map $f$ onto multiple parts:
540+
>> MapAt[f, {a, b, c, d}, {{1}, {4}}]
541+
= {f[a], b, c, f[d]}
542+
539543
Map $f$ onto the at the end:
540544
>> MapAt[f, {a, b, c, d}, -1]
541545
= {a, b, c, f[d]}
@@ -547,30 +551,50 @@ class MapAt(Builtin):
547551
Use negative position in an association:
548552
>> MapAt[f, <|"a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4|>, -3]
549553
= {a -> 1, b -> f[2], c -> 3, d -> 4}
554+
555+
Use the operator form of MapAt:
556+
>> MapAt[f, 1][{a, b, c, d}]
557+
= {f[a], b, c, d}
550558
"""
551559

552-
def apply(self, f, expr, n, evaluation, options={}):
553-
"MapAt[f_, expr_, n_Integer]"
554-
i = n.get_int_value()
560+
rules = {
561+
"MapAt[f_, pos_][expr_]": "MapAt[f, expr, pos]",
562+
}
563+
564+
def apply(self, f, expr, args, evaluation, options={}):
565+
"MapAt[f_, expr_, args_]"
566+
555567
m = len(expr.leaves)
556-
if 1 <= i <= m:
557-
j = i - 1
558-
elif -m <= i <= -1:
559-
j = m + i
560-
else:
561-
raise PartRangeError
562-
563-
new_leaves = list(expr.leaves)
564-
replace_leaf = new_leaves[j]
565-
if hasattr(replace_leaf, "head") and replace_leaf.head == Symbol("System`Rule"):
566-
new_leaves[j] = Expression(
567-
"System`Rule",
568-
replace_leaf.leaves[0],
569-
Expression(f, replace_leaf.leaves[1]),
570-
)
571-
else:
572-
new_leaves[j] = Expression(f, replace_leaf)
573-
return List(*new_leaves)
568+
569+
def map_at_one(i, leaves):
570+
if 1 <= i <= m:
571+
j = i - 1
572+
elif -m <= i <= -1:
573+
j = m + i
574+
else:
575+
raise PartRangeError
576+
replace_leaf = new_leaves[j]
577+
if hasattr(replace_leaf, "head") and replace_leaf.head == Symbol("System`Rule"):
578+
new_leaves[j] = Expression(
579+
"System`Rule",
580+
replace_leaf.leaves[0],
581+
Expression(f, replace_leaf.leaves[1]),
582+
)
583+
else:
584+
new_leaves[j] = Expression(f, replace_leaf)
585+
return new_leaves
586+
587+
a = args.to_python()
588+
if isinstance(a, int):
589+
new_leaves = list(expr.leaves)
590+
new_leaves = map_at_one(a, new_leaves)
591+
return List(*new_leaves)
592+
elif isinstance(a, list):
593+
new_leaves = list(expr.leaves)
594+
for l in a:
595+
if len(l) == 1 and isinstance(l[0], int):
596+
new_leaves = map_at_one(l[0], new_leaves)
597+
return List(*new_leaves)
574598

575599

576600
class Scan(Builtin):

test/test_combinatorica.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,18 @@ def test_combinatorica_permutations_1_2():
259259
"(4 m + 2 m ^ 2 + m ^ 4 + m ^ 8) / 8",
260260
"Polya counting resulting in polynomial 1.2.6, Page 25",
261261
),
262-
# MapAt not finished which is probably causing Poly to fail here...
263-
# (
264-
# "Polya[Automorphisms[Cycle[8]], m]",
265-
# "(4 m + 2 m ^ 2 + m ^ 4 + m ^ 8) / 8",
266-
# "Polya counting resulting in polynomial 1.2.6, Page 26",
267-
# ),
262+
# Automorphism is slow. So we reduce Cycle[8] given as the example in the
263+
# book to Cycle[3].
264+
(
265+
"Polya[Automorphisms[Cycle[3]], m]",
266+
"(2 m + 3 m ^ 2 + m ^ 3) / 6",
267+
"Polya counting resulting in polynomial 1.2.6, Page 26",
268+
),
269+
(
270+
"Factor[(2 m + 3 m ^ 2 + m ^ 3) / 6]",
271+
"m (1 + m) (2 + m) / 6",
272+
"Factor Polya polynomial 1.2.6, Page 26",
273+
),
268274
(
269275
"Factor[(4 m + 2 m^2 + 5m^4 + 4m^5 + m^8)/16]",
270276
"m (1 + m) (4 - 2 m + 2 m ^ 2 + 3 m ^ 3 + m ^ 4 - m ^ 5 + m ^ 6) / 16",

0 commit comments

Comments
 (0)