Вывод 2015 года в виде QR-кода

15

Миссия проста. Просто выведите число 2015 в виде QR-кода и запишите его в файл с именем newyear.pngв формате PNG. Код должен быть действителен в любой день, поэтому, возможно, вы не будете использовать текущий год.

QR-код в виде текста выглядит так:

# # # # # # #   # # # #     # # # # # # #
#           #           #   #           #
#   # # #   #   # #     #   #   # # #   #
#   # # #   #       #   #   #   # # #   #
#   # # #   #       #   #   #   # # #   #
#           #               #           #
# # # # # # #   #   #   #   # # # # # # #
                #   # #
#   #     # #     # #     # #       #   #
  # # #   #   #   #   # #   #     #   # #
#   # #   # # #   # # # # # #   #       #
# # #         # #         # # # #
# # # # #   #   #     #     #   #     #
                      # # # #
# # # # # # #       #   # #   # #   #   #
#           #   #         # # # #
#   # # #   #         #     #   #     #
#   # # #   #     #     # # # # #
#   # # #   #   #   #   # #   # #   #   #
#           #     # #       # # #   # # #
# # # # # # #   #           #   #   #   #

Записанный результат newyear.pngдолжен содержать этот QR-код с белыми 5-пиксельными границами и точками размером один пиксель. Он не должен содержать ничего, кроме QR-кода.

Ханнес Карппила
источник
1
это может быть жестко, или вы должны сгенерировать код qr?
подземный
7
Гораздо больше ответов будет, если это будет основано на выводе ascii art, а не на выводе изображения
Оптимизатор
6
Должен ли код быть точным без ошибок или достаточно, чтобы он сканировался правильно? (QR-коды имеют много преднамеренной избыточности и исправления ошибок, поэтому вы можете переворачивать много пикселей, и они все равно будут работать.) Кроме того, это должен быть PNG или мы можем использовать другие форматы изображений (я думаю, особенно про PBM тут)?
Илмари Каронен

Ответы:

12

Необработанный файл, 184 байта = 173-байтовый файл + 11-байтовое имя файла

Надеюсь, это не сломает ни одной стандартной лазейки. Но вывод «имеет высокую и самый короткий способ его производства - это (скорее всего) просто напечатать его буквально ...».

newyear.png

База 64 файла:

iVBORw0KGgoAAAANSUhEUgAAAB8AAAAfAQAAAAA31SuUAAAAdElEQVR4XnXOMQ5BQRRA0euVRFgGCq1ubIyJpSh11I
qJWIjo+fnt/JnJe55WornlycXMVAB+Qp49A7U/J8rqlIQReG5Quz6Rx8eA6VaF5R7a5arooXg2LaKvd8KGRyBPJLoy
D640pxZ3pay/creL5KnEvwcfvE46ggJMibIAAAAASUVORK5CYII=

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

Итак, я написал программу для генерации всех этих комбинаций (в результате 6720 файлов), а затем использую PNGOUT, чтобы выбрать ту, которая была сжата до самого маленького файла. Это файл, который:

  • Сначала напишите «20» в буквенно-цифровом режиме
  • Затем напишите «1» в числовом режиме
  • Затем напишите «5» в числовом режиме
  • Используйте «H» (высокий) уровень коррекции ошибок
  • Используйте "110" маскирование данных

Это называется, test-3-1-H-Diamonds.bmpесли вы использовали программу ниже. Это изображение длиной 175 байт после запуска PNGOUT. Благодаря «высокому» уровню исправления ошибок в QR-коде «версия 1» мы можем изменять до 8 пикселей в части данных, не разрушая данные. С помощью небольшого количества проб и ошибок я могу уменьшить его до 173 байтов, представленных выше. Вероятно, он может быть меньше, но для исчерпания всех комбинаций требуется 208 C 8 ~ 7,5 × 10 13 проверок, которые я не собираюсь делать;)


Программа Rust (0.13.0-nightly (5ba610265)), которая генерирует все комбинации:

/* 

Also put these into your Cargo.toml: 

[dependencies]
qrcode = "0.0.3"
bmp = "0.0.3"

*/

extern crate qrcode;
extern crate bmp;

use qrcode::bits::Bits;
use qrcode::optimize::Segment;
use qrcode::types::{Version, EcLevel, Mode};
use qrcode::ec::construct_codewords;
use qrcode::canvas::{Canvas, MaskPattern, Module};

use bmp::{Image, Pixel};

use std::num::Int;

const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0};
const WHITE: Pixel = Pixel { r: 255, g: 255, b: 255 };

