Lập trình nội tâm: Mã phân tích nguồn và đầu ra của nó


13

Viết chương trình xuất tổng số ký tự và tần số của mỗi ký tự trong nguồn đầu ra của nó. Bạn phải theo định dạng minh họa trong ví dụ.

Thí dụ

Nếu mã của bạn là

abb1

Đầu ra của nó sẽ phải là

My source has 4 characters.
1 is "a"
2 are "b"
1 is "1"
Besides unquoted numbers, my output has 383 characters.
34 are "
"
79 are " "
63 are """
2 are "'"
2 are ","
4 are "."
2 are "1"
2 are "B"
2 are "I"
2 are "M"
39 are "a"
4 are "b"
6 are "c"
4 are "d"
38 are "e"
3 are "g"
5 are "h"
4 are "i"
4 are "m"
3 are "n"
8 are "o"
3 are "p"
2 are "q"
38 are "r"
12 are "s"
8 are "t"
7 are "u"
3 are "y"
It's good to be a program.

(Đầu ra phải đi đến thiết bị xuất chuẩn.)

Ví dụ, lưu ý rằng đầu ra chứa hai chữ viết hoa. Một cho Myvà một cho 2 are "M". Điều này phải giữ đúng cho tất cả các ký tự để đầu ra không mâu thuẫn với bất kỳ cách nào.

Các số không được trích dẫn được bỏ qua trong đầu ra để tránh các bộ tần số không thỏa mãn. Ví dụ: 1 is "1"không chính xác nếu cả 2 đều được tính. Nó nên đọc 2 are "1", nhưng sau đó chỉ có một 1 nữa.

Định dạng làm rõ

  • "Là" phải được sử dụng cho các lần xuất hiện ký tự đơn.

  • "là" phải được sử dụng cho nhiều lần xuất hiện.

  • "Là" không bao giờ nên xuất hiện trong danh sách các ký tự đầu ra vì nó sẽ không cần thiết. 1 is 'Z'đề cập đến chính Z, vì vậy toàn bộ dòng có thể được gỡ bỏ.

  • Ba cụm từ toàn câu phải xuất hiện theo thứ tự với danh sách tần số ký tự ở giữa (như ví dụ hiển thị). Vì vậy, đầu ra của bạn sẽ bắt đầu với My source...và kết thúc với ...be a program.. Lưu ý rằng không có dòng mới ở cuối đầu ra.

  • Danh sách tần số ký tự có thể theo thứ tự bất kỳ.

  • Dòng mới được tính là một ký tự (trong trường hợp chúng là \ r \ n).

Trình kiểm tra định dạng

Kịch bản Python sau đây lấy mã của bạn và đầu ra của nó dưới dạng chuỗi và khẳng định rằng đầu ra không có mâu thuẫn. Nó cung cấp một thông báo lỗi hữu ích nếu có gì đó không đúng. Bạn có thể chạy nó trực tuyến tại http://ideone.com/6H0ldu bằng cách sử dụng nó, thay thế các chuỗi CODE và OUTPUT, sau đó chạy nó. Nó sẽ không bao giờ đưa ra dương tính giả hoặc phủ định (giả sử không có lỗi).

#Change the CODE and OUTPUT strings to test your program

CODE = r'''abb1'''

OUTPUT = r'''My source has 4 characters.
1 is "a"
2 are "b"
1 is "1"
Besides unquoted numbers, my output has 383 characters.
34 are "
"
79 are " "
63 are """
2 are "'"
2 are ","
4 are "."
2 are "1"
2 are "B"
2 are "I"
2 are "M"
39 are "a"
4 are "b"
6 are "c"
4 are "d"
38 are "e"
3 are "g"
5 are "h"
4 are "i"
4 are "m"
3 are "n"
8 are "o"
3 are "p"
2 are "q"
38 are "r"
12 are "s"
8 are "t"
7 are "u"
3 are "y"
It's good to be a program.'''

#######################################################

import re

amountPattern = r'(\d+) (is|are) "(.)"\n'

class IntrospectionException(Exception):
    pass

def getClaimedAmounts(string, errorOnIs):
    groups = re.findall(amountPattern, string, re.DOTALL)

    for amount, verb, char in groups:
        if verb == 'is':
            if errorOnIs:
                raise IntrospectionException('\'1 is "%s"\' is unnecessary' % char)
            elif amount != '1':
                raise IntrospectionException('At "%s", %s must use "are"' % (char, amount))
        elif verb == 'are' and amount == '1':
            raise IntrospectionException('At "%s", 1 must use "is"' % char)

    amounts = {}
    for amount, verb, char in groups:
        if char in amounts:
            raise IntrospectionException('Duplicate "%s" found' % char)
        amounts[char] = int(amount)
    return amounts

