Вывод 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);
    }
}

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-значного числа путем добавления скаляра к каждому значению вектора.

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


так что я не 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.


Возможно, я могу сохранить персонажи с чем-то вроде, 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")

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-пиксельной рамкой:

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.