15
\$\begingroup\$

Mission is simple. Just output number 2015 as QR code and write it to file named newyear.png in PNG format. Code must be valid any day, so maybe you shall not use current year.

QR code as text looks like this:

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

The result written in newyear.png must contain that QR code with white 5 pixel borders and one pixel sized dots. It must not contain anything else than QR code.

\$\endgroup\$
  • 1
    \$\begingroup\$ can it be hardcoded, or must you generate the qr code? \$\endgroup\$ – undergroundmonorail Dec 29 '14 at 11:14
  • 7
    \$\begingroup\$ Much more answers will come if this is ascii art output based and not image output. \$\endgroup\$ – Optimizer Dec 29 '14 at 11:37
  • 6
    \$\begingroup\$ Does the code have to be exactly correct with no errors, or is it enough that it scans correctly? (QR codes have a lot of deliberate redundancy and error correction, so you can flip a lot of pixels and they'll still work.) Also, does it have to be PNG, or can we use other image formats (I'm thinking particularly about PBM here)? \$\endgroup\$ – Ilmari Karonen Dec 30 '14 at 1:49
12
\$\begingroup\$

Raw file, 184 bytes = 173-byte file + 11-byte filename

I hope this does not break any standard loopholes. But the output "has a high and the shortest way to produce it would (most likely) be to just print it literally...".

newyear.png

Base 64 of the file:

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

Instead of golfing a program I golfed the resulting PNG image. QR code is a very flexible format, there are many parameters that can be fiddled: the encoding of the input, the error correction level, and the masking image. These will all generate different symbols and thus compressed to files of different sizes.

So I have written a program to generate all these combinations (resulting 6720 files), and then use PNGOUT to pick the one which compressed to the smallest file. It turns out to be a file that:

  • First write "20" in alphanumeric mode
  • Then write "1" in numeric mode
  • Then write "5" in numeric mode
  • Use the "H" (High) error correction level
  • Use the "110" data masking

This is called test-3-1-H-Diamonds.bmp if you used the program below. This image is 175-byte long after running PNGOUT. With "high" error correction level in "version 1" QR code, we can modify up to 8 pixels in the data part without ruining the data. With a bit of manual trial-and-error I can reduce it further to 173 bytes presented above. It can probably be smaller but exhausting all combinations requires 208C8 ~ 7.5 × 1013 checks which I'm not going to do ;)


The Rust (0.13.0-nightly (5ba610265)) program that generates all combinations:

