最小运营至100


15

总览

给定一个数字列表,找到最少的运算使100

输入值

一串数字,可以是数字顺序,也可以不是数字顺序。数字的顺序不能更改,但是可以在每个数字之间加上加号(+)或减号(-),以便总和等于100。

输出量

添加的运算符数量,其后是数字和运算符的完整序列。两者可以用空格,制表符或换行符分隔。

例子

有效

输入:123456789
输出:3 123–45–67+89

无效的
输入:123456789
输出:(
6 1+2+34-5+67-8+9
有一些方法可以减少操作次数)



我们必须使用所有数字吗?我们只能使用+-吗?我们可以假设我们始终可以100从输入中获得收益吗?
TheLethalCoder

6
一些更多的测试用例将是非常受欢迎的。
Arnauld

2
您能确认符号不能放在第一位吗?也就是说,给定输入299399,将-299+399是有效的吗?
路易斯·门多

1
是“ 0”数字吗?例如,“ 10808”是否为有效输入?“ 1 108-08”是否有效?
Chas Brown

Answers:


10

JavaScript(ES6),153 176字节

编辑:在非严格模式下,JS将0前缀的数字表达式解释为八进制(例如017,解析为十进制的15)。这是支持前导零的固定版本。

let f =

s=>[...Array(3**(l=s.length,l-1))].map((_,n)=>m=eval((x=s.replace(/./g,(c,i)=>c+['','+','-'][o=(n/3**i|0)%3,j-=!o,o],j=l)).replace(/\b0+/g,' '))-100|j>m?m:(S=x,j),m=l)&&m+' '+S

console.log(f("123456789"))
console.log(f("20172117"))


好的,20172117作为输入呢?
mdahmoune

@LuisMendo实际上,我认为预期的答案是2-017-2+117。但是017是JS中的八进制符号,十进制为15。所以我当前的代码只能找到2-0-17-2+117。我将在今天晚些时候尝试解决该问题。
Arnauld

@Arnauld啊,我还没有看到其他解决方案。删除我的评论
路易斯·门多

@mdahmoune感谢您提出来。现在已修复。
Arnauld

3**(l=s.length,l-1)=>3**~-(l=s.length)
l4m2 '18年

5

MATL37 36字节

n'+-'OhZ^!t2\s&SZ)"G@!vXzU100=?@z3M.

测试用例在TIO中大约需要6秒钟。

在线尝试!

怎么运行的

n        % Implicitly input a string. Number of elements, say k
'+-'     % Push this string
Oh       % Append char 0. This is treated like ' ' (space)
Z^       % Cartesian power of the three-char string '+- ' raised to k.
         % Gives a matrix where each row is a Cartesian k-tuple
!        % Transpose
t        % Duplicate
2\       % Modulo 2. This turns '+' and '-' into 1, and ' ' into 0
s        % Sum of each column: number of '+' and '-' symbols
&S       % Sort and push the indices of the sorting
Z)       % Apply as column indices. This sorts the columns (k-tuples)
         % by the number of '+' and '-' they contain
"        % For each column, i.e. each k-tuple formed by '+', '-' and ' '
  G      %   Push input string again
  @!     %   Push k-tuple as row vector (string)
  v      %   Concatenate vertically into a 2×k char array
  Xz     %   Remove space (and char 0). Gives a string as result. In this
         %   process, the 2×k array is linearized in column major order 
         %   (down, then across). So the '+' and '-' signs are between 
         %   digits of the input, or at the end
  U      %   Convert to number. This performs the operation determined by
         %   by the '+' and '-' signs and returns the result. A trailing
         %   '+' or '-' sign makes the input invalid, which causes an
         %   empty result
  100=   %   Is it equal to 100?
  ?      %   If so
    @    %     Push current k-tuple
    z    %     Number of nonzeros, i.e. of '+' and '-' signs
    3M   %     Push linearized string without spaces again
    .    %     Break for loop
         %   Implicit end
         % Implicit end
         % Implicitly dispplay stack

太好了,输入299399怎么样?
mdahmoune

1
@mdahmoune 299399无解,因此是无效的输入(被指定的经营者去数字“之间”,即输入需要-299+399-数字之间不)。
乔纳森·艾伦

