Vui với cờ!


20

Viết một chương trình đầy đủ với mã nguồn từ 256 byte trở xuống nhìn vào hình ảnh của một lá cờ và xác định quốc gia đó là cờ nào. Một tập tin zip chứa 196 cờ khác nhau trong thử thách có thể được tải xuống từ đây . Nguồn: [ Flagpedia ]. Những hình ảnh cờ 196 này là đầu vào duy nhất mà chương trình của bạn phải xử lý.

Chương trình của bạn sẽ không có đầu vào. Hình ảnh cờ sẽ nằm trong cùng thư mục với chương trình của bạn và được đặt tên là "f.png". Chương trình của bạn sẽ mở tệp này, xác định nó và in hai chữ cái viết tắt cho quốc gia đó . Nếu bạn sử dụng ngôn ngữ không thể mở tệp, bạn cũng có thể chấp nhận chạy chương trình của mình ./program < f.png.

Mỗi tệp cờ được đặt tên giống như đầu ra dự kiến. Tất cả đầu ra trên 2 chữ cái sẽ bị bỏ qua.

Dưới đây là danh sách tất cả các kết quả đầu ra / tên tệp:

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, 

Chấm điểm

Đây là một đoạn script python ngắn mà tôi sẽ sử dụng để ghi điểm cho mỗi lần gửi.

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

Điểm của bạn là tổng số cờ được xác định chính xác. Trong trường hợp hòa, nộp trước đó thắng.

Quy tắc

  • Để thuận tiện cho việc thử nghiệm của tôi, có thể sử dụng bất kỳ ngôn ngữ nào có trình thông dịch / trình biên dịch miễn phí cho Windows 10 hoặc Ubuntu.

  • Thư viện xử lý hình ảnh được cho phép, nhưng bất kỳ nội dung liên quan đến cờ hoặc quốc gia đều không được phép. ( ho Mathicala ho )

  • Vui lòng cung cấp lệnh đầy đủ cần thiết để chạy chương trình của bạn cùng với các liên kết đến bất kỳ thư viện cần thiết nào.

  • Đệ trình có thể không tương tác với bất kỳ tệp nào ngoại trừ "f.png".

  • Tôi không có bất kỳ giới hạn thời gian khó khăn nào trong việc gửi, nhưng vui lòng giữ nó tương đối nhanh. Tôi không muốn kịch bản ghi điểm mất hàng giờ.


4
Giới hạn byte thực sự thấp. Chỉ cần lưu trữ mã 196 hai chữ cái không nén, cần 392 byte
edc65

2
@ edc65 Vấn đề là bạn sẽ chỉ nhận được một số lượng nhỏ cờ.
isaacg

1
@ edc65 Tôi cố tình chọn một con số có thể làm cho số điểm hoàn hảo là 196 về cơ bản là không thể. Đó là nhiều hơn về nén nhận dạng hình ảnh sau đó codegolf.
DJMcMayhem

Chỉ cần kiểm tra hai lần - chúng ta chỉ có thể sử dụng ./program < f.pngtùy chọn nếu ngôn ngữ không có cách đọc tệp, hoặc chúng ta cũng có thể sử dụng nó ngay cả khi ngôn ngữ có thể đọc tệp? (Rõ ràng là CJam có thể đọc từ các tệp mà tôi không biết)
Sp3000

Những hình ảnh cờ 196 này là đầu vào duy nhất mà chương trình của bạn phải xử lý sau đó bạn nói Chương trình của bạn sẽ không có đầu vào . Điều đó có nghĩa là một tệp f.png sẽ là một trong số 196. Vì vậy, chương trình không thể tham chiếu các tệp đã nén? Chỉ cần f.png
Matt

Câu trả lời:


11

CJam, 139 141

Có rất nhiều dấu vết không thể in được trong mã, vì vậy đây 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/=

Đây chính xác là 256 byte, với chương trình đang thực hiện:

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

Chạy chương trình với lệnh

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

Cảm ơn @Dennis đã giúp tôi gửi bài này.


Tôi ngạc nhiên bất cứ ai có được điều này nhiều. 139/196 = 70,9%. Bạn đã đạt điểm A!
Cấp sông St

Bạn có thể biến kết xuất nhị phân thành một xxd -rbiến đổi không? Cygwin nên cóxxd
mèo

1
@tac Phải chọc ngoáy một chút, nhưng tôi không nhận ra Cygwin đã có nó - Tôi chỉ phải chọn thủ công để cài đặt. Tôi sẽ cập nhật nó khi tôi cập nhật câu trả lời tiếp theo.
Sp3000

Tôi đã thử sử dụng kỹ thuật tương tự như mã Morse , nhưng thứ tốt nhất tôi có thể nhận được là 129 cờ và thậm chí tôi chưa kiểm tra xem liệu nó có phù hợp với giới hạn 256 byte hay không. Cũng được thực hiện để tìm một băm tốt như vậy.
Peter Taylor

12

Python 2, Điểm = 68 89

Giải pháp này sử dụng hàm băm của tệp hình ảnh cờ để tạo một chỉ mục vào danh sách các chữ viết tắt của quốc gia. Nếu có nhiều hơn một cờ được băm vào một chỉ mục, chỉ có chữ viết tắt đầu tiên sẽ được trả về (vì vậy nó sẽ thất bại một số thử nghiệm với nhiều quốc gia trong nhóm băm). Tuy nhiên, thuật toán này đảm bảo một câu trả lời đúng cho mọi nhóm hàm băm không trống.

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

Chương trình này là 247 ký tự.

Một phiên bản dễ đọc hơn:

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]

Xây dựng chuỗi được mã hóa

Để xây dựng chuỗi được mã hóa, tôi sử dụng một hàm để đọc trong các tệp cờ dưới dạng chuỗi, tạo hàm băm từ chuỗi và giảm hàm băm xuống số lượng băm giới hạn 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

để trả về từ điển của các quốc gia khớp với từng chữ ký, sau đó sử dụng một số mã để chuyển đổi từ điển thành chuỗi tra cứu:

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

Tôi cần thử nghiệm một chút với giá trị nào bucketscho kết quả tốt nhất.


Đây có phải chỉ lấy màu trung bình của cờ?
Ashwin Gupta

@AshwinGupta, chương trình đọc trong tệp sau đó lấy hàm băm của nó. Số băm lớn này được giảm xuống một chỉ mục trong danh sách chuỗi bằng cách sử dụng toán tử modulo.
Logic Knight

1
Không chắc chắn nếu nó sẽ giúp, nhưng bạn có thể làm print'...'[...:][:2]. Ngoài ra, có thể một bảng tra cứu với >>&cho một số nén cơ bản?
Sp3000

@ Sp3000, ý tưởng chỉ mục kép có vẻ thú vị nhưng tôi không thể biết nơi nào sẽ lưu bất kỳ byte nào ở đây. Tôi đã không xem xét các hàm thao tác bit để nén, nhưng điều đó có thể mang lại lợi thế. Hừm.
Logic Knight

1
Indexing đôi tiết kiệm 3 byte bởi vì bạn không cần phải lưu vào một biến i, nhưng hay không, bạn có thể tận dụng những byte thêm là một câu hỏi khác: P
Sp3000
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.