Đọc một màn hình retro


22

Nghệ thuật bị đánh cắp từ kích thước nào là chữ số?


Các chữ số 7 đoạn có thể được biểu diễn trong ASCII bằng các _|ký tự. Dưới đây là các chữ số 0-9:

 _     _  _       _   _  _   _   _ 
| | |  _| _| |_| |_  |_   | |_| |_|
|_| | |_  _|   |  _| |_|  | |_|  _|

Công việc của bạn là phân tích nghệ thuật thành những con số bình thường.

Ghi chú về số

  • Mỗi chữ số có chiều rộng khác nhau.
    • 1 có chiều rộng 1
    • 372rộng
    • 2456890tất cả đều 3rộng

Ngoài ra giữa mỗi chữ số là một char của đệm. Dưới đây là bộ char đầy đủ:

 // <- nên là một khoảng trắng, nhưng định dạng SE làm rối tung nó
|
|
-------------
 _ 
 _ |
| _ 
-------------
_ 
_ |
_ |
-------------

| _ |
  |
-------------
 _ 
| _ 
 _ |
-------------
 _ 
| _ 
| _ |
-------------
_ 
 |
 |
-------------
 _ 
| _ |
| _ |
-------------
 _ 
| _ |
 _ |
-------------
 _ 
| |
| _ |

Đầu vào

Đầu vào có thể là từ bàn điều khiển hoặc dưới dạng chuỗi đối số với hàm.

Đầu ra

Đầu ra hoặc được đặt vào bàn điều khiển hoặc được trả về từ chức năng.

Ví dụ:

  _  _   _ 
|  |  | |_ 
|  |  | |_|
1776

 _   _     _ 
 _| | | | |_ 
|_  |_| | |_|
2016

   _       _ 
| |_| |_| |_ 
|  _|   |  _|
1945

   _   _   _   _   _   _ 
| | | | | | | | | | | | |
| |_| |_| |_| |_| |_| |_|
1000000

 _     _  _       _   _  _   _   _ 
| | |  _| _| |_| |_  |_   | |_| |_|
|_| | |_  _|   |  _| |_|  | |_|  _|
0123456789

Đây là mã golf nên số byte ngắn nhất sẽ thắng!



Tôi thích tìm hiểu về các thuật toán tốt nhất để giải quyết loại vấn đề này và tôi gặp khó khăn khi học từ các câu trả lời ở đây (chúng rất hay, chỉ rất súc tích). Có một nơi bạn có thể giới thiệu tôi để xem giải thích dài hơn, tốt nhất là với hình ảnh?

Cách làm việc của tôi khá đơn giản. Nó chuyển đổi danh sách và vòng lặp trên nó. Sau đó nó tách ra trên các dòng trống. Mỗi số được kiểm tra đối với một bảng vân tay cho mỗi số. Những cái khác hoạt động giống như của tôi, ngoại trừ thay vì bảng vân tay, về cơ bản chúng có bảng băm mà chúng sử dụng.
J Atkin

Có một tên chung hơn cho loại vấn đề này trong khoa học máy tính?

Tôi không có ý kiến ​​gì;)
J Atkin

Câu trả lời:


4

Bình thường, 33 30 byte

sm@."/9Àøw"%%Csd409hTcC.z*3d

Đây là ý tưởng: Một khi chúng ta hoán đổi đầu vào và chia thành các chữ số, chúng ta có thể sắp xếp băm các chuỗi chữ số riêng lẻ và gán chúng cho các giá trị của chúng.

sm@."/9Àøw"%%Csd409hTcC.z*3d     Implicit: z=input
                      C.z        Transpose input.
                     c   *3d     Split that on "   ", a space between digits.
 m@."/9Àøw"%%Csd409hT            Map the following lambda d over that. d is a digit string.
             Csd                   Flatten the digit string, and convert from base 256.
            %   409                Modulo that by 409
           %       hT              and then by 11. All digits go to a distinct num mod 11.
   ."/9Àøw"                        The compressed string "03924785/61".
  @                                Index into that string.
s                                Flatten and implicitly output.

Hãy thử nó ở đây .


Thật tuyệt, về cơ bản trông giống như cách tiếp cận của tôi nhưng ngắn hơn nhiều!
Lynn

