È tempo di fare i conti


14

introduzione

Questo è uno dei miei puzzle di matematica preferiti.

Data una cifra (diciamo 3) e il numero di volte per usare quella cifra (diciamo 5), genera 10 espressioni che risultano a 1, 2, 3, 4, 5, 6, 7, 8, 9 e 10 usando solo +, -, ×, ÷, ^ e √ (radice) (le parentesi possono raggruppare le operazioni).

Per esempio:

(3^3 + 3)/(3 + 3) = (33 - 3)/(3 + 3) = 3 + 3/3 + 3/3 = 5

Si noti che tutti i precedenti utilizzano cinque 3 e le operazioni matematiche e risultano su 5. È inoltre possibile utilizzare un 3 prima di √ per indicare una radice cubica. Lo stesso vale per l'utilizzo di 4 prima di √ per indicare una quarta radice.

Si noti inoltre che due 3 possono essere utilizzati per formare 33 o tre 3 per formare 333 e così via.

Sfida

  • Ti verranno dati due numeri (entrambi compresi tra 1 e 5) come argomento della funzione, STDIN o argomento della riga di comando.
  • Il primo numero indica quale cifra usare e il secondo numero indica il numero di volte in cui quella cifra deve essere usata nell'espressione.
  • Il tuo programma dovrebbe generare una matrice di dimensioni 10 (o 10 numeri separati da spazi) in cui ogni elemento indica se un'espressione matematica (usando solo gli operatori consentiti) risultante nel (index + 1)numero è possibile o meno usando un valore di verità / falsità.

Ad esempio, se l'ingresso è

1 3

Quindi l'output dovrebbe essere

[1, 1, 1, 0, 0, 0, 0, 0, 0, 1]

perché solo 1, 2, 3 e 10 possono essere espressi usando tre 1.

Punto

  • Questo è un quindi vince la lunghezza minima del codice in byte.

indennità

Stampa tutti [−50]

Sottrai 50 dal tuo punteggio se gli elementi dell'array di output sono uguali al numero totale di combinazioni plausibili per ottenere il (index + 1)valore anziché i valori di verità o falsa.

Ad esempio, se ci sono solo 3 possibili combinazioni di cinque 3 che risultano 5, allora la quarta voce dell'array di output dovrebbe essere 3.

Extreme Maths [−100]

Sottrai 100 dal tuo punteggio se gli elementi dell'array di output contengono almeno una delle espressioni effettive risultanti dal (index + 1)valore.

Ad esempio, se si utilizza cinque 3 di 4 della matrice di uscita th entrata può essere (3^3 + 3)/(3 + 3), (33 - 3)/(3 + 3)o3 + 3/3 + 3/3

Overkilled [−200]

Sottrai 200 dal tuo punteggio se gli elementi dell'array di output contengono tutte le possibili combinazioni (separate da |). Questo bonus viene aggiunto al bonus Extreme Maths , quindi ottieni 300 in totale.

Ad esempio, se si utilizzano cinque 3, dovrebbe essere il 4 ° elemento dell'array di output(3^3 + 3)/(3 + 3)|(33 - 3)/(3 + 3)|3 + 3/3 + 3/3

Nota: due espressioni qualsiasi per ottenere lo stesso risultato dovrebbero essere logicamente diverse con un approccio diverso in entrambe.

Ad esempio, per ottenere 5 usando cinque 3, 3 + 3/3 + 3/3è uguale 3/3 + 3 + 3/3o 3/3 + 3/3 + 3perché viene adottato lo stesso approccio per ciascuno di essi. (3^3 + 3)/(3 + 3)e (33 - 3)/(3 + 3)differiscono, poiché i 30 nel numeratore vengono raggiunti tramite approcci diversi.

AGGIORNAMENTO : Dopo aver esaminato tutte le risposte, si è riscontrato che tutte le risposte presentavano imperfezioni dovute a casi limite di unario -e √. Pertanto, la mancanza di tali casi limite è stata considerata corretta per quanto riguarda la completezza delle risposte.

Questa è una domanda difficile, ma piuttosto interessante.

Buon golf!


1
Mi dispiace, potrebbe essere stupido, ma come fai a ottenere 10 con solo tre 1s?
FryAmTheEggman,

3
@FryAmTheEggman 11-1
Optimizer

1
Ah, quindi ero stupido: p
FryAmTheEggman

