Esponenziazione alla moltiplicazione all'aggiunta


17

La moltiplicazione tra 2 numeri interi può essere ridotta in una serie di aggiunte in questo modo

3 * 5 = 3 + 3 + 3 + 3 + 3 = 5 + 5 + 5

Elevamento a potenza (sollevando un alla potenza b ) può anche essere ridotta in una serie di moltiplicazioni:

5 ^ 3 = 5 * 5 * 5

Pertanto, l'espiazione può essere ridotta in una serie di aggiunte, creando un'espressione di moltiplicazione, quindi in una serie di aggiunte. Ad esempio, 5 ^ 3(5 cubi) può essere riscritto come

5 ^ 3 = 5 * 5 * 5
      = (5 + 5 + 5 + 5 + 5) * 5
      = (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5) + (5 + 5 + 5 + 5 + 5)
      = 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5

Il tuo compito è, dato che le espressioni sommate costituite da esponenziazione, moltiplicazione e addizione, riducono la serie alle aggiunte più brevi. L'espressione "più breve" è definita come l'espressione con il minor numero di +simboli, usando ancora solo uno dei due numeri nell'espressione originale. Ad esempio, l'espressione più breve di 10 * 2è 10 + 10.

I numeri coinvolti nell'input saranno numeri interi positivi e l'espressione sarà composta solo da +(addizione), *(moltiplicazione) e ^(esponenziazione), insieme a numeri interi e parentesi ( ()) per indicare la precedenza.

L'output deve essere composto solo da numeri interi e +simboli positivi . Non dovresti produrre i singoli passaggi delle riduzioni, ma solo l'output finale. L'output potrebbe non essere costituito da numeri che non compaiono nell'input. Tuttavia, è possibile utilizzare qualsiasi 3 simboli distinti invece di +*^, ma si prega di dire quali simboli sono

Gli spazi che separano gli ingressi e le uscite possono o non possono essere utilizzati nei programmi, ovvero 3 * 5possono essere emessi come uno 5 + 5 + 5o 5+5+5.

Si noti che nella maggior parte dei casi l'addizione non viene effettivamente eseguita. L'unico caso in cui l'addizione deve essere eseguita è quando hai qualcosa di simile 5 ^ (1 + 2), nel qual caso l'addizione è necessaria per continuare -> 5 ^ 3 -> 5 * 5 * 5 -> .... Vedi il caso di test n. 4.

Il codice non deve gestire input che arrivano a un'espressione ambigua. Ad esempio (2 + 2) * (4 + 1),. A causa delle regole stabilite finora, l'obiettivo non è calcolare la risposta, l'obiettivo è semplificare le aggiunte. Quindi il risultato potrebbe essere diverso a seconda dell'ordine in cui le espressioni vengono risolte o commutate (quali aggiunte semplificare, quali lasciare?). Un altro esempio valido: ((3 + 2) ^ 2) ^ 3 -> ((3 + 2) * (3 + 2)) ^ 3 -> ???.

Questo è quindi vince il codice più breve

Casi test

Input => output

5 ^ 3 + 4 * 1 ^ 5 => 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 4
2 ^ 1 * 2 + 3 + 9 => 2 + 2 + 3 + 9
2 ^ 1 * (2 + 3) + 9 => 2 + 3 + 2 + 3 + 9
2 ^ (1 * (2 + 3)) + 9 => 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 9
10 + 3 * 2 + 33 ^ 2 => 10 + 3 + 3 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33 + 33
100 * 3 => 100 + 100 + 100
2 ^ 1 + 2 ^ 1 + 2 ^ 2 + 8 ^ 1 => 2 + 2 + 2 + 2 + 8
(1 + 2 + 5 * 8 + 2 ^ 4) * 2 => 1 + 2 + 8 + 8 + 8 + 8 + 8 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + 2 + 8 + 8 + 8 + 8 + 8 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2

Possiamo usare **invece di ^?
Erik the Outgolfer,

@EriktheOutgolfer sì, sembra giusto.
caird coinheringaahing


