Wyjście 2015 jako kod QR

15

Misja jest prosta. Po prostu wypisz numer 2015 jako kod QR i zapisz go do pliku o nazwie newyear.pngw formacie PNG. Kod musi być ważny każdego dnia, więc może nie będziesz używał bieżącego roku.

Kod QR jako tekst wygląda następująco:

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

Zapisany wynik newyear.pngmusi zawierać ten kod QR z białymi 5-pikselowymi ramkami i kropkami o rozmiarze jednego piksela. Nie może zawierać niczego poza kodem QR.

Hannes Karppila
źródło
1
czy może być zakodowany na stałe, czy musisz wygenerować kod qr?
undergroundmonorail
7
O wiele więcej odpowiedzi przyjdzie, jeśli jest to wyjście oparte na ascii art, a nie na obrazie.
Optymalizator
6
Czy kod musi być dokładnie poprawny, bez błędów, czy wystarczy, aby poprawnie skanował? (Kody QR mają dużo celowej redundancji i korekcji błędów, więc możesz przerzucić wiele pikseli, a one nadal będą działać.) Czy to musi być PNG, czy też możemy użyć innych formatów obrazów (myślę szczególnie o PBM tutaj)?
Ilmari Karonen,

Odpowiedzi:

12

Plik raw, 184 bajty = plik 173 bajtów + 11-bajtowa nazwa pliku

Mam nadzieję, że nie złamie to żadnych standardowych luk. Ale wynik „ma wysoką i najkrótszym sposobem jego wytworzenia (najprawdopodobniej) byłoby po prostu wydrukowanie go dosłownie ...”.

newyear.png

Baza 64 pliku:

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

Zamiast grać w golfa w programie, grałem w golfa w uzyskany obraz PNG. Kod QR jest bardzo elastycznym formatem, istnieje wiele parametrów, które można zakłócać: kodowanie wejścia, poziom korekcji błędów i obraz maskowania. Wszystkie one wygenerują różne symbole, a tym samym skompresowane do plików o różnych rozmiarach.

Napisałem więc program, który wygeneruje wszystkie te kombinacje (powstałe 6720 plików), a następnie użyję PNGOUT, aby wybrać kompresję do najmniejszego pliku. Okazuje się, że jest to plik, który:

  • Najpierw napisz „20” w trybie alfanumerycznym
  • Następnie wpisz „1” w trybie numerycznym
  • Następnie wpisz „5” w trybie numerycznym
  • Użyj poziomu korekcji błędów „H” (High)
  • Użyj maskowania danych „110”

Jest to wywoływane, test-3-1-H-Diamonds.bmpjeśli korzystałeś z poniższego programu. Ten obraz ma 175 bajtów długości po uruchomieniu PNGOUT. Dzięki „wysokiemu” poziomowi korekcji błędów w kodzie QR „wersja 1” możemy modyfikować do 8 pikseli w części danych bez rujnowania danych. Przy odrobinie ręcznych prób i błędów mogę go jeszcze bardziej zmniejszyć do 173 bajtów przedstawionych powyżej. Prawdopodobnie może być mniejszy, ale wyczerpanie wszystkich kombinacji wymaga 208 C 8 ~ 7,5 × 10 13 kontroli, których nie zamierzam robić;)


Program Rust (0.13.0-night (5ba610265)), który generuje wszystkie kombinacje:

