Divertimento con le bandiere!


20

Scrivi un programma completo con un codice sorgente di 256 byte o meno che guardi l'immagine di una bandiera e determini da quale paese proviene quella bandiera. Un file zip contenente le 196 bandiere diverse nella sfida può essere scaricato da qui . Fonte: [ Flagpedia ]. Queste 196 immagini di flag sono gli unici input che il tuo programma deve gestire.

Il tuo programma non accetterà alcun input. L'immagine della bandiera sarà nella stessa directory del programma e denominata "f.png". Il tuo programma aprirà questo file, lo identificherà e stamperà l' abbreviazione di due lettere per quel paese . Se usi una lingua che non può aprire i file, è anche accettabile eseguire il tuo programma come ./program < f.png.

Ogni file flag viene chiamato come l'output previsto. Tutti gli output superiori a 2 lettere verranno ignorati.

Ecco un elenco di tutti gli output / nomi dei file:

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, 

punteggio

Ecco un breve script in pitone che userò per assegnare un punteggio a ogni invio.

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

Il tuo punteggio è il numero totale di flag identificati correttamente. In caso di pareggio, vince l'invio precedente.

Regole

  • Per la mia comodità di test, è possibile utilizzare qualsiasi lingua con un interprete / compilatore disponibile gratuitamente per Windows 10 o Ubuntu.

  • Le librerie di elaborazione delle immagini sono consentite, ma non sono consentiti tutti i builtin relativi a flag o paesi. ( tosse Mathematica tosse )

  • Fornisci il comando completo necessario per eseguire il programma insieme ai collegamenti a tutte le librerie necessarie.

  • Gli invii non possono interagire con nessun file tranne "f.png".

  • Non ho alcun limite di tempo per l'invio, ma ti preghiamo di mantenerlo relativamente veloce. Non voglio che la sceneggiatura del punteggio richieda ore.


4
Il limite di byte è davvero basso. La
sola

2
@ edc65 Il punto è che otterrai solo un piccolo numero di bandiere.
isaacg,

1
@ edc65 Ho scelto intenzionalmente un numero che renderebbe praticamente impossibile un punteggio perfetto di 196. Si tratta più di compressione di riconoscere immagini che di codegolf.
DJMcMayhem

Doppio controllo: possiamo usare l' ./program < f.pngopzione solo se la lingua non ha modo di leggere i file o possiamo usarla anche se la lingua può leggere i file? (Apparentemente CJam è in grado di leggere da file, che non sapevo)
Sp3000

Queste 196 immagini di flag sono gli unici input che il tuo programma deve gestire, quindi dici che il tuo programma non prenderà input . Significa che l'unico file f.png sarà uno di quei 196. Quindi il programma non può fare riferimento a quei file compressi? Just f.png
Matt

Risposte:


11

CJam, 139 141

Ci sono molti non stampabili nel codice, quindi ecco il xxdhexdump:

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/=

Sono esattamente 256 byte, con il programma che sta eseguendo:

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

Esegui il programma con il comando

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

Grazie a @Dennis per l'aiuto nel far funzionare questa presentazione.


Sono stupito che qualcuno ne abbia così tanti. 139/196 = 70,9%. Hai grattato un voto A!
Level River St

Potresti rendere il dump binario xxd -r-versibile? Cygwin dovrebbe averexxd
gatto

1
@tac Ho dovuto curiosare un po ', ma non mi ero reso conto che Cygwin ce l'avesse - ho dovuto selezionarlo manualmente per l'installazione. Lo aggiornerò al prossimo aggiornamento della risposta.
Sp3000,

Ho provato a utilizzare la stessa tecnica del codice Morse , ma il migliore che sono riuscito a ottenere è 129 flag e non ho nemmeno verificato se si adatta al limite di 256 byte. Ben fatto per aver trovato un hash così buono.
Peter Taylor,

12

Python 2, Punteggio = 68 89

Questa soluzione utilizza l'hash del file immagine di bandiera per creare un indice in un elenco delle abbreviazioni del paese. Se più di un flag viene eseguito l'hashing di un indice, verrà restituita solo la prima abbreviazione (quindi non supererà alcuni di quei test con più di un paese in un bucket hash). Questo algoritmo garantisce tuttavia una risposta corretta per ogni bucket hash non vuoto.

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

Questo programma ha 247 caratteri.

Una versione più leggibile:

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]

Costruire la stringa codificata

Per creare la stringa codificata, utilizzo una funzione per leggere i file flag come stringhe, generare un hash dalla stringa e ridurre l'hash a un numero limitato di hash 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

per restituire un dizionario di paesi che corrispondono a ciascuna firma, quindi utilizzare un codice per convertire il dizionario in una stringa di ricerca:

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

Avevo bisogno di sperimentare un po 'con quali valori di bucketsdanno i migliori risultati.


Sta prendendo solo il colore medio della bandiera?
Ashwin Gupta,

@AshwinGupta, il programma legge nel file e ne prende un hash. Questo grande numero di hash viene ridotto a un indice in un elenco di stringhe utilizzando un operatore modulo.
Logic Knight,

1
Non sono sicuro se ti aiuterà, ma puoi farlo print'...'[...:][:2]. Inoltre, forse una tabella di ricerca con >>e &per una compressione di base?
Sp3000,

@ Sp3000, l'idea del doppio indice sembra interessante ma non riesco a vedere dove si salverebbe alcun byte qui. Non avevo considerato le funzioni di manipolazione dei bit per la compressione, ma ciò poteva offrire un vantaggio. Hmmmm.
Logic Knight,

1
La doppia indicizzazione consente di risparmiare 3 byte perché non è necessario salvare in una variabile i, ma se è possibile o meno utilizzare quei byte extra è una domanda diversa: P
Sp3000
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.