Diversão com bandeiras!

20

Escreva um programa completo com um código-fonte de 256 bytes ou menos que observe a imagem de uma bandeira e determine de que país é essa bandeira. Um arquivo zip contendo as 196 bandeiras diferentes no desafio pode ser baixado aqui . Fonte: [ Flagpedia ]. Essas 196 imagens de sinalizadores são as únicas entradas que seu programa precisa lidar.

Seu programa não aceita entrada. A imagem do sinalizador estará no mesmo diretório do seu programa e denominada "f.png". Seu programa abrirá esse arquivo, identificá-lo e imprimirá a abreviação de duas letras para esse país . Se você usa um idioma que não pode abrir arquivos, também é aceitável executar o seu programa como ./program < f.png.

Cada arquivo de sinalizador é nomeado da mesma forma que a saída esperada. Toda saída acima de 2 letras será ignorada.

Aqui está uma lista de todas as saídas / nomes de arquivos:

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, 

Pontuação

Aqui está um pequeno script python que usarei para pontuar cada envio.

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

Sua pontuação é o número total de sinalizadores corretamente identificados. Em caso de empate, a finalização anterior vence.

Regras

  • Para minha conveniência de teste, qualquer idioma com um interpretador / compilador disponível gratuitamente para Windows 10 ou Ubuntu pode ser usado.

  • Bibliotecas de processamento de imagens são permitidas, mas não são permitidos quaisquer recursos internos relacionados a sinalizadores ou países. ( tosse Mathematica tosse )

  • Por favor, forneça o comando completo necessário para executar o seu programa, juntamente com os links para as bibliotecas necessárias.

  • Os envios não podem interagir com nenhum arquivo, exceto "f.png".

  • Não tenho limite de tempo para envios, mas mantenha-o relativamente rápido. Não quero que o script de pontuação leve horas.

DJMcMayhem
fonte
4
O limite de bytes é realmente baixo. Apenas armazenar os 196 e duas letras códigos não comprimidos requer 392 bytes
edc65
2
@ edc65 O ponto é que você receberá apenas um pequeno número de sinalizadores.
Isaacg
1
@ edc65 Eu escolhi intencionalmente um número que tornaria praticamente impossível uma pontuação perfeita de 196. É mais uma compressão do reconhecimento de imagens do que um codegolf.
DJMcMayhem
Apenas verifique duas vezes - só podemos usar a ./program < f.pngopção se o idioma não puder ler arquivos ou também podemos usá-lo mesmo que o idioma possa ler arquivos? (Aparentemente, o CJam pode ler arquivos, o que eu não sabia) #
Sp3000 27/03/16
Essas 196 imagens de sinalizador são as únicas entradas que o seu programa precisa manipular e você diz que o seu programa não receberá nenhuma entrada . Isso significa que o arquivo f.png será um daqueles 196. Portanto, o programa não pode fazer referência a esses arquivos compactados? Apenas f.png
Matt

Respostas:

11

CJam, 139 141

Há muitos não imprimíveis no código, então aqui está o 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/=

Isso é exatamente 256 bytes, com o programa fazendo:

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

Execute o programa com o comando

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

Agradecemos a @Dennis pela ajuda para que este envio funcione.

Sp3000
fonte
Estou surpreso que alguém tenha tantos. 139/196 = 70,9%. Você raspou uma nota A!
Level River St
Você poderia tornar o despejo binário um xxd -rreversível? Cygwin deveria terxxd
cat
1
@tac Tive que bisbilhotar um pouco, mas não sabia que o Cygwin tinha - basta selecioná-lo manualmente para instalação. Vou atualizá-lo na próxima atualização da resposta.
SP3000
Tentei usar a mesma técnica do código Morse , mas o melhor que consegui obter são 129 sinalizadores, e nem chequei se isso se encaixa no limite de 256 bytes. Bem feito para encontrar um hash tão bom.
Peter Taylor
12

Python 2, pontuação = 68 89

Esta solução usa o hash do arquivo de imagem da bandeira para criar um índice em uma lista de abreviações de países. Se mais de um sinalizador fizer hash em um índice, somente a primeira abreviação será retornada (portanto, falhará em alguns desses testes com mais de um país em um hash bucket). No entanto, esse algoritmo garante uma resposta correta para cada intervalo de hash não vazio.

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 tem 247 caracteres.

Uma versão mais legível:

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]

Construindo a sequência codificada

Para criar a string codificada, eu uso uma função para ler os arquivos de flag como strings, gerar um hash a partir da string e reduzi-lo a um 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 retornar um dicionário de países que correspondem a cada assinatura e use algum código para converter o dicionário em uma sequência de pesquisa:

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

Eu precisava experimentar um pouco com quais valores de bucketsobtém os melhores resultados.

Cavaleiro Lógico
fonte
Isso está apenas tomando a cor média da bandeira?
Ashwin Gupta 27/03
@AshwinGupta, o programa lê o arquivo e pega um hash dele. Esse grande número de hash é reduzido a um índice em uma lista de cadeias usando um operador de módulo.
Logic Knight
1
Não tenho certeza se isso vai ajudar, mas você pode fazer print'...'[...:][:2]. Além disso, talvez uma tabela de pesquisa com >>e &para alguma compactação básica?
Sp3000 27/03
@ Sp3000, a idéia de índice duplo parece interessante, mas não consigo ver onde está salvaria quaisquer bytes aqui. Eu não havia considerado funções de manipulação de bits para compactação, mas isso poderia oferecer uma vantagem. Hmmmm.
Logic Knight
1
Indexação dupla salva 3 bytes, porque você não precisa para salvar a uma variável i, mas se você pode ou não fazer uso desses bytes extras é uma questão diferente: P
SP3000