将数组变成数学题


35

给定非负整数的非空列表,请考虑将其重写为算术问题,其中:

  • +在成对的数字之间插入一个加号(),这些数字从左到右递增(也就是从列表的开头到结尾)。
  • -在从左到右递减的数字对之间插入一个减号()。
  • *在成对的数字对之间插入一个乘号()。

换一种说法:if ,if 和if a,b会成为任何子列表。a+ba<ba-ba>ba*ba==b

例如清单

[12, 0, 7, 7, 29, 10, 2, 2, 1]

将成为表达

12 - 0 + 7*7 + 29 - 10 - 2*2 - 1

结果 75

编写一个包含此类列表并对其进行评估,打印或返回结果的程序或函数。

  • 操作顺序很重要。乘法应该在任何加法或减法之前完成。
  • 如果输入列表中有一个数字,那应该是它的计算结果。例如[64]应该给64
  • 使用evalexec或类似结构是允许的。

以下是一些其他示例:

[list]
expression
value

[0]
0
0

[1]
1
1

[78557] 
78557
78557

[0,0]
0*0
0

[1,1]
1*1
1

[2,2]
2*2
4

[0,1]
0+1
1

[1,0]
1-0
1

[1,2]
1+2
3

[2,1]
2-1
1

[15,4,4]
15-4*4
-1

[9,8,1]
9-8-1
0

[4,2,2,4]
4-2*2+4
4

[10,9,9,12]
10-9*9+12
-59

[1,1,2,2,3,3]
1*1+2*2+3*3
14

[5,5,4,4,3,3]
5*5-4*4-3*3
0

[3,1,4,1,5,9,2,6,5,3,5,9]
3-1+4-1+5+9-2+6-5-3+5+9
29

[7637,388,389,388,387,12,0,0,34,35,35,27,27,2]
7637-388+389-388-387-12-0*0+34+35*35-27*27-2
7379

以字节为单位的最短代码获胜。决胜局是较早的答案。


5
关于“操作顺序很重要”,最好明确指出加法和减法是左关联的,并且具有相同的优先级。
Martin Ender

Answers:


15

Python 2,63个字节

p=s='print-'
for x in input():s+='*+-'[cmp(x,p)]+`x`;p=x
exec s

构造和创建eval表达式字符串。通过将前一个数字p与当前数字进行比较来选择算术符号x。该符号后附加当前编号。

第一个数字使用Sp3000的巧妙技巧处理。的初始值p设置为字符串,该字符串大于任何数字,因此导致-在第一个数字之前。但是,会s被初始化为print-同时使结果以开头print--(感谢xsot通过使用进行初始化节省了2个字节print)。


我认为您可以print进入字符串并使用exec代替eval
xsot

13

Pyth,31 26 19 17 16 15字节

带有的表达式*不会在线评估,但从理论上讲它们会起作用。

感谢Maltysen 2个字节。

vsm+@"*-+"._-~k

测试套件(带有评估)。

其他情况(未评估)。

历史

  • 31个字节: M+G@"*-+"->GH<GHv+sgMC,JsMQtJ\x60e
  • 26个字节: M+G@"*-+"->GH<GHv+sgVQtQ\x60e
  • 19个字节: vtssVm@"*-+"->Zd<~Z
  • 17个字节: vtssVm@"*-+"._-~Z
  • 16个字节: vssVm@"*-+"._-~k
  • 15个字节: vsm+@"*-+"._-~k

为什么乘法不能在线工作?如果您不确定它是否可行,最好在回答之前再进行一些测试。
加尔文的爱好

由于安全的东西(评估仅适用于+-在线)
漏尼姑

@HelkaHomba我还没有机会离线试用,但是应该可以。在线解释器使用--safe开关,该开关替换evalast.literal_eval
丹尼斯

好,可以。
加尔文的爱好

确认,这可与离线解释器一起使用。
丹尼斯

12

果冻18 16 15 14 字节

I0;ð1g×⁹⁸œṗP€S

不使用内置评估。在线尝试!验证所有测试用例

怎么运行的

I0;ð1g×⁹⁸œṗP€S  Main link. Input: A (list)

I               Increments; compute the deltas of all adjacent items of A.
 0;             Prepend a 0.
   ð            Begin a new, dyadic chain.
                Left argument: D (0 plus deltas). Right argument: A
    1g          Compute the GCD of 1 and each item in D.
                This yields 1 for non-negative items, -1 for negative ones.
      ×⁹        Multiply each 1 or -1 with the corresponding item of A.
                This negates every item in A that follows a - sign.
        ⁸œṗ     Partition the result by D. This splits at occurrences of non-zero
                values of D, grouping items with identical absolute value.
           P€   Take the product of each group.
             S  Sum; add the results.