static SEGMENT_SEPARATIONS: [&'static [(uint, uint)]; 8] = [
    &[(0, 1), (1, 2), (2, 3), (3, 4)],
    &[(0, 1), (1, 2), (2, 4)],
    &[(0, 1), (1, 3), (3, 4)],
    &[(0, 2), (2, 3), (3, 4)],
    &[(0, 1), (1, 4)],
    &[(0, 2), (2, 4)],
    &[(0, 3), (3, 4)],
    &[(0, 4)],
];

const ALL_EC_LEVELS: &'static [EcLevel] = &[EcLevel::L, EcLevel::M, EcLevel::Q, EcLevel::H];
const ALL_MODES: &'static [Mode] = &[Mode::Numeric, Mode::Alphanumeric, Mode::Byte];
const ALL_MASK_PATTERNS: &'static [MaskPattern] = &[
    MaskPattern::Checkerboard,
    MaskPattern::HorizontalLines,
    MaskPattern::VerticalLines,
    MaskPattern::DiagonalLines,
    MaskPattern::LargeCheckerboard,
    MaskPattern::Fields,
    MaskPattern::Diamonds,
    MaskPattern::Meadow,
];

fn run(ec_level: EcLevel, mask_pattern: MaskPattern, segments: &[Segment], filename: &str) {
    let version = Version::Normal(1);
    let mut bits = Bits::new(version);
    if bits.push_segments(b"2015", segments.iter().map(|s| *s)).is_err() {
        return;
    }
    if bits.push_terminator(ec_level).is_err() {
        return;
    }
    let data = bits.into_bytes();
    let (encoded_data, ec_data) = construct_codewords(&*data, version, ec_level).unwrap();
    let mut canvas = Canvas::new(version, ec_level);
    canvas.draw_all_functional_patterns();
    canvas.draw_data(&*encoded_data, &*ec_data);
    canvas.apply_mask(mask_pattern);
    let canvas = canvas;

    let width = version.width();
    let real_image_size = (width + 10) as uint;
    let mut image = Image::new(real_image_size, real_image_size);
    for i in range(0, real_image_size) {
        for j in range(0, real_image_size) {
            image.set_pixel(i, j, WHITE);
        }
    }
    for i in range(0, width) {
        for j in range(0, width) {
            if canvas.get(i, j) == Module::Dark {
                image.set_pixel((i + 5) as uint, real_image_size - (j + 6) as uint, BLACK);
            }
        }
    }
    image.save(filename);
}

fn main() {
    for (z, separations) in SEGMENT_SEPARATIONS.iter().enumerate() {
        let mut segments = separations.iter().map(|&(b, e)| Segment {
            mode: Mode::Numeric, begin: b, end: e
        }).collect::<Vec<_>>();

        let variations_count = ALL_MODES.len().pow(segments.len());
        for i in range(0, variations_count) {
            let mut var = i;
            for r in segments.iter_mut() {
                r.mode = ALL_MODES[var % ALL_MODES.len()];
                var /= ALL_MODES.len();
            }
            for ec_level in ALL_EC_LEVELS.iter() {
                for mask_pattern in ALL_MASK_PATTERNS.iter() {
                    let filename = format!("results/test-{}-{}-{}-{}.bmp", z, i, *ec_level, *mask_pattern);
                    run(*ec_level, *mask_pattern, &*segments, &*filename);
                }
            }
        }
        println!("processed {}/{}", z, 8u);
    }
}
kennytm
источник
1
Главная проблема, которую я вижу здесь, заключается в том, что ваша заявка написана не на языке программирования .
Мартин Эндер
4
@ MartinBüttner Это субъективное мнение избранных. Тем не менее, способ, которым был получен файл, был запрограммирован, поэтому я бы сказал, что это абсолютно верное представление. Кроме того, это чертовски крутой подход.
Нить
1
@Nit Это мета-пост без отрицательных голосов, который, в основном, и заключается в том, как консенсус сообщества работает на SE (по крайней мере, на PPCG). Если вы не согласны, вы можете понизить этот ответ или предоставить альтернативу. При этом, я, вероятно, сделаю отдельный мета-пост, в частности, о сложностях колмогоровской сложности, так как это очень много.
Мартин Эндер
@ Готово. Не стесняйтесь прийти обсудить это на мета.
Мартин Эндер
Конвертация из gif казалась короче.
jimmy23013
5

Mathematica, 217 177 176 166 байт

Вот начало:

"newyear.png"~Export~ImagePad[Image[IntegerDigits[36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okk‌​lg0cymmy2,2,441]~Partition~21],5,1]

Меньше гольфа:

"newyear.png"~Export~ImagePad[
 Image[
  IntegerDigits[
    36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okk‌​lg0cymmy2,
    2,
    441
  ]~Partition~21
 ],
 5,
 1
]