@mdahmoune如果只能在数字之间插入符号(如质询文本所述),我认为没有解决办法。如果也可以将它们放在第一位,则解决方法是-299+399,在这种情况下,我需要对代码进行一些小的更改。我问过OP澄清
路易斯Mendo

另外值得注意的是,如果这注定两者之前之间,然后将该例子123456789应该具有的运营商数量4不是3
乔纳森·艾伦

@mdahmoune OP已确认符号只能在数字之间。所以我的代码是正确的,并且299399是无效的输入,因为正如OP也已阐明的那样,每个输入都应至少有一个解决方案
Luis Mendo

3

[Python 2],164158字节

from itertools import*
f=lambda N:min((len(s)-len(N),s)for s in(''.join(sum(zip(N,p+('',)),()))for p in product(('+','-',''),repeat=len(N)-1))if eval(s)==100)

在线尝试!

以N为一串数字;返回一个元组(numOps,expressionString)。

与其他人基本相同的方法;使用itertools.product构造单个“案例”,例如对于N =='1322',则“案例”为('-','','+'),并将评估为“ 1-32 + 2”。

如果输入无效,则会引发ValueError(但我认为OP保证没有无效的输入)。


3

PHP,166个 171字节

for(;$n<3**$e=strlen($x=$argn);eval("return $s;")-100?:$r[]=sprintf("%2d $s",strlen($s)-$e))for($i=0,$s="",$k=$n++;a&$c=$x[$i];$k/=3)$s.="+-"[$i++?$k%3:2].$c;echo min($r);

作为管道运行-nR在线测试

使用格式化的数字对结果进行排序->
可能会打印前导空格(并且可能无法输入超过99位的数字;请增加%2d进行修复)。

不超过10位数字,161个字节

for(;$n<3**$e=strlen($x=$argn);eval("return $s;")-100?:$r[]=(strlen($s)-$e)." $s")for($i=0,$s="",$k=$n++;a&$c=$x[$i];$k/=3)$s.="+-"[$i++?$k%3:2].$c;echo min($r);

分解

for(;$n<3**$e=strlen($x=$argn); # loop $n up
    eval("return $s;")-100?:        # 2. evaluate term, if 100 then
                                    # prepend number of operations, add to results
        $r[]=sprintf("%2d $s",strlen($s)-$e)
)
                                # 1. create term
    for($i=0,$s="",$k=$n++;         # init variables, increment $n
        a&$c=$x[$i];$k/=3)          # loop through digits/operator index
        $s.="+-"[$i++?$k%3:2].$c;   # prepend operator for base-3 digit (nothing for 2)
echo min($r);                   # print lowest result

3

果冻,32 字节

L’⁾+_ṗż@€
ŒṖÇ€ẎµFV=ȷ2µÐfLÞḢFṄḟ³L

使用Jelly运算符(_而不是-)。

注意:-在输出中显示而不是_(不是必需的),请⁾_-yF(之间添加⁾_-一个字符对文字['_','-']y是二元“翻译”原子)。

怎么样?

L’⁾+_ṗż@€ - Link 1, form all sums from a partition: list of lists of characters
                                     e.g. ["12","345","67"]
L         - length                        3
 ’        - decremented                   2
  ⁾+_     - literal ['+','_']
     ṗ    - Cartesian power               ["++","+_","_+","__"]
      ż@€ - zip for €ach (swap @rguments) ["12+345+67","12+345_67","12_345+67","12_345_67"]

ŒṖÇ€ẎµFV=ȷ2µÐfLÞḢFṄḟ³L - Main link: list of characters
ŒṖ                     - all partitions
  Ç€                   - call the last link (1) as a monad for €ach
    Ẏ                  - tighten (flatten by 1 level)
     µ     µÐf         - filter keep if:
      F                -   flatten
       V               -   evaluate as Jelly code (perform the sum)
         ȷ2            -   literal 100
        =              -   equal?
               Þ       - sort by:
              L        -  length
                Ḣ      - head
                 F     - flatten
                  Ṅ    - print that and a newline
                   ḟ³  - filter out the characters from the input
                     L - length (number of operators)
                       - implicit print

在线尝试!


2