def getActualAmounts(string):
    amounts = {}
    for char in string:
        if char in amounts:
            amounts[char] += 1
        else:
            amounts[char] = 1
    return amounts

def compareAmounts(claimed, actual):
    for char in actual:
        if char not in claimed:
            raise IntrospectionException('The amounts list is missing "%s"' % char)
    for char in actual: #loop separately so missing character errors are all found first
        if claimed[char] != actual[char]:
            raise IntrospectionException('The amount of "%s" characters is %d, not %d' % (char, actual[char], claimed[char]))
    if claimed != actual:
        raise IntrospectionException('The amounts are somehow incorrect')

def isCorrect(code, output):
    p1 = r'^My source has (\d+) characters\.\n'
    p2 = r'Besides unquoted numbers, my output has (\d+) characters\.\n'
    p3 = r"It's good to be a program\.$"
    p4 = '%s(%s)*%s(%s)*%s' % (p1, amountPattern, p2, amountPattern, p3)

    for p in [p1, p2, p3, p4]:
        if re.search(p, output, re.DOTALL) == None:
            raise IntrospectionException('Did not match the regex "%s"' % p)

    claimedCodeSize = int(re.search(p1, output).groups()[0])
    actualCodeSize = len(code)
    if claimedCodeSize != actualCodeSize:
        raise IntrospectionException('The code length is %d, not %d' % (actualCodeSize, claimedCodeSize))

    filteredOutput = re.sub(r'([^"])\d+([^"])', r'\1\2', output)

    claimedOutputSize = int(re.search(p2, output).groups()[0])
    actualOutputSize = len(filteredOutput)
    if claimedOutputSize != actualOutputSize:
        raise IntrospectionException('The output length (excluding unquoted numbers) is %d, not %d' % (actualOutputSize, claimedOutputSize))

    splitIndex = re.search(p2, output).start()

    claimedCodeAmounts = getClaimedAmounts(output[:splitIndex], False)
    actualCodeAmounts = getActualAmounts(code)
    compareAmounts(claimedCodeAmounts, actualCodeAmounts)

    claimedOutputAmounts = getClaimedAmounts(output[splitIndex:], True)
    actualOutputAmounts = getActualAmounts(filteredOutput)
    compareAmounts(claimedOutputAmounts, actualOutputAmounts)

def checkCorrectness():
    try:
        isCorrect(CODE, OUTPUT)
        print 'Everything is correct!'
    except IntrospectionException as e:
        print 'Failed: %s.' % e

checkCorrectness()

Chấm điểm

Đây là môn đánh gôn. Trình với ít nhân vật nhất sẽ thắng. Đệ trình phải vượt qua trình kiểm tra định dạng để có hiệu lực. Các lỗ hổng tiêu chuẩn được áp dụng, mặc dù bạn có thể đọc mã nguồn của riêng mình và / hoặc mã hóa cứng đầu ra của bạn .


Là đọc tập tin nguồn của riêng bạn được cho phép?
Ventero

@MrLore Có thể có các lỗi khác nhưng tôi chỉ nhận ra rằng dấu ngoặc kép ('' ') vẫn thoát khỏi mọi thứ với dấu gạch chéo ngược. Điều này có thể liên quan đến vấn đề của bạn. Tôi đang sửa nó bây giờ.
Sở thích của Calvin

@Ventero Chắc chắn!
Sở thích của Calvin

@MrLore Các regexps cho phép một số dương tính giả, vâng. Để khắc phục sự cố với dấu gạch chéo ngược bên trong ba dấu ngoặc kép, hãy sử dụng chuỗi thô ( r'''CODE''').
Ventero

1
@MrLore Đã sửa lỗi không dấu chấm. Cảm ơn đã chú ý!
Sở thích của Calvin

Câu trả lời:


2

CJam - 189

{`"_~"+:T;"Besides unquoted numbers, my output has &It's good to be a program.&My source has & characters.
"'&/~_]:X2=T,X3=3i({T_&:B{TI/,(" are ":AM`I*N}fIXK=]o
XBA`N+f+2*+s:T,X3=}fK'q];}_~

Dùng thử tại http://cjam.aditsu.net/

Đầu ra:

My source has 189 characters.
3 are "{"
3 are "`"
6 are """
4 are "_"
3 are "~"
4 are "+"
5 are ":"
5 are "T"
2 are ";"
3 are "B"
8 are "e"
9 are "s"
2 are "i"
3 are "d"
17 are " "
6 are "u"
2 are "n"
2 are "q"
8 are "o"
6 are "t"
3 are "m"
2 are "b"
7 are "r"
4 are ","
2 are "y"
2 are "p"
3 are "h"
7 are "a"
5 are "&"
4 are "I"
3 are "'"
2 are "g"
2 are "."
2 are "M"
3 are "c"
2 are "
"
2 are "/"
3 are "]"
5 are "X"
2 are "2"
4 are "="
3 are "3"
2 are "("
2 are "A"
2 are "*"
2 are "N"
3 are "}"
3 are "f"
2 are "K"
Besides unquoted numbers, my output has 988 characters.
3 are "B"
108 are "e"
11 are "s"
3 are "i"
5 are "d"
214 are " "
8 are "u"
4 are "n"
3 are "q"
9 are "o"
9 are "t"
5 are "m"
4 are "b"
108 are "r"
3 are ","
4 are "y"
4 are "p"
6 are "h"
108 are "a"
3 are "I"
3 are "'"
4 are "g"
5 are "."
3 are "M"
7 are "c"
102 are "
"
2 are "{"
198 are """
2 are "`"
2 are "_"
2 are "~"
2 are "+"
2 are ":"
2 are "T"
2 are ";"
2 are "&"
2 are "/"
2 are "]"
2 are "X"
2 are "2"
2 are "="
2 are "3"
2 are "("
2 are "A"
2 are "*"
2 are "N"
2 are "}"
2 are "f"
2 are "K"
It's good to be a program.