QR-код закодирован в базовом номере 36. Конечно, я мог бы закодировать его в расширенный ASCII (основа 256), но это сократит строку только на 30 байт, и я не уверен, что смогу выполнить преобразование по цене, намного меньшей этой.

Конечно, это Mathematica, так что есть также 63 байта

"newyear.png"~Export~ImagePad[BarcodeImage["2015","QR",21],5,1]

но я думаю, что это стандартная лазейка. ;) (В результате получается QR-код, отличный от того, который был в соревновании, поэтому я думаю, QR-код не уникален?)

Мартин Эндер
источник
1
Да, существует несколько способов кодирования одной и той же строки в QR-коде, например, с использованием разных уровней проверки ошибок, схемы кодирования, маскирования изображения и т. Д. Несмотря на то, что сжатый код OP является одним из самых маленьких («версия 1»), тем не менее.
kennytm
FromDigits? Вы могли бы использовать 36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okklg0cymmy2вместо этого.
Кеннитм
@KennyTM Ух ты, ловкий трюк. Спасибо :) Я думаю, что с базовым 256 действительно не стоит (мне нужно ToCharacterCodeи FromDigitsто, и другое .)
Мартин Эндер,
3

Matlab 545 байт

новый год

Твердо закодирован в кропотливой ручной работе и без каких-либо необычных встроенных компрессий / разговоров . Я знаю, что это все еще не так хорошо, как другие ответы, но я все еще счастлив =)

b=[[61:67,69,71:73,75:81,92,98]+100,
    1,3:4,6,12,23,25:27,29,31:35,37,39:41,43,54,56:58,60,63:64,66,68,70:72,74,85,87:89,91,97,99]+200,
    [1:3,5,16,22,24:26,30,36,47:53,55,57,59,61:67,87:89]+300,
    [9,11,15:16,20:21,24,27,29,40,42,48:50,57,59,71,74:75,77:79,81,85,89:90]+400,
    [2,9,11:12,14:15,18,34:37,39,42:43,46:47,50:51,72,74:75,77:79,81:82,95:99]+500,
    [0:1,3:8,10:12,14:15,26,32,37,40:41,43:45,57,59:61,63,67:69,71:77,88,90:92,94,97]+600,
    [19,21:23,25,27,33,37:39,50,56,59,62,66,69,81:87,89:91,95,99:101]+700];
z=zeros(31);z(b)= 1;imwrite(~z,'newyear.png')

Более нечитаемый (актуальная версия 545):

z=zeros(31);
z([
    [61:67, 69, 71:73, 75:81, 92, 98] + 100,
    [1, 3:4, 6, 12, 23, 25:27, 29, 31:35, 37, 39:41, 43, 54, 56:58, 60, 63:64, 66, 68, 70:72, 74, 85, 87:89, 91, 97, 99] + 200,
    [1:3, 5, 16, 22, 24:26, 30, 36, 47:53, 55, 57, 59, 61:67, 87:89] + 300,
    [9, 11, 15:16, 20:21, 24, 27, 29, 40, 42, 48:50, 57, 59, 71, 74:75, 77:79, 81, 85, 89:90] + 400,
    [2, 9, 11:12, 14:15, 18, 34:37, 39, 42:43, 46:47, 50:51, 72, 74:75, 77:79, 81:82, 95:99] + 500,
    [0:1, 3:8, 10:12, 14:15, 26, 32, 37, 40:41, 43:45, 57, 59:61, 63, 67:69, 71:77, 88, 90:92, 94, 97] + 600,
    [19, 21:23, 25,27, 33, 37:39, 50, 56, 59, 62, 66, 69, 81:87, 89:91, 95, 99:101] + 700
])= 1;
imwrite(~z,'newyear.png')

Мы создаем нулевую матрицу 31 x 31, но обращаемся к ней как к вектору, чтобы установить все ячейки с индексами bto 1. Уловки, которые я использовал, были обозначением последовательных целых чисел (например [1,2,3,4] = 1:4) и удалением одного 100-значного числа путем добавления скаляра к каждому значению вектора.

Посмотрим, сможет ли кто-нибудь победить это =)

flawr
источник
так что я не unreadableправильно прочитал слово ... определенно прочитал readable. увидел это сразу после того, как предложил это, и надеялся, что тот, кто прочитал мою редакцию, отверг ее, но они явно пропустили ее. извините за плохое редактирование ...
псевдоним117
ИМХО не имеет значения, просто хотел включить первую версию, потому что это легче сослаться в объяснении.
flawr
2

Баш, 206 252 257 байт

Использование convertкоманды в комплекте imagemagickэкономит еще 46 байтов.

