Code Golf: Quatre c'est magique

88

Le puzzle

Un petit casse-tête que j'ai entendu pendant que j'étais au lycée ressemblait à quelque chose comme ça ...

  • L'intervenant me demandait de lui donner un numéro;
  • En entendant le nombre, le questionneur ferait une sorte de transformation à plusieurs reprises (par exemple, il pourrait dire que dix est trois ) jusqu'à arriver finalement au nombre 4 (à quel point il finirait avec quatre est magique ).
  • N'importe quel nombre semble éventuellement transformable en quatre, quoi qu'il arrive.

L'objectif était d'essayer de comprendre la fonction de transformation et de pouvoir ensuite surveiller de manière fiable ce puzzle vous-même.

La solution

La fonction de transformation à chaque étape était de

  • Prends le numéro en question,
  • Comptez le nombre de lettres dans sa représentation de mot anglais, en ignorant un trait d'union ou des espaces ou "et" (par exemple, "dix" a 3 lettres, "trente-quatre" a 10 lettres, "cent quarante-trois" contient 20 lettres).
  • Renvoyez ce nombre de lettres.

Pour tous les nombres que j'ai jamais voulu tester, cela converge vers 4. Puisque "quatre" contient également quatre lettres, il y aurait une boucle infinie ici; au lieu de cela, on parle simplement de magie par convention pour terminer la séquence.

Le défi

Votre défi est de créer un morceau de code qui lira un nombre de l'utilisateur, puis imprimera des lignes montrant la fonction de transformation appliquée à plusieurs reprises jusqu'à ce que «quatre est magique» soit atteint.

Plus précisément:

  1. Les solutions doivent être des programmes complets en soi. Ils ne peuvent pas être simplement des fonctions qui prennent un nombre - facteur dans l'entrée.
  2. L'entrée doit être lue à partir de l'entrée standard. (La tuyauterie depuis "echo" ou l'utilisation de la redirection d'entrée est très bien puisque cela va également de stdin)
  3. L'entrée doit être sous forme numérique.
  4. Pour chaque application de la fonction de transformation, une ligne doit être imprimée:, a is b.où a et b sont des formes numériques des nombres dans la transformation.
  5. Des arrêts complets (périodes) SONT obligatoires!
  6. La dernière ligne devrait dire naturellement, 4 is magic..
  7. Le code doit produire une sortie correcte pour tous les nombres de 0 à 99 .

Exemples:

> 4
4 is magic.

> 12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.

> 42
42 is 8.
8 is 5.
5 is 4.
4 is magic.

> 0
0 is 4.
4 is magic.

> 99
99 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

Le gagnant est la soumission la plus courte par nombre de caractères du code source qui est également correct .

PRIME

Vous pouvez également essayer d'écrire une version du code qui imprime les NOMS EN ANGLAIS pour les nombres à chaque application de la fonction de transformation. L'entrée d'origine est toujours numérique, mais les lignes de sortie doivent avoir la forme mot du nombre.

(Double bonus pour dessiner des formes avec votre code)

(EDIT) Quelques clarifications:

  1. Je veux que le mot apparaisse des deux côtés dans tous les cas applicables, par exemple Nine is four. Four is magic.
  2. Je me fiche de la capitalisation, cependant. Et je me fiche de la façon dont vous séparez les mots jetons, même s'ils devraient être séparés: ninety-ninec'est bien, ninety ninec'est bien, ninetyninen'est pas bien.

Je les considère comme une catégorie distincte pour la compétition de bonus en ce qui concerne le défi, donc si vous optez pour cela, ne vous inquiétez pas que votre code soit plus long que la version numérique.

N'hésitez pas à soumettre une solution pour chaque version.

Platinum Azure
la source
1
Quel nombre devons-nous gérer? <100? <1000? <1000000? <2 ** 31?
P Daddy
1
Comme cela ne doit aller que de 0 à 99, je soupçonne qu'une solution rapide et courte serait de coder en dur les valeurs vers lesquelles 0-99 mappe, puis de boucler jusqu'à ce que vous atteigniez 4. Après cela, le microtweaking commence.
Beska
@P Daddy ... la partie 6 ne dit que 0-99.
Beska
14
4 n'est que magique car il a été choisi par un jet de dés correct.
VirtuosiMedia

Réponses:

57

GolfScript - 101 96 93 92 91 90 94 86 octets

90 → 94: Sortie fixe pour les multiples de 10
94 → 86.: Code restructuré. Utilisation de la base 100 pour supprimer les caractères non imprimables.
86 → 85: Coulée plus courte en corde.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Nabb
la source
pourquoi est-ce si bas? il est plus court que celui de lisp et n'utilise pas de fonction de formatage intégrée
Claudiu
36
J'aime la façon dont le code se termine "magic.", cela résume assez bien la situation.
Aistina
@Aistina: C'est facile à faire dans ce défi, je pense. :-)
Platinum Azure
9
@Aistina: haha, c'est plutôt drôle. "mumbo jumbo yada yada..magic"
vol7ron
1
@P Daddy Le dest extrait par )as 100et est utilisé comme base pour la conversion de base.
Nabb
85

Perl, environ 147 caractères