11

Ruby, 269 (311, 367) ký tự

Tôi có ba giải pháp khác nhau cho thử thách này. Mỗi người trong số họ sử dụng một loạt các thủ thuật khác nhau:

Giải pháp "đúng", 367 ký tự:

Giải pháp dài nhất ít nhiều chỉ là một bằng chứng về khái niệm rằng có thể giải quyết thách thức này mà không cần bất kỳ thủ thuật nào - và gần như không được đánh gôn hoàn toàn. Đó là một câu hỏi thực sự (nghĩa là nó tạo mã nguồn riêng thay vì đọc nó từ một tệp) và thực sự tính toán tất cả các số mà nó in (độ dài mã, độ dài đầu ra, xuất hiện ký tự). Do cách hoạt động của quine, tất cả các mã phải nằm trên một dòng và bên trong một chuỗi ký tự.

eval r="S='eval r=%p'%r;O=-~$.;q=\"My source has \#{S.size}\"+(X=' characters.\n')+S.chars.uniq.map{|c|[k=S.count(c),k>O ? :are: :is,?\"+c+?\"]*' '}*$/+'\nBesides unquoted numbers, my output has ';r=(w=q+X+s=\"It's good to be a program.\").scan(D=/\\D/).uniq;$><<q<<(w+v=r.map{|c|j=' are \"\n\"';(-~(w+j*r.size).count(c)).to_s+(j[~O]=c;j)}*$/+$/).scan(D).size<<X+v+s"

Đầu ra được mã hóa một phần, 311 ký tự:

Giải pháp ngắn nhất tiếp theo sử dụng hai thủ thuật, nhưng vẫn là một câu hỏi thực sự: - Không có ký tự nào xảy ra chính xác một lần trong mã nguồn. Bằng cách đó, tôi không cần phải quyết định xem tôi nên in ishay aretrong nửa đầu của đầu ra. Nó cũng làm cho việc tính tổng kích thước đầu ra dễ dàng hơn một chút (mặc dù tôi thực sự không cần phải làm điều đó). - Tổng kích thước đầu ra là mã hóa cứng. Vì điều này chỉ phụ thuộc vào số lượng ký tự riêng biệt trong mã nguồn (và trong trường hợp chung, có bao nhiêu ký tự đó chỉ xảy ra một lần), nên dễ dàng tính toán trước.

Lưu ý rằng mã được đặt trước bởi hai dòng mới rất quan trọng, mà StackExchange sẽ không hiển thị trong khối mã. Vì lý do đó, tôi đã thêm một dòng bổ sung ở phía trước nếu những dòng mới đó, không phải là một phần của mã.

#


eval R="I=$/+$/+'eval R=%p'%R;?\\4>w='%d are \"%s\"';B=\"My source has \#{I.size}\#{X=\" characters.\n\"}\#{z=(m=I.chars.uniq).map{|x|w%[I.count(x),x]}*$/}\nBesides unquoted numbers, my output has 1114\"+X;$><<B+m.map{|c|w%[(B+z+$M=\"\nIt's good to be a program.\").gsub!(/\\d++(?!\")/,'').count(c),c]}*$/+$M"

Giải pháp ngắn nhất, 269 ký tự:

