C, (78 + 26 * strlen) codels
Cela a été étonnamment difficile à optimiser, principalement en raison de la possibilité de collisions de couleurs dans les lignes voisines.
Les caractères sont convertis en base 12, donc chaque caractère est un nombre à 2 chiffres. Chaque ligne standard contient les éléments suivants: pointeur (maintenant à droite pour les lignes impaires, à gauche pour les lignes paires), dupliquer (le nombre 12, qui est le premier sur la pile), pousser (1er chiffre), multiplier, pousser (2e chiffre), ajouter , outc, push (1 pour les lignes impaires, 3 pour les lignes paires), dupliquer, espaces, pointeur (maintenant en bas de la ligne).
Pour éviter les collisions de couleurs dans les lignes voisines, l'état après le remplissage des espaces est mémorisé et la génération y est restaurée en cas de collision. Le prochain essai commence là avec la couleur suivante.
Sortie pour "Bonjour 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);\
}