代码高尔夫:三个整数的所有+-*/组合

31

编写一个程序,接受由空格分隔的3个整数,并对所有可能的加法、减法、乘法和除法操作执行每个组合,显示使用的操作组合及其结果。

示例:

$./solution 1 2 3

输出如下:

1+2+3 = 6

1-2-3 = -4

1*2*3 = 6

1/2/3 = 0(只显示整数答案,.5及以上四舍五入)

1*2-3 = -1

3*1+2 = 5

等等...

按照操作顺序规则执行,假设不会使用括号,例如(3-1)*2=4不算作一种组合,但您可以为“额外积分”实现此操作。

对于出现除以0的结果,请返回NaN。

编辑:需要对输入进行排列,即如果输入为1 2 3,则3*1*2是一种有效的组合。


5
@Flash:请遵循http://meta.stackexchange.com/questions/24242/acceptable-level-of-code-golf-questions/24258#24258中描述的规范。 - kennytm
并不是非常清楚重新排列输入数字也是必要的。澄清这一点可能会有所帮助。 - David
1
我不确定,但这难道不有点不公平吗?因为它在大多数解释型语言中都可以极大地受益于内置的 eval() 函数。 - Alexander Gessler
1
@Alexander:这个C语言示例表明,预处理器可以被滥用来进行eval操作。 - SztupY
@Alexander,@SztupY:Java 的邪恶性质也可以被滥用。真的! - Pindatjuh
我最近也遇到了这个问题,用C#写了一个非eval方法。不过使用eval会更容易些。 - Matt Mitchell
17个回答

2

Perl - 76 characters

$a=1;$b=2;$c=3;
warn eval for map{$x=$_;map"$a$x$b$_$c",@a}@a=split//,'+-/*';

干得好。现在如何处理0.5的四舍五入和格式化打印呢? - Zaid
而不是硬编码输入。(我认为需要2个字符的成本。) - walkytalky
使用四舍五入和用户输入,85:($a,$b,$c)=@ARGV;map{$x=$;map printf("%.0f\n",eval"$a$x$b$$c"),@a}@a=split//,"+-/*" - aidan
它如何对输入进行排列? - SztupY
首先要打印字符串表达式。此外,这不会对数字进行排列,而规范要求这样做。 - walkytalky

2

Lua - 240个字符

注意:打印1.#INF和-1.#INF而不是NaN。

a,b,c=...o="+-*/"f=function(...)g=table.concat({...})loadstring('x='..g)()print(g..' = '..math.floor(x+.5))end for d in o:gmatch(".")do for e in o:gmatch(".")do f(a,d,b,e,c)f(a,d,c,e,b)f(b,d,a,e,c)f(b,d,c,e,a)f(c,d,a,e,b)f(c,d,b,e,a)end end

输出

5+0+13 = 18
5+13+0 = 18
0+5+13 = 18
0+13+5 = 18
13+5+0 = 18
13+0+5 = 18
5+0-13 = -8
5+13-0 = 18
0+5-13 = -8
0+13-5 = 8
13+5-0 = 18
13+0-5 = 8
5+0*13 = 5
5+13*0 = 5
0+5*13 = 65
0+13*5 = 65
13+5*0 = 13
13+0*5 = 13
5+0/13 = 5
5+13/0 = 1.#INF
0+5/13 = 0
0+13/5 = 3
13+5/0 = 1.#INF
13+0/5 = 13
5-0+13 = 18
5-13+0 = -8
0-5+13 = 8
0-13+5 = -8
13-5+0 = 8
13-0+5 = 18
5-0-13 = -8
5-13-0 = -8
0-5-13 = -18
0-13-5 = -18
13-5-0 = 8
13-0-5 = 8
5-0*13 = 5
5-13*0 = 5
0-5*13 = -65
0-13*5 = -65
13-5*0 = 13
13-0*5 = 13
5-0/13 = 5
5-13/0 = -1.#INF
0-5/13 = 0
0-13/5 = -3
13-5/0 = -1.#INF
13-0/5 = 13
5*0+13 = 13
5*13+0 = 65
0*5+13 = 13
0*13+5 = 5
13*5+0 = 65
13*0+5 = 5
5*0-13 = -13
5*13-0 = 65
0*5-13 = -13
0*13-5 = -5
13*5-0 = 65
13*0-5 = -5
5*0*13 = 0
5*13*0 = 0
0*5*13 = 0
0*13*5 = 0
13*5*0 = 0
13*0*5 = 0
5*0/13 = 0
5*13/0 = 1.#INF
0*5/13 = 0
0*13/5 = 0
13*5/0 = 1.#INF
13*0/5 = 0
5/0+13 = 1.#INF
5/13+0 = 0
0/5+13 = 13
0/13+5 = 5
13/5+0 = 3
13/0+5 = 1.#INF
5/0-13 = 1.#INF
5/13-0 = 0
0/5-13 = -13
0/13-5 = -5
13/5-0 = 3
13/0-5 = 1.#INF
5/0*13 = 1.#INF
5/13*0 = 0
0/5*13 = 0
0/13*5 = 0
13/5*0 = 0
13/0*5 = 1.#INF
5/0/13 = 1.#INF
5/13/0 = 1.#INF
0/5/13 = 0
0/13/5 = 0
13/5/0 = 1.#INF
13/0/5 = 1.#INF

