C, (78 + 26 * strlen) Codels
Dies war überraschend schwierig zu optimieren, hauptsächlich wegen der Möglichkeit von Farbkollisionen in benachbarten Linien.
Die Zeichen werden in Basis 12 konvertiert, sodass jedes Zeichen eine zweistellige Zahl ist. Jede Standardzeile enthält Folgendes: Zeiger (jetzt rechts für ungerade Zeilen, links für gerade Zeilen), Duplikat (die Zahl 12, die zuerst auf dem Stapel liegt), Push (1. Ziffer), Multiplizieren, Push (2. Ziffer), Addieren , outc, push (1 für ungerade Zeilen, 3 für gerade Zeilen), duplicate, whitespace, pointer (jetzt unten am Zeilenende).
Um Farbkollisionen in benachbarten Zeilen zu vermeiden, wird der Zustand nach dem Füllen mit Leerzeichen gespeichert und die Generierung wird darauf zurückgesetzt, wenn eine Kollision auftritt. Der nächste Versuch beginnt dort mit der nächsten Farbe.
Ausgabe für "Hallo 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);\
}