Amusez-vous avec des drapeaux!

20

Écrivez un programme complet avec un code source de 256 octets ou moins qui examine une image d'un drapeau et détermine de quel pays provient ce drapeau. Un fichier zip contenant les 196 drapeaux différents du défi peut être téléchargé à partir d' ici . Source: [ Flagpedia ]. Ces 196 images de drapeau sont les seules entrées que votre programme doit gérer.

Votre programme ne prendra aucune entrée. L'image du drapeau sera dans le même répertoire que votre programme et nommée "f.png". Votre programme ouvrira ce fichier, l'identifiera et imprimera l' abréviation à deux lettres de ce pays . Si vous utilisez une langue qui ne peut pas ouvrir de fichiers, il est également acceptable d'exécuter votre programme sous ./program < f.png.

Chaque fichier indicateur est nommé de la même manière que la sortie attendue. Toute sortie supérieure à 2 lettres sera ignorée.

Voici une liste de toutes les sorties / noms de fichiers:

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, 

Notation

Voici un court script python que je vais utiliser pour noter chaque soumission.

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

Votre score est le nombre total de drapeaux correctement identifiés. En cas d'égalité, la soumission précédente l'emporte.

Règles

  • Pour mon confort de test, n'importe quelle langue avec un interprète / compilateur disponible gratuitement pour Windows 10 ou Ubuntu peut être utilisée.

  • Les bibliothèques de traitement d'image sont autorisées, mais toutes les extensions liées aux drapeaux ou aux pays ne sont pas autorisées. ( toux Mathematica toux )

  • Veuillez fournir la commande complète nécessaire pour exécuter votre programme ainsi que des liens vers les bibliothèques nécessaires.

  • Les soumissions ne peuvent interagir avec aucun fichier à l'exception de "f.png".

  • Je n'ai pas de limite de temps pour les soumissions, mais veuillez la garder relativement rapide. Je ne veux pas que le script de notation prenne des heures.

DJMcMayhem
la source
4
La limite d'octets est vraiment faible. Le simple stockage des 196 codes à deux lettres non compressés nécessite 392 octets
edc65
2
@ edc65 Le fait est que vous n'obtiendrez qu'un petit nombre de drapeaux.
isaacg
1
@ edc65 J'ai intentionnellement choisi un nombre qui rendrait impossible un score parfait de 196. Il s'agit plus de compression de reconnaissance d'images que de codegolf.
DJMcMayhem
Juste une double vérification - pouvons-nous utiliser cette ./program < f.pngoption uniquement si la langue n'a aucun moyen de lire les fichiers, ou pouvons-nous également l'utiliser même si la langue peut lire les fichiers? (Apparemment, CJam peut lire des fichiers, que je ne connaissais pas)
Sp3000
Ces 196 images de drapeau sont les seules entrées que votre programme doit gérer, alors vous dites que votre programme ne prendra aucune entrée . Est-ce à dire que l'un des fichiers f.png sera l'un de ces 196. Le programme ne peut donc pas référencer ces fichiers zippés? Just f.png
Matt

Réponses:

11

CJam, 139 141

Il y a beaucoup d'imprimables dans le code, voici donc l' 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/=

C'est exactement 256 octets, le programme faisant:

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

Exécutez le programme avec la commande

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

Merci à @Dennis pour son aide à faire fonctionner cette soumission.

Sp3000
la source
Je suis étonné que quiconque en ait autant. 139/196 = 70,9%. Vous avez gratté une note A!
Level River St
Pourriez-vous faire du vidage binaire un xxd -rfichier réversible? Cygwin devrait avoirxxd
cat
1
@tac J'ai dû fouiller un peu, mais je ne savais pas que Cygwin l'avait. Il me suffisait de le sélectionner manuellement pour l'installation. Je le mettrai à jour lors de la prochaine mise à jour de la réponse.
Sp3000
J'ai essayé d'utiliser la même technique que pour le code Morse , mais le meilleur que j'ai pu obtenir est 129 drapeaux, et je n'ai même pas vérifié si cela correspond à la limite de 256 octets. Bravo pour trouver un si bon hachage.
Peter Taylor
12

Python 2, Score = 68 89

Cette solution utilise le hachage du fichier image de drapeau pour créer un index dans une liste des abréviations de pays. Si plusieurs drapeaux sont hachés sur un index, seule la première abréviation sera renvoyée (ainsi, certains de ces tests échoueront avec plus d'un pays dans un compartiment de hachage). Cet algorithme garantit cependant une réponse correcte pour chaque compartiment de hachage non vide.

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

Ce programme contient 247 caractères.

Une version plus lisible:

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]

Construire la chaîne encodée

Pour construire la chaîne encodée, j'utilise une fonction pour lire les fichiers d'indicateurs sous forme de chaînes, générer un hachage à partir de la chaîne et réduire le hachage à un nombre limité de hachage 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

pour renvoyer un dictionnaire des pays qui correspondent à chaque signature, puis utilisez du code pour convertir le dictionnaire en chaîne de recherche:

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

J'avais besoin d'expérimenter un peu avec quelles valeurs de bucketsdonne les meilleurs résultats.

Logic Knight
la source
Est-ce que cela prend simplement la couleur moyenne du drapeau?
Ashwin Gupta
@AshwinGupta, le programme lit le fichier puis en prend un hachage. Ce grand nombre de hachage est réduit à un index dans une liste de chaînes à l'aide d'un opérateur modulo.
Logic Knight
1
Je ne sais pas si cela vous aidera, mais vous pouvez le faire print'...'[...:][:2]. Aussi, peut-être une table de recherche avec >>et &pour une compression de base?
Sp3000
@ Sp3000, l'idée du double index semble intéressante, mais je ne vois pas où se trouverait économiser des octets ici. Je n'avais pas envisagé les fonctions de manipulation de bits pour la compression, mais cela pouvait offrir un avantage. Hmmmm.
Logic Knight
1
La double indexation économise 3 octets parce que vous n'avez pas besoin d'enregistrer dans une variable i, mais si vous pouvez ou non utiliser ces octets supplémentaires est une question différente: P
Sp3000