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.