Un petit casse-tête que j'ai entendu quand j'étais au lycée est allé quelque chose comme ça ...
Le but était d'essayer de comprendre la fonction de transformation et de pouvoir ensuite surveiller ce casse-tête de manière fiable.
La fonction de transformation à chaque étape était de
Pour tous les nombres que je me suis toujours efforcé de tester, cela converge vers 4. Puisque "quatre" contient également quatre lettres, il y aurait une boucle infinie ici; au lieu de cela, il est simplement appelé la magie par convention, mettre fin à la séquence.
Votre défi consiste à créer un morceau de code qui lira un numéro de l'utilisateur, puis à imprimer des lignes montrant la fonction de transformation appliquée de manière répétée jusqu'à ce que "quatre soit magique" soit atteint.
Plus précisément:
a is b.
, où a et b sont des formes numériques des nombres de la transformation.4 is magic.
.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 le soumission la plus courte par nombre de caractères du code source qui est aussi correct.
Vous pouvez également essayer d’écrire une version du code qui affiche les NOMS ANGLAIS pour les nombres avec 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 Word du nombre.
(Double bonus pour dessiner des formes avec votre code)
(MODIFIER) Quelques clarifications:
Nine is four. Four is magic.
ninety-nine
va bien, ninety nine
va bien, ninetynine
ne va pas.Je considère cela comme une catégorie distincte pour la compétition de bonus en ce qui concerne le défi. Donc, si vous y allez, ne vous inquiétez pas de la longueur de votre code par rapport à la version numérique.
N'hésitez pas à soumettre une solution pour chaque version.
90 → 94
: sortie fixe pour des multiples de 10.94 → 86
: code restructuré. Utilisation de la base 100 pour supprimer les caractères non imprimables.86 → 85
: Distribution plus courte vers la chaîne.
{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Librement inspiré de 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
Chars LISP 157 communs
Nouvelle version plus conforme, lisant maintenant l’entrée standard du formulaire et ignorant les espaces et les tirets:
(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 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 essais:
>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.
Cela sépare le nombre en dizaines et en un et les résume. La propriété indésirable de l'opérateur pseudo-ternaire a and b or c
que c
est renvoyée si b
est 0, elle est mal utilisée ici.
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). Il suffit d’encoder 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."
C'est tout. Je ne pense pas pouvoir raccourcir ce délai.
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 quelque peu non approfondi, mais reste 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"*/);
}
Les noms des nombres sont compressés en utilisant 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 correspondance" d'entrées de nom 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é pour 11 est Elm
. La fonction print()
génère les caractères e
et l
('L' minuscule, pas le nombre '1'), mais elle trouve la M
, de sorte qu'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
. Elle génère donc e
et v
, puis s’appelle à nouveau avec l’index de la 28e entrée de la table de recherche, qui est en
, et est reproduit textuellement. Ceci est utile car en
est également utilisé dans eL
pour een
(utilisé après eight
dans eighteen
), qui est utilisé dans tO
pour teen
(utilisé pour tout autre nom -teen
).
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 la décompression.
Les virgules au début et à la fin de la chaîne expliquent de manière simpliste la présence de sous-chaînes dans cette chaîne. Ajouter deux caractères ici enregistre plus de caractères plus tard.
main()
argv
est ignoré (et donc non déclaré dans la version compressée), la valeur de argc est ignorée, mais la mémoire est réutilisée pour contenir le nombre actuel. Cela me évite de devoir déclarer une variable supplémentaire.
#include
Certains vont se plaindre d'omettre #include <stdio.h>
, c'est tricher. Ce n'est pas du tout. Le programme donné est un programme C complètement légal qui compilera correctement tous les compilateurs C que je connaisse (bien qu’avec des avertissements). En l'absence de prototypes pour les fonctions stdio, le compilateur supposera qu'il s'agit de fonctions cdecl renvoyant int
et fera confiance à votre connaissance des arguments à transmettre. De toute façon, les valeurs de retour sont ignorées dans ce programme et il s’agit de fonctions cdecl (convention d’appel "C"), et nous savons en effet quels arguments doivent être passés.
La sortie est comme prévu:
0 Zéro est quatre. Quatre est magique.
1 Un est trois. Trois est cinq. Cinq est quatre. Quatre est magique.
4 Quatre est magique.
20 Vingt, c'est six. Six, trois. Trois, cinq. Cinq, quatre. Quatre, c'est magique .
21 Vingt et un ans c'est neuf. Neuf c'est quatre. Quatre c'est magique.
* La version précédente manquait le repère sur deux parties de la spécification: elle ne gérait pas le zéro et prenait l'entrée sur la ligne de commande au lieu de stdin. La gestion des zéros ajoutés aux caractères, mais l'utilisation de stdin au lieu d'arguments de ligne de commande, ainsi que de quelques optimzations, a enregistré le même nombre de caractères, ce qui a entraîné un lavage.
† Les exigences ont été modifiées pour indiquer clairement que le nombre Word doit être imprimé des deux côtés de "est". Cette nouvelle version répond à cette exigence et implémente plusieurs optimisations supplémentaires afin de prendre en compte la taille supplémentaire nécessaire.
'4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:
(Newline pour la lisibilité seulement)
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.
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 cela ... vraiment je voulais juste écrire un CTE)
Utiliser:
M 95
Résultats
p n
----------- ---- -----------
95 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.
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.'
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 mise en forme (tous les commentaires, les nouvelles lignes et les espaces de début et de fin supprimés):
Assez 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: ne plus utiliser hex, c'est moins de frappes
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.");}
(à l'origine basé 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.");
}
Squished:
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));}}
Expanded:
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)
);
}
}
Astuces cette approche utilise:
Console.
à C.
?:
) au lieu de if/else
.\n
avec le code d'échappement Write
au lieu de WriteLine
Write
(Perl: 233181212206200199198185179149 148 caractères)
r
n'est pas nécessaire, il en a été réduit davantage.Commençons par une tentative modeste en Perl.
@u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_
Des trucs:
Trop!
En guise d’échauffement, voici ma première version (améliore quelques caractères par rapport au précédent meilleur Python).
PS Après quelques expurgations, le nombre de caractères est plus court:
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.'
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.')
Utilisation: echo 42 | js golf.js
Sortie:
42 is 8.
8 is 5.
5 is 4.
4 is magic.
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.')
Sortie:
quatre-vingt-dix-neuf, c'est dix. dix c'est trois. trois c'est cinq. cinq c'est quatre.
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 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
#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");}
#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";}
#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);
}
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.
Formated:
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 compression ... :-P
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."
C # 314286283274289273 252 caractères.
É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: A fait quelques insertions et modifications soigneuses:
object
de la string
"magic"
.o
afin de pouvoir déplacer la break
en dehors de la boucle for
, c'est-à-dire la création d'un do-while
.o
en ligne, ainsi que l'affectation v
, continuent en insérant le calcul de l
dans les arguments de la fonction, ce qui supprime le besoin de l
. Également en ligne l'affectation de m
.int[] x
, int[]x
est également légitime.using System.Linq
était trop pour en faire une amélioration.Edit 2 Dykam Changé le tableau int en un tableau/chaîne de caractères, ajout de l'arithmique appropriée pour corriger cela.
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 terminé:
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 le repère sur deux parties de la spécification: elle ne gérait pas le zéro et prenait l'entrée 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 permettait encore plus d'économiser, ce qui permettait de réaliser des économies nettes.
Je viens de me rendre compte qu'il n'y a pas d'exigence de sortie sur STDOUT, donc affichez plutôt sur 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 retourne des nombres épelés:
@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 réponde aux spécifications, ce n'est pas à 100% bien formaté. 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 Word, même s'ils doivent être séparés"
C'est un peu malsain cependant. Une version plus correcte sur
@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/
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."
Lua 185190 199
ajout de points, ajout de io.read, remove () 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 des 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.'
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"
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.");}
Ruby, 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}
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);
}
//////////// tests //////////////////
$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
# 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/
# 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/
20100714:2223
- changement annulé à 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 inutiles20100713:xxxx
- $=<>;chop;
→ $_=pop;
- gracieuseté de mobrule
Remarque: J'étais fatigué d'améliorer les réponses des autres dans les commentaires. Je suis donc trop gourmand et je peux ajouter mes modifications ici :) C'est une séparation de Platinum Azure 's answer - crédit partiel de Hobbs , mobrule , et Platinum Azure .
Adapté assez directement du code C de P Daddy, avec quelques ajustements à p()
pour lui faire faire la même chose en utilisant des primitives Perl au lieu de C, et une boucle principale principalement 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: il est dommage que Perl print
ne retourne que vrai/faux; si cela retournait, ça me ferait gagner 7 coups.