求幂乘以加法


17

可以将2个整数之间的乘法简化为一系列加法运算,如下所示

3 * 5 = 3 + 3 + 3 + 3 + 3 = 5 + 5 + 5

求幂(将a增大到b)也可以简化为一系列乘法:

5 ^ 3 = 5 * 5 * 5

因此,可以通过创建乘法表达式将乘幂减少为一系列加法,然后减少为一系列加法。例如,5 ^ 3(5立方)可以重写为

5 ^ 3 = 5 * 5 * 5
      = (5 + 5 + 5 + 5 + 5) * 5
      = (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5)
      = 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5

您的任务是,给定由加幂,乘法和加法组成的表达式,将其简化为最短的加法序列。“最短”表达式定义为+符号数量最少的表达式,但仍仅使用原始表达式中两个数字之一。例如,的最短表达式10 * 210 + 10

输入中涉及的数字均为正整数,表达式仅包含+(加法),*(乘)和^(取幂)以及整数和方括号(())表示优先级组成。

输出应包含正整数和 +符号。您不应该输出缩减的各个步骤,而仅输出最终输出。输出中可能没有输入中没有出现的任何数字。但是,您可以使用3个不同的符号代替+*^,但请说出它们是什么符号

输入和输出之间的空格可能会或可能不会在您的程序中使用,即3 * 5可以作为以下两者之一输出5 + 5 + 55+5+5

请注意,在大多数情况下,实际上并不执行加法。唯一要执行加法的情况是5 ^ (1 + 2),在这种情况下,必须继续加法-> 5 ^ 3 -> 5 * 5 * 5 -> ...。参见测试案例4。

您的代码无需处理到达歧义表达式的输入。例如,(2 + 2) * (4 + 1)。由于到目前为止已制定了规则,因此目标不是计算答案,而是将目标简化为加法。因此,结果可能会有所不同,具体取决于表达式被解析或转换的顺序(哪些要简化,哪些要保留?)。另一个无效的示例:((3 + 2) ^ 2) ^ 3 -> ((3 + 2) * (3 + 2)) ^ 3 -> ???

这是所以最短的代码胜出

测试用例

Input => output

5 ^ 3 + 4 * 1 ^ 5 => 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 4
2 ^ 1 * 2 + 3 + 9 => 2 + 2 + 3 + 9
2 ^ 1 * (2 + 3) + 9 => 2 + 3 + 2 + 3 + 9
2 ^ (1 * (2 + 3)) + 9 => 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 9
10 + 3 * 2 + 33 ^ 2 => 10 + 3 + 3 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33
100 * 3 => 100 + 100 + 100
2 ^ 1 + 2 ^ 1 + 2 ^ 2 + 8 ^ 1 => 2 + 2 + 2 + 2 + 8
(1 + 2 + 5 * 8 + 2 ^ 4) * 2 => 1 + 2 + 8 + 8 + 8 + 8 + 8 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + 2 + 8 + 8 + 8 + 8 + 8 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2

我们可以**代替使用^吗?
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer是的,这似乎很公平。
caird coinheringaahing


1
我对有效输出的构成仍然感到困惑。您在问题中说,using only one of the two numbers in the original expression.但是原始表达式可以有两个以上的数字。我不明白为什么8 + 8不是的有效输出2 ^ 1 + 2 ^ 1 + 2 ^ 2 + 8 ^ 1。我仍然不清楚这个问题。
发布Rock Garf Hunter,2017年

Answers:


6

视网膜,302字节

我敢肯定这可以打高尔夫,但是在这一点上,我很高兴它能起作用。取幂和乘法部分都非常相似,但是由于运算顺序很重要,因此我不知道如何将它们组合在一起。

y -求幂
x -乘法
p-加法

