สตริงไปยังรูปภาพ


18

พื้นหลังเล็กน้อย:

เมื่อฉันเรียนรู้เกี่ยวกับ Brainf * ck สิ่งแรกที่ฉันทำคือเขียนแอปพลิเคชัน Java ที่จะใช้สตริงและสร้างโปรแกรมที่ปรับให้เหมาะสมเพื่อพิมพ์สตริงดังกล่าว

เมื่อเร็ว ๆ นี้ฉันได้เล่นกับPietและฉันก็เล่นกับทำสิ่งเดียวกัน ฉันได้ตระหนักว่า Piet เป็นภาษาที่ค่อนข้างน่าสนใจซึ่งเพิ่มความท้าทายนี้เล็กน้อย

ดังนั้นฉันต้องการที่จะนำความท้าทายออกไปให้เพื่อนของฉันที่ SE มาดูกันว่าคุณสามารถทำอะไรกับภาษานี้

ความท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่รับสายอักขระ ASCII ที่ไม่ว่างเปล่า ประมวลผลสตริงเพื่อให้คุณสร้างโปรแกรม Piet ที่จะพิมพ์สตริงและยุติ

เอาต์พุตเป็นรูปภาพต้นฉบับแบบ piet ในรูปแบบใดก็ตามที่ดีที่สุดสำหรับคุณ เป็นที่ต้องการ PNG แต่ไม่บังคับ

ฟังก์ชั่น Piet สามารถทดสอบได้ที่นี่ที่นี่

รหัส Piet จะต้องสร้างสตริงเอาต์พุตเอง ไม่อนุญาตให้ป้อนข้อมูลจากผู้ใช้

อาจใช้สีที่ได้รับการอนุมัติ Piet เท่านั้นดังที่แสดงด้านล่าง:

สีเปีย

เนื่องจากเป็นการประกวดความนิยมผู้ชนะจะถูกเลือกด้วยคะแนนเสียง ความสัมพันธ์จะถูกทำลายโดยขนาดซอร์สโค้ด

คะแนนโบนัสจะมอบให้ตามดุลยพินิจของฉันโดยพิจารณาจากความคิดสร้างสรรค์ของภาพที่ส่งออก นี่คือรูปภาพหลังจากทั้งหมด

คำตอบ:


9

C, (78 + 26 * strlen) โคเดล

นี่เป็นเรื่องยากที่จะปรับให้เหมาะสมอย่างน่าประหลาดใจส่วนใหญ่เป็นเพราะความเป็นไปได้ของการชนกันของสีในเส้นข้างเคียง

อักขระจะถูกแปลงเป็นฐาน 12 ดังนั้นอักขระแต่ละตัวจึงเป็นตัวเลข 2 หลัก ทุกบรรทัดมาตรฐานมีดังต่อไปนี้: ตัวชี้ (ตอนนี้เหมาะสำหรับเส้นคี่, เหลือสำหรับเส้นคู่), ซ้ำ (หมายเลข 12, ซึ่งเป็นอันดับแรกบนสแต็ก), กด (หลักที่ 1), คูณ, ผลัก (หลักที่สอง), เพิ่ม , 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 ลำดับ op คือ push, outc, push, outc, ...

ผลลัพธ์สำหรับ "Hello Piet!" (และซูมของส่วนบน):

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);\
                                       }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.