C, codeles (78 + 26 * strlen)
Esto fue sorprendentemente difícil de optimizar, principalmente debido a la posibilidad de colisiones de color en líneas vecinas.
Los caracteres se convierten a la base 12, por lo que cada carácter es un número de 2 dígitos. Cada línea estándar contiene lo siguiente: puntero (ahora a la derecha para líneas impares, a la izquierda para líneas pares), duplicado (el número 12, que es el primero en la pila), empujar (1er dígito), multiplicar, empujar (2do dígito), agregar , outc, push (1 para líneas impares, 3 para líneas pares), duplicado, espacios en blanco, puntero (ahora hacia abajo al final de la línea).
Para evitar colisiones de color en líneas vecinas, se recuerda el estado después del relleno de espacios en blanco, y la generación se revierte si ocurre una colisión. El siguiente intento comienza allí con el siguiente color.
Salida para "Hello Piet!":
asciipiet2.c
#include "img.h"
#define WIDTH 26
#define OP(op, h, d) int op() { hue += h; dark += d; hue %= 6; dark %= 3; return setp(); }
#define CCMP(c1, c2) (((c1).r == (c2).r) && ((c1).g == (c2).g) && ((c1).b == (c2).b))
#define OPCNT(op) if(op) continue
Color piet[6][2] =
{
{{0xff, 0xc0, 0xc0}, {0xff, 0x00, 0x00}, {0xc0, 0x00, 0x00}},
{{0xff, 0xff, 0xc0}, {0xff, 0xff, 0x00}, {0xc0, 0xc0, 0x00}},
{{0xc0, 0xff, 0xc0}, {0x00, 0xff, 0x00}, {0x00, 0xc0, 0x00}},
{{0xc0, 0xff, 0xff}, {0x00, 0xff, 0xff}, {0x00, 0xc0, 0xc0}},
{{0xc0, 0xc0, 0xff}, {0x00, 0x00, 0xff}, {0x00, 0x00, 0xc0}},
{{0xff, 0xc0, 0xff}, {0xff, 0x00, 0xff}, {0xc0, 0x00, 0xc0}}
};
Color white = {0xff, 0xff, 0xff};
Image img;
int hue, dark, x, y, dx = 1;
void nextline()
{
x -= dx;
dx = -dx;
y += 1;
}
int setp()
{
if(y > 0 && CCMP(piet[hue][dark], imgGetP(img, x, y - 1)))
{
return 1;
}
imgSetP(img, x, y, piet[hue][dark]);
x += dx;
return 0;
}
void whiteto(int to)
{
if(dx == 1)
{
while(x < to) imgSetP(img, x++, y, white);
}
else
{
while(x >= WIDTH - to) imgSetP(img, x--, y, white);
}
}
OP(fill, 0, 0)
OP(pushraw, 0, 1)
OP(pop, 0, 2)
OP(add, 1, 0)
OP(sub, 1, 1)
OP(mul, 1, 2)
OP(divi, 2, 0)
OP(mod, 2, 1)
OP(not, 2, 2)
OP(gt, 3, 0)
OP(pnt, 3, 1)
OP(sw, 3, 2)
OP(dup, 4, 0)
OP(roll, 4, 1)
OP(in, 4, 2)
OP(inc, 5, 0)
OP(out, 5, 1)
OP(outc, 5, 2)
int push(int num);
int pushn(int num) { int i; for(i = 0; i < num - 1; ++i) { if(fill()) return 1; } return pushraw(); }
int push0() { return (push(1) || not()); }
int push8() { return (push(2) || dup() || dup() || mul() || mul()); }
int push9() { return (push(3) || dup() || mul()); }
int push10() { return (push(9) || push(1) || add()); }
int push11() { return (push(9) || push(2) || add()); }
int push(int num)
{
switch(num)
{
case 0: return push0();
case 8: return push8();
case 9: return push9();
case 10: return push10();
case 11: return push11();
default: return pushn(num);
}
}
int main(int argc, char* argv[])
{
char* str;
int len, i;
if(argc != 2)
{
printf("Usage: %s \"string to print\"\n", argv[0]);
return -1;
}
str = argv[1];
len = strlen(str);
imgCreate(img, WIDTH, len + 3);
fill(); push(4); push(3); mul(); push(1); dup(); whiteto(WIDTH - 2);
for(i = 0; i < len; ++i)
{
int var, sx = x, sy = y, sdx = dx, fin = 0, off = rand();
for(var = 0; var < 18 && !fin; var++)
{
x = sx; y = sy; dx = sdx;
hue = ((var + off) % 18) / 3; dark = ((var + off) % 18) % 3;
OPCNT(fill()); OPCNT(pnt());
nextline(); pnt(); dup();
OPCNT(push(str[i] / 12)); OPCNT(mul()); OPCNT(push(str[i] % 12)); OPCNT(add()); OPCNT(outc()); OPCNT(push(2 - dx)); if(i != len - 1) { OPCNT(dup()); }
whiteto(WIDTH - 2);
fin = 1;
}
if (!fin)
{
printf("collision unavoidable\n");
return -1;
}
}
x -= dx;
{
int var, sx = x, sy = y, sdx = dx, fin = 0;
for(var = 0; var < 18 && !fin; var++)
{
x = sx; y = sy; dx = sdx;
hue = var / 3; dark = var % 3;
OPCNT(fill()); OPCNT(pnt()); OPCNT(fill());
fin = 1;
}
if (!fin)
{
printf("collision unavoidable\n");
return -1;
}
}
x -= 2 * dx;
y += 1;
imgSetP(img, x, y, white);
x -= dx;
y += 1;
hue = 0; dark = 1;
fill(); fill(); fill();
imgSave(img, "piet.pnm");
return 0;
}
img.h
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
} Color;
typedef struct
{
Color* data;
int width;
int height;
} Image;
#define imgCreate(img, w, h) {\
int length;\
(img).width = (w);\
(img).height = (h);\
length = (img).width * (img).height * sizeof(Color);\
(img).data = malloc(length);\
memset((img).data, 0, length);\
}
#define imgDestroy(img) {\
free((img).data);\
(img).width = 0;\
(img).height = 0;\
}
#define imgGetP(img, x, y) ((img).data[(int)(x) + (int)(y) * (img).width])
#define imgSetP(img, x, y, c) {\
(img).data[(int)(x) + (int)(y) * (img).width] = c;\
}
#define imgLine(img, x, y, xx, yy, c) {\
int x0 = (x), y0 = (y), x1 = (xx), y1 = (yy);\
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;\
int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;\
int err = dx + dy, e2;\
\
for(;;)\
{\
imgSetP((img), x0, y0, c);\
if (x0 == x1 && y0 == y1) break;\
e2 = 2 * err;\
if (e2 >= dy) {err += dy; x0 += sx;}\
if (e2 <= dx) {err += dx; y0 += sy;}\
}\
}
#define imgSave(img, fname) {\
FILE* f = fopen((fname), "wb");\
fprintf(f, "P6\n%d %d\n255\n", (img).width, (img).height);\
fwrite((img).data, sizeof(Color), (img).width * (img).height, f);\
fclose(f);\
}
#define imgLoad(img, fname) {\
FILE* f = fopen((fname), "rb");\
char buffer[16];\
int index = 0;\
int field = 0;\
int isP5 = 0;\
unsigned char c = ' ';\
while(field < 4)\
{\
do\
{\
if(c == '#') while(c = fgetc(f), c != '\n');\
} while(c = fgetc(f), isspace(c) || c == '#');\
index = 0;\
do\
{\
buffer[index++] = c;\
} while(c = fgetc(f), !isspace(c) && c != '#' && index < 16);\
buffer[index] = 0;\
switch(field)\
{\
case 0:\
if (strcmp(buffer, "P5") == 0) isP5 = 1;\
else if (strcmp(buffer, "P6") == 0) isP5 = 0;\
else fprintf(stderr, "image format \"%s\" unsupported (not P5 or P6)\n", buffer), exit(1);\
break;\
case 1:\
(img).width = atoi(buffer);\
break;\
case 2:\
(img).height = atoi(buffer);\
break;\
case 3:\
index = atoi(buffer);\
if (index != 255) fprintf(stderr, "image format unsupported (not 255 values per channel)\n"), exit(1);\
break;\
}\
field++;\
}\
imgCreate((img), (img).width, (img).height);\
if (isP5)\
{\
int length = (img).width * (img).height;\
for(index = 0; index < length; ++index)\
{\
(img).data[index].r = (img).data[index].g = (img).data[index].b = fgetc(f);\
}\
}\
else\
{\
fread((img).data, sizeof(Color), (img).width * (img).height, f);\
}\
fclose(f);\
}