4
Questa è una regola molto vaga. Potrei decidere che la radice quadrata di 1, la radice quadrata della radice quadrata di 1, ecc. Sono tutti approcci diversi e ho un numero infinito di risposte. A + b è diverso da b + a? (-A) * (-b) è diverso da b * a?
feersum,

2
Ne sono consapevole, ma non posso rappresentare 4 ^ (4 ^ (4 ^ (4 ^ 4))) in qualsiasi formato numerico normale - la memorizzazione di 4 ^ (4 ^ (4 ^ 4)) come numero intero necessita già di più bit di quanto ci siano atomi nell'universo). Quindi, a meno che non utilizzi un sistema di algebra del computer in grado di gestire tali numeri (se ne esiste uno), devo trattarli come casi speciali. Questo, tuttavia, richiede quasi sicuramente più personaggi di quanti ne vinca per eccesso. Pertanto questi premi sono inutili a meno che tu non escluda in qualche modo più radici quadrate.
Wrzlprmft,

Risposte:


1

Python 3 (imperfetto), 449 - 300 = 149

Soffre delle stesse carenze della soluzione di KSab : nessun operatore unario, completamente tra parentesi, contiene espressioni equivalenti come (1+1)+1e 1+(1+1). Ho eliminato i duplicati esatti passando i risultati a set(). L'output potrebbe essere un po 'più brutto per salvare qualche byte, ma mi piace così. Inoltre non ho fatto l'ennesima radice perché non sembra che ti comprino molto in questo problema.

R=range
E=lambda z:eval(z.replace("^","**"))
def m(d,n):_=R(1,11);s={i:[]for i in _};r=R(1,n);n<2 and s[d].append(str(d));d=str(d);t=[[(d*i,i)for i in r]]+[[]]*n;h=[];[(h.append("("+A+o+B+")"),t[l].append((h[0],a+b))if a+b<n else E(*h)in _ and s[E(*h)].append(h[0]),h.pop())for l in r for j in R(l)for A,a in t[j]for k in R(l)for B,b in t[k]if a+b<=n for o in"+-*/^"if(o=="^"and-~-(0<E(B)<9)or 0==E(B)and"/"==o)-1];[print(i,set(s[i])or'')for i in _]

Questa operazione richiederà alcuni minuti se il secondo argomento è 5. Prova chiamando m(digit, number):

>>> m(1,3)
1 {'((1*1)^1)', '(1^(1+1))', '((1-1)+1)', '((1/1)/1)', '((1*1)*1)', '((1^1)/1)', '(1*(1*1))', '(1^(1*1))', '(1+(1-1))', '(1^(1^1))', '((1^1)*1)', '(1^(1/1))', '((1/1)*1)', '(1-(1-1))', '(1/(1^1))', '(1/(1*1))', '(1/(1/1))', '(1*(1^1))', '((1+1)-1)', '((1*1)/1)', '((1^1)^1)', '(1*(1/1))', '((1/1)^1)'}
2 {'(1*(1+1))', '((1^1)+1)', '((1+1)/1)', '((1*1)+1)', '((1+1)^1)', '(1+(1*1))', '((1/1)+1)', '(1+(1^1))', '(1+(1/1))', '((1+1)*1)'}
3 {'((1+1)+1)', '(1+(1+1))'}
4 
5 
6 
7 
8 
9 
10 {'(11-1)'}
>>> m(3,3)
1 {'((3/3)^3)'}
2 {'(3-(3/3))', '((3+3)/3)'}
3 {'(3-(3-3))', '((3-3)+3)', '((3/3)*3)', '(3*(3/3))', '(3/(3/3))', '((3+3)-3)', '(3^(3/3))', '(3+(3-3))', '((3*3)/3)'}
4 {'((3/3)+3)', '(3+(3/3))'}
5 
6 {'((3*3)-3)'}
7 
8 
9 {'(3+(3+3))', '((3+3)+3)', '((3^3)/3)'}
10 

4

Python (imperfetto) 493 474-300 = 174

