Generieren Sie Friedman-Nummern

9

Eine Friedman-Zahl ist eine Zahl, die durch Anwenden grundlegender mathematischer Operationen (^, ​​/, *, +, -) auf alle Ziffern ausgedrückt werden kann. Die Operationen müssen nicht auf jede einzelne Ziffer angewendet werden, sondern alle Ziffern müssen beteiligt sein. Das heißt, 121 = 11 ^ 2 -> alle Ziffern sind beteiligt, aber 1 & 1 wurden zu 11 zusammengeschlagen.

Die Verwendung von Klammern ist zulässig, die triviale Lösung x= (x)ist jedoch keine gültige Lösung. Auch nicht gültig , x= +x.

Beispiele

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

Schreiben Sie ein Programm, das zwei positive Ganzzahlen akzeptiert und die Anzahl der Friedman-Zahlen in diesem Bereich (einschließlich) sowie die Zahlen mit den Ausdrücken in den folgenden Zeilen druckt.

Eingabe -

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

Ausgabe -

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

Der kürzeste Code, der bis Sonntag, den 29. Juli um 00:00 Uhr (GMT) veröffentlicht wurde, ist der Gewinner.

Elssar
quelle
2
Können Sie einige Friedman-Beispielnummern hinzufügen und erklären, wie es /funktioniert? Was ist zum Beispiel 1/3?
JPvdMerwe
Die Zahl wird ausgedrückt, indem die Operationen auf alle Ziffern angewendet werden. dh 25 = 5 ^ 2, 126 = 6 * 21, 343 = (3 + 4) ^ 3 und so weiter
elssar
Erlaubst du unäres Minus? zB -5?
JPvdMerwe
@JPvdMerwe überprüfen Sie die Eingabespezifikation, Sie müssten das nicht tun, aber wenn Sie wollen, schlagen Sie sich aus. Obwohl unary plus nicht erlaubt ist. dh +5 ist keine gültige Lösung
Elssar
1
Sie haben die Frage von JPvdMerwe zur Teilung nicht beantwortet. Muss es genau sein? Können Zwischenergebnisse nicht ganzzahlig sein?
Peter Taylor

Antworten:

3

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

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

Ausgabe:

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

Auch bei größeren Stückzahlen funktioniert es relativ schnell:

% 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
quelle
1
Ich habe es mit der Eingabe ausgeführt 5 40und das Ergebnis erhalten : [11, "11**1", 21, "21**1", 31, "31**1", 41, "41**1"]. Keine Spur von 25dort und ich denke, die richtige Lösung (zum Beispiel für 21) ist 2*1nicht21**1
Cristian Lupascu
@ w0lf Danke! Ich glaube, ich habe es behoben.
Defhlt
Ja, es funktioniert jetzt großartig.
Cristian Lupascu
@ w0lf hat viele Zeichen hinzugefügt, um die Ausgabe nach Bedarf zu formatieren
defhlt
Sie kann durch den Austausch 2 Zeichen gewinnen '+-*/'.chars.to_a+['','**']mit["+","-","*","/","","**"]
Cristian Lupascu
4

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

Nur eine einfache Brute-Force-Suche.

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]

Beispiellauf:

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)

Erläuterung:

s(x) ist eine Funktion, die eine Zeichenfolge mit einer Folge von Ziffern verwendet und alle Ausdrücke mit diesen Ziffern in dieser Reihenfolge zurückgibt.

[x]['1'>x>'0':] ergibt eine Liste mit x, wenn x '0' ist oder eine Folge von Ziffern, die nicht mit '0' beginnen; Andernfalls wird eine leere Liste ausgewertet. Grundsätzlich behandelt dies den Fall, in dem ich alle Ziffern zusammenfüge.

['(%s%s%s)'%f for i in range(1,len(x))for f in product(s(x[:i]),'*/-+^',s(x[i:]))] Grundsätzlich wird x in zwei Teile aufgeteilt (beide haben eine Länge ungleich Null), es wird s () für jeden Teil aufgerufen und alle Ergebnisse zusammen mit einem Operator zwischen ihnen zusammengefügt, indem product () verwendet wird.

E(e) ist im Grunde eine sichere Bewertung. Es gibt den Wert von e zurück, wenn e gültig ist, und andernfalls 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}

Grundsätzlich versucht dieser Code alle Zahlen im Bereich, permutiert ihre Ziffern und testet jeden Ausdruck, den s () für diese Permutation generiert, wobei der erste Ausdruck ignoriert wird, wenn x nicht mit '0' beginnt, denn wenn x nicht mit 'beginnt' 0 'dann ist der erste Ausdruck nur x.

Alternative Version - 397 Zeichen

Hier ist mein Code, wenn Sie Brüche verwenden müssen:

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
quelle
Ich denke nicht, dass dies if len(x)<2jemals in der Funktion wahr sein wird s. Sie können Ihre auch formatdurch ersetzen "a[Fraction(%s)%s%s]='(%s%s%s)'"%(x[:i],o,v,x[:i],o,A), um 4 Zeichen zu speichern.
beary605
@ beary605: Es ist manchmal wahr, wenn i = len (x) -1, dann wird der nächste Aufruf ein einzelnes Zeichen erhalten. Was den zweiten Punkt betrifft, danke! :)
JPvdMerwe
huh ... except:0klug ... sehr klug. Ich werde mich erinnern
Ev_genus
Bitte fügen Sie einige veranschaulichende Ausgaben bei.
DavidC
1
Nein, läuft noch. Ich muss meinen PC jetzt bewegen, aber ich werde ihn einige Tage laufen lassen und sehen, ob er fertig ist.
JPvdMerwe
3

Python3 (436) (434) (443)

Es war schwer. Ich kann einige Zeichen sparen, wenn ich die Ausgabe nativer mache.

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)

Ausgabe

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
quelle
1
Sie haben also viele clevere Tricks. Ich sollte jedoch erwähnen, dass Sie 1 bis 9 nicht richtig behandeln und Ihre Eingabe nicht inklusive ist. Sie können 2 Zeichen entfernen , obwohl durch den Raum nach dem Entfernen "("+i+c+j+")"und Ersetzen len(n)>1durch , 1<len(n)nach dem Sie den Raum nach dem Ausdruck entfernen.
JPvdMerwe
Messe. Alle
behoben
Sie können die letzte Zeile durch ersetzen for j in r:print(r[j],j), um 7 Zeichen zu speichern.
JPvdMerwe
1

Mathematica 456 416 402 404 400 396 Zeichen

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

Beispiel :

v[1,300]//TableForm

Ausgabe :

Friedman-Ausgabe

DavidC
quelle