@Lynn Xin lỗi về điều đó; về cơ bản có một cách ngắn nhất để làm điều này trong Pyth.
lirtosiast

4

Ruby, 184 byte

a=0
l=$<.map{|x|x.bytes.map{|y|y==32?0:1}+[0]*2}
(0..l[0].count-1).map{|i|l[0][i]+2*l[1][i]+4*l[2][i]}.each{|x|
x>0?(a=x+2*a):(p Hash[[40,6,32,20,18,26,42,8,44,64].zip(0..9)][a];a=0)}

Giải trình

  • lấy đầu vào từ stdin
  • chuyển đổi chuỗi thành chuỗi nhị phân, 1/0 cho bật / tắt phân đoạn
  • mã hóa cột thành số nhị phân 3 bit
  • mã hóa chuỗi số 3 bit thành số 9 bit, sử dụng cột '0' làm ký hiệu dừng
  • sử dụng bảng tra cứu để chuyển đổi các số 9 bit thành chữ số

Đây là mã golf đầu tiên của tôi. Cảm ơn vì niềm vui!


2
Chào mừng đến với PPCG! Rất tốt công việc trên bài viết đầu tiên của bạn!
J Atkin


2

Japt, 119 byte

Ur"[|_]"1 z r" +
"R x1 qR² £"11
1 1
1151151
111
 15111
115 1
 1
115 1
111
1511
111
15  1
11511
111
115 1
111
11"q5 bXÃq

Try it here!

Oh geez, cái này thực sự dài. Tôi không nghĩ rằng tôi đã chơi golf xong.

Giải trình

Chuẩn bị

Chúng tôi lấy đầu vào và chuyển đổi bất kỳ |_sang 1. Sau đó, chúng tôi hoán chuyển, loại bỏ không gian kết thúc và phân chia theo hai dòng mới.

Dịch

Chúng tôi ánh xạ qua mảng kết quả và tìm chỉ mục nơi biểu mẫu xuất hiện trong một mảng tham chiếu. Đây là một sơ đồ để giúp:

MAPITEM
  11
  1 1 --> This same form appears at index 0 in the reference array
  11                            |
                                |
                                V
                        change the mapitem to 0!

Sau đó, chúng tôi tham gia vào mảng số và đầu ra!

LƯU Ý : Bạn có thể tự hỏi tại sao chúng ta phải thay đổi mỗi nhân vật nghệ thuật thành một chuỗi 1. Điều này là do dường như có một lỗi (hoặc một cái gì đó tương tự) không cho phép tôi lưu trữ các ký tự như với |_.


Tôi nhận thấy _lỗi, nhưng tôi không biết điều gì gây ra nó.
Sản xuất ETH

OK, "\n\n"có thể được thay thế bằng , và "\\||_"với "%||_". Tôi nghĩ bạn cũng có thể tiết kiệm một số byte bằng cách mã hóa các chuỗi dài trong cơ sở 4 (thay đổi mỗi 4 chars disinctive để 0, 1, 2, hay 3, đệm để chiều dài của một bội số của 4, sau đó chạy r"...."_n4 d}qua nó), nhưng vì một lý do Tôi chưa làm việc này được.
Sản xuất ETH

2

Python2, 299 261 244 byte

s=lambda a,i=0:[a]if i==len(a[0])else[[j[:i]for j in a]]+s([j[i+1:]for j in a])if all(j[i]==' 'for j in a)else s(a,i=i+1)
p=lambda l:['95572431508448853268'.find(`sum(ord(c)**i for i,c in enumerate("".join(n)))%108`)/2for n in s(l.split('\n'))]

Tôi thực sự thích thử thách này, công việc tốt!

Giải trình

Hàm slấy ba dòng làm đầu vào, nó cố gắng tìm một phân tách chữ số (tất cả các ký tự là khoảng trắng). Khi tìm thấy sự phân tách như vậy, nó gọi svới phần còn lại của ba dòng và thêm giá trị được trả về bởi lệnh gọi vào ba dòng tạo thành chữ số. Nếu không có sự phân tách có nghĩa là chỉ có một chữ số.