Basée librement sur la solution Platinum Azure:

               chop
              ($_.=
              <>);@
             u="433
            5443554
           366  887
          798   866
         555    766
        "=~     /\d
       /gx      ;#4
      sub       r{4
     -$_        ?$_
    <20         ?$u
   [$_          ]:(
  $'?           $u[
 $']            :0)
+$u[18+$&]:magic}print"
$_ is ",$_=r(),'.'while
                /\d
                /x;
                444
mob
la source
1
@Platinum Azure, la façon dont cela obtient ses entrées se fait par l'utilisation de pop, sans aucun argument. En dehors d'un sous-programme, popsupprime et renvoie la dernière valeur @ARGVdont la liste des arguments du programme Perl. Il pourrait tout aussi bien être remplacé par shift, mais cela ajoute 2 autres caractères. Voir: p3rl.org/pop
Brad Gilbert
il semble que vous ayez besoin d'un caractère de nouvelle ligne dans '.', qui est 2 pour \nou 1 si vous comptez les espaces dans le '. '(l'espace étant le littéral de nouvelle ligne)
vol7ron
Un peu plus longtemps, mais la créativité va très loin dans mon livre.
Beska
@Platinum Azure et al: Il reçoit ses commentaires de stdin. C'est la manière de le faire en Perl. (Peut-être qu'il l'a changé après votre commentaire?)
Frank
@P Daddy: gémissement mais +1 à votre commentaire quand même
Platinum Azure
30

Common Lisp 157 caractères

Nouvelle version plus conforme, maintenant la lecture de l'entrée standard et ignorant les espaces et les traits d'union:

(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))

Sous une forme lisible par l'homme:

 (labels ((g (x)
           (if (= x 4)
            (princ "4 is magic.")
            (let ((n (length (remove-if (lambda(x) (find x " -"))
                                        (format nil "~r" x)))))
               (format t"~a is ~a.~%" x n)
               (g n)))))
    (g (read)))

Et quelques tests:

>24
24 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

>23152436
23152436 is 64.
64 is 9.
9 is 4.
4 is magic.

Et la version bonus, à 165 caractères:

 (labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))

Donnant

>24
twenty-four is ten.
ten is three.
three is five.
five is four.
four is magic.

>234235
two hundred thirty-four thousand two hundred thirty-five is forty-eight.
forty-eight is ten.
ten is three.
three is five.
five is four.
four is magic.
utilisateur110763
la source
5
Je pensais que "vingt-quatre" n'a que 10 lettres?
kennytm
1
Les nombres après «est» doivent également être du texte.
Mike DeSimone
5
pourquoi est-ce si haut? d'autres n'utilisent pas de fonction de format intégrée et ce sont moins de caractères
Claudiu
3
@Claudiu Parce que Common Lisp est génial.
Mornedhel
3
Peu importe le nombre de coups que vous prenez si vous n'obtenez pas la balle dans le trou. Les gens semblent oublier cela lorsqu'ils votent pour des solutions incorrectes.
Mark Peters
21

Python 2.x, 144 150 154 166 caractères

Cela sépare le nombre en dizaines et unités et les résume. La propriété indésirable de l'opérateur pseudo-ternaire a and b or cqui cest retourné si best 0 est ici abusée.

n=input()
x=0x4d2d0f47815890bd2
while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p
print"4 is magic."

La version naïve précédente (150 caractères). Encodez simplement toutes les longueurs sous forme d'entier.

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."
KennyTM
la source
Désolé, je voulais spécifiquement des arrêts complets juste à cause de choses comme celle-ci. :-) Bonne entrée cependant! (EDIT: Je ne connais pas Python, mais pourriez-vous n,"is",p,"."? Je pense que vous enregistrez encore quelques caractères si je compte bien)
Platinum Azure
2
@Plat: Cela entraînerait un espace supplémentaire avant le ..
kennytm
@KennyTM: Oh, duh, j'aurais dû le remarquer même à partir de l'extrait. Oups! Eh bien, de toute façon, comme je l'ai dit, certaines des spécifications ont été spécifiquement conçues pour compliquer un peu les choses. :-)
Platinum Azure
Pouvons-nous raccourcir cela en utilisant une base supérieure à 36?
MikeD
@MikeD: Non. D'après la documentation Python: "Le paramètre de base donne la base de la conversion (qui est de 10 par défaut) et peut être n'importe quel entier dans la plage [2, 36] ou zéro." Maintenant, vous pourrez peut- être utiliser une fonction autre que int(), dites quelque chose en dehors des modules structou base64...
Mike DeSimone
20

C - avec des mots numériques

445 431 427 421 399 386 371 359 * 356 354 348 347 caractères

C'est tout. Je ne pense pas pouvoir raccourcir cela.

Toutes les nouvelles lignes sont destinées à la lisibilité et peuvent être supprimées:

i;P(x){char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,
fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,
4RmagicS,zero,";while(x--)if(*++p-44&&!x++)*p>95|*p<48?putchar(*p),++i:P(*p-48);
}main(c){for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))P(c?c>19?P(c/10+18),
(c%=10)&&putchar(45):0,c:37);P(36);}

Ci-dessous, il est un peu non réduit, mais toujours assez difficile à lire. Voir ci-dessous pour une version plus lisible.

i;
P(x){
    char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";
    while(x--)
        if(*++p-44&&!x++)
            *p>95|*p<48?putchar(*p),++i:P(*p-48);
}
main(c){
    for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))
        P(c?
            c>19?
                P(c/10+18),
                (c%=10)&&
                    putchar(45)
            :0,
            c
        :37);
    P(36);
}

Développé et commenté:

int count; /* type int is assumed in the minified version */

