¡Diversión con banderas!

20

Escriba un programa completo con un código fuente de 256 bytes o menos que observe la imagen de una bandera y determine de qué país es esa bandera. Un archivo zip que contiene las 196 banderas diferentes en el desafío se puede descargar desde aquí . Fuente: [ Flagpedia ]. Estas 196 imágenes de bandera son las únicas entradas que su programa tiene que manejar.

Su programa no tendrá entrada. La imagen de bandera estará en el mismo directorio que su programa y se llamará "f.png". Su programa abrirá este archivo, lo identificará e imprimirá la abreviatura de dos letras para ese país . Si usa un idioma que no puede abrir archivos, también es aceptable ejecutar su programa como ./program < f.png.

Cada archivo de marca se denomina igual que el resultado esperado. Todas las salidas por encima de 2 letras serán ignoradas.

Aquí hay una lista de todas las salidas / nombres de archivo:

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, 

Puntuación

Aquí hay un breve script de Python que usaré para calificar cada envío.

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

Su puntaje es el número total de banderas correctamente identificadas. En caso de empate, gana la presentación anterior.

Reglas

  • Para mi conveniencia de prueba, se puede usar cualquier idioma con un intérprete / compilador disponible gratuitamente para Windows 10 o Ubuntu.

  • Las bibliotecas de procesamiento de imágenes están permitidas, pero no se permite ninguna construcción relacionada con banderas o países. ( Tos Mathematica tos )

  • Proporcione el comando completo necesario para ejecutar su programa junto con enlaces a las bibliotecas necesarias.

  • Los envíos no pueden interactuar con ningún archivo excepto "f.png".

  • No tengo ningún límite de tiempo difícil para las presentaciones, pero manténgalo relativamente rápido. No quiero que el guión de puntuación tome horas.

DJMcMayhem
fuente
44
El límite de bytes es realmente bajo. Solo almacenar los 196 códigos de dos letras sin comprimir requiere 392 bytes
edc65
2
@ edc65 El punto es que solo obtendrás un pequeño número de banderas.
isaacg
1
@ edc65 Intencionalmente elegí un número que haría una puntuación perfecta de 196 básicamente imposible. Se trata más de la compresión de reconocer imágenes que de codegolf.
DJMcMayhem
Solo doble comprobación: ¿podemos usar la ./program < f.pngopción solo si el idioma no tiene forma de leer archivos, o también podemos usarla incluso si el idioma puede leer archivos? (Aparentemente, CJam puede leer de archivos, lo que no sabía)
Sp3000
Estas 196 imágenes de bandera son las únicas entradas que su programa tiene que manejar, entonces usted dice que su programa no tomará ninguna entrada . ¿Eso significa que el único archivo f.png será uno de esos 196. ¿Entonces el programa no puede hacer referencia a esos archivos comprimidos? Solo f.png
Matt

Respuestas:

11

CJam, 139 141

Hay un montón de no imprimibles en el código, así que aquí está el 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/=

Esto es exactamente 256 bytes, con el programa haciendo:

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

Ejecute el programa con el comando

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

Gracias a @Dennis por su ayuda para que esta presentación funcione.

Sp3000
fuente
Me sorprende que alguien tenga tantos. 139/196 = 70.9%. ¡Raspó una calificación A!
Level River St
¿Podría hacer que el volcado binario sea xxd -rreversible? Cygwin debería tenerxxd
gato
1
@tac Tuve que hurgar un poco, pero no me di cuenta de que Cygwin lo tenía, solo tuve que seleccionarlo manualmente para la instalación. Lo actualizaré la próxima vez que actualice la respuesta.
Sp3000
Intenté usar la misma técnica que para el código Morse , pero lo mejor que he podido obtener es 129 banderas, y ni siquiera he comprobado si eso encaja en el límite de 256 bytes. Bien hecho por encontrar un buen hash.
Peter Taylor
12

Python 2, Puntuación = 68 89

Esta solución utiliza el hash del archivo de imagen de la bandera para crear un índice en una lista de las abreviaturas de los países. Si hay más de un indicador en hash a un índice, solo se devolverá la primera abreviatura (por lo que fallará algunas de esas pruebas con más de un país en un depósito de hash). Sin embargo, este algoritmo garantiza una respuesta correcta para cada cubo de hash no vacío.

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

Este programa tiene 247 caracteres.

Una versión más legible:

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]

Construyendo la cadena codificada

Para construir la cadena codificada, utilizo una función para leer los archivos de marca como cadenas, generar un hash de la cadena y reducir el hash a un número limitado de 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

para devolver un diccionario de países que coincidan con cada firma, luego use un código para convertir el diccionario en una cadena de búsqueda:

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

Necesitaba experimentar un poco con qué valores de bucketsda los mejores resultados.

Caballero Lógico
fuente
¿Esto solo toma el color promedio de la bandera?
Ashwin Gupta
@AshwinGupta, el programa lee el archivo y luego lo analiza. Este número hash grande se reduce a un índice en una lista de cadenas mediante el uso de un operador de módulo.
Caballero Lógico
1
No estoy seguro de si ayudará, pero puede hacerlo print'...'[...:][:2]. Además, ¿tal vez una tabla de búsqueda con >>y &para una compresión básica?
Sp3000
@ Sp3000, la idea de doble índice parece interesante, pero no puedo ver dónde se guardarían los bytes aquí. No había considerado las funciones de manipulación de bits para la compresión, pero eso podría ofrecer una ventaja. Hmmmm
Logic Knight
1
La indexación doble ahorra 3 bytes porque no necesita guardar en una variable i, pero si puede o no usar esos bytes adicionales es una pregunta diferente: P
Sp3000