以QR码输出2015


15

任务很简单。只需将数字2015输出为QR码并将其写入以newyear.pngPNG格式命名的文件即可。代码必须在任何一天都有效,因此也许您不应该使用当年。

文字的QR码如下所示:

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

写入的结果newyear.png必须包含带有白色5像素边框和1像素大小点的QR码。除QR码外,不得包含其他任何内容。


1
可以对其进行硬编码,还是必须生成二维码?
undergroundmonorail

7
如果这是基于ASCII输出而不是图像输出,将会有更多的答案。
Optimizer

6
代码是否必须正确无误,还是足以正确扫描?(QR码具有很多故意的冗余和纠错功能,因此您可以翻转很多像素,它们仍然可以工作。)此外,它是否必须是PNG,还是可以使用其他图像格式(我在想特别是关于PBM)?
Ilmari Karonen 2014年

Answers:


12

原始文件184字节= 173字节文件+ 11字节文件名

我希望这不会破坏任何标准漏洞。但是输出结果“具有很高的 ,并且最短的生产方式(很可能)将是按字面意义打印...”。

newyear.png

文件的基数64:

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

我没有打高尔夫球,而是打了高尔夫球。QR码是一种非常灵活的格式,可以修改许多参数:输入的编码,纠错级别和掩盖图像。这些都将生成不同的符号,并因此压缩为不同大小的文件。

因此,我编写了一个程序来生成所有这些组合(结果为6720个文件),然后使用PNGOUT来选择压缩到最小文件的文件。原来是一个文件,该文件:

  • 首先以字母数字模式写入“ 20”
  • 然后在数字模式下写“ 1”
  • 然后在数字模式下输入“ 5”
  • 使用“ H”(高)错误纠正级别
  • 使用“ 110”数据屏蔽

test-3-1-H-Diamonds.bmp如果您使用下面的程序,则称为。运行PNGOUT后,此图像的长度为175字节。通过“版本1” QR码中的“高”错误校正级别,我们最多可以修改数据部分中的8个像素,而不会破坏数据。借助一些手动试验和错误,我可以将其进一步减少为上述的173个字节。它可能可以更小,但耗尽所有组合,需要208个 Ç 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
我在这里看到的主要问题是,您提交的内容本身不是用编程语言编写的。
Martin Ender 2014年

4
@MartinBüttner这是少数几个人的主观意见。话虽这么说,文件的获取方式已经过编程,所以我认为这是一个完全有效的提交。另外,这是一种令人生畏的方法。
2014年

1
@Nit这是一个没有下注的meta帖子,基本上是社区共识在SE上的工作方式(至少在PPCG上如此)。如果您不同意,则可以拒绝该答案或提供替代方法。话虽这么说,我可能会单独发表一个元文章,特别是关于kolmogorov复杂性挑战的文章,因为这会涉及很多问题。
马丁·恩德2014年

@Nit 完成。随时可以在meta上进行讨论。
Martin Ender 2014年

从gif转换似乎更短。
jimmy23013 2014年

5

数学,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 2014年

FromDigits?您可以36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okklg0cymmy2改用。
kennytm 2014年

@KennyTM哦,哇,整洁的把戏。谢谢:)我认为,以256为基数确实不值得(我需要两者ToCharacterCode同时使用FromDigits。)
Martin Ender 2014年

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的零矩阵,但将其作为向量访问以设置所有索引b为的像元1。我使用的技巧是连续整数的表示法(例如[1,2,3,4] = 1:4),并通过向向量的每个值添加标量来删除100位数字。

让我们看看是否有人可以击败=)


所以我没有unreadable正确读这个词readable。在提出建议后立即看到了该内容,并希望阅读我的编辑的人都拒绝了它,但他们显然太错过了。很抱歉编辑不正确...
pseudonym117

无关紧要的恕我直言,只是想包括第一个版本,因为在解释中更容易提及。
瑕疵的

2

Bash,206252257字节

使用convert捆绑的命令imagemagick可以节省46个字节。

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

转换base64编码pbm图像到png与图像imagemagickconvert

您可能需要将decode (-d)参数调整为特定的base64二进制文件。在我的Ubuntu 14.04 LTS上测试。

使用<<</ here-string节省了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

只是一个简单的shell命令链,将base64编码的png文件写入stdin的标准输入,base64由于该-d标志而对其进行解码,并将其stdout写入newyear.png。


大概可以保存的东西,如人物base64 -d>newyear.png<<<[the long string],但我不是在Linux机器RN,我不知道哪个空白是强制性的
undergroundmonorail

确认可以base64 -d>newyear.png<<<[base64 string]在Ubuntu 14.04上使用。
PurkkaKoodari 2014年

如果要使用建议的代码,只需将答案标题编辑为特定的内容,例如Bash,Ksh或Zsh。一般而言,Shell(例如与POSIX兼容的Sh,Ash或Dash)不支持here-string语法。
manatwork 2014年

如果我们能使用的NetPBM程序,我们可以养活压缩位,失去40个字节:回声UDQKMzEgMzEKAAAAAAAAAAAAAAAAAAAAAAAAAAAH95 / ABBBQQAXWV0AF0VdABdFXQAQQEEAH9V / AAAWAAAUzMUADqtLABbv0QAcMPAAH1JSAAADwAAfxbUAEFDwABdCUgAXSfAAF1W1ABBMdwAf0FUAAAAA AAAAAAAAAAAAAAAAAAAAAAA == |的base64 -d | pnmtopng> newyear.png
swstephe

@manatwork刚编辑过,应该可以在Bash上使用,就像我在Android手机上测试它一样。
GiantTree 2014年

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

有点令人费解,但比其他shell回答要短

  • Base64从base64转换为256(扩展ASCII)
  • xxd转换为十六进制
  • tr使十六进制大写,适用于dc
  • dc读取十六进制并输出1和0的二进制字符串
  • tr删除\和空格
  • 折叠使行长21个字符(21个像素)
  • 这个输出,具有沿P1\n21 21PBM P1格式
  • convert(Imagemagick)将其转换为具有5像素边框的.png:

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.