Riduzione delle dichiarazioni matematiche


18

La sfida

Sei il proprietario di un fantastico servizio chiamato Coyote Beta , che risponde magicamente alle domande di matematica che gli utenti gli inviano su Internet.

Ma si scopre che la larghezza di banda è costosa. Hai due scelte, o creare un " Coyote Beta Pro" o trovare un modo per risolverlo. Proprio di recente, qualcuno ha interrogato (x + 2). Il client non è in grado di inviare x+2e l'utente non vedrebbe alcuna differenza?

L'obiettivo

Il tuo compito è "minimizzare" le espressioni matematiche. Data un'espressione di input, è necessario sbarazzarsi di spazi bianchi e parentesi fino a quando non fornisce una rappresentazione minima dello stesso input. Non è necessario conservare le parentesi attorno alle operazioni associative.

Gli unici operatori qui riportati sono +, -, *, /, e ^(elevamento a potenza), con standard di associatività matematica e la precedenza. L'unico spazio bianco indicato nell'input sarà lo spazio reale dei caratteri.

Ingresso / uscita campione

Input       | Output
------------|--------------
(2+x) + 3   | 2+x+3
((4+5))*x   | (4+5)*x
z^(x+42)    | z^(x+42)
x - ((y)+2) | x-(y+2)
(z - y) - x | z-y-x
x^(y^2)     | x^y^2
x^2 / z     | x^2/z
- (x + 5)+3 | -(x+5)+3

punteggio

Input / output può utilizzare qualsiasi metodo preferito. Vince il programma più piccolo in byte.

Bit esatti

L'esponenziazione è associativa corretta e segue anche la precedenza matematica standard (essendo la più alta). Un letterale numerico valido è /[0-9]+/e un letterale variabile valido è /[a-z]+/. Un letterale a singola variabile rappresenta un singolo valore anche quando la lunghezza del carattere è maggiore di 1.

Ciò che si intende per "non è necessario conservare le parentesi attorno alle operazioni associative" è che l'output dovrebbe consistere in un'espressione che si traduce in un albero di analisi identico, con l'eccezione che le operazioni associative possono essere riorganizzate.


L'idea è quella di creare un'istruzione equivalente minima che risulti nello stesso albero di analisi. In questo modo Coyote Beta può visualizzarlo visivamente quando l'utente effettua una query.
TND,

Se una variabile valida è /[a-z]+/, ciò significa che la moltiplicazione per giustapposizione come abnon è consentita?
Joe Z.

1
Vuoi 2+(3+4)essere cambiato in 2+3+4, giusto? Questo cambia l'albero di analisi.
feersum

2
Metto in dubbio l'affermazione che x^(y/2)=x^y/2; elevamento a potenza ha una precedenza ordine superiore, ergo, x^y/2=(x^y)/2.
Conor O'Brien,

1
Oh, amico, stavo per presentare Prompt X:expr(X)in TI-BASIC ma non puoi semplificare :(
DankMemes,

Risposte:


1

C #, 523 519 504 byte

Controlla i commenti nel codice per vedere come funziona!


golfed

using System;using System.Collections.Generic;namespace n{class p{static void Main(string[]a){foreach(String s in a){String r=s.Replace(" ","");List<int>l=new List<int>();for(int i=0;i<r.Length;i++){if(r[i]=='('){l.Add(i);continue;}if(r[i]==')'){switch(r[Math.Max(l[l.Count-1]-1,0)]){case'+':case'(':switch(r[Math.Min(i+1,r.Length-1)]){case'+':case'-':case')':r=r.Remove(Math.Max(l[l.Count-1],0),1);r=r.Remove(Math.Min(i,r.Length)-1,1);i-=2;break;}break;}l.RemoveAt(l.Count-1);}}Console.WriteLine(r);}}}}

Ungolfed

using System;
using System.Collections.Generic;

namespace n {
    class p {
        static void Main( string[] a ) {
            // Loop every String given for the program
            foreach (String s in a) {
                // Get rid of the spaces
                String r = s.Replace( " ", "" );

                // A little helper that will have the indexes of the '('
                List<int> l = new List<int>();

                // Begin the optimizatio process
                for (int i = 0; i < r.Length; i++) {
                    // If char is an '(', add the index to the helper list and continue
                    if (r[ i ] == '(') {
                        l.Add( i );
                        continue;
                    }

                    // If the char is an ')', validate the group
                    if (r[ i ] == ')') {
                        // If the char before the last '(' is an '+' or '(' ...
                        switch (r[ Math.Max( l[ l.Count - 1 ] - 1, 0 ) ]) {
                            case '+':
                            case '(':
                                // ... and the char after the ')' we're checking now is an '+', '-' or ')' ...
                                switch (r[ Math.Min( i + 1, r.Length - 1 ) ]) {
                                    case '+':
                                    case '-':
                                    case ')':
                                        // Remove the '()' since they're most likely desnecessary.
                                        r = r.Remove( Math.Max( l[ l.Count - 1 ], 0 ), 1 );
                                        r = r.Remove( Math.Min( i, r.Length ) - 1, 1 );

                                        // Go two steps back in the loop since we removed 2 chars from the String,
                                        //   otherwise we would miss some invalid inputs
                                        i -= 2;
                                        break;
                                }

                                break;
                        }

                        // Remove the last inserted index of '(' from the list,
                        //   since we matched an ')' for it.
                        l.RemoveAt( l.Count - 1 );
                    }
                }

                // Print the result
                Console.WriteLine( r );
            }
        }
    }
}

Note a margine

  1. Risolti alcuni errori di battitura e ribattezzati alcuni var.
  2. Annidato un interruttore per sbarazzarsi di una variabile non necessaria. Inoltre, risolto un bug che rendeva non valide alcune soluzioni, riportato da Anders Kaseorg .

PS: Se hai un suggerimento o hai trovato un bug, fammi sapere nei commenti e proverò a risolverlo (aggiungerò quindi una nota sulla correzione del bug con il tuo nome;))


Bella risposta! : D Le risposte sostanziali qui sono generalmente meglio ricevute se includi una spiegazione: P
cat

Posso farlo sotto forma di commenti in codice?
auhmaan,

Certo, qualunque cosa funzioni c:
cat

Allora lo farò! Proverò anche ad aggiungere un riepilogo da qualche parte.
auhmaan,

Benvenuto a Programming Puzzles e Code Golf, a proposito! (anche se non è la tua prima risposta)
gatto

0

C ++, 284 byte

golfed

#include<iostream>
#include<algorithm>
int main(){std::string e;std::getline(std::cin,e);e.erase(std::remove_if(e.begin(),e.end(),isspace),e.end());for(int x=0;x<e.length();x++){if(e[x]=='('&&e[x+1]=='('){e.erase(x,1);}if(e[x]==')'&&e[x+1]==')'){e.erase(x,1);}}std::cout<<e;return 0;}

Ungolfed

#include<iostream>
#include<algorithm>

int main()
{
    std::string e;
    std::getline(std::cin, e);
    e.erase(std::remove_if(e.begin(), e.end(), isspace), e.end());
    for(int x = 0; x < e.length(); x++) {
        if (e[x] == '(' && e[x+1] == '('){
            e.erase(x, 1);
        }
        if (e[x] == ')' && e[x+1] == ')'){
            e.erase(x, 1);
        }
    }
    std::cout<<e;
    return 0;
}

Questo non ha alcuna logica di precedenza e fallisce molti dei casi di test indicati.
Anders Kaseorg,
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.