Строка в изображение

18

Немного предыстории:

Когда я впервые узнал о Brainf * ck, одной из первых вещей, которые я сделал, было написание приложения Java, которое будет принимать строку и создавать несколько оптимизированную программу для печати указанной строки.

Недавно я играл с Питом , и я играл с тем же. Я понял, что Piet - довольно интересный язык, который добавляет немного этой проблемы.

Итак, я хотел бросить вызов своим друзьям в SE. Давайте посмотрим, что вы можете сделать с этим языком.

Соревнование

Напишите программу или функцию, которая принимает некоторую непустую строку символов ASCII. Обработайте строку так, чтобы вы сгенерировали программу Piet, которая напечатает строку и завершит работу.

Вывод является исходным изображением в любом формате, который вам подходит. PNG является предпочтительным, но не обязательным.

Функциональность Пита может быть проверена здесь .

Код Пита должен генерировать саму строку вывода. Вход от пользователей запрещен.

Можно использовать только цвета, одобренные Piet, как показано ниже:

пит-цвета

Поскольку это конкурс популярности, победители будут выбраны путем голосования. Связи будут разбиты по размеру исходного кода.

Бонусные баллы будут начисляться на мое усмотрение в зависимости от креативности выходных изображений. В конце концов, это картинки.

tfitzger
источник

Ответы:

9

C, (78 + 26 * strlen) кодов

Это было удивительно сложно оптимизировать, в основном из-за возможности цветных коллизий в соседних линиях.

Символы преобразуются в основание 12, поэтому каждый символ представляет собой двузначное число. Каждая стандартная строка содержит следующее: указатель (теперь справа для нечетных строк, слева для четных строк), дубликат (число 12, которое является первым в стеке), push (1-ая цифра), умножение, push (2-ая цифра), add , outc, push (1 для нечетных строк, 3 для четных строк), дубликат, пробел, указатель (теперь вниз в конце строки).

Чтобы избежать цветовых коллизий в соседних строках, запоминается состояние после заполнения пробелов, и генерация откатывается к нему, если происходит коллизия. Следующая попытка начинается со следующего цвета.

Вывод для «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);\
                                       }
Мануэль Кастен
источник
5

C, (384 + 256 * strlen) кодов, без оптимизации

Нет умного взлома в этом решении. Каждый символ представлен одной строкой с высотой в пикселях = значение ascii. Операционная последовательность - это push, outc, push, outc, ...

Вывод для "Hello Piet!" (и масштаб верхней части):

болтушка

asciipiet.c

#include "img.h"

Color piet[6][3] = {
    {{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};

int main(int argc, char* argv[])
{
    char* str;
    int len, i, hue, dark;
    Image out;

    if(argc != 2)
    {
        printf("Usage: %s \"string to print\"\n", argv[0]);
        return -1;
    }

    str = argv[1];
    len = strlen(str);

    imgCreate(out, len * 2 + 3, 128);

    hue = 0;
    dark = 1;
    for(i = 0; i < len; i++)
    {
        imgLine(out, i * 2, 0, i * 2, str[i] - 1, piet[hue][dark]);
        dark = (dark + 1) % 3;
        imgSetP(out, i * 2 + 1, 0, piet[hue][dark]);
        dark = (dark + 2) % 3;
        hue = (hue + 5) % 6;
    }
    imgSetP(out, len * 2, 0, piet[hue][dark]);
    imgSetP(out, len * 2 + 1, 0, white);
    imgSetP(out, len * 2 + 2, 0, white);
    imgSetP(out, len * 2 + 2, 1, white);
    imgSetP(out, len * 2 + 2, 2, white);
    imgSetP(out, len * 2 + 2, 3, white);
    imgSetP(out, len * 2 + 1, 3, white);
    imgSetP(out, len * 2, 2, piet[0][4]);
    imgSetP(out, len * 2, 3, piet[0][5]);
    imgSetP(out, len * 2, 4, piet[0][6]);

    imgSave(out, "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);\
                                       }
Мануэль Кастен
источник