É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'''
).Réponses:
CJam - 189
Essayez-le sur http://cjam.aditsu.net/
Production:
la source
Ruby, 269 (311, 367) caractères
J'ai trois solutions différentes pour ce défi. Chacun d'eux utilise un ensemble différent d'astuces:
Solution "correcte", 367 caractères:
La solution la plus longue est plus ou moins juste une preuve de concept qu'il est possible de résoudre ce défi sans aucune astuce - et n'est pas presque entièrement jouée. C'est un vrai quine (c'est-à-dire qu'il génère son propre code source au lieu de le lire à partir d'un fichier) et calcule en fait tous les nombres qu'il imprime (longueur de code, longueur de sortie, occurrences de caractères). En raison de la façon dont fonctionne le quine, tout le code doit être sur une seule ligne et à l'intérieur d'un littéral de chaîne.
Sortie partiellement codée en dur, 311 caractères:
La solution la plus courte suivante utilise deux astuces, mais reste une vraie quine: - Aucun caractère n'apparaît exactement une fois dans le code source. De cette façon, je n'ai pas besoin de décider si je dois imprimer
is
ouare
dans la première moitié de la sortie. Cela facilite également un peu le calcul de la taille de sortie totale (même si je n'ai pas vraiment besoin de le faire). - La taille de sortie totale est codée en dur. Comme cela ne dépend que du nombre de caractères distincts dans le code source (et dans le cas général, combien de ces caractères n'apparaissent qu'une seule fois), il est facile de le calculer à l'avance.Notez que le code est précédé de deux sauts de ligne très importants, que StackExchange ne montrerait pas dans le bloc de code. Pour cette raison, j'ai ajouté une ligne supplémentaire devant si ces nouvelles lignes, qui ne font pas partie du code.
Solution la plus courte, 269 caractères:
La solution la plus courte code en outre en dur sa propre longueur source. En utilisant des noms de variables qui font / ne font pas déjà partie du code source, il est possible de trouver un "point fixe" où tous les caractères du code source (y compris les chiffres des longueurs codées en dur!) Apparaissent au moins deux fois.
Cette solution enregistre également quelques caractères supplémentaires en lisant simplement son propre code source à partir du fichier de code, au lieu de le générer. Comme un effet secondaire agréable, cela rend le code beaucoup plus "lisible" (mais qui se soucie du code lisible dans un code-golf ...), car maintenant le code n'a plus à être à l'intérieur d'un littéral de chaîne.
J'ai également modifié un peu le script de test pour réduire le copier-coller nécessaire pour vérifier le code. En remplaçant les définitions de
CODE
etOUTPUT
parle script exécute maintenant automatiquement mon code, lit sa sortie et récupère le code source du fichier de code.
Voici la sortie générée par le code le plus court:
la source