2

好的,虽然有点长,但我还是会发布它,只是为了好玩...

请注意,与大多数其他答案不同,此答案不使用eval,因为在C#中不可用(如果使用eval将更短)

C#,729个字符

using System;using System.Linq;using w=System.Double;class Op{public char c;public int p;public Func<w,w,w>f;}class Program{static void Main(string[]p){var nb=p.Select((n,i)=>new{n=w.Parse(n),i});var op=new[]{new Op{c='+',p=0,f=(a,b)=>a+b},new Op{c='-',p=0,f=(a,b)=>a-b},new Op{c='*',p=1,f=(a,b)=>a*b},new Op{c='/',p=1,f=(a,b)=>a/b},};Func<Op,Op,Func<w,w,w,w>>fg=(o1,o2)=>(x,y,z)=>o1.p>=o2.p?o2.f(o1.f(x,y),z):o1.f(x,o2.f(y,z));Func<w,w>nan=d=>w.IsInfinity(d)?w.NaN:d;var res=from o1 in op from o2 in op from x in nb from y in nb where x.i!=y.i from z in nb where z.i!=x.i&&z.i!=y.i let r=nan(fg(o1,o2)(x.n,y.n,z.n))select string.Format("{0}{1}{2}{3}{4}={5:F0}",x.n,o1.c,y.n,o2.c,z.n,r);res.ToList().ForEach(Console.WriteLine);}}

扩展版本

using System;
using System.Linq;
using w=System.Double;

// Operator class
// c = character
// p = priority
// f = function
class Op { public char c; public int p; public Func<w, w, w> f; }
class Program
{
    static void Main(string[] args)
    {
        // Parse the input and associate each number with its index
        var nb = args.Select((n, i) => new { n = w.Parse(n), i });

        // Operators definition
        var op = new[]
        {
            new Op { c = '+', p = 0, f = (a, b) => a + b },
            new Op { c = '-', p = 0, f = (a, b) => a - b },
            new Op { c = '*', p = 1, f = (a, b) => a * b },
            new Op { c = '/', p = 1, f = (a, b) => a / b },
        };

        // Function generator to compute the result ; handles operator priority
        Func<Op, Op, Func<w, w, w, w>> fg =
            (o1, o2) =>
                (x, y, z) =>
                    o1.p >= o2.p
                        ? o2.f(o1.f(x, y), z)
                        : o1.f(x, o2.f(y, z));

        // Converts +/- Infinity to NaN
        Func<w, w> nan = d => w.IsInfinity(d) ? w.NaN : d;

        // Results
        var res =
            // Combinations of 2 operators
            from o1 in op
            from o2 in op
            // Permutations of numbers
            from x in nb
            from y in nb
            where x.i != y.i
            from z in nb
            where z.i != x.i && z.i != y.i
            // Compute result
            let r = nan(fg(o1, o2)(x.n, y.n, z.n))
            // Format output
            select string.Format("{0} {1} {2} {3} {4} = {5:F0}", x.n, o1.c, y.n, o2.c, z.n, r);

        res.ToList().ForEach(Console.WriteLine);
    }
}

谁说C#不能进行函数式编程? ;)


编辑:修复了可以使用重复数字的问题


@Dykam:已修复。但没有测试过。 - Mauricio Scheffer
能否去掉 Func<w,w,w> f 中的空格?这样它的长度就和 Java 一样了 ;) - kennytm
@Mauricio Scheffer,感谢您的修复。我在LinqPad中进行了测试,因此省略了通常的程序结构...关于您的第二条评论,您可以添加更多的'+'符号;)。@KennyTM,是的,这是可能的,我已经移除了它。谢谢! - Thomas Levesque
您的解决方案不支持输入中相同的数字:“1 2 2”。 - stacker
@stacker,确实,我错过了那个情况...现在已经修复了。 - Thomas Levesque

2

F#: 280个字符,包括换行符

不易读的版本:

let q s=System.Data.DataTable().Compute(s,"")|>string|>float
let e(a,b,c)=let o=["+";"-";"*";"/"]in for x in o do for y in o do let s=a+x+b+y+c in printfn"%s=%.0f"s (q s)
[<EntryPoint>]let p(A:_[])=(for i=0 to 2 do let p,q,r=A.[i],A.[(i+1)%3],A.[(i+2)%3]in e(p,q,r);e(p,r,q));0

简而言之:
//This program needs to be compiled as a console project
//It needs additional references to System.Data and System.Xml