Esistono numerosi problemi con questa soluzione, in primo luogo che ignora qualsiasi esponente troppo grande (qualsiasi in cui l'esponente sia maggiore di 100). In realtà non penso che questo rimuova alcuna possibilità per input inferiori o uguali a 5, ma non sono sicuro al 100%.

Un'altra cosa è che non considera alcuna radice quadrata unaria, poiché sarebbe complicata (qualsiasi soluzione con un termine uguale a 0 o 1 produrrebbe un numero infinito di soluzioni). Inoltre non considera alcuna negazione unaria (il simbolo '-') per lo stesso motivo, così come il fatto che non sono effettivamente sicuro se la domanda lo abbia posto.

Ho anche considerato quali criteri dovrebbero decidere se due espressioni fossero equivalenti, ma non sono riuscito a trovare un modo per definirlo rigorosamente in un modo che ho trovato intuitivo, quindi (almeno per ora) non ho implementato nulla del genere. Ciò significa che produce parecchi risultati e usa anche la parentesi in un modo abbastanza ingenuo.

Da un lato, penso che questo potrebbe includere la più lunga riga di codice che ho scritto, soprattutto prima che fosse completamente golfato.

R=range
F=lambda s:lambda a,b:eval(s)
L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)|(b>99)else a**b")),('v',F("b**(1./a)if a and(a>=0 or b)and(b>=0 or int(1./a)==1./a)&(1./a<99)else''"))]if o(u,v)!='']
A=L(*input())
for i in R(11):
 for v,s in A:
    if v==i:print i,s[1:-1]

Esempio: ('v' rappresenta '√')

2,3

0 2*(2-2)
0 2v(2-2)
0 (2-2)*2
0 (2-2)/2
0 (2-2)^2
1 2^(2-2)
1 2-(2/2)
1 2v(2/2)
1 (2/2)^2
2 2v(2+2)
2 2+(2-2)
2 2-(2-2)
2 2v(2*2)
2 2*(2/2)
2 2/(2/2)
2 2^(2/2)
2 2v(2^2)
2 (2+2)-2
2 (2+2)/2
2 (2-2)+2
2 (2*2)-2
2 (2*2)/2
2 (2/2)*2
2 (2/2)v2
2 (2^2)-2
2 (2^2)/2
3 2+(2/2)
3 (2/2)+2
6 2+(2+2)
6 2+(2*2)
6 2+(2^2)
6 (2+2)+2
6 (2*2)+2
6 (2^2)+2
8 2*(2+2)
8 2*(2*2)
8 2*(2^2)
8 (2+2)*2
8 (2*2)*2
8 (2^2)*2

Ho trovato un paio di cose che puoi fare per abbreviare L:L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)or b>100 else a**b")),('v',F("''if a==0 or(b<0 and int(1./a)!=(1./a))or(b or a<0)or(1./a)>100 else b**(1./a)"))]if o(u,v)!='']
FryAmTheEggman,

