Output 2015 sebagai kode QR

15

Misi itu sederhana. Keluarkan nomor 2015 sebagai kode QR dan tulis ke file dengan nama newyear.pngdalam format PNG. Kode harus valid setiap hari, jadi mungkin Anda tidak akan menggunakan tahun ini.

Kode QR sebagai teks terlihat seperti ini:

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

Hasil yang ditulis newyear.pngharus mengandung kode QR dengan batas putih 5 piksel dan satu titik berukuran piksel. Itu tidak boleh mengandung apa pun selain kode QR.

Hannes Karppila
sumber
1
dapatkah hardcoded, atau Anda harus menghasilkan kode qr?
undergroundmonorail
7
Jauh lebih banyak jawaban akan datang jika ini berbasis keluaran ascii dan bukan keluaran gambar.
Pengoptimal
6
Apakah kodenya harus benar-benar benar tanpa kesalahan, atau cukupkah memindai dengan benar? (Kode QR memiliki banyak redundansi dan koreksi kesalahan yang disengaja, sehingga Anda dapat membalik banyak piksel dan mereka akan tetap bekerja.) Juga, apakah itu harus PNG, atau dapatkah kita menggunakan format gambar lain (saya pikir khususnya tentang PBM di sini)?
Ilmari Karonen

Jawaban:

12

File mentah, 184 byte = file 173-byte + nama file 11-byte

Saya harap ini tidak merusak celah standar apa pun. Tetapi hasilnya "memiliki tinggi dan cara terpendek untuk memproduksinya adalah (kemungkinan besar) hanya dengan mencetaknya secara harfiah ...".

newyear.png

Basis 64 file:

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

Alih-alih bermain golf program saya bermain golf gambar PNG yang dihasilkan. Kode QR adalah format yang sangat fleksibel, ada banyak parameter yang dapat diutak-atik: pengkodean input, tingkat koreksi kesalahan, dan gambar masking. Ini semua akan menghasilkan simbol yang berbeda dan dengan demikian dikompresi ke file dengan ukuran berbeda.

Jadi saya telah menulis sebuah program untuk menghasilkan semua kombinasi ini (menghasilkan 6720 file), dan kemudian menggunakan PNGOUT untuk memilih yang dikompres ke file terkecil. Ternyata menjadi file yang:

  • Pertama tulis "20" dalam mode alfanumerik
  • Kemudian tulis "1" dalam mode numerik
  • Kemudian tulis "5" dalam mode numerik
  • Gunakan tingkat koreksi kesalahan "H" (Tinggi)
  • Gunakan masking data "110"

Ini disebut test-3-1-H-Diamonds.bmpjika Anda menggunakan program di bawah ini. Gambar ini panjangnya 175 byte setelah menjalankan PNGOUT. Dengan tingkat koreksi kesalahan "tinggi" dalam kode QR "versi 1", kita dapat memodifikasi hingga 8 piksel di bagian data tanpa merusak data. Dengan sedikit trial-and-error manual saya bisa menguranginya menjadi 173 byte yang disajikan di atas. Mungkin bisa lebih kecil tetapi melelahkan semua kombinasi membutuhkan 208 C 8 ~ 7.5 × 10 13 cek yang saya tidak akan lakukan;)


Program Rust (0.13.0-nightly (5ba610265)) yang menghasilkan semua kombinasi:

/* 

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
sumber
1
Masalah utama yang saya lihat di sini, adalah bahwa kiriman Anda sendiri tidak ditulis dalam bahasa pemrograman .
Martin Ender
4
@ MartinBüttner Itu pendapat subjektif dari beberapa orang terpilih. Yang sedang berkata, cara file itu diperoleh diprogram jadi saya akan mengatakan ini adalah pengiriman yang sepenuhnya valid. Juga, ini adalah pendekatan yang luar biasa.
Nit
1
@Nit Ini adalah pos meta tanpa downvotes, yang pada dasarnya adalah bagaimana konsensus komunitas bekerja pada SE (setidaknya pada PPCG). Jika Anda tidak setuju, Anda bisa menurunkan jawaban itu atau memberikan alternatif. Yang sedang berkata, saya mungkin akan membuat meta post terpisah, khususnya tentang tantangan kompleksitas kolmogorov, karena ini banyak muncul.
Martin Ender
@Nit Selesai. Jangan ragu untuk membicarakan hal ini dengan meta.
Martin Ender
Konversi dari gif tampak lebih pendek.
jimmy23013
5

Mathematica, 217 177 176 166 byte

Inilah awalnya:

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

Lebih sedikit golf:

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

Kode QR dikodekan dalam nomor basis 36. Tentu saja, saya dapat menyandikannya dalam ASCII yang diperluas (basis 256), tetapi itu hanya akan mempersingkat string sebesar 30 byte, dan saya tidak yakin saya dapat melakukan konversi dengan biaya yang jauh lebih murah dari itu.

Tentu saja, ini adalah Mathematica, jadi ada juga 63-byte

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

tapi saya kira itu celah standar. ;) (Ini menghasilkan kode QR yang berbeda dari yang ada di tantangan, jadi saya kira kode QR tidak unik?)

Martin Ender
sumber
1
Ya ada beberapa cara untuk menyandikan string yang sama dalam kode QR, misalnya menggunakan tingkat pemeriksaan kesalahan yang berbeda, skema pengkodean, masking image, dll. Namun tidak mempertimbangkan kompresi kode OP adalah salah satu yang terkecil ("versi 1").
kennytm
DariDigits? Anda bisa menggunakannya 36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okklg0cymmy2sebagai gantinya.
kennytm
@ KennyTM oh wow, trik yang rapi. Terima kasih :) Saya pikir dengan itu, basis 256 benar-benar tidak layak (saya akan membutuhkan keduanya ToCharacterCodedan FromDigitskemudian.)
Martin Ender
3

Matlab 545 Bytes

tahun baru

Hardcoded dalam pekerjaan manual yang melelahkan dan tanpa kompresi string mewah / percakapan . Saya tahu itu masih tidak sebagus jawaban yang lain tapi saya masih senang =)

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

Lebih tidak dapat dibaca (versi 545 yang sebenarnya):

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

Kami membuat matriks nol 31 x 31, tetapi mengaksesnya sebagai vektor untuk mengatur semua sel dengan indeks bke 1. Trik yang saya gunakan adalah notasi bilangan bulat berurutan (seperti [1,2,3,4] = 1:4) dan menghapus satu 100-digit dengan menambahkan skalar ke setiap nilai vektor.

Mari kita lihat apakah ada yang bisa mengalahkan itu =)

cacat
sumber
jadi saya tidak membaca kata unreadabledengan benar ... pasti membaca readable. melihat itu tepat setelah menyarankannya dan berharap siapa pun yang membaca edit saya menolaknya, tetapi ternyata mereka juga melewatkannya. maaf tentang hasil edit yang buruk ...
pseudonym117
Tidak masalah IMHO, hanya ingin memasukkan versi pertama karena lebih mudah untuk merujuk pada penjelasannya.
flawr
2

Bash, 206 252 257 Bytes

Menggunakan convertperintah yang dibundel dalam imagemagickmenyimpan 46 byte lebih banyak.

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

Bertobat base64-encoded pbmgambar ke pnggambar dengan imagemagick's convert.

Anda mungkin perlu menyesuaikan decode (-d)parameter ke base64biner spesifik Anda . Diuji pada Ubuntu 14.04 LTS saya.

Disimpan 5 byte dengan menggunakan <<</ di sini-string .

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

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

Hanya rantai perintah shell sederhana yang menulis pngfile yang disandikan base64 ke stdin base64yang menerjemahkannya karena -dflag dan menulis stdout ke newyear.png.

GiantTree
sumber
Mungkin bisa menyimpan karakter dengan sesuatu seperti base64 -d>newyear.png<<<[the long string]tapi saya tidak di mesin linux rn dan saya tidak tahu spasi mana yang wajib
undergroundmonorail
Dikonfirmasi untuk bekerja dengan base64 -d>newyear.png<<<[base64 string]di Ubuntu 14.04.
PurkkaKoodari
Jika Anda akan menggunakan kode yang disarankan, cukup edit tajuk jawaban ke sesuatu yang spesifik seperti Bash, Ksh atau Zsh. Shell secara umum (seperti Sh, Ash, atau Dash yang kompatibel dengan POSIX) tidak mendukung sintaks string-sini .
manatwork
Jika kita dapat menggunakan rutinitas netpbm, kita bisa memberi makan bitmap terkompresi dan kehilangan 40 byte: echo UDQKMzEgMzEKAAAAAAAAAAAAAAAAAAAAAAAAAAAH95 / ABBBQQAXWV0AF0VdABdFXQAQQEEAH9V / AAAWAAAUzMUADqtLABbv0QAcMPAAH1JSAAADwAAfxbUAEFDwABdCUgAXSfAAF1W1ABBMdwAf0FUAAAAA AAAAAAAAAAAAAAAAAAAAAAA == | base64 -d | pnmtopng> newyear.png
swstephe
@manatwork Baru diedit, harus bekerja pada Bash saat saya mengujinya di ponsel Android saya.
GiantTree
1

Python 2 + PIL, 216 215

Pada dasarnya port dari solusi 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
sumber
0

Alat Shell umum + 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

Sedikit berbelit-belit , tetapi lebih pendek dari jawaban shell lainnya .

  • Base64 mengkonversi dari base64 ke basis 256 (diperpanjang ASCII)
  • xxd dikonversi menjadi hex
  • tr membuat huruf besar hex, cocok untuk dc
  • dc membaca hex dan mencetak string biner dari 1s dan 0s
  • tr menghapus \ dan spasi putih
  • lipatan membuat garis 21 karakter (21 piksel) panjangnya
  • Output ini, bersama dengan P1\n21 21adalah format PBM P1
  • convert (Imagemagick) mengonversikan ini menjadi .png dengan batas 5 piksel:

masukkan deskripsi gambar di sini

Trauma Digital
sumber