1
Sono ancora confuso su ciò che costituisce un output valido. Nella domanda che dici, using only one of the two numbers in the original expression.ma l'espressione originale può avere più di due numeri. Non capisco perché 8 + 8non sia un output valido per 2 ^ 1 + 2 ^ 1 + 2 ^ 2 + 8 ^ 1. Questa domanda non è ancora abbastanza chiara per me.
Post Rock Garf Hunter,

Risposte:


6

Retina , 302 byte

Sono sicuro che questo può essere giocato a golf, ma a questo punto, sono solo felice che funzioni. Le sezioni di esponenziazione e moltiplicazione sono entrambe molto simili, ma poiché l'ordine delle operazioni è importante, non so come combinarle.

y- Esponenziazione
x- Moltiplicazione
p- Aggiunta

\d+
$*
{1`(\(\w+\)|1+)y(\(\w+\)|1+)
>$0<
(?<=>(\(\w+\)|1+)y1*)1
$1x
>(\(\w+\)|1+)y
(
x<
)
\((1+(x1+)*)\)(?!y)
$1
(?<!1)(1+)x(\(\w+\)|1+\1)(?!1)
$2x$1
1`(\(\w+\)|1+)x1+
>$0<
(?<=>(\(\w+\)|1+)x1*)1
$1p
>(\(\w+\)|1+)x
(
p<
)
(?<!x|y)\((1+(p1+)*)\)(?!x|y)
$1
y\((1+)p([1p]*\))
y($1$2
}`y\((1+)\)
y$1
1+
$.0

Provalo online - tutti i casi di test

Convertitore per test case

Spiegazione

\d+                             Convert to unary
$*
{1`(\(\w+\)|1+)y(\(\w+\)|1+)    Begin loop: Delimit current exponentiation group
>$0<
(?<=>(\(\w+\)|1+)y1*)1          Replace exponentiation with multiplication
$1x
>(\(\w+\)|1+)y                  Replace garbage with parentheses
(
x<
)
\((1+(x1+)*)\)(?!y)             Remove unnecessary parentheses around multiplication
$1
(?<!1)(1+)x(\(\w+\)|1+\1)(?!1)  Maybe swap order of multiplicands
$2x$1
1`(\(\w+\)|1+)x1+               Delimit current multiplication group
>$0<
(?<=>(\(\w+\)|1+)x1*)1          Replace multiplication with addition
$1p
>(\(\w+\)|1+)x                  Replace garbage with parentheses
(
p<
)
(?<!x|y)\((1+(p1+)*)\)(?!x|y)   Remove unnecessary parentheses around addition
$1
y\((1+)p([1p]*\))               Handle the 4th test case by adding if necessary
y($1$2
}`y\((1+)\)                     End of loop
y$1
1+                              Convert unary back to decimal
$.0

Si può anche notare che il gruppo più comunemente usato è (\(\w+\)|1+). Ciò corrisponde a un'espressione interiore con parentesi o un numero intero. Ho scelto di usare i simboli che ho fatto in modo da poter usare \wpiuttosto che una classe di caratteri. Non sono sicuro se sarebbe meglio usare simboli non di parole e sostituire alcuni lookaround con bordi di parole ( \b).


5

Mathematica, 250 218 183 170 byte

f~(s=SetAttributes)~HoldAll;{a,t}~s~Flat;f@n_:=Infix[Hold@n//.{a_~Power~b_:>t@@Hold@a~Table~b,Times->t,Plus->a,Hold->Dot}/.t->(a@@Table[#,1##2]&@@Reverse@Sort@{##}&),"+"]

Funziona! Infine!

Definisce la funzione in f.

L'input è una semplice espressione matematica. (cioè 1 + 2no "1 + 2").

Provalo online!

Si noti che il collegamento TIO ha un codice leggermente diverso, poiché a TIO (che, presumo, utilizza il kernel Mathematica) non piace Infix. Ho usato Riffleinvece per ottenere lo stesso aspetto di REPL di Mathematica.

Ungolfed

f~(s = SetAttributes)~HoldAll;  (* make f not evaluate its inputs *)

{a, t}~s~Flat;  (* make a and t flat, so that a[a[1,a[3]]] == a[1,3] *)

f@n_ :=  (* define f, input n *)

 Infix[

  Hold@n  (* hold the evaluation of n for replacement *)

    //. {  (* expand exponents *)

     (* change a^b to t[a,a,...,a] (with b a's) *)
     a_~Power~b_ :> t @@ Hold@a~Table~b,

     (* Replace Times and Plus with t and a, respectively *)
     Times -> t, 
     Plus -> a, 

     (* Replace the Hold function with the identity, since we don't need
         to hold anymore (Times and Plus are replaced) *)
     Hold -> Dot 

     } /.  (* Replace; expand all t (= `Times`) to a (= `Plus`) *)

        (* Take an expression wrapped in t. *)
        (* First, sort the arguments in reverse. This puts the term
            wrapped in `a` (if none, the largest number) in the front *)
        (* Next, repeat the term found above by <product of rest
            of the arguments> times *)
        (* Finally, wrap the entire thing in `a` *)
        (* This will throw errors when there are multiple elements wrapped
           in `a` (i.e. multiplying two parenthesized elements) *)
        t -> (a @@ Table[#, 1 ##2] & @@
               Reverse@Sort@{##} &),

  "+"]  (* place "+" between each term *)

6
Ok, sono felice di aver creato una sfida per la quale Mathematica non ha una funzione integrata per: P
caird coinheringaahing

3

Mathematica, 405 406 byte

f~SetAttributes~HoldAll;p=(v=Inactive)@Plus;t=v@Times;w=v@Power;f@x_:=First@MinimalBy[Inactivate@{x}//.{w[a___,b_List,c___]:>(w[a,#,c]&/@b),t[a___,b_List,c___]:>(t[a,#,c]&/@b),p[a___,b_List,c___]:>(p[a,#,c]&/@b),p[a_]:>a,w[a_,b_]:>t@@Table[a,{Activate@b}],t[a___,t[b__],c___]:>t[a,b,c],p[a___,p[b__],c___]:>p[a,b,c],{a___,{b__},c___}:>{a,b,c},t[a__]:>Table[p@@Table[i,{Activate[t@a/i]}],{i,{a}}]},Length];f

Ungolfed e spiegato

SetAttributes[f, HoldAll]
p = Inactive[Plus]; t = Inactive[Times]; w = Inactive[Power];
f[x_] := First@MinimalBy[
   Inactivate[{x}] //. {
     w[a___, b_List, c___] :> (w[a, #, c] & /@ b),
     t[a___, b_List, c___] :> (t[a, #, c] & /@ b),
     p[a___, b_List, c___] :> (p[a, #, c] & /@ b),
     (* distribute lists of potential expansions over all operations *)
     p[a_] :> a,
     (* addition of a single term is just that term *)
     w[a_, b_] :> t @@ Table[a, {Activate@b}],
     (* a^b simplifies to a*a*...*a b times no matter what b is *)
     t[a___, t[b__], c___] :> t[a, b, c],
     p[a___, p[b__], c___] :> p[a, b, c],
     {a___, {b__}, c___} :> {a, b, c},
     (* operations are associative *)
     t[a__] :> Table[p @@ Table[i, {Activate[t@a/i]}], {i, {a}}]
     (* for a product, generate a list of potential expansions *)}
   , Length]
f

Sono andato a una grande quantità di problemi per ottenere il seguente effetto: questa funzione prende in input un'espressione standard di Mathematica, con il solito +, *e ^le operazioni (e parentesi) in esso, e le uscite che sembra un'espressione standard di Mathematica (ma con segni "disattivati") come risposta.

La funzione sopra inizia disattivando tutte le operazioni nell'ingresso. Quindi applica ripetutamente le regole di espansione fino a quando non è più possibile semplificare nulla. Ogni volta che incontra un prodotto come 2 * 3 * 4, che può essere espanso in più modi, fa un elenco di possibili espansioni e continua. Alla fine, otteniamo un elenco di possibili risposte finali e viene scelta la più breve.

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.