Zabawa z flagami!

20

Napisz pełny program o kodzie źródłowym 256 bajtów lub mniejszym, który patrzy na obraz flagi i określa, z jakiego kraju pochodzi ta flaga. Plik zip zawierający 196 różnych flag w wyzwaniu można pobrać tutaj . Źródło: [ Flagpedia ]. Te 196 obrazów flag to jedyne dane wejściowe, które program musi obsłużyć.

Twój program nie będzie pobierał danych. Obraz flagi będzie w tym samym katalogu co twój program i będzie miał nazwę „f.png”. Twój program otworzy ten plik, zidentyfikuje go i wydrukuje dwuliterowy skrót dla tego kraju . Jeśli używasz języka, w którym nie można otwierać plików, dopuszczalne jest również uruchamianie programu jako ./program < f.png.

Każdy plik flagi ma taką samą nazwę jak oczekiwany wynik. Wszystkie dane wyjściowe powyżej 2 liter zostaną zignorowane.

Oto lista wszystkich wyjść / nazw plików:

ad, ae, af, ag, al, am, ao, ar, at, au, az, ba, bb, bd, be, bf, bg, bh, bi, bj,
bn, bo, br, bs, bt, bw, by, bz, ca, cd, cf, cg, ch, ci, cl, cm, cn, co, cr, cu,
cv, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, eh, er, es, et, fi, fj, fm, fr,
ga, gb, gd, ge, gh, gm, gn, gq, gr, gt, gw, gy, hn, hr, ht, hu, id, ie, il, in,
iq, ir, is, it, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, ks, kw, kz, la, lb,
lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mr,
mt, mu, mv, mw, mx, my, mz, na, ne, ng, ni, nl, no, np, nr, nz, om, pa, pe, pg,
ph, pk, pl, pt, pw, py, qa, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, si, sk, sl,
sm, sn, so, sr, st, sv, sy, sz, td, tg, th, tj, tl, tm, tn, to, tr, tt, tv, tw,
tz, ua, ug, us, uy, uz, va, vc, ve, vn, vu, ws, ye, za, zm, zw, 

Punktacja

Oto krótki skrypt Pythona, którego użyję do oceny każdego zgłoszenia.

import os
import subprocess
import random

botlist = []
with open("bots.txt") as bots:
    for line in bots:
        line = line.split(", ")
        if len(line) >= 2:
            botLine = line + [0]
            botlist.append(botLine)

files = os.listdir(os.getcwd() + "/flags")
random.shuffle(files)

def test(bot_command):
    score = 0
    for filename in files:
        command = "COPY flags\\{} f.png".format(filename)
        os.system(command)

        print bot_command

        result = subprocess.check_output(bot_command, shell = True)
        if result[:2] == filename[:2]:
            score += 1

    return score

for i in range(len(botlist)):
    command = botlist[i][1]
    botlist[i][2] = test(command)

with open("output.txt", "w+") as output:
    for bot in botlist:
        output.write("{} got a score of {}.".format(bot[0], bot[2]))

os.system("del f.png")

Twój wynik to całkowita liczba poprawnie zidentyfikowanych flag. W przypadku remisu wygrywa wcześniejsze zgłoszenie.

Zasady

  • Dla mojej wygody testowania można używać dowolnego języka z swobodnie dostępnym tłumaczem / kompilatorem dla systemu Windows 10 lub Ubuntu.

  • Biblioteki przetwarzania obrazu są dozwolone, ale żadne wbudowane funkcje związane z flagami lub krajami nie są dozwolone. ( Kaszel Mathematica kaszel )

  • Podaj pełne polecenie potrzebne do uruchomienia programu wraz z linkami do niezbędnych bibliotek.

  • Zgłoszenia nie mogą wchodzić w interakcje z żadnym plikiem oprócz „f.png”.

  • Nie mam żadnych trudnych terminów składania wniosków, ale proszę zachować je stosunkowo szybko. Nie chcę, żeby skrypt oceniania zajmował godziny.