Mathematica,136 146 149 156 165 166 个字节

#&@@Sort[{StringLength@#-e+9!(ToExpression@#-100)^2,#}&/@StringJoin/@(Riffle[b,#]&)/@Tuples[{"","+","-"},(e=Length[b=Characters@#])-1]]&

{3, 123-45-67+89}例如返回。

测试用例大约需要0.09秒才能完成。


2

Python 2中256 230 208 205 172 171 170 165字节,迭代方法

  • 33感谢Chas Brown
  • 替换len(a)为一个保存的字节w
  • 替换z-=1;d=z为一个保存的字节d=z=z-1
q=[];a=input()
w=len(a);z=n=3**w
while z-n/3:
 d=z=z-1;j=0;b=''
 while d:r=d%3;d/=3;b+=a[j]+chr(r+43)*(d>0!=r-1);j+=1
 if eval(b)==100:q+=[(len(b)-w,b)]
print min(q)

在线尝试!

小小的解释 使用基数3中的表示形式,代码根据所有可能的组合将数字与运算符{'+','-',concatenation}交错。

Python 2 167字节,递归方法

def f(s):
 if len(s)==1:return[s]
 b=s[0];q=[]
 for z in f(s[1:]):q+=[b+'+'+z,b+'-'+z,b+z]
 return q
a=input()
print min((len(x)-len(a),x)for x in f(a)if eval(x)==100)

在线尝试!

一些输出

"399299"    --> (1, '399-299')
"987654321" --> (4, '98-76+54+3+21')
"1111111"   --> (3, '1+111-1-11')

1
我喜欢使用divmod!我可以看到一些高尔夫球:list(input())用just 代替input(),因为字符串已经可以迭代以节省6个字节;替换b.count('+')+b.count('-')len(b)-len(a)以节省12个字节;并替换chr(r+43)chr(r+43)*(d>0!=r-1),然后您可以删除该行b=b[:-1].replace(',','')以节省净15个字节((d>0!=r-1)等于(d>0 and 0!=r-1))。
Chas Brown

2

Brachylog,36个字节

~cịᵐ{|ṅ}ᵐ{+100&{ℕṫ,"+"↻|ṫ}ᵐcbE&kl;E}

在线尝试!

尽管其中一半以上是正确的输出格式。实际的核心逻辑只是:

15字节

~cịᵐ{|ṅ}ᵐ.+100∧

在线尝试!

这将返回类似[123,–45,–67,89]的列表。表达式是元素的总和,运算符的数量比列表的长度小1。

~cLhℕ∧100~+L几乎可以工作12个字节(请在线尝试!)-但是在TIO上处理完整的9位数输入太慢了,更重要的是,它对于诸如10808-的输入失败-Brachylog太聪明了,无法分割数字以使其具有前导零,所以没有。 t请参阅[108,-08]分区。


1

Haskell中180个 178字节

m#[a]=[[a]]
m#(b:r)|s<-m#r=m(b:)=<<[s,m('+':)s,m('-':)s]
o '-'=(-)
o _=(+)
(p:r)?a|[(b,s)]<-lex r=s?o p a(read b)
_?a=a
g s=minimum[(sum[1|c<-t,c<'0'],t)|t<-map#s,('+':t)?0==100]

在线尝试!用法:g "123456789"产量(3,"123-45-67+89")

#构建所有可能项的列表,?评估一个项并g过滤那些计算结果为100的项,并返回操作数最少的项。


0

果冻,27个字节

L’““+“_”ṗ⁸żF¥ⱮV⁼ȷ2ƊƇLÞḢṄḟ⁸L

在线尝试!

不能说我没有从乔纳森·艾伦的较早答案中得到一些提示。;-)

与他的答案相比,如果由于语言更新而使比较公平,则此长度仅短两个字节(30),而不是五个字节:

L’““+“_”ṗ⁸żF¥Ð€V⁼ȷ2$$ÐfLÞḢṄḟ⁸L

如果我们用另一种方式比较(新版本而不是旧版本),则差异是相同的(他变成29个字节,如下所示):

ŒṖżⱮL’⁾+_ṗƲ$€ẎFV=ȷ2ƲƇLÞḢFṄḟ³L
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.