void print(int index){ /* the minified version assumes a return type of int, but it's ignored */
    /* see explanation of this string after code */
    char *word =
        /* 1 - 9 */
        ",one,two,three,four,five,six,sM,eight,nine,"
        /* 10 - 19 */
        "tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,"
        /* 20 - 90, by tens */
        "twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,"
        /* lookup table */
        "en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";

    while(index >= 0){
        if(*word == ',')
            index--;
        else if(index == 0) /* we found the right word */
            if(*word >= '0' && *word < 'a') /* a compression marker */
                print(*word - '0'/*convert to a number*/);
            else{
                putchar(*word); /* write the letter to the output */
                ++count;
            }
        ++word;
    }
}
int main(int argc, char **argv){ /* see note about this after code */
    scanf("%d", &argc); /* parse user input to an integer */

    while(argc != 4){
        count = 0;
        if(argc == 0)
            print(37/*index of "zero"*/);
        else{
            if(argc > 19){
                print(argc / 10/*high digit*/ + 20/*offset of "twenty"*/ - 2/*20 / 10*/);
                argc %= 10; /* get low digit */

                if(argc != 0) /* we need a hyphen before the low digit */
                    putchar('-');
            }
            print(argc/* if 0, then nothing is printed or counted */);
        }
        argc = count;
        print(34/*" is "*/);
        print(argc); /* print count as word */
        print(35/*".\n"*/);
    }
    print(36/*"four is magic.\n"*/);
}

À propos de la chaîne codée vers le début

Les noms des nombres sont compressés à l'aide d'un schéma très simple. Les sous-chaînes fréquemment utilisées sont remplacées par des index à un caractère dans le tableau de noms. Une «table de recherche» d'entrées de noms supplémentaires est ajoutée à la fin pour les sous-chaînes non utilisées dans leur intégralité dans le premier ensemble. Les recherches sont récursives: les entrées peuvent faire référence à d'autres entrées.

Par exemple, le nom compressé de 11 est elM. La print()fonction sort les caractères eet l(minuscule 'L', pas le nombre '1') textuellement, mais ensuite elle trouve le M, donc elle s'appelle avec l'index de la 29e entrée (ASCII 'M' - ASCII '0') dans la table de recherche. Cette chaîne est evL, donc elle produit eet v, puis s'appelle à nouveau avec l'index de la 28e entrée dans la table de recherche, qui est enet est sortie textuellement. Ceci est utile car il enest également utilisé dans eLfor een(utilisé après eightin eighteen), qui est utilisé dans tOfor teen(utilisé pour tous les autres -teennoms).

Ce schéma entraîne une compression assez importante des noms de nombres, tout en ne nécessitant qu'une petite quantité de code pour décompresser.

Les virgules au début et à la fin de la chaîne expliquent la manière simpliste dont les sous-chaînes se trouvent dans cette chaîne. L'ajout de deux caractères ici enregistre plus de caractères plus tard.

À propos de l'abus de main()

argvest ignoré (et donc non déclaré dans la version compressée), la valeur d'argc est ignorée, mais le stockage est réutilisé pour contenir le numéro actuel. Cela m'évite simplement d'avoir à déclarer une variable supplémentaire.

À propos du manque de #include

Certains se plaindront qu'omettre #include <stdio.h>c'est tricher. Ce n'est pas du tout. Le donné est un programme C complètement légal qui se compilera correctement sur n'importe quel compilateur C que je connais (bien qu'avec des avertissements). Faute de protoypes pour les fonctions stdio, le compilateur supposera que ce sont des fonctions cdecl qui retournent int, et sera sûr que vous savez quels arguments transmettre. Les valeurs de retour sont ignorées dans ce programme, de toute façon, et ce sont toutes des fonctions cdecl (convention d'appel "C"), et nous savons en effet quels arguments passer.

Production

La sortie est conforme aux attentes:

0
zéro est quatre.
quatre est magique.
1
un fait trois.
trois est cinq.
cinq fait quatre.
quatre est magique.
4
quatre est magique.
20
vingt est six.
six est trois.
trois est cinq.
cinq fait quatre.
quatre est magique.
21
vingt et un sont neuf.
neuf fait quatre.
quatre est magique.

* La version précédente manquait la marque sur deux parties de la spécification: elle ne traitait pas zéro, et elle prenait des entrées sur la ligne de commande au lieu de stdin. La gestion des zéros a ajouté des caractères, mais l'utilisation de stdin au lieu d'arguments de ligne de commande, ainsi que quelques autres optimisations ont enregistré le même nombre de caractères, ce qui a entraîné un lavage.

Les exigences ont été modifiées pour préciser que le mot numérique doit être imprimé des deux côtés de «est». Cette nouvelle version répond à cette exigence et implémente quelques optimisations supplémentaires pour (plus de) tenir compte de la taille supplémentaire nécessaire.

P Papa
la source
C'est facilement mon préféré des réponses de mot ... Bravo, bravo. +1 pour vous, et si je pouvais donner deux coches, je le ferais.
Platinum Azure du
5
C'est amusant à lire, je pense que je vais désormais utiliser ces chiffres dans la vie quotidienne. Six, sem, huit, neuf, tel, elem, douze, enpee, fourpee, fifpee, sixpee, sevenpee, eightoh, ninepee, twelkyu ... =)
deceze
10

J, 107 112 caractères

'4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:

(Newline pour la lisibilité uniquement)

Utilisation et sortie:

    '4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:12
12 is 6.    
6 is 3.     
3 is 5.     
5 is 4.     
4 is magic. 
David
la source
15
Il est compilé en chinois
Dr belisarius
3
Veuillez choisir un arbitre non chinois
Dr. belisarius
3
@beli: 멩, 겻, 곋, 멩 sont coréens.
kennytm
1
Ma femme (de langue maternelle chinoise) dit que c'est un mélange de chinois et de coréen.
Loren Pechtel
3
@belisarius: 1) Elle ne connaît pas le coréen. 2) Le chinois est charabia.
Loren Pechtel le
10

T-SQL, 413 451 499 caractères