1
做得很好。我应该将Python eval作为一个原子...
Dennis

9
我让你失望了。:P
丹尼斯(Dennis)

做得好,轮到你了!
Leaky Nun

9

MATL,12字节

Y'^l6MdZSh*s

这使用@aditsu的游程长度编码的非常好主意

在线尝试!

说明

       % Take input vector implicitly
Y'     % RLE. Produces two vectors: values and lengths
^      % Rise each value to the number of consecutive times it appears. This
       % realizes the product of consecutive equal values
l      % Push 1
6M     % Push vector of values again
d      % Consecutive differences
ZS     % Sign function. Gives 1 or -1 (no 0 in this case)
h      % Concatenate horizontally with previous 1
*      % Multiply. This gives plus or minus depending on increasing character
s      % Sum of vector. This realizes the additions or subtractions
       % Display implicitly

哈哈刚刚写了类似的东西。RLE为此非常有效
Suever 2016年

@Suever我看到了:-D
Luis

7

果酱20

q~e`{~_W-g\:W@#*}%:+

在线尝试

说明:

q~       read and evaluate the input (array of numbers)
e`       RLE encode, obtaining [count number] pairs
{…}%     map each pair
  ~_     dump the count and number on the stack, and duplicate the number
  W-     subtract the previous number (W is initially -1 by default)
  g      get the sign of the result
  \      swap with the other copy of the number
  :W     store it in W (for next iteration)
  @#     bring the count to the top, and raise the number to that power
  *      multiply with the sign
:+       add all the results together

7

JavaScript(ES6),54

p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

eval 接收以逗号分隔的表达式列表,并返回最后一个表达式的值。

测试

f=p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