base64 -d<<<UDQKMzAgMzAKAAAAAAAAAAAAAAAAAAAAAAAAAAAH9L+ABBkggAXULoAF2S6ABdOugAQeoIAH+r+AB9zVAABIlwABHU6AAsIaAAFXS4AAD+QAB/ywAAQT5QAF3pIABd6SAAXdTgAEHBsAB/1OAAAAAAAAAAAAAAAAAAAAAAAAAAAA|convert - newyear.png

Преобразует pbmизображение в кодировке base64 в pngизображение с imagemagickсимволом 's convert.

Возможно, вам придется настроить decode (-d)параметр для вашего конкретного base64двоичного файла. Проверено на моем Ubuntu 14.04 LTS.

Сохранено 5 байтов с помощью <<</ здесь-строка .

base64 -d>newyear.png<<<iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEX///8AAABVwtN+AAAAX0lEQVQI12PACdi/7G9gYJFUaGBgvaIHJG6CiMvrgGJyCxoY2H/tBxJ3rgIVekxnYGCU9WtgYDokBWSFezcwMPA/ARrwZwMDA4vwUwYG1nuTYMRdP6CYjDRQ9q8fbrsBLRkaYOOP83wAAAAASUVORK5CYII=

Старая версия (257 байт):
echo iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEX///8AAABVwtN+AAAAX0lEQVQI12PACdi/7G9gYJFUaGBgvaIHJG6CiMvrgGJyCxoY2H/tBxJ3rgIVekxnYGCU9WtgYDokBWSFezcwMPA/ARrwZwMDA4vwUwYG1nuTYMRdP6CYjDRQ9q8fbrsBLRkaYOOP83wAAAAASUVORK5CYII=|base64 -d > newyear.png

Простая цепочка команд оболочки, которая записывает в кодировке base64 png файл в стандартный ввод, base64который декодирует его из-за -dфлага и записывает свой стандартный вывод в newyear.png.

GiantTree
источник
Возможно, я могу сохранить персонажи с чем-то вроде, base64 -d>newyear.png<<<[the long string]но я не на Linux-машине, и я не знаю, какие пробелы обязательны
андерграундмонорельс
Подтвердили работу с base64 -d>newyear.png<<<[base64 string]Ubuntu 14.04.
PurkkaKoodari
Если вы собираетесь использовать предложенный код, просто измените заголовок ответа на что-то конкретное, например Bash, Ksh или Zsh. Оболочка в целом (как POSIX-совместимые Sh, Ash или Dash) не поддерживает синтаксис здесь-строки .
Манатворк
Если мы можем использовать Netpbm процедуры, мы можем кормить сжатого растрового изображения и теряют 40 байт: эхо UDQKMzEgMzEKAAAAAAAAAAAAAAAAAAAAAAAAAAAH95 / ABBBQQAXWV0AF0VdABdFXQAQQEEAH9V / AAAWAAAUzMUADqtLABbv0QAcMPAAH1JSAAADwAAfxbUAEFDwABdCUgAXSfAAF1W1ABBMdwAf0FUAAAAA AAAAAAAAAAAAAAAAAAAAAAA == | base64 -d | pnmtopng> newyear.png
swstephe
@manatwork Только что отредактированный, должен работать на Bash, как я тестировал на своем телефоне Android.
GiantTree
1

Python 2 + PIL, 216 215

В основном это порт решения Mathematica.

from PIL import*
b=Image.new("1",[21]*2)
b.putdata(map(int,'0'*7+bin(int('FL6IBG25C8Z00UEF53P4657DGD6HJZG41E5JOEAD1QGZ0L2XCHQGSO5R1A51V5NO4ZKW9V22OKKLG0CYMMY2',36))[2:]))
ImageOps.expand(b,5,255).save("newyear.png")
PurkkaKoodari
источник
0

Общие инструменты Shell + Imagemagick, 215

(echo "P1
21 21"
base64 -d<<<H95/ggoN1lduirt0VdggIP9V/ALAFMzFdVpdu/R4YeH1JSAB4H8W1goeF0JSuk+F1W1gmO/9BVA=|xxd -c99 -p|tr a-f A-F|dc -e2o16i?p|tr -d '\n\\'|fold -21)|convert -border 5 -bordercolor white - newyear.png

Немного запутанный , но короче, чем ответ другой оболочки .

  • Base64 конвертирует из base64 в base 256 (расширенный ASCII)
  • xxd конвертируется в гекс
  • tr делает шестнадцатеричные прописные буквы, подходит для
  • dc читает hex и печатает двоичную строку 1 и 0
  • tr удаляет \ и пробелы
  • сгиб делает строки длиной 21 символ (21 пиксель)
  • Этот выход, наряду с P1\n21 21это формат PBM Р1
  • convert (Imagemagick) преобразует это в .png с 5-пиксельной рамкой:

введите описание изображения здесь

Цифровая травма
источник