CREATE FUNCTION d(@N int) RETURNS int AS BEGIN
Declare @l char(50), @s char(50)
Select @l='0066555766',@s='03354435543668877987'
if @N<20 return 0+substring(@s,@N+1,1) return 0+substring(@l,(@N/10)+1,1) + 0+(substring(@s,@N%10+1,1))END
GO
CREATE proc M(@x int) as BEGIN
WITH r(p,n)AS(SELECT p=@x,n=dbo.d(@x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,'is',n,'.' from r print '4 is magic.'END

(Non pas que je suggère sérieusement que vous fassiez ça ... vraiment je voulais juste écrire un CTE)

Utiliser:

M 95

Retour

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
Leon Bambrick
la source
Ne pouvez-vous pas simplement imprimer les résultats individuels au lieu de renvoyer un tableau? Cela rendrait la sortie plus agréable.
Joey
1
Je ne pense pas qu'il gère le zéro correctement. Que diriez-vous de quelque chose comme ça:CREATE FUNCTION d(@ int) RETURNS int AS BEGIN Declare @l char(9),@s char(50) Select @l='066555766',@s='03354435543668877987' if @=0 return 4 if @<20 return 0+substring(@s,@+1,1)return 0+substring(@l,@/10,1)+substring(@s,@%10+1,1)END
Gabe
9

Java (avec boilerplate), 308 290 286 282 280 caractères

class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}

Je suis sûr que Groovy s'en débarrasserait en grande partie.

Explication et formatage (tous les commentaires, nouvelles lignes et espaces blancs de début / de fin supprimés dans le compte):

Raisonnablement simple, mais

//boilerplate
class A{
   public static void main(String[]a){
      //i is current/left number, j right/next number.  i=4 signals to start
      //by reading input
      int i=4,j=0;
      for(;;)
         //print in the form "<left> is <right>."
         System.out.printf(
            "%d is %s.%n",
            i=i==4?
               //<left>: if i is 4 <left> will be a new starting number
               new java.util.Scanner(System.in).nextInt():
               //otherwise it's the next val
               j,
            i!=4?
               //use string to map number to its length (:;< come after 9 in ASCII)
               //48 is value of '0'.  store in j for next iteration
               j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:
               //i==4 is special case for right; print "magic"
               "magic");
   }
}

Edit: n'utilisez plus hexadécimal, c'est moins de frappes

Mark Peters
la source
1
249 sans importations, classe def ou def principale.
Mark Peters
1
C'est diabolique. J'aime la base 16. (+1)
Platinum Azure
Vous pouvez économiser un espace en utilisant String[]aau lieu de String[] a.
BalusC
Merci @Balus, a également éliminé un tas de choses en faisant de l'arithmétique simple sur le personnage au lieu d'utiliser l'analyse hexadécimale.
Mark Peters
@Mark Peters: Encore plus méchant. Je me sens tellement vanillé par rapport à ça.
Platine Azure
9

Windows PowerShell: 152 153 184 octets

basé sur la solution précédente, avec plus d'influence d'autres solutions

$o="03354435543668877988"
for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a
"$a is $b."}'4 is magic.'
seulement
la source
Correction de la prise en charge des multiples de 10 ("quatre-vingt-dix" plutôt que "quatre-vingt-dix-zéro").
Gabe
Salut @Gabe :), merci; je n'ai pas eu beaucoup de temps pour jouer au golf ces derniers temps. Pourtant, les guillemets $inputdoivent rester car vous ne pouvez pas convertir directement un énumérateur int; ça marche quand on passe en stringpremier :-)
Joey
8

C, 158 caractères

main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d.\n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}