t=p=>(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

function Test() {
  var a=I.value.match(/\d+/g).map(x=>+x) // convert input to a numeric array
  
  var x=f(a),y=t(a)
  O.textContent='Value '+x+'\n(no eval '+y+')'
}  

Test()
#I { width:80%}
<input value='12, 0, 7, 7, 29, 10, 2, 2, 1' id=I>
<button onclick='Test()'>Test</button>
<pre id=O></pre>


4
这是对逗号运算符的最严重滥用,我记得在此站点上看到过……
Neil,

5

朱莉娅76 57字节

!x=[[" ""-*+"[2+sign(diff(x))]...] x]'|>join|>parse|>eval

我第一次打高尔夫球朱莉娅,所以也许有明显的进步。 在线尝试!

丹尼斯节省了很多字节。


不错的工作。我没有意识到您可以为定义自定义函数!
Rɪᴋᴇʀ

@EᴛᴇʀʟʏsIcodegolf.stackexchange.com/ a
Dennis,


3

R,92个字节

这里仍然可能有一些不错的高尔夫运动。

eval(parse(t=paste(i<-scan(),c(ifelse(d<-diff(i),ifelse(d>0,"+","-"),"*"),""),collapse="")))

取消高尔夫:

i = scan()                # Read list from stdin
d = diff(i)               # Calculate difference between each element of list
s = ifelse(d,             # If d!=0
             ifelse(d>0,  # And if d>1
                    "+",  # Return plus
                    "-"), # Else return minus
             "*")         # Else (i.e. d==0) return multiply.
s = c(s,"")               # Pad the list s with an empty string, so it's the same
                          # length as i
p = paste(i,s,collapse="")# Paste the elements of i and s into one long string.
eval(parse(t=p))          # Evaluate the string as a language object.

我使用索引方法
JayCe


2

TI-BASIC,146字节

如果不在手机上,我会很好地格式化它。睡眠使我逃脱,所以你明白了。请享用。

Prompt L₁
"(→Str1
For(A,1,dim(L₁
{0,1→L₂
{0,L₁(A→L₃
LinReg(ax+b) L₁,L₃,Y₁
Equ►String(Y₁,Str2
sub(Str2,1,-1+inString(Str2,"X→Str2
If A>1
Then
L₁(A-1
2+(Ans>L₁(A))-(Ans<L₁(A
Str1+sub("+*-",Ans,1→Str1
End
Str1+Str2→Str2
End
expr(Str1

2

的Javascript ES6,64 62个字符

a=>eval(a.map((x,i)=>x+('*+-'[x<a[++i]|(x>a[i])*2])).join``+1)

3
这不应该是函数和a参数吗?
edc65

这是无效的。
Rɪᴋᴇʀ

@ edc65,是的,应该。但是实际上它已经计算在内(指定了61个,但实际代码长度为59个),我只是严重复制了一个新代码(编辑应a[i+1]...a[i+1]== a[++i]...a[i]-缩短2个字符,但我错误地替换了掉落的整个代码a=>)。
Qwertiy

@EᴀsᴛᴇʀʟʏIʀᴋ,这只是一个错误的粘贴。请参阅上面的评论并编辑历史记录以获取更多详细信息。
Qwertiy

@Qwertiy好的,很酷。尼斯回答顺便说一句..
Rɪᴋᴇʀ

1

Java,384个字节

int s(int[]l){int n=l[0],m;for(int i=0;i<l.length-1;i++)if(l[i]<l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;}else if(l[i]>l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n-=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n-=m;}else{m=l[i];while(i<l.length-1&&l[i]==l[i+1])m*=l[i++];n+=m;}return n;}

取消高尔夫 在线尝试

int s(int[] l)
{
    int n=l[0], m;

    for(int i=0; i<l.length-1; i++)
    {
        if(l[i] < l[i+1])
        {
            if (i<l.length-2 && l[i+1]!=l[i+2])
            {
                n += l[i+1];
            }
            else
            {
                m = l[i+1];
                while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
                n += m;
            }
        }
        else if(l[i] > l[i+1])
        {
            if (i<l.length-2 && l[i+1]!=l[i+2])
            {
                n -= l[i+1];
            }
            else
            {
                m = l[i+1];
                while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
                n -= m;
            }
        }
        else
        {
            m = l[i];
            while(i<l.length-1 && l[i]==l[i+1]) m *= l[i++];
            n += m;
        }
    }

    return n;
}

1
一些快速的高尔夫球:int a=l.length&&=> &和放在int i=0同一行上int n=l[0],m
Leaky Nun

在中if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;,您可以将其替换为else块内的内容。
Leaky Nun

1

Javascript ES6,79个字符

a=>eval(`${a}`.replace(/(\d+),(?=(\d+))/g,(m,a,b)=>a+('*+-'[+a<+b|(+a>+b)*2])))

1

Perl,49个字节

48个字节的代码+ 1个 -p

s/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval

用法

perl -pe 's/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval' <<< '12 0 7 7 29 10 2 2 1'
75

笔记

我在这里了解到,尽管有点不直观((?=(\d+))而不是((?=\d+))),但您可以在PCRE中取得先机。读完后确实有道理,因为您将捕获与后者的零长度匹配(超前),而与前者捕获零匹配)。

感谢@ninjalj节省了8个字节!


@LeakyNun我永远不知道该算什么,我找不到相关的元文章,我很高兴能增加这个数,但是我认为既然您可以-e免费运行,那么p将其添加-pe为+1 ?现在会更新,但是如果您能找到我可以引用/链接的来源,那就太好了!
Dom Hastings

3
@DomHastings 1是正确的,根据您说+ 这个meta post
Sp3000

谢谢@ Sp3000!我找不到我终身的职位!根据Sp3000的评论,@ LeakyNun meta帖子为+1
Dom Hastings

代替使用链式条件运算符,您可以使用太空飞船运算符从列表中进行选择:$&.qw(* - +)[$&<=>$1]s///运算符的替换部分。
ninjalj

@ninjalj当然!太好了,谢谢!-8!
Dom Hastings

1

其实是30个位元组

;2@VpXdX`i-su"+*-"E`M' @o♀+εj≡

不幸的是,由于eval()命令仅计算TIO上的文字,因此该程序不适用于TIO。

说明:

;2@VpXdX`i-su"+*-"E`M' @o♀+εj≡
;                               duplicate input
 2@V                            overlapping sublists of length <= 2
    pXdX                        discard first and last element (length-1 sublists)
        `i-su"+*-"E`M           map: for each pair of elements
         i-su                     flatten, subtract, sign, increment (results in a 0 if b < a, 1 if b == a, and 2 if b > a)
             "+*-"E               select the correct operation
                     ' @o       put a space at the beginning of the list to pad it properly
                         ♀+     pairwise addition (since addition is not defined for strings and integers, this just zips the lists and flattens the result into a single flat list)
                           εj   join with empty string
                             ≡  eval

1

R120 44字节

r=rle(scan());c(1,sign(diff(r$v)))%*%r$v^r$l

在线尝试!

该算法类似于该答案的,但是我只有在对答案进行编码后才意识到它。比我原来使用的答案好得多eval(parse)

充分利用R的向量化运算- *首先使用rle(x)$values ^ rle(x)$lenghts该向量进行运算,并对该向量进行点积运算sign( diff( rle(x)$values ) )(以开头1)。


1

05AB1E(旧版)17 16 15 字节

ü.S…*-+sè‚ζJJ.E

-2个字节,感谢@Emigna

在线尝试验证所有测试用例

说明:

ü                  # Pair-wise loop over the (implicit) input-list
                   #  i.e. [12,0,7,7] → [[12,0],[0,7],[7,7]]
 .S                # Calculate the signum of the pair (-1 for a<b; 0 for a==b; 1 for a>b)
                   #  i.e. [[12,0],[0,7],[7,7]] → [1,-1,0]
   …*-+sè          # Index over "*-+" (with wrap-around)
                   #  i.e. [1,-1,0] → ['-','+','*']
         ‚ζ        # Zip the two lists together (appending the operands to the numbers)
                   #  i.e. [12,0,7,7] and ['-','+','*','+']
                   #   → [[12,'-'],[0,'+'],[7,'*'],[7,' ']]
           JJ      # Join them together
                   #  [[12,'-'],[0,'+'],[7,'*'],[7,' ']] → '12-0+7*7 '
             .E    # Evaluate as Python code
                   #  i.e. '12-0+7*7' → 61

1
由于采用了模块化索引,因此可以>移至+字符串的末尾进行删除。
Emigna '18

@Emigna不确定我怎么想的..谢谢!
凯文·克鲁伊森

1
您可以通过删除Ć和来保存另一个字节(¨如果使用的话),‚ζ而不是ø
Emigna'Aug

@Emigna哦,这很聪明!谢谢。我知道外壳有点怪异的解决方法,但不知道如何解决。‚ζ是完美的替代解决方法,因为在评估中忽略了空间。再次感谢。:)
Kevin Cruijssen

0

PHP,103字节

整洁的挑战。这比预期的时间更长。我认为使用array_map或类似方法不会提高字节数,因为匿名函数在PHP 中仍然很昂贵。

foreach(fgetcsv(STDIN)as$v)(0<=$p?$o.=$p.('*-+'[($p>$v)+2*($p<$v)]):_)&&$p=$v;echo eval("return$o$v;");

从命令行运行,将提示输入逗号分隔的列表,例如:

php array_to_math.php
12, 0, 7, 7, 29, 10, 2, 2, 1

0

PowerShell v2 +,62个字节

-join($args|%{"$o"+'*+-'[($o-lt$_)+2*($o-gt$_)];$o=$_})+$o|iex

将输入作为空格分隔的命令行参数,将其转换为自动array $args。我们遍历每个元素,$o每次迭代都使用helper变量来记住上一个条目。我们使用一个索引串拉出相应的操作员,通过对隐式转换的布尔值进行数学运算(例如,如果先前的条目是小,做[]计算结果为1+2*0使'*+-'[1]手段+选择了)。

串联的字符串留在管道上。我们收集所有这些片断在一起(例如3-1+4-等)与-join操作,串连最终数量(隐式转换为字符串),和管道它iex(别名Invoke-Expression和类似eval)。


值得关注的是,如果调用者已经给定了$ oa的值(例如$ o = 999),则该条目中的表达式将无法计算出正确的值。$ o的初始化需要添加到该解决方案中。
2016年

@Bevo这是一个完整的脚本,可以通过命令行执行,而不是通过函数或交互式Shell执行。我提交的绝大多数内容都是这样,因为在这种情况下,无需担心任何预定义的变量,因此代码可能会短一些。
AdmBorkBork


0

Japt -x21 19字节

änJ f mÎí*Uò¦ ®ÎpZÊ

试试吧


说明

                        :Implicit input of array U
  J                     :Prepend -1
än                      :Get deltas
    f                   :Filter (remove 0s)
      m                 :Map
       Î                : Signs
        í               :Interleave
          U             :  Original input
           ò            :  Partition on
            ¦           :   Inequality
              ®         :  Map each sub-array Z
               Î        :    Get first element
                p       :    Raise to the power of
                 ZÊ     :     Length of Z
         *              :Reduce each pair of elements by multiplcation
                        :Implicitly reduce by addition and output
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.