Moltiplicare per operazioni limitate


44

C'è una generosità non ufficiale di 500 rappresentanti per battere la migliore risposta attuale .

Obbiettivo

Il tuo obiettivo è moltiplicare due numeri usando solo un insieme molto limitato di operazioni aritmetiche e assegnazione di variabili.

  1. aggiunta x,y -> x+y
  2. Reciproco x -> 1/x( non divisione x,y -> x/y)
  3. Negazione x -> -x( non sottrazione x,y -> x-y, sebbene sia possibile farlo come due operazioni x + (-y))
  4. La costante 1(non sono consentite altre costanti, ad eccezione di quelle prodotte dalle operazioni da 1)
  5. Assegnazione variabile [variable] = [expression]

Punteggio: i valori iniziano in variabili ae b. Il tuo obiettivo è salvare il loro prodotto a*bnella variabile cusando il minor numero di operazioni possibile. Ogni operazione e assegnazione +, -, /, =costa un punto (equivalentemente, ogni utilizzo di (1), (2), (3) o (4)). Le costanti 1sono gratuite. Vince la soluzione con il minor numero di punti. Tiebreak è il primo post.

Indennità: la tua espressione deve essere aritmeticamente corretta per i reali "casuali" ae b. Può fallire su un sottoinsieme di zero di misura di R 2 , cioè un insieme che non ha area se tracciato nel piano a- bcartesiano. (È probabile che ciò sia necessario a causa dei reciproci di espressioni che potrebbero essere 0simili 1/a.)

Grammatica:

Questo è un . Non è possibile utilizzare altre operazioni. In particolare, ciò significa nessuna funzione, condizionali, loop o tipi di dati non numerici. Ecco una grammatica per le operazioni consentite (le possibilità sono separate da |). Un programma è una sequenza di <statement>s, dove a <statement>è dato come segue.

<statement>: <variable> = <expr>
<variable>: a | b | c | [string of letters of your choice]
<expr>: <arith_expr> | <variable> | <constant>
<arith_expr>: <addition_expr> | <reciprocal_expr> | <negation_expr> 
<addition_expr>: <expr> + <expr>
<reciprocal_expr>: 1/(<expr>)
<negation_expr>: -<expr>
<constant>: 1

In realtà non è necessario inserire il codice in questa grammatica esatta, purché sia ​​chiaro cosa stai facendo e il conteggio delle operazioni sia corretto. Ad esempio, è possibile scrivere a-bper a+(-b)e contare come due operazioni, o definire le macro per brevità.