DJMcMayhem
źródło
4
Limit bajtów jest naprawdę niski. Samo przechowywanie 196
dwuliterowych
2
@ edc65 Chodzi o to, że dostaniesz tylko niewielką liczbę flag.
isaacg
1
@ edc65 Celowo wybrałem liczbę, która sprawiłaby, że idealny wynik 196 byłby w zasadzie niemożliwy. Chodzi bardziej o kompresję rozpoznawania obrazów niż kodegolf.
DJMcMayhem
Tylko podwójne sprawdzanie - czy możemy skorzystać z ./program < f.pngopcji tylko wtedy, gdy język nie ma możliwości odczytu plików, czy możemy go również użyć, nawet jeśli język potrafi czytać pliki? (Najwyraźniej CJam potrafi czytać z plików, których nie znałem)
Sp3000
Te 196 obrazów flag są jedynymi danymi wejściowymi, które program musi obsłużyć, a następnie informujesz, że Twój program nie przyjmuje danych wejściowych . Czy to oznacza, że ​​jeden plik f.png będzie jednym z tych 196. Czyli program nie może odwoływać się do tych spakowanych plików? Just f.png
Matt

Odpowiedzi:

11

CJam, 139 141

W kodzie jest wiele niezadrukowanych elementów, więc oto xxdzrzut heksowy:

00000000: 7132 3925 3162 226d cec5 9635 b14b 69ee  q29%1b"m...5.Ki.
00000010: d9d0 66e8 97b8 e88d 2366 7857 9595 1c73  ..f.....#fxW...s
00000020: 9324 11b2 ddb8 7a3f 19ed bd37 07c0 cb86  .$....z?...7....
00000030: 394e b34a ecf0 8c9b f300 a216 2e2e 594a  9N.J..........YJ
00000040: 9a6b 3b2f 250a 9a25 783b 0e49 3e9c 6ab9  .k;/%..%x;.I>.j.
00000050: 8d6d d729 42d0 85f3 657b 7d86 af48 c6cb  .m.)B...e{}..H..
00000060: f7ff 980f b81c dd5e e8cb 4e34 d8ec edca  .......^..N4....
00000070: 6646 1b4d 7605 8937 ed58 2302 1cc1 ebfd  fF.Mv..7.X#.....
00000080: 16d3 b53e 3e2c d879 fe33 feef dd65 d49f  ...>>,.y.3...e..
00000090: 5d73 7ced 92e6 9526 c186 00bf d2a8 ffaa  ]s|....&........
000000a0: 65a0 3001 f42a 94d7 592f ebe7 8bdf 97a7  e.0..*..Y/......
000000b0: 0681 8ee1 9e0e 424b f6a1 4c50 1c8a 8de5  ......BK..LP....
000000c0: 481a 388c 6eaa 0c43 e1db 69df 567b 323f  H.8.n..C..i.V{2?
000000d0: 2573 c4ce b348 6fff 37e0 55b4 7c9a 7e7d  %s...Ho.7.U.|.~}
000000e0: 73a4 ef74 2b99 b765 2a2d d99f 986a 355c  s..t+..e*-...j5\
000000f0: db22 3236 3362 3236 6227 6166 2b32 2f3d  ."263b26b'af+2/=

To dokładnie 256 bajtów, przy czym program wykonuje:

q29%                          Read input and keep every 29th char
    1b                        Sum code points
      "..."                   Push long string
           263b               Convert long string to base 263
               26b            Convert result to base 26
                  'af+        Add 'a to each element in the resulting array
                      2/      Split into chunks of length 2
                        =     Index sum cyclically to extract output

Uruchom program za pomocą polecenia

java -Dfile.encoding=ISO-8859-1 -jar cjam-0.6.5.jar flags.cjam < f.png

Dziękujemy @Dennis za pomoc w uruchomieniu tego zgłoszenia.

