生成弗里德曼数


9

弗里德曼数是可以通过基本的数学运算(^,/,*,+, - )来表示一个数字,它的所有的数字。无需将操作应用于每个数字,但必须包含所有数字。也就是说,121 = 11 ^ 2->包含所有数字,但是1和1被组合在一起成为11。

允许使用括号,但平凡的解决方案x= (x)不是有效的解决方案。也无效x= +x

例子

  • 25 = 5 ^ 2
  • 121 = 11 ^ 2
  • 343 =(3 + 4)^ 3
  • 2048 =(8 ^ 4)/ 2 + 0

编写一个程序,该程序将使用两个正整数,并在该范围(含)范围内打印弗里德曼数字的数量,并在随后的行中打印带有表达式的数字。

输入-

n m    | n, m integers, n>=0, m>n

输出-

count    | number of Friedman numbers in the given range
fn1 exp1 | Friedman number, expression
fn2 exp2
fn3 exp3
.
.
.

7月29日(星期日)格林尼治标准时间00:00点之前发布的最短代码将成为赢家。


2
您可以添加一些弗里德曼数示例并解释其/工作原理吗?例如什么1/3
JPvdMerwe

通过将运算应用于所有数字来表示该数字。即25 = 5 ^
2、126

你允许一元减吗?例如-5
JPvdMerwe

@JPvdMerwe检查输入规范,您不需要这样做,但是如果您愿意,可以将自己淘汰。虽然一元加号是不允许的。即+5不是有效的解决方案
elssar

1
您尚未回答JPvdMerwe有关分裂的问题。一定要准确吗?中间结果可以是非整数吗?
彼得·泰勒

Answers:


3

Ruby,456 438 408 390 370 349 344 334 [已固定]

g={}
f=->a,b{a.permutation(b).to_a.uniq.flatten.each_slice b}
F,T=$*
([F.to_i,10].max..T.to_i).map{|c|f[a="#{c}".split(''),v=a.size].map{|m|f[[?+,?-,?*,?/,'','**'],v-1].map{|w|(d=(s=m.zip(w)*'').size)==v&&next
0.upto(d){|y|y.upto(d+1){|u|begin(r=eval t="#{s}".insert(y,?().insert(u,?)))==c&&g[r]=t
rescue Exception
end}}}}}
p g.size,g

输出:

% ruby ./friedman-numbers.rb 1 300
9
{25=>"(5)**2", 121=>"(11)**2", 125=>"5**(2+1)", 126=>"(6)*21", 127=>"(2)**7-1", 128=>"2**(8-1)", 153=>"(3)*51", 216=>"6**(1+2)", 289=>"(9+8)**2"}

对于较大的数量,它也相对较快地工作:

% time ruby friedman-numbers.rb 3863 3864   
1
{3864=>"(6**4-8)*3"}
ruby friedman-numbers.rb 3863 3864  14.05s user 0.17s system 99% cpu 14.224 total

1
我使用输入来运行它,5 40并得到了结果:[11, "11**1", 21, "21**1", 31, "31**1", 41, "41**1"]。没有迹象25在那里,我认为正确的解决方案(例如用于21)是2*1,不是21**1
克里斯蒂安Lupascu

@ w0lf谢谢!我想我已经解决了。
2012年

是的,现在效果很好。
克里斯蒂安·卢帕斯库

@ w0lf根据需要添加了许多字符以格式化输出
defhlt 2012年

您可以通过替换'+-*/'.chars.to_a+['','**']为获得2个字符["+","-","*","/","","**"]
Cristian Lupascu 2012年

4

蟒2.7 - 380 378 372 371 367 363 357 354 352 348 336个字符

只是一个简单的蛮力搜索。

from itertools import*
s=lambda x:[x]['1'>x>'0':]+['(%s%s%s)'%f for i in range(1,len(x))for f in product(s(x[:i]),'*/-+^',s(x[i:]))]
def E(e):
 try:return eval(e.replace("^","**"))
 except:0
A={i:e for i in range(input(),input()+1)for x in permutations(`i`)for e in s("".join(x))[x>='1':]if E(e)==i}
print len(A)
for v in A:print v,A[v]

示例运行:

1
300
9
128 (2^(8-1))
289 ((9+8)^2)
216 (6^(1+2))
121 (11^2)
153 (3*51)
25 (5^2)
125 (5^(2+1))
126 (6*21)
127 ((2^7)-1)

说明:

s(x) 是一个函数,它接收包含数字序列的字符串,并按该顺序返回使用这些数字的所有表达式。