(C'era una domanda precedente Moltiplica senza moltiplica , ma consentiva una serie di operazioni molto più rilassate.)


4
È possibile?
— Ypnypn,

1
@Ypnypn Sì, e ho scritto un esempio per esserne sicuro.
— xnor

2
Sembra una sfida in cui è probabile che si trovi una soluzione ottimale (una volta trovata una soluzione). Allora, qual è il pareggio in quel caso?
— Martin Ender,

1
@ MartinBüttner Tiebreak è la prima pubblicazione in quel caso. Penso che ci sia un buon margine di ottimizzazione, quindi non penso che sarà solo una corsa per trovarne uno che funzioni e scriverlo in modo pulito. Almeno, è quello che ho trovato provandolo; forse qualcuno troverà una soluzione chiaramente minima.
— xnor

2
Ok, dato che non tutti pensavano che la mia risposta fosse divertente come me, l'ho cancellata e commentata qui: la regola sull'insieme di misure zero non è scelta molto saggiamente poiché i numeri razionali sono una misura di zero relativa alla misura di Lebesgue, suggerirei usando invece una certa percentuale. (O un altro tipo) Ma mi piace assolutamente l'idea di questa sfida!
— flawr

Risposte:


34

22 operazioni

itx = 1/(1+a+b)     #4
nx = -1/(itx+itx)   #4
c = -( 1/(itx + itx + 1/(1+nx)) + 1/(1/(a+nx) + 1/(b+nx)) ) #14

Provalo online!

Le operazioni sono 10 aggiunte, 7 inverse, 2 negazioni e 3 assegnazioni.

Quindi, come ho ottenuto questo? Ho iniziato con il modello dall'aspetto promettente della somma di due frazioni a due piani, un motivo che era apparso in molti tentativi precedenti.

c = 1/(1/x + 1/y) + 1/(1/z + 1/w)

Quando limitiamo la somma a x+y+z+w=0, si verificano belle cancellazioni, che danno:

c = (x+z)*(y+z)/(x+y),

che contiene un prodotto. (Spesso è più facile ottenere t*u/vpiuttosto che t*uperché il primo ha un grado 1.)

C'è un modo più simmetrico di pensare a questa espressione. Con la restrizione x+y+z+w=0, i loro valori sono specificati da tre parametri p,q,rdelle loro somme a coppie.

 p = x+y
-p = z+w
 q = x+z
-q = y+w
 r = x+w
-r = y+z

e abbiamo c=-q*r/p. La somma psi distingue per essere nel denominatore corrispondente alle coppie (x,y)e (z,w)alle variabili che si trovano nella stessa frazione.

Questa è una bella espressione per cin p,q,r, ma la frazione a due piani è in, x,y,z,wquindi dobbiamo esprimere la prima in termini di seconda:

x = ( p + q + r)/2
y = ( p - q - r)/2
z = (-p + q - r)/2
w = (-p - q + r)/2

Ora, vogliamo scegliere in p,q,rmodo che sia c=-q*r/puguale a*b. Una scelta è:

p = -4
q = 2*a
r = 2*b

Quindi, i valori raddoppiati per qe rvengono opportunamente dimezzati in:

x = -2 + a + b
y = -2 - a - b
z =  2 + a - b
w =  2 - a + b

Salvare 2come variabile te collegarle all'equazione per cfornisce una soluzione a 24 operazioni.

#24 ops
t = 1+1   #2
c = 1/(1/(-t+a+b) + 1/-(t+a+b))  +  1/(1/(-b+t+a) + 1/(-a+b+t)) #1, 10, 1, 10

Ci sono 12 aggiunte, 6 inverse, 4 negazioni e 2 assegnazioni.

Si spendono molte operazioni espresse x,y,z,win termini di 1,a,b. Per salvare ops, invece di esprimere xin p,q,r(e quindi a,b,1) e poi scrivere y,z,win termini di x.

y = -x + p
z = -x + q
w = -x + r

scelta

p = 1
q = a
r = b

ed esprimendo ccon una negazione come c=-q*r/p, otteniamo

x = (1+a+b)/2
y = -x + 1
z = -x + a
w = -x + b

Sfortunatamente, dimezzarsi xè costoso. Deve essere fatto invertendo, aggiungendo il risultato a se stesso e invertendolo di nuovo. Neghiamo anche la produzione nxper -x, dal momento che è quello che y,z,wserve. Questo ci offre la soluzione 23-op:

#23 ops
itx = 1/(1+a+b)     #4
nx = -1/(itx+itx)   #4
c = -( 1/(1/(-nx) + 1/(1+nx))  +  1/(1/(a+nx) + 1/(b+nx)) ) #15

itxè 1 / (2 * x) ed nxè -x. Un'ottimizzazione finale dell'espressione 1/xcome itx+itxinvece del modello 1/(-nx)modellato taglia un personaggio e porta la soluzione a 22 operazioni.


C'è una facile ottimizzazione per 21 operazioni. itx + itxsi verifica due volte, ma itxnon si verifica in nessun altro contesto. Definisci invece ix = (1+1)/(1+a+b)e sostituisci due aggiunte con una.
— Peter Taylor,

E estraendo m = -1è possibile ottenere 20:nx = (1+a+b)/(m+m); c = m/(m/nx + 1/(1+nx)) + m/(1/(a+nx) + 1/(b+nx))
— Peter Taylor il

3
Ah, entrambe queste ottimizzazioni falliscono perché l'operazione supportata è reciproca piuttosto che divisione.
— Peter Taylor,

Se ae bsono solo uno a parte, quindi uno a + nx = 0o b + nx = 0, causando la divisione della soluzione per zero.
— MooseOnTheRocks

1
@MooseOnTheRocks Va bene, vedi la "tolleranza" nella sfida che il codice può fallire su un sottoinsieme di misura zero. Penso che la sfida sia impossibile altrimenti.
— xnor

26

23 operazioni

z = 1/(1/(1/(1/(a+1)+1/(b+1))-1+1/(a+b+1+1))-(1/a+1/b))
res = z+z

prova di esplosione:

z = 1/(1/(1/(1/(a+1)+1/(b+1))-1+1/(a+b+1+1))-(1/a+1/b))
             1/(a+1)+1/(b+1)                            == (a+b+2) / (ab+a+b+1)
          1/(1/(a+1)+1/(b+1))                           == (ab+a+b+1) / (a+b+2)
          1/(1/(a+1)+1/(b+1))-1                         == (ab - 1) / (a+b+2)
          1/(1/(a+1)+1/(b+1))-1+1/(a+b+1+1)             == ab / (a+b+2)
       1/(1/(1/(a+1)+1/(b+1))-1+1/(a+b+1+1))            == (a+b+2) / ab
                                              1/a+1/b   == (a+b) / ab
       1/(1/(1/(a+1)+1/(b+1))-1+1/(a+b+1+1))-(1/a+1/b)  == 2 / ab
    1/(1/(1/(1/(a+1)+1/(b+1))-1+1/(a+b+1+1))-(1/a+1/b)) == ab / 2

z = ab / 2 and therefore z+z = ab

Ho abusato di wolfram alpha per ottenere questa bellissima immagine (wolfram alpha ha cercato di farmi iscrivere a pro per salvarlo, ma poi ctrl-c ctrl-v ;-)):