(basé à l'origine sur le code Python de Vlad, emprunté une astuce à la solution C ++ de Tom Sirgedas pour extraire quelques caractères supplémentaires)

version étendue:

main(n, c) {
    char *d = "03354435543668877988";
    for (scanf("%d",&n); n-4; n = c)
        printf("%d is %d.\n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10]  : 4);
    puts("4 is magic.");
}
Ferruccio
la source
Cela ne semble pas fonctionner pour moi: ./magic 10 10 est -27. Erreur de segmentation
Casey
@Casey - l'appel scanf () était un peu sommaire. Il lisait un int dans un caractère. Je me débrouillais avec OSX et sous Windows, cela fonctionnait mais s'est écrasé à la sortie. Alors, j'ai refait des n & c ints. J'ai réalisé que je pouvais supprimer le mot-clé int en en faisant des paramètres en utilisant la notation K&R. Le résultat est plus sûr et un caractère plus court.
Ferruccio
Vous pouvez enregistrer 3 caractères en remplaçant " 466555766" [n / 10] + d [n% 10] -96 par d [n% 10] - " , +++) " [n / 10]
Tom Sirgedas
6

Python, 129 133 137 148 caractères

En guise d'échauffement, voici ma première version (améliore quelques caractères par rapport au meilleur Python précédent).

PS. Après quelques expurgations, il est maintenant plus court d'environ vingt caractères:

n=input()
while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,'is %d.'%p;n=p
print'4 is magic.'
Nas Banov
la source
6

C #: 210 caractères.

Écrasé:

using C=System.Console;class B{static void Main(){int
x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}.\n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}

Étendu:

using C=System.Console;
class B
{
    static void Main()
    {
        int x=0,y=int.Parse(C.ReadLine());
        while(x!=4)
            C.Write((x=y)+" is {0}.\n",
                x==4?
                     "magic":
                     ""+(y= x==0?
                                4:
                                "03354435543668877988"[x<20?x:x%10]+
                                "0066555766"[x/10]-96)
                   );
    }
}

Trucs que cette approche utilise:

  • Créez une table de recherche pour les longueurs de nom de numéro en fonction des chiffres qui apparaissent dans le numéro.
  • Utilisez la recherche de tableau de caractères sur une chaîne et l'arithmétique de caractères au lieu d'un tableau numérique.
  • Utiliser le nom de classe aliasing à court Console.deC.
  • Utilisez l'opérateur conditionnel (ternaire) ( ?:) au lieu de if/else.
  • Utilisez le \navec le Writecode d'échappement au lieu deWriteLine
  • Utilisez le fait que C # a un ordre d'évaluation défini pour autoriser les affectations à l'intérieur du Write appel de fonction
  • Utilisez les expressions d'affectation pour éliminer les instructions supplémentaires, et donc les accolades supplémentaires
LBushkin
la source
int[] zserait plus court car il n'a pas besoin denew[]
Joey
Révisé pour utiliser l'arithmétique des caractères au lieu de la recherche de tableau.
LBushkin
@ mdm20: Vous avez raison. J'ai eu une erreur dans la table de consultation. Corrigé maintenant.
LBushkin
Eh bien, la douzième fois c'est le charme: * D
LBushkin
A Quicky pour enregistrer 5 caractères: Plus court que la coulée "magic"à object, serait implicitement appel ToString()à yen ajoutant "". Mais, à cause +a une priorité supérieure ?:, vous devez mettre dans la vraie partie au lieu de la fausse partie: x!=4?y+"":"magic".
P Daddy le
6

Perl: 148 caractères

(Perl: 233 181 212 206 200 199 198 185 179 149 148 caractères)

  • Déplacement du hachage des exceptions dans le tableau d'unités. Cela m'a permis de couper beaucoup de personnages :-)
  • mobrule a signalé un méchant bug. Le correctif rapide ajoute 31 caractères, aïe!
  • Refactorisé pour zéro cas particulier, golf doux également.
  • Accès direct à la liste à usage unique plutôt que stockage dans la baie? Putain, oui!
  • TELLEMENT REFACTORISANT pour UN SEUL personnage sanglant. C'est vraiment la vie d'un golfeur. :-(
  • Oups, solution facile pour les espaces blancs. 198 maintenant.
  • Refactorisation d'un code redondant.
  • Le dernier mot-clé de retour rest inutile, rasé un peu plus.
  • Refactoring massif par commentaires; Malheureusement, je n'ai pu l'obtenir qu'à 149 parce que j'ai dû corriger un bogue qui était présent à la fois dans mon code précédent et dans les versions des commentateurs.
  • Essayer les mots nus "magie".

Lançons ce bal avec une modeste tentative en Perl.

@u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_

Des trucs:

Trop!

Platine Azure
la source
ACK! Comment je n'ai jamais testé que je ne le saurai jamais.
Platinum Azure
Avez-vous du code mort là-dedans? Je ne vois pas en quoi le cas spécial pour zéro est nécessaire lorsque $ u [0] vaut 4. J'ai une version apparemment fonctionnelle de votre code @ 166 caractères, et je pense qu'il est possible de devenir un peu plus court que cela.
hobbs
@hobbs: Bon point, je vais regarder à nouveau. L'histoire est que je suis arrivé à mi-chemin de quelques révisions et que soudainement les choses se sont cassées (à peu près au point où j'ai choisi d'avoir 4 -> 0). Je pense que vous avez raison à ce stade, cependant :-)
Platinum Azure
Je ne me considère pas comme un grand programmeur Perl, mais vous pouvez réduire certains caractères: @u=split$x,'43350435543668877988';vos virgules utilisent 19 caractères inutiles, se divisant sur une undefdivision à chaque caractère, j'utilise $xcomme variable indéfinie pour remplacer `undef` - total économies: 11 caractères. De plus, retirez le mdans chompet vous obtenez un autre personnage rasa votre score.
vol7ron
Faire mieux, mais vous pouvez toujours économiser plus en perdant sub rentièrement - vous ne l'utilisez qu'une seule fois et vous pouvez tout remplacer par un seul ternaire imbriqué sans même parenthèse. Ma version est de 144 caractères pour le moment: gist.github.com/473289
hobbs
5

JavaScript 1.8 (SpiderMonkey) - 153 caractères

l='4335443554366887798866555766'.split('')
for(b=readline();(a=+b)-4;print(a,'is '+b+'.'))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10])
print('4 is magic.')

Usage: echo 42 | js golf.js

Production:

42 is 8.
8 is 5.
5 is 4.
4 is magic.

Avec bonus - 364 caractères

l='zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ')
z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?' '+l[a%10]:'')
for(b=+readline();(a=b)-4;print(z(a),'is '+z(b)+'.'))b=z(a).replace(' ','').length
print('four is magic.')

Production:

quatre-vingt dix neuf est dix.
dix fait trois.
trois est cinq.
cinq fait quatre.
quatre est magique.
gnarf
la source
4

Haskell, 224 270 caractères

o="43354435543668877988"
x!i=read[x!!i]
n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10
f x=zipWith(\a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"]
main=readLn>>=mapM putStrLn.f

Et un peu plus lisible -

ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8]
tens = [0,0,6,6,5,5,5,7,6,6]

n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10)

f x = zipWith (\a b -> a ++ " is " ++ b ++ ".") l (tail l)
    where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"]
    
main = readLn >>= mapM putStrLn . f
Matajon
la source
4

Version C ++ Stdio, minifiée: 196 caractères

#include <cstdio>
#define P;printf(
char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d.\n%d",p,p);}P" is magic.\n");}

Version C ++ Iostreams, minifiée: 195 caractères

