0votos

Ecuación de primer grado en C

por josejuan hace 6 años

Ahora me da por C :) La solución procesa la fórmula una única vez de izq. a der. (no hace falta almacenar el árbol) procesando directamente el árbol AST. Para simplificar se asume un acumulador de la forma (A + Bx) / C. El resultado final se obtiene ignorando C y despejando directamente. La máquina de estados la he escrito directamente (L1, L2, L3a, ...).

Resolución de ecuación de primer grado

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 
 
typedef struct { long a, b, c; } R; 
 
#define PC (*c) 
#define C (**c) 
 
void Error(char *msg) { 
    fprintf(stderr, "ERROR: %s\n", msg); 
    exit(1); 
 
R L2(char **c); 
R L3a(char **c); 
R L3b(char **c, R m); 
R L3c(char **c, R m); 
 
R L1(char **c) { 
    if(C == '(') { 
        PC++; 
        R a = L2(c); 
        if(C != ')') Error("Se esperaba cierre de paréntesis"); 
        PC++; 
        return a; 
    return L2(c); 
 
#define ADD(OP) { r.a = a.a * b.c OP a.c * b.a; \ 
          r.b = a.b * b.c OP a.c * b.b; \ 
          r.c = a.c * b.c; } 
 
R L2(char **c) { 
    R a = L3a(c); 
    char o = C; 
    if(o == '-' || o == '+') { 
        PC++; 
        R r, b = L2(c); 
        if(o == '-') ADD(-) else ADD(+) 
        return r; 
    return a; 
 
char N(char **c, R *n) { 
    if(C == '(') { 
        *n = L1(c); 
        return 1; 
    if(C == 'x') { 
        PC++; 
        n->a = 0; 
        n->b = n->c = 1; 
        return 1; 
    if(isdigit(C)) { 
        n->a = atoi(PC); 
        n->b = 0; 
        n->c = 1; 
        while(isdigit(C)) PC++; 
        return 1; 
    return 0; 
 
R L3a(char **c) { 
    R a; 
    if(C == '-') { 
        PC++; 
        a = L3a(c); 
        a.c -= a.c; 
        return a; 
    if(N(c, &a)) 
        return L3b(c, a); 
    Error("Se esperaba una expresión"); 
    /**/return a;/**/ 
 
R L3b(char **c, R m) { 
    R a, r; 
    if(N(c, &a)) { 
        if(m.b != 0 && a.b != 0) Error("Se aplica el cuadrado de la variable"); 
        r.a = m.a * a.a; 
        r.b = m.a * a.b + m.b * a.a; 
        r.c = a.c * m.c; 
        return L3b(c, r); 
    if(C == '/') { 
        PC++; 
        return L3b(c, L3c(c, m)); 
    return m; 
 
R L3c(char **c, R m) { 
    R a; 
    if(C == '-') { 
        PC++; 
        a = L3c(c, m); 
        a.c = -a.c; 
        return a; 
    if(N(c, &a)) { 
        if(a.b != 0) Error("Se divide por la variable"); 
        m.a *= a.c; 
        m.b *= a.c; 
        m.c *= a.a; 
        return m; 
    Error("Se esperaba un número o variable"); 
    /**/return a;/**/ 
 
int mcd(int n, int d) { 
    if(d) return mcd(d, n % d); 
    return n; 
 
void Solve(char *p) { 
    R a = L1(&p), b, r; 
    if(*p++ != '=') Error("Se esperaba el símblo de identidad"); 
    b = L1(&p); 
    ADD(-); 
    if(r.b < 0) {r.a = -r.a; r.b = -r.b; } 
    long d = mcd(r.a < 0 ? -r.a : r.a, r.b); 
    printf("x = %i / %i\n", -r.a / d, r.b / d); 
 
int main(int argc, char **argv) { 
    Solve(argv[1]); 
    return 0; 

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.