punteggio (con aggiunta +sulla sottrazione):

z = ////++/++-+/++++-/+/
res = +

Complimenti per la soluzione più breve!
— xnor

@xnor grazie per avermi dato la mia prima risposta accettata e la mia prima taglia!
— orgoglioso haskeller l'

Non essere pignolo, ma non dovrebbe ... (b + 1)) - 1 + 1 ... e ... 1)) - (1 / a + ... be ... (b + 1 )) + - 1 + 1 ... e ... 1)) + - (1 / a + ... rispettivamente?
— tfitzger

@tfitzger Penso che sia più facile in questo modo. La domanda dice che non importa. Nota conto il punteggio correttamente (ogni meno è un due)
— orgoglioso haskeller

Wolfram Alpha ha una prova gratuita di 7 giorni, fyi.
— ghosts_in_the_code il

13

29 operazioni

Non funziona per il set {(a, b) ∈ R 2 | a + b = 0 o a + b = -1 o ab = 0 o ab = -1}. È probabilmente misura zero?

sum = a+b
nb = -b
diff = a+nb
rfc = 1/(1/(1/sum + -1/(sum+1)) + -1/(1/diff + -1/(diff+1)) + nb + nb)  # rfc = 1/4c
c = 1/(rfc + rfc + rfc + rfc)

# sum  is  2: =+
# nb   is  2: =-
# diff is  2: =+
# rfc  is 18: =///+-/++-//+-/+++
# c    is  5: =/+++
# total = 29 operations

La struttura di rfc(Reciprocal-Four-C) è più evidente se definiamo una macro:

s(x) = 1/(1/x + -1/(x+1))              # //+-/+ (no = in count, macros don't exist)
rfc = 1/(s(sum) + - s(diff) + nb + nb) # =/s+-s++ (6+2*s = 18)

Facciamo la matematica:

  • s(x), matematicamente, è 1/(1/x - 1/(x+1))che è dopo che un po 'di algebra è x*(x+1)o x*x + x.
  • Quando subisci tutto in rfc, è davvero ciò 1/((a+b)*(a+b) + a + b - (a-b)*(a-b) - a + b + (-b) + (-b))che è giusto 1/((a+b)^2 - (a-b)^2).
  • Dopo differenza di quadrati, o solo l'espansione pianura, si ottiene che rfcè 1/(4*a*b).
  • Infine, cè il reciproco di 4 volte rfc, così 1/(4/(4*a*b))diventa a*b.

2
+1, ero nel bel mezzo del completamento di questo identico calcolo
— Eric Tressler,

1
Questo è sicuramente misura zero; è un'unione di linee.
— xnor

Non farò un commento sull'unione delle linee ... @algorithmshark Puoi dirci di più come hai avuto questa identità? Come hai affrontato il problema?
— flawr

1
@flawr Ho ricordato che le proprietà di s(x)adattano i requisiti della domanda, dal calcolo, quindi ciò significava che avevo una funzione quadrata. Dopo un po 'di dissolvenza, ho scoperto che avrei potuto ottenere un a*btermine con la differenza del trucco dei quadrati. Una volta che l'ho avuto, si trattava di provare quali incarichi salvassero le operazioni.
— algoritmo

Dato che usi -1tre volte in entrata rfc, non puoi golfare un personaggio assegnandolo a una variabile?
— Isaacg,

9

27 operazioni

tmp = 1/(1/(1+(-1/(1/(1+(-a))+1/(1+b))))+1/(1/(1/b+(-1/a))+1/(a+(-b))))
res = tmp+tmp+(-1)

# tmp is 23: =//+-//+-+/++///+-/+/+-
# res is 4: =++-

Non c'è teoria dietro questo. Ho appena provato a iniziare (const1+a*b)/const2e ho iniziato con (1/(1-a)+1/(1+b))e (-1/a+1/b).


In tmprealtà il tuo è 23, facendo il tuo punteggio 27. Bella scoperta, però.
— algoritmo
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.