\d+
$*
{1`(\(\w+\)|1+)y(\(\w+\)|1+)
>$0<
(?<=>(\(\w+\)|1+)y1*)1
$1x
>(\(\w+\)|1+)y
(
x<
)
\((1+(x1+)*)\)(?!y)
$1
(?<!1)(1+)x(\(\w+\)|1+\1)(?!1)
$2x$1
1`(\(\w+\)|1+)x1+
>$0<
(?<=>(\(\w+\)|1+)x1*)1
$1p
>(\(\w+\)|1+)x
(
p<
)
(?<!x|y)\((1+(p1+)*)\)(?!x|y)
$1
y\((1+)p([1p]*\))
y($1$2
}`y\((1+)\)
y$1
1+
$.0

在线试用 -所有测试案例

测试用例转换器

说明

\d+                             Convert to unary
$*
{1`(\(\w+\)|1+)y(\(\w+\)|1+)    Begin loop: Delimit current exponentiation group
>$0<
(?<=>(\(\w+\)|1+)y1*)1          Replace exponentiation with multiplication
$1x
>(\(\w+\)|1+)y                  Replace garbage with parentheses
(
x<
)
\((1+(x1+)*)\)(?!y)             Remove unnecessary parentheses around multiplication
$1
(?<!1)(1+)x(\(\w+\)|1+\1)(?!1)  Maybe swap order of multiplicands
$2x$1
1`(\(\w+\)|1+)x1+               Delimit current multiplication group
>$0<
(?<=>(\(\w+\)|1+)x1*)1          Replace multiplication with addition
$1p
>(\(\w+\)|1+)x                  Replace garbage with parentheses
(
p<
)
(?<!x|y)\((1+(p1+)*)\)(?!x|y)   Remove unnecessary parentheses around addition
$1
y\((1+)p([1p]*\))               Handle the 4th test case by adding if necessary
y($1$2
}`y\((1+)\)                     End of loop
y$1
1+                              Convert unary back to decimal
$.0

您可能还会注意到,最常用的组是(\(\w+\)|1+)。这使带有括号或整数的内部表达式匹配。我选择使用我做过的符号,以便可以使用\w而不是字符类。我不确定使用非文字符号并用文字边框(\b)代替某些环视效果是否更好。


5

数学,250个 218 183 170字节

f~(s=SetAttributes)~HoldAll;{a,t}~s~Flat;f@n_:=Infix[Hold@n//.{a_~Power~b_:>t@@Hold@a~Table~b,Times->t,Plus->a,Hold->Dot}/.t->(a@@Table[#,1##2]&@@Reverse@Sort@{##}&),"+"]

有用!最后!

在中定义功能 f

输入是一个简单的数学表达式。(即1 + 2不是"1 + 2")。

在线尝试!

请注意,TIO链接的代码略有不同,因为TIO(我想使用Mathematica内核)不喜欢Infix。我改Riffle而使用了与Mathematica REPL相同的外观。

不打高尔夫球

f~(s = SetAttributes)~HoldAll;  (* make f not evaluate its inputs *)

{a, t}~s~Flat;  (* make a and t flat, so that a[a[1,a[3]]] == a[1,3] *)

f@n_ :=  (* define f, input n *)

 Infix[

  Hold@n  (* hold the evaluation of n for replacement *)

    //. {  (* expand exponents *)

     (* change a^b to t[a,a,...,a] (with b a's) *)
     a_~Power~b_ :> t @@ Hold@a~Table~b,

     (* Replace Times and Plus with t and a, respectively *)
     Times -> t, 
     Plus -> a, 

     (* Replace the Hold function with the identity, since we don't need
         to hold anymore (Times and Plus are replaced) *)
     Hold -> Dot 

     } /.  (* Replace; expand all t (= `Times`) to a (= `Plus`) *)

        (* Take an expression wrapped in t. *)
        (* First, sort the arguments in reverse. This puts the term
            wrapped in `a` (if none, the largest number) in the front *)
        (* Next, repeat the term found above by <product of rest
            of the arguments> times *)
        (* Finally, wrap the entire thing in `a` *)
        (* This will throw errors when there are multiple elements wrapped
           in `a` (i.e. multiplying two parenthesized elements) *)
        t -> (a @@ Table[#, 1 ##2] & @@
               Reverse@Sort@{##} &),

  "+"]  (* place "+" between each term *)

6
好的,我很高兴我提出了一个挑战,那就是Mathematica没有内置的:P
caird coinheringaahing 17-10-4

3

数学,405个 406字节

f~SetAttributes~HoldAll;p=(v=Inactive)@Plus;t=v@Times;w=v@Power;f@x_:=First@MinimalBy[Inactivate@{x}//.{w[a___,b_List,c___]:>(w[a,#,c]&/@b),t[a___,b_List,c___]:>(t[a,#,c]&/@b),p[a___,b_List,c___]:>(p[a,#,c]&/@b),p[a_]:>a,w[a_,b_]:>t@@Table[a,{Activate@b}],t[a___,t[b__],c___]:>t[a,b,c],p[a___,p[b__],c___]:>p[a,b,c],{a___,{b__},c___}:>{a,b,c},t[a__]:>Table[p@@Table[i,{Activate[t@a/i]}],{i,{a}}]},Length];f

脱节和解释

SetAttributes[f, HoldAll]
p = Inactive[Plus]; t = Inactive[Times]; w = Inactive[Power];
f[x_] := First@MinimalBy[
   Inactivate[{x}] //. {
     w[a___, b_List, c___] :> (w[a, #, c] & /@ b),
     t[a___, b_List, c___] :> (t[a, #, c] & /@ b),
     p[a___, b_List, c___] :> (p[a, #, c] & /@ b),
     (* distribute lists of potential expansions over all operations *)
     p[a_] :> a,
     (* addition of a single term is just that term *)
     w[a_, b_] :> t @@ Table[a, {Activate@b}],
     (* a^b simplifies to a*a*...*a b times no matter what b is *)
     t[a___, t[b__], c___] :> t[a, b, c],
     p[a___, p[b__], c___] :> p[a, b, c],
     {a___, {b__}, c___} :> {a, b, c},
     (* operations are associative *)
     t[a__] :> Table[p @@ Table[i, {Activate[t@a/i]}], {i, {a}}]
     (* for a product, generate a list of potential expansions *)}
   , Length]
f

我去的带来很大的麻烦得到以下效果:此功能需要输入一个标准的数学表达式,与往常一样+*^操作(和括号)在里面,输出看起来像一个标准的数学表达式(但“停用”加号)作为答案。

上面的功能首先禁用输入中的所有操作。然后,它反复应用扩展规则,直到无法简化为止。每当遇到诸如2 * 3 * 4可以通过多种方式扩展的产品时,它都会列出可能的扩展并继续进行。最后,我们获得了可能的最终答案列表,并选择了最短的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.