#include <iostream>
#define O;std::cout<<
char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<".\n"<<p;}O" is magic.\n";}

Original, non minifié: 344 caractères

#include <cstdio>

int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 };
int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 };

int n(int n) {
    return n<20 ? ones[n] : tens[n/10] + ones[n%10];
}

int main(int p) {
    scanf("%d", &p);
    while(p!=4) {
        int q = n(p);
        printf("%i is %i\n", p, q);
        p = q;
    }
    printf("%i is magic\n", p);
}
Karl von Moor
la source
Fixé. Cela a aussi été un peu plus court.
Mike DeSimone
Bien fait. (J'ai beaucoup ri de l'énigme std à 20 caractères!)
Platinum Azure
Ouais, c'était un vrai headbanger, jusqu'à ce qu'il me vienne à l'esprit que ce #defineserait encore plus court car cela pourrait remplacer plusieurs jetons.
Mike DeSimone
printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Non seulement plus court mais plus rapide aussi.
Ben Voigt
2
@Mike DeSimone: Je pense que cela while(p!=4)pourrait être abrégé while(p-4). Un personnage entier, je sais, mais quand même. :-)
Platinum Azure
3

Delphi: 329 caractères

Version à une seule ligne:

program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A='EDDFEEDFFEDGGIIHHJII';B='DGGFFFJGG';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write('> ');ReadLn(X);repeat Y:=Z(X);WriteLn(Format('%d is %d.',[X,Y]));X:=Y;until X=4;WriteLn('4 is magic.');end.

Formé:

program P;

{$APPTYPE CONSOLE}

uses
  SysUtils;

const
  S = 65;
  A = 'EDDFEEDFFEDGGIIHHJII';
  B = 'DGGFFFJGG';

function Z(X:Byte):Byte;
begin
  if X<20
  then Z := Ord(A[X+1])-S
  else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10);
end;

var
  X,Y: Byte;

begin
  Write('> ');
  ReadLn(X);

  repeat
    Y:=Z(X);
    WriteLn(Format('%d is %d.' , [X,Y]));
    X:=Y;
  until X=4;

  WriteLn('4 is magic.');
end.

Probablement de la place pour un peu plus de pression ... :-P

Jørn E. Angeltveit
la source
3

C # 314 286 283 274 289 273 252 car.

Écrasé:

252 

Ordinaire:

using C = System.Console;
class P
{
    static void Main()
    {
        var x = "4335443554366877798866555766";
        int m, o, v = int.Parse(C.ReadLine());
        do {
            C.Write("{0} is {1}.\n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48));
        } while (o != 4);
        C.ReadLine();
    }
}

Edit Dykam: J'ai fait quelques insertions et modifications soigneuses:

  • Changement du l.ToString () en un cast objectdu string "magic".
  • oJ'ai créé une variable temporaire pour que je puisse déplacer l' breakextérieur de la forboucle, c'est-à-dire créer un fichier do-while.
  • A ajouté l' oaffectation, ainsi que l' vaffectation, en continuant à insérer le calcul de ldans les arguments de la fonction, supprimant ainsi le besoin de l. Également intégré l'attribution de m.
  • Suppression d'un espace dans int[] x, int[]xest également légitime.
  • J'ai essayé de transformer le tableau en une transformation de chaîne, mais le using System.Linq c'était trop pour en faire une amélioration.

Edit 2 Dykam Changement du tableau int en tableau / chaîne de caractères, ajout d'arithmiques appropriées pour corriger cela.

mdm20
la source
Ouais, c'est plus court que la version Java.
Dykam
3

Lua, 176 caractères

o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."

ou

  o={[0]=4,3,3,5,4,4
  ,3,5,5,4,3,6,6,8,8
  ,7,7,9,8,8}t={3,6,
   6,5,5,5,7,6,6}n=
   0+io.read()while
   n ~= 4 do a= o[n
   ]or o[n%10]+t[(n
   -n%10)/10]print(
n.." is "..a.."." )n=a
end print"4 is magic."
gwell
la source
3

C - sans mots numériques

180 175 * 172 167 caractères

Toutes les nouvelles lignes sont destinées à la lisibilité et peuvent être supprimées:

i;V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}main(c){for(scanf("%d",&c);
c-4;)i=c,printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);puts(
"4 is magic.");}

Légèrement non minimisé:

i;
V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}
main(c){
    for(scanf("%d",&c);c-4;)
        i=c,
        printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);
    puts("4 is magic.");
}

* La version précédente manquait la marque sur deux parties de la spécification: elle ne traitait pas zéro, et elle prenait des entrées sur la ligne de commande au lieu de stdin. La gestion de zéro caractère ajouté, mais l'utilisation de stdin au lieu d'arguments de ligne de commande enregistre encore plus, ce qui entraîne des économies nettes.

P Daddy
la source
2

perl, 123122 caractères

Je viens de réaliser qu'il n'est pas nécessaire de sortir vers STDOUT, alors sortez plutôt vers STDERR et supprimez un autre caractère.

@u='0335443554366887798866555766'=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,".\n"until/g/

Et, une version qui renvoie des nombres épelés:

279 278 276 280 caractères

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

Bien que cela respecte les spécifications, il n'est pas bien formaté à 100%. Il renvoie un espace supplémentaire après les nombres se terminant par zéro. La spécification dit:

"Je me fiche de la façon dont vous séparez les jetons de mots, même s'ils devraient être séparés"

C'est plutôt farfelu. Une version plus correcte à

