Hasilkan nomor Friedman

9

Angka Friedman adalah angka yang dapat diekspresikan dengan menerapkan operasi matematika dasar (^, /, *, +, -) untuk semua digit itu. Operasi tidak perlu diterapkan ke setiap digit individu, tetapi semua digit harus dilibatkan. Artinya, 121 = 11 ^ 2 -> semua digit terlibat, tetapi 1 & 1 telah dipukuli bersama untuk menghasilkan 11.

Penggunaan tanda kurung diperbolehkan, tetapi solusi sepele x= (x)bukan solusi yang valid. Juga tidak valid x= +x,.

Contohnya

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

Tulis program yang akan mengambil dua bilangan bulat positif dan mencetak jumlah angka Friedman dalam rentang itu (inklusif), dan angka-angka dengan ekspresi di baris berikutnya.

Memasukkan -

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

Keluaran -

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

Kode terpendek diposting oleh Minggu 29 Juli 00:00 GMT akan menjadi pemenang.

elssar
sumber
2
Bisakah Anda menambahkan beberapa contoh nomor Friedman dan menjelaskan cara /kerjanya? Misalnya apa 1/3?
JPvdMerwe
Angka tersebut dinyatakan dengan menerapkan operasi ke semua digit itu. yaitu 25 = 5 ^ 2, 126 = 6 * 21, 343 = (3 + 4) ^ 3 dan seterusnya
elssar
Apakah Anda mengizinkan minus unary? misalnya -5?
JPvdMerwe
@ JPvdMerkami memeriksa spesifikasi input, Anda tidak perlu melakukan itu, tetapi jika Anda ingin, bunuh diri. Padahal plus unary tidak diperbolehkan. yaitu +5 bukan solusi yang valid
elssar
1
Anda belum menjawab pertanyaan JPvdMerwe tentang pembagian. Haruskah ini tepat? Bisakah hasil antara menjadi non-integral?
Peter Taylor

Jawaban:

3

Ruby, 456 438 408 390 370 349 344 334 [diperbaiki]

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

Keluaran:

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

Juga bekerja relatif cepat untuk jumlah yang lebih besar:

% 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
defhlt
sumber
1
Aku berlari dengan input 5 40dan mendapat hasilnya: [11, "11**1", 21, "21**1", 31, "31**1", 41, "41**1"]. Tidak ada tanda-tanda 25di sana dan saya pikir solusi yang tepat (misalnya untuk 21) adalah 2*1, tidak21**1
Cristian Lupascu
@ w0lf Terima kasih! Saya pikir saya sudah memperbaikinya.
defhlt
Ya, itu bekerja dengan baik sekarang.
Cristian Lupascu
@ w0lf menambahkan banyak karakter untuk memformat output sesuai kebutuhan
defhlt
Anda bisa mendapatkan 2 karakter dengan menggantinya '+-*/'.chars.to_a+['','**']dengan["+","-","*","/","","**"]
Cristian Lupascu
4

Python 2.7 - 380 378 372 371 367 363 357 354 352 348 336 karakter

Hanya pencarian brute force sederhana.

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]

Contoh dijalankan:

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)

Penjelasan:

s(x) adalah fungsi yang mengambil string yang berisi urutan digit dan mengembalikan semua ekspresi menggunakan digit tersebut dalam urutan itu.

[x]['1'>x>'0':] mengevaluasi ke daftar yang berisi x jika x adalah '0' atau urutan digit yang tidak dimulai dengan '0'; jika tidak, ia mengevaluasi ke daftar kosong. Pada dasarnya ini menangani kasus di mana saya menggabungkan semua angka.

['(%s%s%s)'%f for i in range(1,len(x))for f in product(s(x[:i]),'*/-+^',s(x[i:]))] pada dasarnya partisi x menjadi dua bagian (keduanya panjangnya tidak nol), memanggil s () pada setiap bagian dan menggabungkan semua hasil bersama beberapa operator di antara mereka, dengan menggunakan produk ().

E(e) pada dasarnya adalah eval yang aman. Ini mengembalikan nilai e jika e valid dan Tidak ada sebaliknya.

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}

Pada dasarnya, kode ini mencoba semua angka dalam rentang, membolehkan digitnya dan menguji setiap ekspresi yang dihasilkan () untuk permutasi itu, mengabaikan ekspresi pertama jika x tidak dimulai dengan '0', karena jika x tidak memulai dengan ' 0 'maka ekspresi pertama hanya akan menjadi x.

Versi alternatif - 397 karakter

Ini kode saya jika Anda diharuskan menggunakan pecahan:

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","")
JPvdMerwe
sumber
Saya pikir if len(x)<2fungsi tidak akan pernah benar s. Anda juga dapat mengganti formatdengan "a[Fraction(%s)%s%s]='(%s%s%s)'"%(x[:i],o,v,x[:i],o,A)untuk menyimpan 4 karakter.
beary605
@ beary605: Memang benar kadang-kadang, ketika i = len (x) -1, maka panggilan berikutnya akan mendapatkan satu karakter. Adapun poin kedua, terima kasih! :)
JPvdMerwe
huh ... except:0pintar .. sangat pintar. Saya akan ingat
Ev_genus
Harap sertakan beberapa output ilustrasi.
DavidC
1
Tidak, masih berjalan. Saya harus memindahkan PC saya sekarang, tetapi saya akan membiarkannya berjalan selama beberapa hari dan melihat apakah itu selesai.
JPvdMerwe
3

Python3 (436) (434) (443)

Itu sulit. Saya dapat menyimpan beberapa karakter jika saya membuat output lebih asli.

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)

Keluaran

n100
m200
6
(2^(8-1)) 128
(3*(51)) 153
((11)^2) 121
(5^(1+2)) 125
(6*(21)) 126
((2^7)-1) 127
Ev_genus
sumber
1
Jadi Anda punya banyak trik pintar; namun, saya harus menyebutkan Anda tidak menangani 1 hingga 9 dengan benar dan input Anda tidak termasuk. Anda dapat menghapus 2 karakter dengan menghapus spasi setelah "("+i+c+j+")"dan mengganti len(n)>1dengan 1<len(n)yang Anda dapat menghapus ruang setelah ekspresi itu.
JPvdMerwe
Adil. Memperbaiki semua, +7 karakter
Ev_genus
Anda dapat mengganti baris terakhir dengan for j in r:print(r[j],j)menyimpan 7 karakter.
JPvdMerwe
1

Mathematica 456 416 402 404 400 396 karakter

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

Contoh :

v[1,300]//TableForm

Keluaran :

keluaran friedman

DavidC
sumber