Giải pháp ngắn nhất bổ sung thêm mã hóa chiều dài nguồn của chính nó. Bằng cách sử dụng các tên biến đã / không phải là một phần của mã nguồn, có thể tìm thấy "điểm cố định" trong đó tất cả các ký tự trong mã nguồn (bao gồm các chữ số từ độ dài được mã hóa cứng!) Xảy ra ít nhất hai lần.

Giải pháp này cũng lưu thêm một vài ký tự bằng cách đọc mã nguồn của chính nó từ tệp mã, thay vì tạo nó. Là một hiệu ứng phụ tuyệt vời, điều này làm cho mã trở nên "dễ đọc" hơn nhiều (nhưng ai quan tâm đến mã có thể đọc được trong một ...), vì bây giờ mã không còn phải nằm trong một chuỗi ký tự nữa.

U='%d are "%s"'
O=IO.read$0
?\126>B="My source has 269#{X=" characters.
"}#{z=(m=O.chars.uniq).map{|c|U%[O.count(c),c]}*$/}
Besides unquoted numbers, my output has 1096"+X
$><<B+m.map{|c|U%[(B+z+$M="
It's good to be a program.").gsub!(/\d++(?!")/,"").count(c),c]}*$/+$M

Tôi cũng đã sửa đổi tập lệnh kiểm tra một chút để giảm bớt việc sao chép cần thiết để kiểm tra mã. Bằng cách thay thế các định nghĩa của CODEOUTPUTvới

import subprocess

CODE = open("packed.rb").read()
OUTPUT = subprocess.check_output(["ruby", "packed.rb"])

print CODE
print len(CODE)

tập lệnh bây giờ tự động chạy mã của tôi, đọc đầu ra của nó và lấy mã nguồn từ tệp mã.


Đây là đầu ra được tạo bởi mã ngắn nhất:

My source has 269 characters.
3 are "U"
7 are "="
3 are "'"
4 are "%"
6 are "d"
17 are " "
11 are "a"
9 are "r"
9 are "e"
11 are """
11 are "s"
6 are "
"
4 are "O"
2 are "I"
10 are "."
6 are "$"
2 are "0"
2 are "?"
2 are "\"
2 are "1"
2 are "2"
3 are "6"
2 are ">"
4 are "B"
3 are "M"
2 are "y"
9 are "o"
10 are "u"
12 are "c"
4 are "h"
2 are "9"
2 are "#"
4 are "{"
2 are "X"
8 are "t"
4 are "}"
2 are "z"
6 are "("
7 are "m"
5 are "n"
2 are "i"
2 are "q"
6 are ")"
4 are "p"
4 are "|"
2 are "["
4 are ","
2 are "]"
2 are "*"
4 are "/"
3 are "b"
7 are "+"
2 are "<"
3 are "g"
2 are "!"
Besides unquoted numbers, my output has 1096 characters.
2 are "U"
2 are "="
3 are "'"
2 are "%"
5 are "d"
238 are " "
120 are "a"
120 are "r"
120 are "e"
222 are """
11 are "s"
114 are "
"
2 are "O"
3 are "I"
5 are "."
2 are "$"
2 are "0"
2 are "?"
2 are "\"
2 are "1"
2 are "2"
2 are "6"
2 are ">"
3 are "B"
3 are "M"
4 are "y"
9 are "o"
8 are "u"
7 are "c"
6 are "h"
2 are "9"
2 are "#"
2 are "{"
2 are "X"
9 are "t"
2 are "}"
2 are "z"
2 are "("
5 are "m"
4 are "n"
3 are "i"
3 are "q"
2 are ")"
4 are "p"
2 are "|"
2 are "["
3 are ","
2 are "]"
2 are "*"
2 are "/"
4 are "b"
2 are "+"
2 are "<"
4 are "g"
2 are "!"
It's good to be a program.

Bạn có thể đăng một bản sao chính xác của mã và đầu ra của bạn để tôi có thể dễ dàng kiểm tra nó không? Mã không nên tự xuất và đầu ra sẽ kết thúc trong một khoảng thời gian không phải là dòng mới.
Sở thích của Calvin

@ Calvin'sHobbies Khối mã đầu tiên là mã thực tế của tôi. Mặc dù vậy, nó in đầu ra với một dòng mới cuối cùng, vì vậy hãy cho tôi vài phút để khắc phục điều đó (đây là điều mà bạn chắc chắn nên đề cập trong thông số kỹ thuật).
Ventero

Chắc chắn, tôi chỉ cập nhật thông số kỹ thuật.
Sở thích của Calvin

@ Calvin'sHob sở thích Xong. Khối mã đầu tiên là mã thực tế được tạo bởi khối mã thứ hai (do đó tôi không phải lo việc thoát chuỗi và mọi thứ trong khi viết mã).
Ventero
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.