Utolsó módosítás: 2008. november 14.
Itt van egy-egy megoldás az első verseny feladataira. Ezek persze nem feltétlenül a legszebb vagy legegyszerűbb megoldások.
A feladat kiírása; megoldás letöltése: z0f0.c.
#include <stdio.h>
#include <stdlib.h>
int
main(void) {
int k, last, cur;
last = -1;
for (k = 0; k < 14; k++) {
if (1 != scanf("%d", &cur))
exit(1);
if (0 != cur)
last = cur;
printf("%d%c", last, 13 == k ? '\n' : ' ');
}
return 0;
}
A feladat kiírása; megoldás letöltése: z0f1.c.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
die(char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
#define TEMPLATE_MAXLEN 10100
char
template[TEMPLATE_MAXLEN];
void
read_template(void) {
int stop = 0;
size_t pos = 0;
while (!stop) {
if (
TEMPLATE_MAXLEN - pos < 2 ||
!fgets(template + pos, TEMPLATE_MAXLEN - pos, stdin)
)
die("error reading template");
if ('$' == template[pos])
stop = 1;
else
pos += strlen(template + pos);
}
}
#define LINE_MAXLEN 4010
char
line[LINE_MAXLEN];
int
more_mail(void) {
int i;
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record head");
if (1 != sscanf(line, "%d", &i))
die("error: record head has wrong format");
return i;
}
void
process_mail(int wt) {
size_t pos;
size_t len;
int cnt_mmark = 0;
int k;
for (pos = 0; '$' != template[pos]; pos++) {
if ('@' == template[pos]) {
pos++;
if ('i' == template[pos]) {
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record body");
len = strlen(line);
line[len - 1] = 0;
fputs(line, stdout);
} else if ('m' == template[pos] && '\n' == template[pos + 1]) {
cnt_mmark++;
for (k = 0; k < wt; k++) {
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record body");
fputs(line, stdout);
}
pos++;
} else
die("error: field marker has wrong format");
} else
putchar(template[pos]);
}
if (1 != cnt_mmark)
die("exactly one m marker required in the template");
}
int
main(void) {
int wt;
read_template();
while ((wt = more_mail()))
process_mail(wt);
return 0;
}
A feladat kiírása; megoldás letöltése: z0f2.c.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
die(char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
char
mirror_char(char *key, char c) {
while (key[0] && key[1]) {
if (c == key[0])
return key[1];
if (c == key[1])
return key[0];
key += 2;
}
return c;
}
#define TEMPLATE_MAXHEIGHT 20
#define TEMPLATE_MAXWIDTH 20
#define STRIP_MAXWIDTH (2 + TEMPLATE_MAXWIDTH * 10)
int
template_height,
template_width;
char
template[TEMPLATE_MAXHEIGHT][TEMPLATE_MAXWIDTH];
int
num_copies,
copy_mode,
num_vert_copies,
vert_copy_mode;
char
mirrored[TEMPLATE_MAXHEIGHT][TEMPLATE_MAXWIDTH];
char
strip[TEMPLATE_MAXHEIGHT][STRIP_MAXWIDTH],
strip_vert_mirrored[TEMPLATE_MAXHEIGHT][STRIP_MAXWIDTH];
void
read_template(void) {
char line[TEMPLATE_MAXWIDTH + 5];
int r;
for (r = 0; r < template_height; r++) {
if (!fgets(line, TEMPLATE_MAXWIDTH + 5, stdin))
die("eof or error reading template line");
if (template_width != strlen(line) - 1)
die("template line length wrong");
memcpy(template[r], line, template_width);
}
}
void
mirror_template(void) {
int r, c;
for (r = 0; r < template_height; r++) {
for (c = 0; c < template_width; c++)
mirrored[r][c] = mirror_char("()<>[]\\/", template[r][template_width - c - 1]);
}
}
void
output_strip(void) {
int row, copy;
char *p; int l; char *out;
for (row = 0; row < template_height; row++) {
out = strip[row];
for (copy = 0; copy < num_copies; copy++) {
if (0 == copy % 2 || 0 == copy_mode) {
p = template[row]; l = template_width;
} else if (2 == copy_mode) {
p = mirrored[row] + 1; l = template_width - 1;
} else {
p = mirrored[row]; l = template_width;
}
memcpy(out, p, l);
out += l;
}
*out++ = '\n'; *out++ = 0;
}
}
void
mirror_strip(void) {
int r, c;
for (r = 0; r < template_height; r++) {
for (c = 0; strip[r][c]; c++) {
strip_vert_mirrored[r][c] = mirror_char(",'\\/", strip[r][c]);
}
}
}
void
output_all(void) {
int copy, row;
for (copy = 0; copy < num_vert_copies; copy++) {
if (0 == copy % 2 || 0 == vert_copy_mode) {
for (row = 0; row < template_height; row++)
fputs(strip[row], stdout);
} else if (2 == vert_copy_mode) {
for (row = template_height - 2; 0 <= row; row--)
fputs(strip_vert_mirrored[row], stdout);
} else {
for (row = template_height - 1; 0 <= row; row--)
fputs(strip_vert_mirrored[row], stdout);
}
}
}
int
main(void) {
char line[500];
if (!fgets(line, sizeof(line), stdin))
die("error reading parameters");
if (6 != sscanf(line, "%d%d%d%d%d%d",
&template_height, &template_width, &num_copies, ©_mode, &num_vert_copies, &vert_copy_mode
))
die("error parsing parameters");
if (
TEMPLATE_MAXHEIGHT < template_height || template_height < 0 ||
TEMPLATE_MAXWIDTH < template_width || template_width < 0 ||
2 < copy_mode || copy_mode < 0
)
die("invalid parameters");
read_template();
mirror_template();
output_strip();
mirror_strip();
output_all();
return 0;
}
A feladat kiírása; megoldás letöltése: z0f3.c.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int
max(int x, int y) {
return x < y ? y : x;
}
#define PLANBUF_LEN 512
#define PREC_ATOM 0
#define PREC_POWER 2
#define PREC_QUOTIENT 3
#define PREC_PRODUCT 4
#define PREC_SUM 5
#define PREC_FACTOR 6
struct
plan {
int width;
int height;
int depth;
int prec;
int head;
const struct plan *lhs;
const struct plan *rhs;
} planbuf[PLANBUF_LEN];
int
plancnt;
void
init(void) {
plancnt = 0;
}
struct plan *
allocplan(void) {
struct plan *r;
r = planbuf + plancnt++;
if (PLANBUF_LEN < plancnt)
exit(1);
r->lhs = r->rhs = 0;
r->prec = r->head = -1;
r->width = r->height = r->depth = 32767;
return r;
}
const struct plan *
parenthisize(const struct plan *l) {
struct plan *p;
p = allocplan();
p->head = '(';
p->lhs = l;
p->width = l->width + 2;
p->height = l->height;
p->depth = l->depth;
p->prec = PREC_ATOM;
return p;
}
const struct plan *
layout(const char **formulap) {
struct plan *p;
char head;
const struct plan *l, *r;
p = allocplan();
p->head = head = *(*formulap)++;
if (isdigit(head) || islower(head)) {
p->width = 1;
p->height = 1;
p->depth = 0;
p->prec = PREC_ATOM;
} else {
l = layout(formulap);
if ('!' == head) {
if (PREC_POWER <= l->prec)
l = parenthisize(l);
p->width = l->width + 1;
p->height = l->height;
p->depth = l->depth;
p->prec = PREC_ATOM;
} else {
r = layout(formulap);
if ('^' == head) {
if (PREC_POWER <= l->prec)
l = parenthisize(l);
p->width = l->width + r->width;
p->height = l->height + r->depth + r->height;
p->depth = l->depth;
p->prec = PREC_POWER;
} else if ('/' == head) {
p->width = 2 + max(l->width, r->width);
p->height = 1 + l->height + l->depth;
p->depth = r->height + r->depth;
p->prec = PREC_QUOTIENT;
} else if ('*' == head) {
if (PREC_PRODUCT < l->prec)
l = parenthisize(l);
if (PREC_PRODUCT <= r->prec)
r = parenthisize(r);
p->width = 1 + l->width + r->width;
p->height = max(l->height, r->height);
p->depth = max(l->depth, r->depth);
p->prec = PREC_PRODUCT;
} else if ('+' == head || '-' == head) {
if (PREC_SUM <= r->prec)
r = parenthisize(r);
p->width = 3 + l->width + r->width;
p->height = max(l->height, r->height);
p->depth = max(l->depth, r->depth);
p->prec = PREC_SUM;
} else
exit(1);
p->rhs = r;
}
p->lhs = l;
}
return p;
}
#define PAPER_WIDTH 500
#define PAPER_HEIGHT 100
char
paper[PAPER_HEIGHT][PAPER_WIDTH];
int
box_height, box_width;
void
erase(const struct plan *p) {
int r, c;
box_height = p->height + p->depth;
box_width = p->width;
if (PAPER_HEIGHT < box_height || PAPER_WIDTH < box_width)
exit(1);
for (r = 0; r < box_height; r++)
for (c = 0; c < box_width; c++)
paper[r][c] = ' ';
}
void
output(void) {
int r, w, c;
for (r = 0; r < box_height; r++) {
w = box_width;
while (' ' == paper[r][w - 1])
w--;
for (c = 0; c < w; c++)
putchar(paper[r][c]);
putchar('\n');
}
putchar('\n');
}
void
paint(const struct plan *p, int row, int col) {
int r, c;
int head;
if (
row - p->height + 1 < 0 ||
box_height < row + p->depth ||
col < 0 ||
box_width < col + p->width
)
exit(1);
head = p->head;
switch (head) {
case '(':
for (r = row - p->height + 1; r <= row + p->depth; r++) {
paper[r][col] = '(';
paper[r][col + p->width - 1] = ')';
}
paint(p->lhs, row, 1 + col);
break;
case '!':
paint(p->lhs, row, col);
paper[row][col + p->lhs->width] = '!';
break;
case '^':
paint(p->lhs, row, col);
paint(p->rhs, row - p->lhs->height - p->rhs->depth, col + p->lhs->width);
break;
case '/':
for (c = col; c < col + p->width; c++)
paper[row][c] = '-';
paint(p->lhs, row - 1 - p->lhs->depth, col + (p->width - p->lhs->width)/2);
paint(p->rhs, row + p->rhs->height, col + (p->width - p->rhs->width)/2);
break;
case '*':
paint(p->lhs, row, col);
paint(p->rhs, row, 1 + col + p->lhs->width);
break;
case '+': case '-':
paint(p->lhs, row, col);
paper[row][1 + col + p->lhs->width] = head;
paint(p->rhs, row, 3 + col + p->lhs->width);
break;
default:
if (isdigit(head) || islower(head))
paper[row][col] = head;
else
exit(1);
break;
}
}
void
paint_main(const struct plan *p) {
paint(p, p->height - 1, 0);
}
#define FORMULA_LEN 512
int
main(void) {
char formulabuf[FORMULA_LEN];
const struct plan *p;
const char *formula;
while (fgets(formulabuf, FORMULA_LEN, stdin)) {
formula = formulabuf;
init();
p = layout(&formula);
if ('\n' != *formula)
exit(1);
erase(p);
paint_main(p);
output();
}
return 0;
}
A feladat kiírása; megoldás letöltése: z1f0.c.
#include <stdio.h>
#include <stdlib.h>
int
main(void) {
int k, e0, e1, sum;
sum = 0;
for (k = 0; k < 7; k++) {
if (2 != scanf("%d%d", &e0, &e1))
exit(1);
sum = sum + e0 - e1;
}
printf("%d\n", sum);
return 0;
}
A feladat kiírása; megoldás letöltése: z1f1.c.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
die(char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
#define TEMPLATE_MAXLEN 10100
char
template[TEMPLATE_MAXLEN];
void
read_template(void) {
int stop = 0;
size_t pos = 0;
while (!stop) {
if (
TEMPLATE_MAXLEN - pos < 2 ||
!fgets(template + pos, TEMPLATE_MAXLEN - pos, stdin)
)
die("error reading template");
if ('$' == template[pos])
stop = 1;
else
pos += strlen(template + pos);
}
}
#define LINE_MAXLEN 4010
char
line[LINE_MAXLEN];
int
more_mail(void) {
int i;
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record head");
if (1 != sscanf(line, "%d", &i))
die("error: record head has wrong format");
return i;
}
void
process_mail(int weight) {
size_t pos;
size_t len;
int state, branch;
state = -1; branch = -99;
for (pos = 0; '$' != template[pos]; pos++) {
if ('@' == template[pos]) {
pos++;
if ('i' == template[pos]) {
if (state || weight == branch) {
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record body");
len = strlen(line);
line[len - 1] = 0;
fputs(line, stdout);
}
} else if ('s' == template[pos]) {
if (-1 != state)
die("error: multiple select case markers");
state = 0; branch = 1;
} else if ('c' == template[pos]) {
if (0 != state)
die("error: case marker outside select");
branch++;
} else if ('e' == template[pos]) {
if (0 != state)
die("error: end select marker outside select");
state = 1;
} else
die("error: field marker has wrong format");
} else {
if (state || weight == branch)
putchar(template[pos]);
}
}
}
int
main(void) {
int wt;
read_template();
while ((wt = more_mail()))
process_mail(wt);
return 0;
}
A feladat kiírása; megoldás letöltése: z1f2.c.
#include <stdio.h>
#include <stdlib.h>
#define NUM_DAYS 60
int
main(void) {
int reserve1[NUM_DAYS], reserve2[NUM_DAYS];
int num_rooms1, num_rooms2, num_calls;
int first, last, need1, need2;
int r, d, ok;
for (d = 0; d < NUM_DAYS; d++) {
reserve1[d] = 0; reserve2[d] = 0;
}
if (3 != scanf("%d%d%d", &num_rooms1, &num_rooms2, &num_calls))
exit(1);
for (r = 0; r < num_calls; r++) {
if (4 != scanf("%d%d%d%d", &first, &last, &need1, &need2))
exit(1);
if (first < 0 || last < first || NUM_DAYS <= last || need1 < 0 || need2 < 0)
exit(1);
ok = 1;
for (d = first; d <= last; d++) {
if (num_rooms1 < reserve1[d] + need1 || num_rooms2 < reserve2[d] + need2)
ok = 0;
}
if (ok) {
for (d = first; d <= last; d++) {
reserve1[d] += need1; reserve2[d] += need2;
}
printf("1\n");
} else {
printf("0\n");
}
}
return 0;
}
A feladat kiírása; megoldás letöltése: z1f3.c.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int
max(int x, int y) {
return x < y ? y : x;
}
#define PLANBUF_LEN 512
#define PREC_ATOM 0
#define PREC_POWER 2
#define PREC_QUOTIENT 3
#define PREC_PRODUCT 4
#define PREC_SUM 5
struct
plan {
int width;
int height;
int depth;
int prec;
int head;
const struct plan *lhs;
const struct plan *rhs;
} planbuf[PLANBUF_LEN];
int
plancnt;
void
init(void) {
plancnt = 0;
}
struct plan *
allocplan(void) {
struct plan *r;
r = planbuf + plancnt++;
if (PLANBUF_LEN < plancnt)
exit(1);
r->lhs = r->rhs = 0;
r->prec = r->head = -1;
r->width = r->height = r->depth = 32767;
return r;
}
const struct plan *
parenthisize(const struct plan *l) {
struct plan *p;
p = allocplan();
p->head = '(';
p->lhs = l;
p->width = l->width + 2;
p->height = l->height;
p->depth = l->depth;
p->prec = PREC_ATOM;
return p;
}
const struct plan *
layout(const char **formulap) {
struct plan *p;
char head;
const struct plan *l, *r;
p = allocplan();
p->head = head = *(*formulap)++;
if (isdigit(head) || islower(head)) {
p->width = 1;
p->height = 1;
p->depth = 0;
p->prec = PREC_ATOM;
} else {
l = layout(formulap);
r = layout(formulap);
if ('?' == head) {
p->width = 2 + max(l->width, r->width);
p->height = 1 + l->height + l->depth;
p->depth = r->height + r->depth;
p->prec = PREC_ATOM;
} else if ('^' == head) {
if (PREC_POWER <= l->prec)
l = parenthisize(l);
p->width = l->width + r->width;
p->height = l->height + r->depth + r->height;
p->depth = l->depth;
p->prec = PREC_POWER;
} else if ('/' == head) {
p->width = 2 + max(l->width, r->width);
p->height = 1 + l->height + l->depth;
p->depth = r->height + r->depth;
p->prec = PREC_QUOTIENT;
} else if ('*' == head) {
if (PREC_PRODUCT < l->prec)
l = parenthisize(l);
if (PREC_PRODUCT <= r->prec)
r = parenthisize(r);
p->width = 1 + l->width + r->width;
p->height = max(l->height, r->height);
p->depth = max(l->depth, r->depth);
p->prec = PREC_PRODUCT;
} else if ('+' == head || '-' == head) {
if (PREC_SUM <= r->prec)
r = parenthisize(r);
p->width = 3 + l->width + r->width;
p->height = max(l->height, r->height);
p->depth = max(l->depth, r->depth);
p->prec = PREC_SUM;
} else
exit(1);
p->lhs = l;
p->rhs = r;
}
return p;
}
#define PAPER_WIDTH 500
#define PAPER_HEIGHT 100
char
paper[PAPER_HEIGHT][PAPER_WIDTH];
int
box_height, box_width;
void
erase(const struct plan *p) {
int r, c;
box_height = p->height + p->depth;
box_width = p->width;
if (PAPER_HEIGHT < box_height || PAPER_WIDTH < box_width)
exit(1);
for (r = 0; r < box_height; r++)
for (c = 0; c < box_width; c++)
paper[r][c] = ' ';
}
void
output(void) {
int r, w, c;
for (r = 0; r < box_height; r++) {
w = box_width;
while (' ' == paper[r][w - 1])
w--;
for (c = 0; c < w; c++)
putchar(paper[r][c]);
putchar('\n');
}
putchar('\n');
}
void
paint(const struct plan *p, int row, int col) {
int r, c;
int head;
if (
row - p->height + 1 < 0 ||
box_height < row + p->depth ||
col < 0 ||
box_width < col + p->width
)
exit(1);
head = p->head;
switch (head) {
case '(':
for (r = row - p->height + 1; r <= row + p->depth; r++) {
paper[r][col] = '(';
paper[r][col + p->width - 1] = ')';
}
paint(p->lhs, row, 1 + col);
break;
case '?':
for (r = row - p->height + 1; r <= row + p->depth; r++) {
paper[r][col] = '(';
paper[r][col + p->width - 1] = ')';
}
paint(p->lhs, row - 1 - p->lhs->depth, col + (p->width - p->lhs->width)/2);
paint(p->rhs, row + p->rhs->height, col + (p->width - p->rhs->width)/2);
break;
case '^':
paint(p->lhs, row, col);
paint(p->rhs, row - p->lhs->height - p->rhs->depth, col + p->lhs->width);
break;
case '/':
for (c = col; c < col + p->width; c++)
paper[row][c] = '-';
paint(p->lhs, row - 1 - p->lhs->depth, col + (p->width - p->lhs->width)/2);
paint(p->rhs, row + p->rhs->height, col + (p->width - p->rhs->width)/2);
break;
case '*':
paint(p->lhs, row, col);
paint(p->rhs, row, 1 + col + p->lhs->width);
break;
case '+': case '-':
paint(p->lhs, row, col);
paper[row][1 + col + p->lhs->width] = head;
paint(p->rhs, row, 3 + col + p->lhs->width);
break;
default:
if (isdigit(head) || islower(head))
paper[row][col] = head;
else
exit(1);
break;
}
}
void
paint_main(const struct plan *p) {
paint(p, p->height - 1, 0);
}
#define FORMULA_LEN 512
int
main(void) {
char formulabuf[FORMULA_LEN];
const struct plan *p;
const char *formula;
while (fgets(formulabuf, FORMULA_LEN, stdin)) {
formula = formulabuf;
init();
p = layout(&formula);
if ('\n' != *formula)
exit(1);
erase(p);
paint_main(p);
output();
}
return 0;
}
A feladat kiírása; megoldás letöltése: z2f0.c.
#include <stdio.h>
#include <stdlib.h>
int
main(void) {
int k, last, cur, out;
last = 0;
out = 0;
for (k = 0; k < 14; k++) {
if (1 != scanf("%d", &cur))
exit(1);
if (0 < k && cur < last)
out++;
last = cur;
}
printf("%d\n", out);
return 0;
}
A feladat kiírása; megoldás letöltése: z2f1.c.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
die(char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
#define TEMPLATE_MAXLEN 10100
char
template[TEMPLATE_MAXLEN];
void
read_template(void) {
int stop = 0;
size_t pos = 0;
while (!stop) {
if (
TEMPLATE_MAXLEN - pos < 2 ||
!fgets(template + pos, TEMPLATE_MAXLEN - pos, stdin)
)
die("error reading template");
if ('$' == template[pos])
stop = 1;
else
pos += strlen(template + pos);
}
}
#define LINE_MAXLEN 4010
char
line[LINE_MAXLEN];
int
more_mail(void) {
int i;
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record head");
if (1 != sscanf(line, "%d", &i))
die("error: record head has wrong format");
return i;
}
void
process_mail(int wt) {
size_t pos;
size_t len;
int k;
for (pos = 0; '$' != template[pos]; pos++) {
if ('@' == template[pos]) {
pos++;
if ('i' == template[pos]) {
if (!fgets(line, LINE_MAXLEN, stdin))
die("error reading record body");
len = strlen(line);
line[len - 1] = 0;
fputs(line, stdout);
} else if ('h') {
for (k = 0; k < wt; k++)
putchar('-');
} else
die("error: field marker has wrong format");
} else
putchar(template[pos]);
}
}
int
main(void) {
int wt;
read_template();
while ((wt = more_mail()))
process_mail(wt);
return 0;
}
A feladat kiírása; megoldás letöltése: z2f2.c.
#include <stdio.h>
#include <stdlib.h>
#define MAX_TRAIN 50
void
printtime(int t) {
printf("%02d:%02d", t/60, t%60);
}
int
scantime() {
int hour, min;
if (2 != scanf("%d:%d", &hour, &min))
exit(1);
return 60 * hour + min;
}
int
train0_depart[MAX_TRAIN],
train0_arrive[MAX_TRAIN];
int
train1_depart[MAX_TRAIN],
train1_arrive[MAX_TRAIN];
int
main(void) {
int ntrains0, ntrains1, k;
int leave_time, first_walk, board0_time, board1_time,
latest_unboard0_time, latest_unboard1_time, second_walk, latest_arrive_time;
if (1 != scanf("%d", &first_walk))
exit(1);
latest_arrive_time = scantime();
if (1 != scanf("%d", &second_walk))
exit(1);
latest_unboard1_time = latest_arrive_time - second_walk;
if (1 != scanf("%d", &ntrains0))
exit(1);
for (k = 0; k < ntrains0; k++) {
train0_depart[k] = scantime();
train0_arrive[k] = scantime();
}
if (1 != scanf("%d", &ntrains1))
exit(1);
for (k = 0; k < ntrains1; k++) {
train1_depart[k] = scantime();
train1_arrive[k] = scantime();
}
board1_time = -10000;
for (k = 0; k < ntrains1; k++) {
if (train1_arrive[k] <= latest_unboard1_time) {
if (board1_time < train1_depart[k]) {
board1_time = train1_depart[k];
}
}
}
latest_unboard0_time = board1_time;
board0_time = -10000;
for (k = 0; k < ntrains0; k++) {
if (train0_arrive[k] <= latest_unboard0_time) {
if (board0_time < train0_depart[k]) {
board0_time = train0_depart[k];
}
}
}
leave_time = board0_time - first_walk;
printtime(leave_time);
printf("\n");
return 0;
}
A feladat kiírása; megoldás letöltése: z2f3.c.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int
max(int x, int y) {
return x < y ? y : x;
}
#define PLANBUF_LEN 512
#define PREC_ATOM 0
#define PREC_POWER 2
#define PREC_QUOTIENT 3
#define PREC_PRODUCT 4
#define PREC_SUM 5
struct
plan {
int width;
int height;
int depth;
int prec;
int head;
const struct plan *lhs;
const struct plan *rhs;
} planbuf[PLANBUF_LEN];
int
plancnt;
void
init(void) {
plancnt = 0;
}
struct plan *
allocplan(void) {
struct plan *r;
r = planbuf + plancnt++;
if (PLANBUF_LEN < plancnt)
exit(1);
r->lhs = r->rhs = 0;
r->prec = r->head = -1;
r->width = r->height = r->depth = 32767;
return r;
}
const struct plan *
parenthisize(const struct plan *l) {
struct plan *p;
p = allocplan();
p->head = '(';
p->lhs = l;
p->width = l->width + 2;
p->height = l->height;
p->depth = l->depth;
p->prec = PREC_ATOM;
return p;
}
const struct plan *
layout(const char **formulap) {
struct plan *p;
char head;
const struct plan *l, *r;
p = allocplan();
p->head = head = *(*formulap)++;
if (isdigit(head) || islower(head)) {
p->width = 1;
p->height = 1;
p->depth = 0;
p->prec = PREC_ATOM;
} else {
l = layout(formulap);
r = layout(formulap);
if ('^' == head) {
if (PREC_POWER <= l->prec)
l = parenthisize(l);
p->width = l->width + r->width;
p->height = max(l->height, 1 + r->depth + r->height);
p->depth = l->depth;
p->prec = PREC_POWER;
} else if ('/' == head) {
p->width = 2 + max(l->width, r->width);
p->height = 1 + l->height + l->depth;
p->depth = r->height + r->depth;
p->prec = PREC_QUOTIENT;
} else if ('*' == head) {
if (PREC_PRODUCT < l->prec)
l = parenthisize(l);
if (PREC_PRODUCT <= r->prec)
r = parenthisize(r);
p->width = 1 + l->width + r->width;
p->height = max(l->height, r->height);
p->depth = max(l->depth, r->depth);
p->prec = PREC_PRODUCT;
} else if ('+' == head || '-' == head) {
if (PREC_SUM <= r->prec)
r = parenthisize(r);
p->width = 3 + l->width + r->width;
p->height = max(l->height, r->height);
p->depth = max(l->depth, r->depth);
p->prec = PREC_SUM;
} else
exit(1);
p->lhs = l;
p->rhs = r;
}
return p;
}
#define PAPER_WIDTH 500
#define PAPER_HEIGHT 100
char
paper[PAPER_HEIGHT][PAPER_WIDTH];
int
box_height, box_width;
void
erase(const struct plan *p) {
int r, c;
box_height = p->height + p->depth;
box_width = p->width;
if (PAPER_HEIGHT < box_height || PAPER_WIDTH < box_width)
exit(1);
for (r = 0; r < box_height; r++)
for (c = 0; c < box_width; c++)
paper[r][c] = ' ';
}
void
output(void) {
int r, w, c;
for (r = 0; r < box_height; r++) {
w = box_width;
while (' ' == paper[r][w - 1])
w--;
for (c = 0; c < w; c++)
putchar(paper[r][c]);
putchar('\n');
}
putchar('\n');
}
void
paint(const struct plan *p, int row, int col) {
int r, c;
int head;
if (
row - p->height + 1 < 0 ||
box_height < row + p->depth ||
col < 0 ||
box_width < col + p->width
)
exit(1);
head = p->head;
switch (head) {
case '(':
for (r = row - p->height + 1; r <= row + p->depth; r++) {
paper[r][col] = '(';
paper[r][col + p->width - 1] = ')';
}
paint(p->lhs, row, 1 + col);
break;
case '^':
paint(p->lhs, row, col);
paint(p->rhs, row - max(p->lhs->height - p->rhs->height, 1 + p->rhs->depth), col + p->lhs->width);
break;
case '/':
for (c = col; c < col + p->width; c++)
paper[row][c] = '-';
paint(p->lhs, row - 1 - p->lhs->depth, col + (p->width - p->lhs->width)/2);
paint(p->rhs, row + p->rhs->height, col + (p->width - p->rhs->width)/2);
break;
case '*':
paint(p->lhs, row, col);
paint(p->rhs, row, 1 + col + p->lhs->width);
break;
case '+': case '-':
paint(p->lhs, row, col);
paper[row][1 + col + p->lhs->width] = head;
paint(p->rhs, row, 3 + col + p->lhs->width);
break;
default:
if (isdigit(head) || islower(head))
paper[row][col] = head;
else
exit(1);
break;
}
}
void
paint_main(const struct plan *p) {
paint(p, p->height - 1, 0);
}
#define FORMULA_LEN 512
int
main(void) {
char formulabuf[FORMULA_LEN];
const struct plan *p;
const char *formula;
while (fgets(formulabuf, FORMULA_LEN, stdin)) {
formula = formulabuf;
init();
p = layout(&formula);
if ('\n' != *formula)
exit(1);
erase(p);
paint_main(p);
output();
}
return 0;
}