[x]['1'>x>'0':] 如果x为'0'或不以'0'开头的数字序列,则求值为包含x的列表;否则,它将评估为空列表。基本上,这可以处理我将所有数字连在一起的情况。

['(%s%s%s)'%f for i in range(1,len(x))for f in product(s(x[:i]),'*/-+^',s(x[i:]))] 基本上将x分为两部分(均为非零长度),在每个部分上调用s(),并使用product()将所有结果与它们之间的某些运算符连接在一起。

E(e) 基本上是安全的评估。如果e有效,则返回e的值,否则返回None。

A={i:e for i in range(input(),input()+1)for x in permutations(`i`)for e in s("".join(x))[x>='1':]if E(e)==i}

基本上,这段代码会尝试该范围内的所有数字,排列其数字并测试s()为该排列生成的每个表达式,如果x的开头不是'0',则忽略第一个表达式,因为如果x的开头不是' 0',那么第一个表达式就是x。

替代版本-397个字符

如果需要使用分数,这是我的代码:

from fractions import*
from itertools import*
s=lambda x:["Fraction(%s)"%x]['1'>x>'0':]+['(%s%s%s)'%f for i in range(1,len(x))for f in product(s(x[:i]),'*/-+^',s(x[i:]))]
def E(e):
 try:return eval(e.replace("^","**"))
 except:0
A={i:e for i in range(input(),input()+1)for x in permutations(`i`)for e in s("".join(x))[x>='1':]if E(e)==i}
print len(A)
for v in A:print v,A[v].replace("Fraction","")

我认为if len(x)<2功能永远不会正确s。另外,您可以替换format"a[Fraction(%s)%s%s]='(%s%s%s)'"%(x[:i],o,v,x[:i],o,A)以保存4个字符。
beary605

@ beary605:的确有时,当i = len(x)-1时,下一个调用将得到一个字符。至于第二点,谢谢!:)
JPvdMerwe 2012年

嗯... except:0聪明..非常聪明。我会记得
Ev_genus 2012年

请提供一些说明性输出。
DavidC 2012年

1
不,仍在运行。我现在必须移动PC,但是我将让它运行几天,看看它是否完成。
JPvdMerwe 2012年

3

Python3 (436) (434)(443)

那个挺难。如果我使输出更加本地化,​​则可以保留一些字符。

from itertools import*
r={};k=product;m=map
q=lambda n,h=1:["("+i+c+j+")"for(i,j),c in k(chain(*[k(*m(q,f))for f in sum(([(x[:q],x[q:])for q in range(1,len(x))]for x in m("".join,permutations(n))),[])]),list("+-*/^")+[""]*h)]if 1<len(n)else[n]*h
a,b=m(int,m(input,"nm"))
for i,j in chain(*[k(q(str(n),0),[n])for n in range(a,b+1)]):
    try:exec("if eval(%r)==j:r[j]=i"%i.replace("^","**"))
    except:0
print(len(r))
for j,i in r.items():print(i,j)

输出量

n100
m200
6
(2^(8-1)) 128
(3*(51)) 153
((11)^2) 121
(5^(1+2)) 125
(6*(21)) 126
((2^7)-1) 127

1
所以你有很多聪明的把戏;但是,我应该提一下,您不能正确处理1到9,并且您的输入内容不包括在内。您可以删除2个字符,但是可以通过删除后面的空格"("+i+c+j+")"然后替换len(n)>11<len(n)之后的字符来删除该表达式之后的空格。
JPvdMerwe

公平。固定了所有+7个字符
Ev_genus 2012年

您可以将最后一行替换为for j in r:print(r[j],j)以节省7个字符。
JPvdMerwe

1

数学456 416 402 404 400 396个字符

<< Combinatorica`; l = Length; p = Permutations; f = Flatten; c = Cases;
u[d_, o_, s_] := 
 Fold[#2[[1]] @@ If[s == 1, {#1, #2[[-1]]}, {#2[[-1]], #1}] &, 
 d[[1]], Thread@{o, Rest@d}];
q[t_, r_] := {u[t, #, r], u[HoldForm /@ t, #, r]} & /@ 
p[{Plus, Subtract, Times, Divide, Power}, {l@t - 1}];
v[m_, n_] := (t = Table[Union@
  c[f[{#~q~1, #~q~0} & /@ 
     f[p /@ c[
        FromDigits /@ # & /@ 
         f[SetPartitions /@ p@IntegerDigits@j, 1], x_ /; l@x > 1],
       1], 2], {j, _}], {j, m, n}]~f~1; {l@t}~Join~t)

范例

v[1,300]//TableForm

输出

弗里德曼输出

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.