Tạo số Friedman


9

Một số Friedman là một con số có thể được thể hiện bằng cách áp dụng các phép toán cơ bản (^, /, *, +, -) cho tất cả các chữ số của nó. Các hoạt động không cần phải được áp dụng cho từng chữ số riêng lẻ, nhưng tất cả các chữ số phải được tham gia. Nghĩa là, 121 = 11 ^ 2 -> tất cả các chữ số đều có liên quan, nhưng 1 & 1 đã được ghép lại với nhau để tạo thành 11.

Sử dụng dấu ngoặc đơn được cho phép, nhưng giải pháp tầm thường x= (x)không phải là giải pháp hợp lệ. Cũng không hợp lệ x= +x,.

Ví dụ

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

Viết chương trình sẽ lấy hai số nguyên dương và in số lượng số Friedman trong phạm vi đó (đã bao gồm) và các số có biểu thức trong các dòng tiếp theo.

Đầu vào -

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

Đầu ra -

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

Mã ngắn nhất được đăng vào Chủ nhật ngày 29 tháng 7 00:00 Hrs GMT sẽ là người chiến thắng.


2
Bạn có thể thêm một số ví dụ số Friedman và giải thích cách làm /việc? Ví dụ là 1/3gì?
JPvdMerwe

Số được thể hiện bằng cách áp dụng các thao tác cho tất cả các chữ số của nó. tức là 25 = 5 ^ 2, 126 = 6 * 21, 343 = (3 + 4) ^ 3 và cứ thế
elssar

Bạn có cho phép trừ unary? ví dụ -5?
JPvdMerwe

@JPvdMerwe kiểm tra thông số kỹ thuật đầu vào, bạn sẽ không cần phải làm điều đó, nhưng nếu bạn muốn, hãy tự đánh gục mình. Mặc dù cộng unary không được phép. tức là +5 không phải là một giải pháp hợp lệ
elssar

1
Bạn chưa trả lời câu hỏi của JPvdMerwe về phân chia. Nó phải chính xác chứ? Kết quả trung gian có thể là không tích phân?
Peter Taylor

Câu trả lời:


3

Ruby, 456 438 408 390 370 349 344 334 [đã sửa]

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

Đầu ra:

% 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"}

Ngoài ra, nó hoạt động tương đối nhanh cho số lượng lớn hơn:

% 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
Tôi chạy nó với đầu vào 5 40và nhận được kết quả : [11, "11**1", 21, "21**1", 31, "31**1", 41, "41**1"]. Không có dấu hiệu nào 25trong đó và tôi nghĩ giải pháp phù hợp (ví dụ cho 21) là 2*1, không phải21**1
Cristian Lupascu

@ w0lf Cảm ơn bạn! Tôi nghĩ rằng tôi đã sửa nó.
defhlt

Vâng, nó hoạt động tuyệt vời bây giờ.
Cristian Lupascu

@ w0lf đã thêm rất nhiều ký tự để định dạng đầu ra theo yêu cầu
defhlt

bạn có thể nhận được 2 ký tự bằng cách thay thế '+-*/'.chars.to_a+['','**']bằng["+","-","*","/","","**"]
Cristian Lupascu

4

Python 2.7 - 380 378 372 371 367 363 357 354 352 348 336 ký tự

Chỉ cần một cuộc tìm kiếm vũ phu đơn giản.

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]

Chạy ví dụ:

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)

Giải trình:

s(x) là một hàm lấy một chuỗi chứa một chuỗi các chữ số và trả về tất cả các biểu thức sử dụng các chữ số đó theo thứ tự đó.

[x]['1'>x>'0':] ước tính cho một danh sách chứa x nếu x là '0' hoặc một chuỗi các chữ số không bắt đầu bằng '0'; mặt khác, nó đánh giá một danh sách trống. Về cơ bản, điều này xử lý trường hợp tôi nối tất cả các chữ số lại với nhau.

['(%s%s%s)'%f for i in range(1,len(x))for f in product(s(x[:i]),'*/-+^',s(x[i:]))] về cơ bản phân vùng x thành hai phần (cả hai đều có độ dài khác không), gọi s () trên mỗi phần và nối tất cả các kết quả cùng với một số toán tử giữa chúng, bằng cách sử dụng sản phẩm ().

E(e) về cơ bản là một eval an toàn. Nó trả về giá trị của e nếu e hợp lệ và Không có gì khác.

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}

Về cơ bản, mã này thử tất cả các số trong phạm vi, hoán vị các chữ số của chúng và kiểm tra từng biểu thức s () tạo ra hoán vị đó, bỏ qua biểu thức đầu tiên nếu x không bắt đầu bằng '0', vì nếu x không bắt đầu bằng ' 0 'thì biểu thức đầu tiên sẽ chỉ là x.

Phiên bản thay thế - 397 ký tự

Đây là mã của tôi nếu bạn được yêu cầu sử dụng phân số:

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","")

Tôi không nghĩ if len(x)<2sẽ bao giờ đúng trong chức năng s. Ngoài ra, bạn có thể thay thế formatbằng "a[Fraction(%s)%s%s]='(%s%s%s)'"%(x[:i],o,v,x[:i],o,A)để lưu 4 ký tự.
beary605

@ beary605: Đôi khi đúng, khi i = len (x) -1, thì cuộc gọi tiếp theo sẽ nhận được một char duy nhất. Về điểm thứ hai, cảm ơn! :)
JPvdMerwe

huh ... except:0thông minh .. rất thông minh. Tôi sẽ nhớ
Ev_genus

Vui lòng bao gồm một số đầu ra minh họa.
DavidC

1
Không, vẫn chạy. Tôi phải di chuyển PC của mình bây giờ, nhưng tôi sẽ để nó chạy trong vài ngày và xem nó đã hoàn thành chưa.
JPvdMerwe

3

Python3 (436) (434) (443)

Nó thật khó. Tôi có thể phụ tùng một số ký tự nếu tôi tạo đầu ra nhiều hơn.

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)

Đầu ra

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
Vì vậy, bạn có rất nhiều thủ thuật thông minh; tuy nhiên, tôi nên đề cập rằng bạn không xử lý chính xác 1 đến 9 và đầu vào của bạn không bao gồm. Bạn có thể loại bỏ 2 chars dù bằng cách loại bỏ các khoảng trắng sau "("+i+c+j+")"và thay thế len(n)>1bởi 1<len(n)sau đó bạn có thể loại bỏ các không gian sau khi biểu hiện đó.
JPvdMerwe

Hội chợ. Đã sửa tất cả, +7 ký tự
Ev_genus

Bạn có thể thay thế dòng cuối cùng bằng cách for j in r:print(r[j],j)lưu 7 ký tự.
JPvdMerwe

1

Mathematica 456 416 402 404 400 396 chars

<< 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í dụ :

v[1,300]//TableForm

Đầu ra :

đầu ra Friedman

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.