Écrivez un programme qui produit le nombre total de caractères et la fréquence de chaque caractère dans sa source et sa sortie. Vous devez suivre le format illustré dans l'exemple.
Exemple
Si votre code était
abb1
Sa sortie devrait être
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.
(La sortie doit aller à stdout.)
Notez, par exemple, que la sortie contient deux m en majuscule. Un pour My
et un pour 2 are "M"
. Cela doit être vrai pour tous les caractères afin que la sortie ne se contredit en aucune façon.
Les nombres non cotés sont ignorés dans la sortie pour éviter des ensembles de fréquences insatisfaisants. Par exemple, 1 is "1"
est incorrect si les deux 1 sont comptés. Il devrait être lu 2 are "1"
, mais il n'y a encore qu'un seul 1.
Clarifications de format
"est" doit être utilisé pour les occurrences d'un seul caractère.
"are" doit être utilisé pour les occurrences de plusieurs caractères.
"is" ne devrait jamais apparaître dans la liste des caractères de sortie car il serait superflu.
1 is 'Z'
fait référence au Z en lui-même, de sorte que toute la ligne peut être supprimée.Les trois phrases complètes doivent apparaître dans l'ordre avec les listes de fréquence des caractères entre les deux (comme le montre l'exemple). Ainsi, votre sortie commencera par
My source...
et se terminera par...be a program.
. Notez qu'il n'y a pas de nouvelle ligne à la fin de la sortie.Les listes de fréquences des caractères elles-mêmes peuvent être dans n'importe quel ordre.
Les sauts de ligne comptent comme un caractère (au cas où ils seraient \ r \ n).
Vérificateur de format
Le script Python suivant prend votre code et sa sortie sous forme de chaînes et affirme que la sortie n'a pas de contradictions. Il fournit un message d'erreur utile en cas de problème. Vous pouvez l'exécuter en ligne sur http://ideone.com/6H0ldu en le forçant, en remplaçant les chaînes CODE et OUTPUT, puis en l'exécutant. Il ne donnera jamais de faux positifs ou négatifs (en supposant qu'il est exempt d'erreur).
#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()
Notation
C'est du code-golf. La soumission avec le moins de personnages gagne. Les soumissions doivent passer le vérificateur de format pour être valides. Les failles standard s'appliquent, bien que vous puissiez lire votre propre code source et / ou coder en dur votre sortie .
r'''CODE'''
).