Mi dispiace, quel commento sembra davvero brutto :( Comunque, per spiegare: quando 0ho confrontato , ho provato a negare l'affermazione, quindi a scambiarne le conseguenze. Ho anche trovato alcuni posti da usare |e &invece di ore and. Entrambi questi trucchi potrebbe essere usato per abbreviare l'ultima chiamata a F, ma quello richiederebbe un po 'di Demorgan e ho finito il tempo del becco; p
FryAmTheEggman

@FryAmTheEggman Oh, è una buona idea, ho aggiornato la mia risposta con quello che hai pubblicato e quando avrò tempo guarderò l'ultimo. Quei condizionali per controllare la validità dell'ingresso ha ottenuto un po 'più pesante di quanto mi aspettassi: /
KSab

+10 per lo splendore degli lambda annidati e eval- mi ci è voluto un po 'di tempo per capire la tua seconda linea! Penso di averti battuto sulla "linea singola più lunga", però. ;) Accetto di ignorare i grandi esponenti; in effetti, penso che qualsiasi esponente più grande di 9 non sarà utile (tranne come no-op quando la base è 1).
DLosc,

@DLosc Beh, uno scenario che puoi avere è qualcosa di simile 3 = 33 √ (3 ^ 33). In realtà mentre scrivo mi rendo conto che due (probabilmente le uniche due?) Combinazioni che mancano alla mia risposta 4 = (4^4) √ (4 ^ (4^4))e l'espressione equivalente con 5s. È vero che le radici non sembrano aggiungere molto al problema, poiché la stragrande maggioranza di esse viene utilizzata come no-op su 0 o 1, no-op quando la radice è 1 o semplicemente per annullare un potere.
KSab il

3

Python 3 - 349 346

r=range
l=lambda s:eval("lambda a"+s)
def T(u,f,X,Y):
    try:return u(f(X,Y))
    except:0
c=l(',x:{x}.union(*[{u(int("1"*a)*x)}|{T(u,f,X,Y)for j in r(1,a)for X in c(j,x)for Y in c(a-j,x)for f in[l(",b:a%sb"%o)for o in{"**"}|set("+-*/")]+[l(",b:a**b**-1")]}for u in[l(":-a")]+[l(":a**.5**%i"%k)for k in r(9)]])')
R=l(",i:[{n+1}<c(i,a)for n in r(10)]")

Ecco una versione piuttosto non golfata:

def R(x,i):
    # Unary Operations
    U = [lambda a:-a] + [eval("lambda a:a**(1/2.**%i)" % j) for j in range(9)]
    # Binary Operations
    F = [eval("lambda a,b:a%sb"%o) for o in ["+","-","*","/","**"]] + [lambda a,b:a**(1./b)]

    def combos(i):
        L = {x}
        for u in U:
            # 3, 33, 333, etc.
            L |= {u(int(str(x)*i))}

            for j in range(1,i):
                for X in combos(j):
                    for Y in combos(i-j):
                        for f in F:
                            # To avoid trouble with division by zero, overflows and similar:
                            try:
                                L |= {u(f(X,Y))}
                            except:
                                pass
        return L

    return [n in combos(i) for n in range(1,11)]

Per i test, consiglio di passare (9)a qualcosa di più piccolo, poiché questo è il numero di più radici quadrate prese in considerazione, il che ha un impatto enorme sulle prestazioni.

Alla fine, questo mi ha fatto domandare se il meno unario sia effettivamente necessario in qualche caso ...


1
Penso che tu abbia ragione sull'unario "-" probabilmente non aggiungendo nulla (almeno alla domanda di base senza i bonus). L'unico scenario non banale a cui riesco a pensare sarebbe qualcosa di simile 1 = 3^3 * 3^(-3), ma anche considerando questi, dubito che ci siano numeri per i quali questa è una possibile soluzione quando non ce ne sono altri.
KSab il

1
Puoi salvare 3 byte usando a**.5**%iinvece di a**(1/2**%i)calcolare le radici quadrate multiple.
DLosc,

@DLosc: davvero grazie.
Wrzlprmft,

È possibile salvare sei byte riducendo i quattro rientri di spazio in uno spazio.
Decadimento beta

@BetaDecay: non uso mai rientri a quattro spazi (brivido), utilizzo le schede. Guarda nella fonte del mio post. Stack Exchange li rende semplicemente come quattro spazi.
Wrzlprmft,

2

Mathematica - 246 personaggi (nessun bonus richiesto)

f[x_,y_]:=x-y
g[x_,y_]:=x/y
h[x_,y_]:=x^(1/y)
j[x_,y_]:=FromDigits@Join[IntegerDigits@x,{y}]
z[{r_,n_,L_}]:=z[{L[[1]][r,n],n,Rest@L}]
z[{r_,n_,{}}]:=r
a[n_,t_]:=Union@Select[z[{n,n,#}]&/@Tuples[{Plus,f,Times,g,Power,h,j},t-1],IntegerQ@#&&0<#<11&]

Spiegazione

La funzione jconcatena due numeri in cifre.

La funzione zaccetta un risultato r, un numero ne un elenco di funzioni L, ognuna delle quali opera su due argomenti. Quindi applica l'elenco di funzioni in sequenza agli argumnts [r,n]usando la ricorsione, fino a quando l'elenco è vuoto, dopodiché restituisce il risultato.

La funzione arichiede un numero ne un numero di copie t. Crea tutte le tuple di lunghezza (t-1) dall'elenco delle funzioni {Plus, f, Times, g, Power, h, j}e invia ciascuna tupla attraverso la funzione z, quindi restituisce un elenco di tutti i numeri da 1 a 10 che sono stati creati.

Esecuzione dell'esempio di a[2,3]ritorno {1, 2, 3, 6, 8}.

limitazioni

Poiché l'elenco di funzioni viene applicato in sequenza, consumando una copia del numero ogni volta, è possibile che manchino alcune combinazioni. Ad esempio, quando si opera su quattro due, mancherebbe 22/22 = 1 a causa della sua incapacità di valutare l'elenco delle funzioni fuori servizio. Naturalmente, 2/2 * 2/2 = 1 copre questo caso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.