//This function evaluates a string expression to a float
//It (ab)uses the Compute method of System.Data.DataTable which acts 
//as .Net's own little eval()
let q s =
    //the answer is an object
    System.Data.DataTable().Compute(s,"")
    //so convert it to a string and then parse it as a float
    |> string
    |> float

//This function first generates all 6 permutations of a 3-tuple of strings
//and then inserts all operator combination between the entries
//Finally it prints the expression and its evaluated result
let e (a,b,c) =
    let o = ["+";"-";"*";"/"] 
    //a double loop to get all operator combos
    for x in o 
        do for y in o do 
            let s=a+x+b+y+c //z is expression to evaluate
            //print the result as expression = result, 
            //the %.0f formatter takes care of rounding
            printfn "%s=%.0f" s (q s)

//This is the entry point definition. 
//A is the array of command line args as strings.
[<EntryPoint>]
let p(A:_[]) = 
    //Generate all permutations: 
    //for each index i: 
    //  put the i-th element at the front and add the two remaining elements
    //  once in original order and once swapped. Voila: 6 permutations.
    for i=0 to 2 do 
        let p,q,r = A.[i], A.[(i+1)%3], A.[(i+2)%3] 
        e(p,q,r) //evaluate and print "p + <op> + q + <another op> + r"
        e(p,r,q) //evaluate and print "p + <op> + r + <another op> + q"
    0 //the execution of the program apparently needs to return an integer

示例输出:

> ConsoleApplication1 1 2 0
1+2+0=3
1+2-0=3
1+2*0=1
1+2/0=Infinity
1-2+0=-1
1-2-0=-1
1-2*0=1
1-2/0=-Infinity
1*2+0=2
1*2-0=2
1*2*0=0
1*2/0=Infinity
1/2+0=1
1/2-0=1
1/2*0=0
1/2/0=Infinity
1+0+2=3
1+0-2=-1
1+0*2=1
1+0/2=1
...

1

Ruby

(从参数列表中读取并在不可被整除时返回NaN)

(如果Ruby有一个排列库,那么这将是最后一行)

class Array
  def perm(n = size)
    if size < n or n < 0
    elsif n == 0
      yield([])
    else
      self[1..-1].perm(n - 1) do |x|
        (0...n).each do |i|
          yield(x[0...i] + [first] + x[i..-1])
        end
      end
      self[1..-1].perm(n) do |x|
        yield(x)
      end
    end
  end
end

ARGV.perm(3){|a,b,c| "++//**--".split(//).perm(2){ |d,e| x=a+d+b+e+c;puts "#{x} = #{eval(x)}" rescue puts "#{x} = NaN"} }

1

Python(171个字符)

这避免了以前Python解决方案的缺陷(仅支持硬编码1位数字,依赖于更新的库)。从stdin读取 - 如果您想要命令行,请将“raw_input().split()”替换为“sys.argv[1:4]”

x=raw_input().split()
for e in[x[i/3]+p+x[i%3]+'.'+q+x[3-i/3-i%3]for i in range(9)if i%4for p in'+-*/'for q in'+-*/']:
    try:r=round(eval(e))
    except:r='NaN'
    print e,'=',r

附注:从147减少到138
附注2:更改计算方式,从整数变为浮点数并进行四舍五入,从138增加到153
附注3:添加/0=NaN的支持,从153增加到179
附注4:从179减少到177
附注5:为简洁而牺牲美观,从177减少到171


Python中的<>运算符是什么? - kennytm
是的,在Python中,<>和!=意思相同,都表示“不等于”。 "!="类似于C语言,并且在Java、Perl等编程语言中也使用。"<>"类似于Basic语言,并且在Pascal、SQL、*ML等编程语言中也使用。 - Nas Banov
现在它可以处理/0的情况了,并且会正确地四舍五入。此外,它不使用一些新奇的库函数:-D - Nas Banov

0

F#,584字节

(包括必要的缩进和换行符)

let d a b=if b=0.0 then nan else a/b
let o=["*",((*),1);"+",((+),0);"/",(d,1);"-",((-),0)]
let b=double
let rec z=function|[x]->[x,[]]|x::s->(x,s)::List.map(fun(y,l)->y,x::l)(z s)
let rec p=function|[]->[[]]|l->z l|>List.collect(fun(x,r)->p r|>List.map(fun l->x::l))
let f=fst
let e o p x y z=if snd o<snd p then (f o)x ((f p) y z) else (f p)((f o) x y)z
[<EntryPoint>]let m a=
for i in p(Seq.toList a)do
 let x,y,z=b i.[0],b i.[1],b i.[2]
 for j in[for j in o do for k in o do yield[j;k]]do
  printfn "%.0f%s%.0f%s%.0f = %.0f" x (f j.[0])y (f j.[1])z (e(snd j.[0])(snd j.[1])x y z)
0

kvb致敬,感谢他/她的排列函数

它的结构与Thomas的C#解决方案非常相似(也许是因为他的解决方案已经非常实用了)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接