/* 

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);
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ The main problem I see here, is that your submission itself is not written in a programming language. \$\endgroup\$ – Martin Ender Dec 30 '14 at 0:12
  • 4
    \$\begingroup\$ @MartinBüttner That's a subjective opinion of a selected few people. That being said, the way the file was obtained was programmed so I'd say this is a completely valid submission. Also, this is a frigging awesome approach. \$\endgroup\$ – Nit Dec 30 '14 at 1:21
  • 1
    \$\begingroup\$ @Nit It's a meta post without downvotes, which is basically how community consensus works on SE (at least on PPCG). If you disagree, you could downvote that answer or provide an alternative. That being said, I'll probably make a separate meta post, specifically about kolmogorov complexity challenges, as this is coming up a lot. \$\endgroup\$ – Martin Ender Dec 30 '14 at 9:58
  • \$\begingroup\$ @Nit Done. Feel free to come discuss this on meta. \$\endgroup\$ – Martin Ender Dec 30 '14 at 10:33
  • \$\begingroup\$ Converting from gif seemed shorter. \$\endgroup\$ – jimmy23013 Dec 31 '14 at 10:09
5
\$\begingroup\$

Mathematica, 217 177 176 166 bytes

Here is a start:

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

Less golf:

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

The QR code is encoded in a base 36 number. Of course, I could encode it in extended ASCII (base 256), but that would only shorten the string by 30 bytes, and I'm not sure I can do the conversion at the cost of much less than that.

Of course, this is Mathematica, so there's also the 63-byte

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

but I guess that's a standard loophole. ;) (This produces a different QR code than the one in the challenge, so I guess the QR code isn't unique?)

\$\endgroup\$
  • 1
    \$\begingroup\$ Yes there are multiple ways to encode the same string in QR code, e.g. using different levels of error checking, encoding scheme, masking image, etc. Not considering compression OP's code is one of the smallest ("version 1") nevertheless. \$\endgroup\$ – kennytm Dec 29 '14 at 13:11
  • \$\begingroup\$ FromDigits? You could use 36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okklg0cymmy2 instead. \$\endgroup\$ – kennytm Dec 30 '14 at 0:06
  • \$\begingroup\$ @KennyTM oh wow, neat trick. Thank you :) I think with that, base 256 is really not worth it (I'd need both ToCharacterCode and FromDigits then.) \$\endgroup\$ – Martin Ender Dec 30 '14 at 0:09
3
\$\begingroup\$

Matlab 545 Bytes

newyear

Hardcoded in painstaking manual work and without any fancy builtin string compression/conversation. I know it still is not as good as the other answers but I am still happy=)

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')

More unreadable (the actual 545 version):

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')

We create a 31 x 31 zero matrix, but access it as vector to set all cells with the indices of b to 1. The tricks I used were the notation of consecutive integers (like [1,2,3,4] = 1:4) and removing one the 100-digit by adding a scalar to every value of the vector.

Let's see if anyone can beat that=)

\$\endgroup\$
  • \$\begingroup\$ so i didnt read the word unreadable correctly... definitely read readable. saw that right after suggesting it and was hoping whoever read my edit rejected it, but they missed it too apparently. sorry about the bad edit... \$\endgroup\$ – pseudonym117 Dec 29 '14 at 18:42
  • \$\begingroup\$ Does not relly matter IMHO, just wanted to include the first version because it is easier to refer to in the explaination. \$\endgroup\$ – flawr Dec 29 '14 at 19:35
2
\$\begingroup\$

Bash, 206 252 257 Bytes

Using the convert command bundled in imagemagick saves 46 more bytes.

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

Converts the base64-encoded pbm image to a png image with imagemagick's convert.

You may need to adjust the decode (-d) parameter to your specific base64 binary. Tested on my Ubuntu 14.04 LTS.

Saved 5 bytes by using <<</here-string.

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

Old version (257 bytes):
echo iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEX///8AAABVwtN+AAAAX0lEQVQI12PACdi/7G9gYJFUaGBgvaIHJG6CiMvrgGJyCxoY2H/tBxJ3rgIVekxnYGCU9WtgYDokBWSFezcwMPA/ARrwZwMDA4vwUwYG1nuTYMRdP6CYjDRQ9q8fbrsBLRkaYOOP83wAAAAASUVORK5CYII=|base64 -d > newyear.png

Just a simple shell command chain that writes the base64 encoded png file into stdin of base64 that decodes it because of the -d flag and writes its stdout to newyear.png.

\$\endgroup\$
  • \$\begingroup\$ can probably save characters with something like base64 -d>newyear.png<<<[the long string] but i'm not at a linux machine rn and i don't know which whitespace is mandatory \$\endgroup\$ – undergroundmonorail Dec 29 '14 at 16:32
  • \$\begingroup\$ Confirmed to work with base64 -d>newyear.png<<<[base64 string] on Ubuntu 14.04. \$\endgroup\$ – PurkkaKoodari Dec 29 '14 at 16:54
  • \$\begingroup\$ If you are going to use the suggested code, just edit the answer heading to something specific like Bash, Ksh or Zsh. Shell in general (like POSIX compatible Sh, Ash or Dash) does not support the here-string syntax. \$\endgroup\$ – manatwork Dec 29 '14 at 17:00
  • \$\begingroup\$ If we can use netpbm routines, we can feed the compressed bitmap and lose 40 bytes: echo UDQKMzEgMzEKAAAAAAAAAAAAAAAAAAAAAAAAAAAH95/ABBBQQAXWV0AF0VdABdFXQAQQEEAH9V/ AAAWAAAUzMUADqtLABbv0QAcMPAAH1JSAAADwAAfxbUAEFDwABdCUgAXSfAAF1W1ABBMdwAf0FUAAAAA AAAAAAAAAAAAAAAAAAAAAAA==|base64 -d|pnmtopng>newyear.png \$\endgroup\$ – swstephe Dec 29 '14 at 17:14
  • \$\begingroup\$ @manatwork Just edited, should work on Bash as I tested it on my Android phone. \$\endgroup\$ – GiantTree Dec 29 '14 at 17:27
1
\$\begingroup\$

Python 2 + PIL, 216 215

Basically a port of the Mathematica solution.

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")
\$\endgroup\$
0
\$\begingroup\$

Common Shell tools + 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

A bit convoluted, but shorter than the other shell answer.

  • Base64 converts from base64 to base 256 (extended ASCII)
  • xxd converts to hex
  • tr makes hex uppercase, suitable for dc
  • dc reads hex and prints binary string of 1s and 0s
  • tr removes \ and whitespace
  • fold makes lines 21 chars (21 pixels) long
  • This output, along with P1\n21 21 is the PBM P1 format
  • convert (Imagemagick) converts this to .png with a 5 pixel border:

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.