İçgözlemsel Programlama: Kaynağını ve çıktısını analiz eden kod


13

Toplam karakter sayısını ve kaynağındaki ve çıktısındaki her karakterin sıklığını çıkaran bir program yazın . Örnekte gösterilen biçimi izlemelisiniz.

Misal

Kodunuz

abb1

Çıktısı

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.

(Çıktı stdout'a gitmelidir.)

Örneğin, çıktının iki büyük harf içerdiğine dikkat edin. Biri Myve biri için 2 are "M". Bu, tüm karakterler için geçerli olmalıdır, böylece çıktı hiçbir şekilde kendisiyle çelişmez.

Karşılıksız frekans setlerini önlemek için çıkışta alıntılanmamış sayılar yok sayılır. Örneğin, 1 is "1"her iki 1 de sayılırsa yanlıştır. Okumalı 2 are "1", ama sonra yine sadece bir tane var.

Biçim Açıklamaları

  • "is", tek karakterli oluşumlar için kullanılmalıdır.

  • "are" ifadesi birden çok karakter oluşumunda kullanılmalıdır.

  • "is" hiçbir zaman çıkış karakterleri listesinde görünmemelidir çünkü gereksiz olur. 1 is 'Z'"Z" kendi başına Z anlamına gelir, böylece tüm çizgi kaldırılabilir.

  • Üç tam cümle cümlesi, karakter sıklığı listeleri arasında (örnekte gösterildiği gibi) sırayla görünmelidir. Böylece çıktınız ile başlar My source...ve biter ...be a program.. Çıktının sonunda yeni satır olmadığını unutmayın.

  • Karakter sıklığı listelerinin kendileri herhangi bir sırada olabilir.

  • Yeni satırlar bir karakter olarak sayılır (\ r \ n olması durumunda).

Biçim Denetleyicisi

Aşağıdaki Python betiği kodunuzu ve çıktısını dize olarak alır ve çıktının çelişkisi olmadığını ileri sürer. Bir şeyler yanlışsa yararlı bir hata mesajı sağlar. Http://ideone.com/6H0ldu adresinden çevrimiçi olarak çatalını çevirerek, KOD ve ÇIKIŞ dizelerini değiştirip çalıştırarak çalıştırabilirsiniz. Asla yanlış pozitif veya negatif vermeyecektir (hatasız olduğu varsayılarak).

#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()

puanlama

Bu kod golfü. En az karakter içeren gönderim kazanır. Gönderimlerin geçerli olması için biçim denetleyicisini geçmesi gerekir. Standart boşluklar uygulanır, ancak kendi kaynak kodunuzu okuyabilir ve / veya çıktınızı sabit kodlayabilirsiniz .


Kendi kaynak dosyanızı okuma izni var mı?
Ventero

@MrLore Başka hatalar olabilir, ancak üçlü tırnakların ('' ') hala ters eğik çizgiyle kaçtığını fark ettim. Bu, sorununuzla ilgili olabilir. Şimdi düzeltiyorum.
Calvin'in Hobileri

@Ventero Kesinlikle!
Calvin'in Hobileri

@MrLore Normal ifadeler bazı yanlış pozitiflere izin verir, evet. Üçlü tırnak içindeki ters eğik çizgilerle ilgili sorunu gidermek için ham dizeleri ( r'''CODE''') kullanın .
Ventero

1
@MrLore Kaçan noktalar düzeltildi. Fark ettiğiniz için teşekkürler!
Calvin'in Hobileri

Yanıtlar:


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];}_~

Http://cjam.aditsu.net/ adresinde deneyin.

Çıktı:

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

Bu meydan okuma için üç farklı çözümüm var. Her biri farklı numaralar kullanır:

"Uygun" çözüm, 367 karakter:

En uzun çözüm az ya da çok sadece bu zorluğu herhangi bir hile olmadan çözmenin mümkün olduğuna dair bir kanıtıdır - ve neredeyse tamamen golf oynamamıştır. Bu gerçek bir soru (yani bir dosyadan okumak yerine kendi kaynak kodunu üretir) ve aslında yazdırdığı tüm sayıları (kod uzunluğu, çıktı uzunluğu, karakter oluşumları) hesaplar. Ayranın çalışma şekli nedeniyle, tüm kod tek bir satırda ve bir dizgi hazır bilgisi içinde olmalıdır.

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"

Kısmen sabit kodlanmış çıktı, 311 karakter:

Bir sonraki en kısa çözüm iki hile kullanır, ancak yine de gerçek bir tırnaktır: - Kaynak kodda tam olarak bir karakter oluşmaz. Bu şekilde, ben yazdırmak konusunda karar vermek gerekmez isveya areçıkışının ilk yarısında. Ayrıca toplam çıktı boyutunu hesaplamayı biraz kolaylaştırır (aslında bunu yapmam gerekmiyor). - Toplam çıktı boyutu sabit kodlanmıştır. Bu sadece kaynak koddaki farklı karakterlerin sayısına (ve genel durumda, bu karakterlerden kaç tanesinin yalnızca bir kez oluştuğuna) bağlı olduğundan, bunu önceden hesaplamak kolaydır.

Kodun StackExchange kod bloğunda gösterilmeyeceği iki önemli yeni satırdan önce geldiğini unutmayın. Bu nedenle, kodun bir parçası olmayan bu satırlar varsa, ek bir satır ekledim .

#


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"

En kısa çözüm, 269 karakter:

En kısa çözüm ayrıca kendi kaynak uzunluğunu da kodlar. Zaten kaynak kodun parçası olan / olmayan değişken adları kullanarak, kaynak koddaki tüm karakterlerin (sabit kodlu uzunluklardaki rakamlar dahil!) En az iki kez oluştuğu bir "düzeltme noktası" bulmak mümkündür.

Bu çözüm aynı zamanda kod dosyasından kendi kaynak kodunu okumak yerine, onu oluşturmak yerine birkaç karakter daha kaydeder. Güzel bir yan etki olarak, bu kodu çok daha "okunabilir" yapar (ancak bir golfünde okunabilir kodu önemseyen ...), çünkü kod artık bir dizgi değişmezinin içinde olmak zorunda değildir.

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

Ayrıca kodu kontrol etmek için gerekli olan kopya yapışmayı azaltmak için test komut dosyasını biraz değiştirdim. Tanımlarını değiştirerek CODEve OUTPUTile

import subprocess

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

print CODE
print len(CODE)

komut dosyası artık kodumu otomatik olarak çalıştırıyor, çıktısını okuyor ve kaynak kodunu kod dosyasından alıyor.


En kısa kod tarafından üretilen çıktı:

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.

Kolayca test edebilmem için kodunuzun ve çıktınızın kesin bir kopyasını gönderebilir misiniz? Kod kendi çıktısını almamalı ve çıktı bir satırsonu değil bir süre içinde sona ermelidir.
Calvin'in Hobileri

@ Calvin'sHobbies İlk kod bloğu benim gerçek kodum. Çıktıyı son bir satırsonu ile basar, bu yüzden bunu düzeltmek için bana birkaç dakika verin (bu kesinlikle spesifikasyonda belirtmeniz gereken bir şeydir).
Ventero

Tabii ki, ben sadece spec güncelledim.
Calvin'in Hobileri

@ Calvin'sHobbies Yapıldı. İlk kod bloğu, ikinci kod bloğu tarafından oluşturulan gerçek koddur (böylece kod yazarken kaçan dize ve her şeyi halletmek zorunda değilim).
Ventero
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.