C, (78 + 26 * strlen) codels
Ini mengejutkan sulit untuk dioptimalkan, terutama karena kemungkinan tabrakan warna di garis tetangga.
Karakter dikonversi ke basis 12, sehingga setiap karakter adalah angka 2 digit. Setiap baris standar berisi yang berikut: pointer (sekarang tepat untuk garis ganjil, kiri untuk garis genap), duplikat (angka 12, yang pertama di tumpukan), tekan (digit 1), gandakan, tekan (digit kedua), tambahkan , outc, push (1 untuk garis ganjil, 3 untuk garis genap), duplikat, spasi putih, pointer (sekarang turun di akhir baris).
Untuk menghindari tabrakan warna di garis tetangga, keadaan setelah mengisi spasi putih diingat, dan generasi digulirkan kembali ke sana jika terjadi tabrakan. Percobaan berikutnya dimulai dengan warna berikutnya.
Output untuk "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
#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);\
}