282 281 279 283 caractères

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("\x8",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/
user397369
la source
1

Python:

#!/usr/bin/env python

# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls  = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens  =  ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )

def Count(n):
    if n > 10 and n < 20: return Teens[n-11]
    return   Smalls[n % 10 ] + Decades [ n / 10 ]

N = input()

while N-4:
    Cnt = Count(N)
    print "%d is %d" % ( N, Cnt)
    N = Cnt

print "4 is magic"
Vlad
la source
4
Je l'aime. Vous pourriez probablement le resserrer un peu.
Josh K
@Vlad: l'entrée doit être lue à partir de stdin au lieu des arguments. Cela signifie que vous pouvez simplement utiliser N = input()(ou raw_input()) et éliminer les syséléments.
kennytm
Vous pouvez également faire en sorte que les petits incluent les adolescents, alors l'instruction if ne serait que "si n <20: return Smalls [n]". Smalls fonctionnerait toujours pour le cas> = 20, en raison du module de 10.
Jon Smock
5
Ce doit être la première fois que je vois le (entièrement optionnel) she-bangdans une réponse code-golf ;-)
ChristopheD
On dirait un bon début ... Serrez-le définitivement, même Python n'a pas besoin de TOUS ces espaces. :-) De plus, comme le souligne Ferruccio, 0 ne fonctionne pas, en particulier il semble entrer dans une boucle infinie.
Platinum Azure
1

C ++, 171 caractères (#include omis)

void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d.\n",x,y);puts("4 is magic.");}
Tom Sirgedas
la source
Je pense que si vous considérez que c'est C, vous pouvez éviter le besoin de #includecar les fonctions seront simplement supposées prendre des intparamètres. Vous pouvez même enregistrer un coup en effectuant un mainretour int.
Gabe
1

Rubis, 164 caractères

n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."

décodé:

n = gets.to_i
s = "03354435543668877987"
if n == 0
  puts "0 is 4."
else
  puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4
end

puts "4 is magic."
Jon Smock
la source
Belle solution Ruby, en restant simple. :-) (+1)
Platinum Azure
Rester simple n'est pas une excuse pour le garder trop long, cependant ;-)
Joey
Je pense que vous pouvez remplacer «if n == 0» par «if! N»
Vincent
2
En Ruby? J'ai toujours pensé que toutes les valeurs sauf false et nil étaient évaluées à true :-(
Platinum Azure
1

Lua 185 190 199

points ajoutés, ajout de io.read, suppression de () lors de la dernière impression

 n=io.read();while(n~=4)do m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;print(n,' is ',m,'.')n=m;end print'4 is magic.'

avec sauts de ligne

 n=io.read()
 while (n~=4) do
    m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;
    print(n,' is ',m,'.')
    n=m;
 end 
 print'4 is magic.'
Nick
la source
Nécessite un n=io.read()(+11 caractères) pour se conformer à la règle de lecture du nombre à partir de l'entrée standard. Changer print('4 is magic.')en print'4 is magic.'économisera 2 caractères. Supprimer ;après )sauvera 1 caractère. L' printutilisation de virgules semble tricher, mais les spécifications ne sont pas claires. Autant le changer en print(n,'is',m,'.')pour enregistrer 2 caractères.
gwell
Les virgules sont-elles rendues comme des retours à la ligne dans Lua? Cela fait un moment que je ne l'ai pas utilisé.
Nick Van Brunt
Les virgules sont rendues sous forme de tabulations.
gwell
0

Code PhP

function get_num_name($num){  
    switch($num){  
        case 1:return 'one';  
    case 2:return 'two';  
    case 3:return 'three';  
    case 4:return 'four';  
    case 5:return 'five';  
    case 6:return 'six';  
    case 7:return 'seven';  
    case 8:return 'eight';  
    case 9:return 'nine';  
    }  
}  