Sp3000
źródło
Dziwi mnie, że ktoś ma ich tak wiele. 139/196 = 70,9%. Zeskrobałeś ocenę A!
Level River St
Czy możesz uczynić zrzut binarny xxd -rodwracalnym? Cygwin powinien miećxxd
kot
1
@tac Musiałem trochę pogrzebać, ale nie zdawałem sobie sprawy, że Cygwin go miał - musiałem tylko wybrać go ręcznie do instalacji. Zaktualizuję go, kiedy następnym razem zaktualizuję odpowiedź.
Sp3000,
Próbowałem użyć tej samej techniki, co w przypadku kodu Morse'a , ale najlepsze, co udało mi się uzyskać, to 129 flag, a nawet nie sprawdziłem, czy mieści się w limicie 256 bajtów. Dobra robota dla znalezienia tak dobrego skrótu.
Peter Taylor
12

Python 2, wynik = 68 89

To rozwiązanie wykorzystuje skrót pliku obrazu flagi, aby utworzyć indeks do listy skrótów kraju. Jeśli więcej niż jedna flaga ma skrót do indeksu, zwracany jest tylko pierwszy skrót (więc nie powiedzie się niektóre z tych testów z więcej niż jednym krajem w zasobniku mieszającym). Algorytm ten gwarantuje jednak jedną poprawną odpowiedź dla każdego niepustego segmentu mieszania.

i=hash(open('f.png').read())%99*2
print'kgmviruasefridusvakpsmbtgrpwcdsdauninrsyalsg--game--espyscmtyebhgqom--kh--inhudjbw--ltroilbicv--jonaugke--svhtbg--simcknbnpelcplgncmmacimytnttlytgcflirsvemhtzuyqaerbfbepa--uzaenearcl--jmbbphkzrwieet'[i:i+2]

Ten program ma 247 znaków.

Bardziej czytelna wersja:

encoded = 'kgmviruasefridusvakpsmbtgrpwcdsdauninrsyalsg--game--espyscmtyebhgqom--kh--inhudjbw--ltroilbicv--jonaugke--svhtbg--simcknbnpelcplgncmmacimytnttlytgcflirsvemhtzuyqaerbfbepa--uzaenearcl--jmbbphkzrwieet'
index = hash(open('f.png').read())%99 * 2
print encoded[index : index+2]

Budowanie zakodowanego ciągu

Aby zbudować zakodowany ciąg, używam funkcji do odczytywania plików flag jako ciągów, generowania skrótu z łańcucha i redukowania skrótu do ograniczonej liczby skrótów buckets:

def encode(buckets):
    lookup = {}
    for fn in os.listdir('flags'):
        name = fn[:2]
        signature = hash(open('flags/'+fn).read()) % buckets
        lookup[signature] = lookup.get(signature, '')+name
    return lookup

aby zwrócić słownik krajów pasujących do każdego podpisu, a następnie użyj kodu do konwersji słownika na ciąg wyszukiwania:

encoded = ''.join(lookup.get(v, '--')[:2] for v in range(buckets))

Musiałem trochę poeksperymentować z wartościami, które bucketsdają najlepsze wyniki.

Logic Knight
źródło
Czy to tylko przybiera średni kolor flagi?
Ashwin Gupta
@AshwinGupta, program wczytuje plik, a następnie pobiera jego skrót. Ta duża liczba skrótów jest redukowana do indeksu na liście ciągów za pomocą operatora modulo.
Logic Knight
1
Nie jestem pewien, czy to pomoże, ale możesz to zrobić print'...'[...:][:2]. A może tabela przeglądowa z >>i &dla podstawowej kompresji?
Sp3000,
@ Sp3000, pomysł podwójnego indeksu wygląda interesująco, ale nie widzę, gdzie mógłby zapisać tutaj bajty. Nie brałem pod uwagę funkcji manipulacji bitami do kompresji, ale może to być zaletą. Hmmmm
Logic Knight
1
Podwójne indeksowanie pozwala zaoszczędzić 3 bajty, ponieważ nie trzeba zapisywać w zmiennej i, ale czy można skorzystać z dodatkowych bajtów, to inne pytanie: P
Sp3000