Hàm pnày là điểm vào để nó lấy một chuỗi đại diện cho các chữ số. Các chữ số được lưu trữ dưới dạng "băm" được tính toán sum(ord(c)**i for i,c in enumerate("".join(n)))%108để tiết kiệm dung lượng (nhờ các câu trả lời khác!).

Mẫu mực

digits="""
 _     _ 
| | |  _|
|_| | |_ """[1:]  # remove the '\n' at the beginning

p(digits)  # [0, 1, 2]

Các phiên bản khác

261 byte (py3):

s=lambda a,i=0:[a]if i==len(a[0])else[[j[:i]for j in a]]+s([j[i+1:]for j in a])if all(j[i]==' 'for j in a)else s(a,i=i+1)
def p(l):[print([91,21,84,31,58,76,88,41,80,68].index(sum(ord(c)**i%20 for i,c in enumerate("".join(n)))),end="")for n in s(l.split('\n'))]

249 byte, cái này hoán chuyển các dòng (py2):

f="".join
s=lambda a,i=0:[a]if i==len(a)else[a[:i]]+s(a[i+1:])if all(c==' 'for c in a[i])else s(a,i=i+1)
h=lambda s:ord(s[0])**len(s)+h(s[1:])if s else 0
p=lambda l:["10220907112527153129".index(`h(f(map(f,n)))%34`)/2for n in s(zip(*l.split('\n')))]

2

JavaScript (ES6), 169 byte

a=>[...(a=a.split`
`)[0]].map((b,c)=>(d={' ':0,'|':1,'_':2})[b]+d[a[1][c]]*2+d[a[2][c]]).join``.split(0).map(b=>[343,3,182,83,243,281,381,23,383,283].indexOf(+b)).join``

Bắt đầu bằng cách chia thành ba dòng, ánh xạ lại mỗi cột thành một giá trị và sau đó xây dựng một danh tính duy nhất cho mỗi cột từ các giá trị đó. Sau đó, nó phân tách theo 0(danh tính cho khoảng trắng giữa các cột) và cuối cùng ánh xạ từng danh tính tới các giá trị số của nó, mà nó nối và xuất ra.


Rất đẹp! Tôi ước python có chức năng phân chia danh sách ...
J Atkin

@JAtkin Tôi joined thành một chuỗi để tôi có thể tách nó. Tôi tin rằng bạn cũng có thể làm điều đó trong Python?
Mwr247

0

Python 3, 281 254 byte

Chỉnh sửa

Tôi chỉ nhìn vào mã cho câu trả lời python khác và nhận thấy rằng phần lớn mã là tương tự. Điều này đã đến một cách độc lập.

(dòng mới được thêm vào cho "khả năng đọc")

def p(i):
 n=[[]]
 for l in zip(*i.split('\n')):
  if all(i==" "for i in l):n+=[[]]
  else:n[-1]+=l
 return''.join(map(lambda l:str([''.join(l[2:])==x for x in
             "|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||"
                     .split(',')].index(1)),n))

Ung dung:

def parse(input):
    lines = list(input.split('\n'))
    numbers = [[]]
    for lst in zip(*lines):
        if all(i==" " for i in lst):
            numbers += [[]]
        else:
            numbers[-1] += lst
    return ''.join(map(digit, numbers))

def digit(num):
    fingerprint = 
        "|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||".split(',')
    return str([''.join(num[2:]) == y for y in fingerprint].index(True))

Các xét nghiệm:

assert (parse("   _   _   _   _   _   _ \n| | | | | | | | | | | | |\n| |_| |_| |_| |_| |_| |_|") == '1000000')
assert (parse("   _       _ \n| |_| |_| |_ \n|  _|   |  _|") == '1945')
assert (parse(" _   _     _ \n _| | | | |_ \n|_  |_| | |_|") == '2016')
assert (parse(" _     _  _       _   _  _   _   _ \n| | |  _| _| |_| |_  |_   | |_| |_|\n|_| | |_  _|   |  _| |_|  | |_|  _|") == '0123456789')
assert (parse("  _  _   _ \n|  |  | |_ \n|  |  | |_|") == '1776')

Làm thế nào nó hoạt động

(Lưu ý: Tôi đang giải thích chương trình không mã hóa ở đây vì nó dễ đọc hơn và nó có cùng mã chính xác, ngoại trừ digitchức năng được xếp vào một lambda)