function num_to_words($number, $real_name, $decimal_digit, $decimal_name){  
    $res = '';  
    $real = 0;  
    $decimal = 0;  

    if($number == 0)  
        return 'Zero'.(($real_name == '')?'':' '.$real_name);  
    if($number >= 0){  
        $real = floor($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }else{  
        $real = ceil($number) * (-1);  
        $number = abs($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }  
    $decimal = substr($decimal, strpos($decimal, '.') +1);  

    $unit_name[1] = 'thousand';  
    $unit_name[2] = 'million';  
    $unit_name[3] = 'billion';  
    $unit_name[4] = 'trillion';  

    $packet = array();    

    $number = strrev($real);  
    $packet = str_split($number,3);  

    for($i=0;$i<count($packet);$i++){  
        $tmp = strrev($packet[$i]);  
        $unit = $unit_name[$i];  
        if((int)$tmp == 0)  
            continue;  
        $tmp_res = '';  
        if(strlen($tmp) >= 2){  
            $tmp_proc = substr($tmp,-2);  
            switch($tmp_proc){  
                case '10':  
                    $tmp_res = 'ten';  
                    break;  
                case '11':  
                    $tmp_res = 'eleven';  
                    break;  
                case '12':  
                    $tmp_res = 'twelve';  
                    break;  
                case '13':  
                    $tmp_res = 'thirteen';  
                    break;  
                case '15':  
                    $tmp_res = 'fifteen';  
                    break;  
                case '20':  
                    $tmp_res = 'twenty';  
                    break;  
                case '30':  
                    $tmp_res = 'thirty';  
                    break;  
                case '40':  
                    $tmp_res = 'forty';  
                    break;  
                case '50':  
                    $tmp_res = 'fifty';  
                    break;  
                case '70':  
                    $tmp_res = 'seventy';  
                    break;  
                case '80':  
                    $tmp_res = 'eighty';  
                    break;  
                default:  
                    $tmp_begin = substr($tmp_proc,0,1);  
                    $tmp_end = substr($tmp_proc,1,1);  

                    if($tmp_begin == '1')  
                        $tmp_res = get_num_name($tmp_end).'teen';  
                    elseif($tmp_begin == '0')  
                        $tmp_res = get_num_name($tmp_end);  
                    elseif($tmp_end == '0')  
                        $tmp_res = get_num_name($tmp_begin).'ty';  
                    else{  
                        if($tmp_begin == '2')  
                            $tmp_res = 'twenty';  
                        elseif($tmp_begin == '3')  
                            $tmp_res = 'thirty';  
                        elseif($tmp_begin == '4')  
                            $tmp_res = 'forty';  
                        elseif($tmp_begin == '5')  
                            $tmp_res = 'fifty';  
                        elseif($tmp_begin == '6')  
                            $tmp_res = 'sixty';  
                        elseif($tmp_begin == '7')  
                            $tmp_res = 'seventy';  
                        elseif($tmp_begin == '8')  
                            $tmp_res = 'eighty';  
                        elseif($tmp_begin == '9')  
                            $tmp_res = 'ninety';  

                        $tmp_res = $tmp_res.' '.get_num_name($tmp_end);  
                    }  
                    break;  
            }  

            if(strlen($tmp) == 3){  
                $tmp_begin = substr($tmp,0,1);  

                $space = '';  
                if(substr($tmp_res,0,1) != ' ' && $tmp_res != '')  
                    $space = ' ';  

                if($tmp_begin != 0){  
                    if($tmp_begin != '0'){  
                        if($tmp_res != '')  
                            $tmp_res = 'and'.$space.$tmp_res;  
                    }  
                    $tmp_res = get_num_name($tmp_begin).' hundred'.$space.$tmp_res;  
                }  
            }  
        }else  
            $tmp_res = get_num_name($tmp);  
        $space = '';  
        if(substr($res,0,1) != ' ' && $res != '')  
            $space = ' ';  
        $res = $tmp_res.' '.$unit.$space.$res;  
    }  

    $space = '';  
    if(substr($res,-1) != ' ' && $res != '')  
        $space = ' ';  

    if($res)  
        $res .= $space.$real_name.(($real > 1 && $real_name != '')?'s':'');  

    if($decimal > 0)  
        $res .= ' '.num_to_words($decimal, '', 0, '').' '.$decimal_name.(($decimal > 1 && $decimal_name != '')?'s':'');  
    return ucfirst($res);  
}  

//////////// test ////////////////

 $str2num = 12;
    while($str2num!=4){
        $str = num_to_words($str2num, '', 0, '');  
        $str2num = strlen($str)-1;
        echo $str . '=' . $str2num .'<br/>';
        if ($str2num == 4)
            echo 'four is magic';
    }

////// Résultats /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
Développeur
la source
4
@wallacoloo: Une solution minable pour une langue minable: D
Thomas Eding
5
Ou un 178 caractères beaucoup plus court:$l='4335443554366887798866555766';for($b=(int)fgets(fopen('php://stdin','r'));($a=$b)-4;){$b=$a<20?$l[$a]:$l[18+$a/10]+($a%10?$l[$a%10]:0);echo"$a is $b.\n";}echo"4 is magic.\n";
gnarf
Bonne blague. :-D Si bien programmé.
Tom Pažourek
0

Perl - 130 caractères


5.12.1 (130 caractères) 121 123 132 136 140

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123

@u='4335443554366887798866555766'=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until/\D/


5.10.1 (134 caractères) 125 127 136 140 144

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234

@u='4335443554366887798866555766'=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,".\n"until/\D/


Historique des modifications:

20100714:2223- annulé le changement à l'attention de mobrule , mais ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), qui est le même nombre de caractères, mais je l'ai fait au cas où quelqu'un verrait un moyen de l'améliorer

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ suppression des parenthèses inutiles
20100713:xxxx- $=<>;chop;$_=pop;- courtoisie envers mobrule


Remarque: J'étais fatigué d'améliorer les réponses des autres dans les commentaires, alors maintenant je suis avide et je peux simplement ajouter mes modifications ici :) Ceci est une scission de la réponse de Platinum Azure - crédit en partie à Hobbs , mobrule et Platine Azure .

vol7ron
la source
Lorsque vous vous êtes débarrassé de la $_%10&&...construction, vous avez cassé les spécifications pour les entrées 20, 30, 40, ...
mob
+1 Bien fait. Cependant, vous êtes sorti de stdin en args :-(
Platinum Azure
À droite, remplacé par ARGV, qui est rempli par STDIN:) ou .. echo bar | xargs perl foo.pl, techniquement transféré de l'écho dans les arguments pour perl :)
vol7ron
0

Perl sans vergogne avec mots numériques (329 caractères)

Adapté assez directement du code C de P Daddy, avec quelques ajustements pour p()lui faire faire la même chose en utilisant des primitives Perl au lieu de celles C, et une boucle principale en grande partie réécrite. Voir le sien pour une explication. Les nouvelles lignes sont toutes facultatives.

@t=(qw(zero one two three four five six sM eight nine
tL elM twelve NP 4P fifP 6P 7P 8O 9P twLQ NQ forQ fifQ
6Q 7Q 8y 9Q en evL thir eL tO ty 4SmagicT)," is ",".\n");
sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e;
print;length}$_=<>;chop;while($_-4){
$_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_;
p 35;p$_;p 36}p 34

Note latérale: c'est dommage que perl printrenvoie juste vrai / faux; s'il retournait un compte, cela me sauverait 7 coups.

hobbs
la source
0

Rubis, 141 caractères:

n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? 'magic': n}.";n==s &&break}
Krzysztof
la source
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
user368038
la source