/* 

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
źródło
1
Główny problem, jaki tu widzę, polega na tym, że samo zgłoszenie nie jest napisane w języku programowania .
Martin Ender
4
@ MartinBüttner To subiektywna opinia wybranych kilku osób. To powiedziawszy, sposób, w jaki plik został uzyskany, został zaprogramowany, więc powiedziałbym, że jest to całkowicie poprawne przesłanie. Jest to także niesamowicie niesamowite podejście.
Nit
1
@Nit To jest meta post bez głosów negatywnych, co w zasadzie działa konsensus społeczności w sprawie SE (przynajmniej PPCG). Jeśli się nie zgadzasz, możesz głosować za tą odpowiedzią lub podać alternatywę. To powiedziawszy, prawdopodobnie utworzę osobny meta post, szczególnie na temat wyzwań związanych ze złożonością Kołmogorowa, ponieważ często się to pojawia.
Martin Ender
@Nit Done. Zapraszamy do dyskusji na ten temat na stronie meta.
Martin Ender
Konwersja z gif wydawała się krótsza.
jimmy23013
5

Mathematica, 217 177 176 166 bajtów

Oto początek:

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

Mniej golfa:

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

Kod QR jest zakodowany w podstawowym numerze 36. Oczywiście, mógłbym zakodować go w rozszerzonym ASCII (podstawa 256), ale to tylko skróciłoby ciąg o 30 bajtów i nie jestem pewien, czy mogę wykonać konwersję kosztem znacznie mniejszym.

Oczywiście jest to Mathematica, więc jest też 63-bajtowy

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

ale myślę, że to standardowa luka. ;) (Daje to inny kod QR niż ten w konkursie, więc chyba kod QR nie jest unikalny?)

Martin Ender
źródło
1
Tak, istnieje wiele sposobów kodowania tego samego ciągu w kodzie QR, np. Przy użyciu różnych poziomów sprawdzania błędów, schematu kodowania, maskowania obrazu itp. Mimo to, nie biorąc pod uwagę kompresji, kod OP jest jednym z najmniejszych („wersja 1”).
kennytm
FromDigits? Możesz 36^^fl6ibg25c8z00uef53p4657dgd6hjzg41e5joead1qgz0l2xchqgso5r1a51v5no4zkw9v22okklg0cymmy2zamiast tego użyć .
kennytm
@KennyTM o wow, fajna sztuczka. Dziękuję :) Myślę, że z tym, baza 256 naprawdę nie jest tego warta (potrzebowałbym obu ToCharacterCodei FromDigitswtedy.)
Martin Ender
3

Matlab 545 Bytes

nowy Rok

Zakodowany w żmudnej pracy ręcznej i bez żadnych fantazyjnych wbudowanych kompresji / konwersacji strun . Wiem, że to nie jest tak dobre, jak inne odpowiedzi, ale nadal jestem szczęśliwy =)

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

Bardziej nieczytelne (aktualna wersja 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')

Tworzymy macierz zerową 31 x 31, ale uzyskujemy do niej dostęp jako wektor, aby ustawić wszystkie komórki o indeksach bdo 1. Sztuczki, których użyłem, to zapisanie kolejnych liczb całkowitych (jak [1,2,3,4] = 1:4) i usunięcie jednej 100-cyfrowej przez dodanie skalara do każdej wartości wektora.

Zobaczmy, czy ktokolwiek może to pokonać =)

wada
źródło
więc nie przeczytałem słowa unreadablepoprawnie ... zdecydowanie przeczytałem readable. zobaczyłem to zaraz po zasugerowaniu tego i miałem nadzieję, że ktokolwiek przeczytał moją edycję, odrzucił ją, ale najwyraźniej jej brakowało. przepraszam za złą edycję ...
pseudonim
IMHO nie ma znaczenia, po prostu chciałem dołączyć pierwszą wersję, ponieważ łatwiej jest odwołać się do wyjaśnienia.
flawr
2

Bash, 206 252 257 bajtów

Użycie convertpolecenia w pakiecie imagemagickpozwala zaoszczędzić 46 bajtów.

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

Konwertuje pbmobraz zakodowany w standardzie base64 na pngobraz z imagemagick„s” convert.

Może być konieczne dostosowanie decode (-d)parametru do konkretnego base64pliku binarnego. Testowany na moim Ubuntu 14.04 LTS.

Zapisano 5 bajtów za pomocą <<</ here-string .

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

Stara wersja (257 bajtów):
echo iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEX///8AAABVwtN+AAAAX0lEQVQI12PACdi/7G9gYJFUaGBgvaIHJG6CiMvrgGJyCxoY2H/tBxJ3rgIVekxnYGCU9WtgYDokBWSFezcwMPA/ARrwZwMDA4vwUwYG1nuTYMRdP6CYjDRQ9q8fbrsBLRkaYOOP83wAAAAASUVORK5CYII=|base64 -d > newyear.png

Po prostu prosty łańcuch poleceń powłoki, który zapisuje pngplik stdin w formacie base64, base64który dekoduje go ze względu na -dflagę i zapisuje jego stdout do newyear.png.

GiantTree
źródło
Prawdopodobnie mogę uratować postacie za pomocą czegoś takiego, base64 -d>newyear.png<<<[the long string]ale nie jestem na komputerze z linuksem rn i nie wiem, która biała spacja jest obowiązkowa
metro
Potwierdzono współpracę z base64 -d>newyear.png<<<[base64 string]Ubuntu 14.04.
PurkkaKoodari
Jeśli zamierzasz użyć sugerowanego kodu, po prostu edytuj nagłówek odpowiedzi na coś konkretnego, takiego jak Bash, Ksh lub Zsh. Powłoka ogólnie (podobnie jak Sh, Ash lub Dash kompatybilne z POSIX) nie obsługuje składni ciągów tutaj .
manatwork
Jeśli możemy użyć Netpbm rutyny, możemy nakarmić sprężonego bitmapy i stracić 40 bajtów: echo UDQKMzEgMzEKAAAAAAAAAAAAAAAAAAAAAAAAAAAH95 / ABBBQQAXWV0AF0VdABdFXQAQQEEAH9V / AAAWAAAUzMUADqtLABbv0QAcMPAAH1JSAAADwAAfxbUAEFDwABdCUgAXSfAAF1W1ABBMdwAf0FUAAAAA AAAAAAAAAAAAAAAAAAAAAAA == | base64 -d | pnmtopng> newyear.png
swstephe
@manatwork Właśnie edytowany, powinien działać na Bash, gdy testowałem go na moim telefonie z Androidem.
GiantTree,
1

Python 2 + PIL, 216 215

Zasadniczo port rozwiązania 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
źródło
0

Wspólne narzędzia 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

Trochę skomplikowane , ale krótsze niż druga odpowiedź powłoki .

  • Base64 konwertuje z base64 na base 256 (rozszerzony ASCII)
  • xxd konwertuje na hex
  • tr tworzy sześciokątne wielkie litery, odpowiednie dla dc
  • dc odczytuje hex i wypisuje ciąg binarny 1s i 0s
  • tr usuwa \ i białe znaki
  • fold sprawia, że ​​linie mają 21 znaków (21 pikseli)
  • To wyjście, wraz z P1\n21 21jest w formacie PBM P1
  • convert (Imagemagick) konwertuje to na .png z 5-pikselową ramką:

wprowadź opis zdjęcia tutaj

Cyfrowa trauma
źródło