def parse(input):
    lines = list(input.split('\n'))
    numbers = [[]]

Chức năng chính là parse. Đầu tiên nó chia đầu vào thành các dòng và tạo numbersmảng.

    for lst in zip(*lines):
        if all(i==" " for i in lst):
            numbers += [[]]
        else:
            numbers[-1] += lst

Đây là phần yêu thích của tôi (vì mất quá nhiều thời gian để tìm ra). Ở đây chúng tôi zipcác dòng để về cơ bản chúng ta có thể đi ngang theo đầu vào. Khi dòng có ký tự trên nó, chúng ta thêm nó vào số cuối cùng trong numbersmảng. Nếu nó không có bất kỳ ký tự nào trên đó, chúng ta thêm một số mới vào mảng.

    return ''.join(map(digit, numbers))

Thực sự đơn giản, numbersđược ánh xạ với digithàm và được chuyển đổi thành một chuỗi.

def digit(num):
    fingerprint = 
        "|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||".split(',')
    return str([''.join(x[2:]) == y for x, y in zip([num]*10, fingerprint)].index(True))

Điều này là (khá) đơn giản. fingerprintlà biểu diễn chuỗi của các chữ số được tạo ở trên trừ đi 2 ký tự đầu tiên (đây là dấu vân tay nhỏ nhất tôi có thể tìm thấy). Chúng tôi trả lại chỉ số của trận đấu đầu tiên.


0

Haskell, 270 207 byte

Đừng quá khó khăn, đây là chương trình haskell đầu tiên của tôi;) Tôi gần như chắc chắn điều này có thể được đánh gôn hơn nữa, nhưng tôi không biết làm thế nào tôi có kiến ​​thức hạn chế về ngôn ngữ.

import Data.Lists
b n=map c$splitOn["   "]$transpose$lines n
c n|e<-drop 2$concat n,Just r<-elemIndex True[e==f|f<-splitOn",""|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||"]=(show r)!!0

Ung dung:

module Main where
import Data.Lists

main :: IO ()
main = print $ parse " _     _  _       _   _  _   _   _ \n| | |  _| _| |_| |_  |_   | |_| |_|\n|_| | |_  _|   |  _| |_|  | |_|  _|"

parse :: String -> String
parse n = let lst = transpose $ lines n
              numbers = splitOn ["   "] lst --"   " lst
              number = map digit numbers
          in number

digit :: [String] -> Char
digit n | e <- drop 2 $ intercalate "" n
        , fingerprint <- ["|_ _ ||","|","|___ | ","_ ||","  _  ||"," ___  |","|___  |","  ||","|___ ||"," ___ ||"]
        , Just res <- elemIndex True [e == finger | finger <- fingerprint]
        = head $ show res

Cảm ơn rất nhiều vì @nimi vì những lời khuyên!


tin xấu trước tiên: tôi e rằng bạn phải import Data.Listtính số byte của mình. Tin tốt: a) nếu bạn đã Data.Listscài đặt, bạn có thể nhập nó thay thế và thay thế abằng splitOn: ...map c$splitOn[" "]$transpose......f<-splitOn",""|_.... b) intercalate "" nconcat nhoặc id=<<n. c) thay thế resbằng một tên chữ cái duy nhất. d) sử dụng các mẫu bảo vệ thay vì let ... in: c n|e<-drop 2$id=<<n,Just r<-elemIndex ... ]=(show r)!!0.
nimi

Hehehe, Rất tiếc! Việc nhập đã bị mất trong bản sao / dán;) Cảm ơn tất cả các mẹo!
J Atkin

@nimi Xin lỗi đã làm phiền bạn về điều đó, nhưng bạn có phiền giải thích những gì =<<không? Cả tài liệu hoogle hoặc chữ ký loại đều rất hữu ích với tôi.
J Atkin

=<<trong ngữ cảnh danh sách là concatMap, nghĩa là nó ánh xạ hàm đã cho qua danh sách và kết hợp các kết quả thành một danh sách. >>=làm như vậy nhưng với các đối số lật. id =<< n(hoặc n >>= id) ánh xạ chức năng nhận dạng qua danh sách (danh sách), tức là không làm gì với danh sách phụ và nối chúng. Vì vậy, nó giống như concat.
nimi
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.