Problema Ecuații – OJI 2006, Clasa a 10-a

Problema Ecuații – OJI 2006, Clasa a 10-a

Rezumat

Se dau n ecuații de gradul I, cu necunoscuta x. Fiecare ecuație are un membru stâng și un membru drept. Fiecare membru este constituit dintr-o succesiune de operanzi, despărțiți prin operatorii de adunare (+) și de scădere (-). Fiecare operand este un număr natural, un număr natural urmat de x, sau doar x.

Se cere să se afișeze soluția fiecărei ecuații. Dacă o ecuație admite o infinitate de soluții (poate fi redusă la identitatea 0 = 0), se va afișa infinit. Dacă o ecuație nu admite nicio soluție (se reduce la o ecuație de genul 1 = 2), se va afișa mesajul imposibil.

Soluție

Am procedat ca la orice problemă de evaluare de expresii. Dar, pentru a lucra mai ușor, am definit niște constante utile:

// Semnul pe care îl poate avea operandul curent:
#define MINUS -1
#define PLUS +1
// Valorile pe care le poate avea membrul curent (stânga/dreapta):
#define LEFT +1
#define RIGHT -1

Pentru fiecare expresie, am inițializat membrul curent (mmbr) cu LEFT, semnul curent (sign) cu PLUS și numărul curent (nr) cu 0. Apoi, am parcurs expresia astfel:

  • Dacă am găsit o cifră, actualizez nr.
  • Dacă am găsit un semn și caracterul precedent era o cifră, înseamnă că am terminat de citit un termen liber. Actualizez variabila b (suma termenilor liberi) prin b += nr * semn * mmbr, precum și semnul curent. Resetez nr la 0.
  • Dacă am găsit un x, actualizez suma coeficienților termenilor cu x (a) prin a += nr * semn * mmbr. Sunt atent că dacă x nu e precedat de o cifră, înseamnă că are coeficientul 1. Apoi resetez nr la 0.
  • Dacă am găsit semnul =, actualizez b dacă e cazul, și resetez nr la 0. Apoi, marchez că am trecut la membrul drept prin mmbr = RIGHT. De asemenea, setez semnul curent la PLUS.

Am definit acele constante folosind -1 și +1 ca să scriu ușor expresiile pentru actualizarea variabilelor a și b. De exemplu, dacă mmbr == -1 și sign == -1, atunci ar trebui să adăugăm la a (sau b) valoarea nr, pentru că un termen cu semnul minus din membrul drept se trece în cel stâng cu plus. Și chiar asta se întâmplă, pentru că -1 * -1 == 1. Dacă aș fi folosit valori ca true și false, ar fi trebuit să mă complic cu niște if-uri imbricate.

La final, dacă a și b sunt 0, soluția va fi infinit, dacă a este 0, soluția va fi imposibil, iar altfel -b / a. Mai trebuie să fim atenți că soluțiile se afișează cu 4 zecimale. Pentru asta am folosit fixed și funcția setprecision(4). În plus, am declarat variabilele a și b drept double, ca să se efectueze împărțirea reală.

Sursă C++

Problema Ecuații
#include <ios>
#include <iomanip>
#include <fstream>
#define SMAX 260
#define PLUS +1
#define MINUS -1
#define LEFT +1
#define RIGHT -1
using std::fixed;
using std::setprecision;
std::ifstream fin("ecuatii.in");
std::ofstream fout("ecuatii.out");
int n;
double a, b;
char str[SMAX];
void eval() {
char *p;
int nr = 0;
int mmbr = LEFT;
int sign = PLUS;
a = b = 0;
for (p = str; *p; p++)
if (*p == '-') {
if ('0' <= *(p - 1) && *(p - 1) <= '9')
b += nr * sign * mmbr, nr = 0;
sign = MINUS;
}
else if (*p == '+') {
if ('0' <= *(p - 1) && *(p - 1) <= '9')
b += nr * sign * mmbr, nr = 0;
sign = PLUS;
}
else if (*p == '=') {
if ('0' <= *(p - 1) && *(p - 1) <= '9')
b += nr * sign * mmbr;
nr = 0;
mmbr = RIGHT;
sign = PLUS;
}
else if (*p == 'x') {
if ('0' <= *(p - 1) && *(p - 1) <= '9')
a += nr * sign * mmbr, nr = 0;
else
a += sign * mmbr;
}
else
nr = nr * 10 + *p - '0';
if ('0' <= *(p - 1) && *(p - 1) <= '9')
b += nr * sign * mmbr;
}
int main() {
fin >> n;
fout << fixed << setprecision(4);
for (int i = 0; i < n; i++) {
fin >> str;
eval();
if (!a && !b)
fout << "infinit\n";
else if (!a)
fout << "imposibil\n";
else
fout << -b / a << '\n';
}
return 0;
}

Dacă ai vreo nedumerire cu privire la problema Ecuații, lasă un comentariu și te voi ajuta

Mulțumesc că ai citit acest articol.
Dacă vrei să susții blogul, poți cumpăra un abonament de 2$.

patreon

Lasă un comentariu!

0 comentarii