Escreva um programa que produza o número total de caracteres e a frequência de cada caractere em sua origem e em sua saída. Você deve seguir o formato ilustrado no exemplo.
Exemplo
Se o seu código foi
abb1
Sua produção teria que ser
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.
(A saída deve ir para stdout.)
Observe, por exemplo, que a saída contém dois m maiúsculos. Um para My
e um para 2 are "M"
. Isso deve ser verdadeiro para todos os caracteres, para que a saída não se contradiga de forma alguma.
Os números não citados são ignorados na saída para evitar conjuntos de frequências insatisfatórios. Por exemplo, 1 is "1"
está incorreto se os 1s forem contados. Deve ler 2 are "1"
, mas só há um 1 novamente.
Esclarecimentos sobre o formato
"is" deve ser usado para ocorrências de caracteres únicos.
"are" deve ser usado para várias ocorrências de caracteres.
"is" nunca deve aparecer na lista de caracteres de saída porque seria supérfluo.
1 is 'Z'
refere-se ao Z em si, para que toda a linha possa ser removida.As três frases completas devem aparecer em ordem com as listas de frequência de caracteres entre elas (como mostra o exemplo). Portanto, sua saída começará com
My source...
e terminará com...be a program.
. Observe que não há nova linha no final da saída.As listas de frequência de caracteres em si podem estar em qualquer ordem.
As novas linhas contam como um caractere (caso sejam \ r \ n).
Verificador de formato
O script Python a seguir usa seu código e sua saída como strings e afirma que a saída não tem contradições. Ele fornece uma mensagem de erro útil se algo estiver errado. Você pode executá-lo on-line em http://ideone.com/6H0ldu , bifurcando-o, substituindo as seqüências de código e OUTPUT e executando-o. Ele nunca fornecerá falsos positivos ou negativos (assumindo que não haja erros).
#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()
Pontuação
Isso é código-golfe. A submissão com o menor número de caracteres vence. Os envios devem passar no verificador de formato para serem válidos. Aplicam-se brechas padrão, embora você possa ler seu próprio código-fonte e / ou codificar sua saída .
r'''CODE'''
).Respostas:
CJam - 189
Experimente em http://cjam.aditsu.net/
Resultado:
fonte
Ruby, 269 (311, 367) caracteres
Eu tenho três soluções diferentes para esse desafio. Cada um deles usa um conjunto diferente de truques:
Solução "adequada", 367 caracteres:
A solução mais longa é mais ou menos apenas uma prova de conceito de que é possível resolver esse desafio sem truques - e não é quase totalmente disputada. É um verdadeiro quine (isto é, gera seu próprio código-fonte em vez de lê-lo em um arquivo) e, na verdade, calcula todos os números que imprime (comprimento do código, comprimento da saída, ocorrências de caracteres). Devido à maneira como o quine funciona, todo o código deve estar em uma única linha e dentro de uma string literal.
Saída parcialmente codificada, 311 caracteres:
A próxima solução mais curta usa dois truques, mas ainda é uma verdadeira solução: - Nenhum caractere ocorre exatamente uma vez no código-fonte. Dessa forma, não preciso decidir se devo imprimir
is
ouare
na primeira metade da saída. Também facilita um pouco o cálculo do tamanho total da saída (embora eu realmente não precise fazer isso). - O tamanho total da saída é codificado. Como isso depende apenas do número de caracteres distintos no código-fonte (e, no caso geral, quantos desses caracteres ocorrem apenas uma vez), é fácil calculá-lo com antecedência.Observe que o código é precedido por duas novas linhas muito significativas, que o StackExchange não mostraria no bloco de código. Por esse motivo, adicionei uma linha adicional na frente se essas novas linhas, que não fazem parte do código.
Solução mais curta, 269 caracteres:
A solução mais curta também codifica seu próprio tamanho de fonte. Usando nomes de variáveis que já não fazem parte do código-fonte, é possível encontrar um "ponto de correção" onde todos os caracteres no código-fonte (incluindo os dígitos dos comprimentos codificados!) Ocorrem pelo menos duas vezes.
Essa solução também salva mais alguns caracteres, simplesmente lendo seu próprio código-fonte do arquivo de código, em vez de gerá-lo. Como um bom efeito colateral, isso torna o código muito mais "legível" (mas quem se importa com o código legível em um código-golfe ...), pois agora o código não precisa mais estar dentro de uma string literal.
Também modifiquei um pouco o script de teste para reduzir a cópia-colagem necessária para verificar o código. Substituindo as definições de
CODE
eOUTPUT
como script agora executa automaticamente meu código, lê sua saída e pega o código fonte do arquivo de código.
Aqui está a saída gerada pelo código mais curto:
fonte