Code Golf: Four é mágico

88

O quebra-cabeça

Um pequeno quebra-cabeça que ouvi quando estava no colégio foi mais ou menos assim ...

  • O questionador pedia que eu desse um número;
  • Ao ouvir o número, o questionador faria algum tipo de transformação nele repetidamente (por exemplo, ele poderia dizer que dez é três ) até finalmente chegar ao número 4 (nesse ponto ele terminaria com quatro é mágico ).
  • Qualquer número parece ser transformável em quatro eventualmente, não importa o quê.

O objetivo era tentar descobrir a função de transformação e, então, ser capaz de supervisionar esse quebra-cabeça de maneira confiável.

A solução

A função de transformação em qualquer etapa era

  • Pegue o número em questão,
  • Conte o número de letras em sua representação de palavra em inglês, ignorando um hífen ou espaços ou "e" (por exemplo, "dez" tem 3 letras, "trinta e quatro" tem 10 letras, "cento e quarenta e três" tem 20 letras).
  • Retorne aquele número de letras.

Para todos os números que já me preocupei em testar, isso converge para 4. Como "quatro" também tem quatro letras, haveria um loop infinito aqui; em vez disso, é apenas referido como mágica por convenção para encerrar a sequência.

O desafio

Seu desafio é criar um pedaço de código que lerá um número do usuário e então imprimirá linhas mostrando a função de transformação sendo aplicada repetidamente até que "quatro é mágico" seja alcançado.

Especificamente:

  1. As soluções devem ser programas completos por si mesmas. Eles não podem ser meramente funções que recebem um número - fator na entrada.
  2. A entrada deve ser lida a partir da entrada padrão. (Canalizar de "echo" ou usar redirecionamento de entrada é bom, pois também vai de stdin)
  3. A entrada deve ser em formato numérico.
  4. Para cada aplicação da função de transformação, uma linha deve ser impressa:, a is b.onde a e b são as formas numéricas dos números na transformação.
  5. Paradas completas (períodos) SÃO obrigatórios!
  6. A última linha deve naturalmente dizer 4 is magic.,.
  7. O código deve produzir uma saída correta para todos os números de 0 a 99 .

Exemplos:

> 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.

O vencedor é o envio mais curto por contagem de caracteres do código-fonte, que também está correto .

BÔNUS

Você também pode tentar escrever uma versão do código que imprima os NOMES EM INGLÊS para os números com cada aplicação da função de transformação. A entrada original ainda é numérica, mas as linhas de saída devem ter a forma de palavra do número.

(Bônus duplo para desenhar formas com seu código)

(EDIT) Alguns esclarecimentos:

  1. Eu quero que a palavra apareça em ambos os lados em todos os casos aplicáveis, por exemplo Nine is four. Four is magic.
  2. Não me importo com letras maiúsculas, no entanto. E eu não me importo como você separa as palavras tokens, embora elas devam ser separadas: ninety-nineestá certo, ninety nineestá certo, ninetyninenão está certo.

Estou considerando isso como uma categoria separada para competição de bônus no que diz respeito ao desafio, então, se você for para isso, não se preocupe com o seu código ser mais longo do que a versão numérica.

Sinta-se à vontade para enviar uma solução para cada versão.

Platinum Azure
fonte
1
Qual é o número que devemos controlar? <100? <1000? <1000000? <2 ** 31?
P Daddy
1
Como isso só precisa ir de 0 a 99, suspeito que uma solução rápida e curta seria codificar os valores para os quais 0-99 mapeiam e depois fazer um loop até chegar a 4. Depois disso, o microtweaking começa.
Beska
@P Daddy ... a parte 6 diz apenas 0-99.
Beska
14
4 é apenas mágico porque foi escolhido por um bom lançamento de dados.
VirtuosiMedia

Respostas:

57

GolfScript - 101 96 93 92 91 90 94 86 bytes

90 → 94: Saída fixa para múltiplos de 10
94 → 86.: Código reestruturado. Usando base 100 para remover caracteres não imprimíveis.
86 → 85: Shorter cast para string.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Nabb
fonte
por que isso está tão baixo? é mais curto que o lisp e não usa uma função de formatação embutida
Claudiu
36
Eu gosto de como o código termina com "magic.", ele basicamente resume tudo.
Aistina
@Aistina: Isso é fácil de fazer neste desafio, eu acho. :-)
Platinum Azure
9
@Aistina: haha, isso é meio engraçado. "mumbo jumbo yada yada..magic"
vol7ron
1
@P A papai dé extraída pelo )que 100e é utilizado como a raiz para a conversão de base.
Nabb
85

Perl, cerca de 147 char

Vagamente baseado na solução 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
fonte
1
@Platinum Azure a forma como ele obtém sua entrada é por meio do uso de pop, sem nenhum argumento. Fora de uma sub-rotina popremove e retorna o último valor do @ARGVqual é a lista de argumentos para o programa Perl. Ele poderia ser facilmente substituído por shift, mas isso adiciona outros 2 caracteres. Veja: p3rl.org/pop
Brad Gilbert
parece que você precisa de um caractere de nova linha em '.', que é 2 para \nou 1 se você estiver contando espaços em branco no '. '(espaço sendo o literal de nova linha)
vol7ron
Um pouco mais, mas a criatividade vai longe no meu livro.
Beska
@Platinum Azure et al: Ele está recebendo sua opinião de stdin. É assim que se faz em Perl. (Talvez ele tenha mudado após o seu comentário?)
Frank
@P Daddy: resmungue, mas marque seu comentário com +1
Platinum Azure
30

Common Lisp 157 Chars

Nova versão mais conforme, agora lendo a entrada padrão do formulário e ignorando espaços e hifens:

(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)))

Em forma legível:

 (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)))

E alguns testes são executados:

>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.

E a versão bônus, em 165 caracteres:

 (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)))

Dando

>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.
user110763
fonte
5
Eu pensei que "vinte e quatro" só tem 10 letras?
kennytm
1
Os números depois de "é" também devem ser texto.
Mike DeSimone
5
por que isso é tão alto? outros não usam uma função de formato embutida e são menos caracteres
Claudiu
3
@Claudiu Porque Common Lisp é incrível.
Mornedhel
3
Não importa quantas tacadas você dê se não colocar a bola no buraco. As pessoas parecem esquecer disso quando votam em soluções incorretas.
Mark Peters
21

Python 2.x, 144 150 154 166 chars

Isso separa o número em dezenas e unidades e soma-os. A propriedade indesejável do operador pseudo-ternário a and b or cque cé retornado se bfor 0 está sendo abusada aqui.

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."

A versão ingênua anterior (150 caracteres). Apenas codifique todos os comprimentos como um inteiro.

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
fonte
Desculpe, eu queria pontos finais especificamente apenas por causa de coisas como esta. :-) Boa entrada embora! (EDIT: Eu não sei Python, mas você poderia n,"is",p,"."? Eu acho que você ainda economiza alguns caracteres se estou contando direito)
Platinum Azure
2
@Plat: Isso causaria um espaço extra antes de ..
kennytm
@KennyTM: Oh, duh, eu deveria ter notado isso até pelo snippet. Ops! Bem, de qualquer maneira, como eu disse, algumas das especificações foram projetadas especificamente para complicar um pouco as coisas. :-)
Platinum Azure
Podemos encurtar isso usando uma base maior do que 36?
MikeD
@MikeD: Não. Dos documentos do Python: "O parâmetro base fornece a base para a conversão (que é 10 por padrão) e pode ser qualquer número inteiro no intervalo [2, 36] ou zero." Agora você pode ser capaz de usar uma função diferente de int(), dizer algo fora dos módulos structou base64...
Mike DeSimone
20

C - com palavras numéricas

445 431 427 421 399 386 371 359 * 356 354 348 347 caracteres

É isso aí. Eu não acho que posso tornar isso mais curto.

Todas as novas linhas são legíveis e podem ser removidas:

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);}

Abaixo, está um pouco não reduzido, mas ainda muito difícil de ler. Veja abaixo uma versão mais legível.

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);
}

Expandido e comentado:

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"*/);
}

Sobre a string codificada perto do início

Os nomes dos números são compactados usando um esquema muito simples. Subcadeias de caracteres usadas com frequência são substituídas por índices de um caractere na matriz de nomes. Uma "tabela de pesquisa" de entradas de nomes extras é adicionada ao final para substrings não usadas em sua totalidade no primeiro conjunto. As pesquisas são recursivas: as entradas podem referir-se a outras entradas.

Por exemplo, o nome compactado para 11 é elM. A print()função produz os caracteres ee l('L' minúsculo, não o número '1') literalmente, mas depois encontra o M, então se chama com o índice da entrada 29 (ASCII 'M' - ASCII '0') na tabela de pesquisa. Essa string é evL, portanto, ela produz ee v, em seguida, chama a si mesma novamente com o índice da 28ª entrada na tabela de pesquisa, que é en, e é gerada literalmente. Isso é útil porque entambém é usado em eLpara een(usado após eightem eighteen), que é usado em tOpara teen(usado para todos os outros -teennomes).

Este esquema resulta em uma compressão bastante significativa dos nomes dos números, enquanto requer apenas uma pequena quantidade de código para descompactar.

As vírgulas no início e no final da string representam a maneira simplista como as substrings são encontradas nessa string. Adicionar dois caracteres aqui salva mais caracteres posteriormente.

Sobre o abuso de main()

argvé ignorado (e, portanto, não declarado na versão compactada), o valor de argc é ignorado, mas o armazenamento é reutilizado para conter o número atual. Isso apenas me salva de ter que declarar uma variável extra.

Sobre a falta de #include

Alguns reclamarão que omitir #include <stdio.h>é trapacear. Não é de todo. O dado é um programa C completamente legal que irá compilar corretamente em qualquer compilador C que eu conheço (embora com avisos). Na falta de protótipos para as funções stdio, o compilador assumirá que são funções cdecl retornando inte confiará que você sabe quais argumentos passar. Os valores de retorno são ignorados neste programa, de qualquer maneira, e são todas funções cdecl (convenção de chamada "C") e realmente sabemos quais argumentos passar.

Resultado

O resultado é o esperado:

0
zero é quatro.
quatro é mágico.
1
um é três.
três são cinco.
cinco são quatro.
quatro é mágico.
4
quatro é mágico.
20
vinte são seis.
seis são três.
três são cinco.
cinco são quatro.
quatro é mágico.
21
vinte e um são nove.
nove são quatro.
quatro é mágico.

* A versão anterior errou o alvo em duas partes da especificação: não manipulava zero e recebia entrada na linha de comando em vez de stdin. O tratamento de zeros adicionando caracteres, mas usando stdin em vez de argumentos de linha de comando, bem como algumas outras otimizações salvou o mesmo número de caracteres, resultando em uma lavagem.

Os requisitos foram alterados para deixar claro que a palavra numérica deve ser impressa em ambos os lados de "é". Esta nova versão atende a esse requisito e implementa mais algumas otimizações para (mais de) considerar o tamanho extra necessário.

P papai
fonte
Esta é facilmente a minha favorita das respostas de palavras ... Bravo, muito bem. +1 para você, e se eu pudesse dar duas marcas de seleção, eu o faria.
Platinum Azure
5
É divertido de ler, acho que vou usar esses números de agora em diante no dia a dia. Seis, sem, oito, nove, tel, elem, doze, enpee, fourpee, fifpee, sixpee, sevenpee, eightoh, ninepee, twelkyu ... =)
deceze
10

J, 107 112 caracteres

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

(Nova linha apenas para legibilidade)

Uso e saída:

    '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
fonte
15
Está compilado em chinês
Dr. belisarius
3
Escolha um árbitro não chinês
Dr. belisarius
3
@beli: 멩, 겻, 곋, 멩 são coreanos.
kennytm
1
Minha esposa (falante nativa de chinês) diz que é uma mistura de chinês e coreano.
Loren Pechtel
3
@belisarius: 1) Ela não sabe coreano. 2) O chinês é um jargão.
Loren Pechtel
10

T-SQL, 413 451 499 caracteres

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

(Não que eu esteja realmente sugerindo que você faça isso ... na verdade, eu só queria escrever um CTE)

Usar:

M 95

Devoluções

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
Leon Bambrick
fonte
Você não pode simplesmente imprimir os resultados individuais em vez de retornar uma tabela? Isso tornaria a saída mais agradável.
Joey
1
Eu não acho que ele lida com zero corretamente. Que tal algo assim: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 (com clichê), 308 290 286 282 280 caracteres

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");}}

Tenho certeza de que o Groovy se livraria de grande parte disso.

Explicação e formatação (todos os comentários, novas linhas e espaços em branco iniciais / finais removidos na contagem):

Razoavelmente direto, mas

//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");
   }
}

Editar: Não use mais hex, isso significa menos pressionamentos de tecla

Mark Peters
fonte
1
249 sem importações, def classe ou def principal.
Mark Peters
1
Isso é diabólico. Eu gosto da base 16. (+1)
Platinum Azure
Você pode economizar um espaço usando em String[]avez de String[] a.
BalusC de
Obrigado @Balus, também eliminou um monte fazendo aritmética simples no personagem em vez de usar a análise hexadecimal.
Mark Peters
@Mark Peters: Ainda mais desagradável. Eu me sinto tão baunilha em comparação com isso.
Platinum Azure
9

Windows PowerShell: 152 153 184 bytes

com base na solução anterior, com mais influência de outras soluções

$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.'
bom
fonte
Corrigido para suportar múltiplos de 10 ("noventa" em vez de "noventa zero").
Gabe
Ei @Gabe :), obrigado; não tenho tido muito tempo para jogar golfe ultimamente. Ainda assim, as aspas ao redor $inputprecisam permanecer, já que você não pode lançar um enumerador diretamente para int; funciona ao passar pela stringprimeira vez :-)
Joey
8

C, 158 caracteres

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.");}

(originalmente baseado no código Python de Vlad, peguei emprestado um truque da solução C ++ de Tom Sirgedas para espremer mais alguns caracteres)

versão expandida:

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
fonte
Não parece funcionar para mim: ./magic 10 10 é -27. Falha de segmentação
Casey
@Casey - a chamada scanf () foi um pouco incompleta. Ele estava lendo um int em um char. Eu estava fugindo com ele no OSX e no Windows funcionou, mas travou ao sair. Então, fiz n & c ints novamente. Percebi que poderia eliminar a palavra-chave int tornando-os parâmetros usando a notação K&R. O resultado é mais seguro e um caractere mais curto.
Ferruccio
Você pode salvar 3 caracteres substituindo " 466555766" [n / 10] + d [n% 10] -96 por d [n% 10] - " , +++) " [n / 10]
Tom Sirgedas
6

Python, 129 133 137 148 chars

Como aquecimento, aqui está minha primeira versão (melhora alguns caracteres em relação ao melhor Python anterior).

PS. Depois de algumas redações, agora é cerca de vinte caracteres mais curto:

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
fonte
6

C #: 210 caracteres.

Esmagado:

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));}}

Expandido:

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)
                   );
    }
}

Truques que essa abordagem usa:

  • Crie uma tabela de pesquisa para comprimentos de nome de número com base nos dígitos que aparecem no número.
  • Use a pesquisa de matriz de caracteres em uma string e aritmética char em vez de uma matriz numérica.
  • Use o apelido do nome da classe para abreviar Console.paraC.
  • Use o operador condicional (ternário) ( ?:) em vez de if/else.
  • Use o \ncom Writecódigo de escape em vez deWriteLine
  • Use o fato de que C # tem uma ordem definida de avaliação para permitir atribuições dentro da Writechamada de função
  • Use as expressões de atribuição para eliminar instruções extras e, portanto, colchetes extras
LBushkin
fonte
int[] zseria mais curto, pois não precisa donew[]
Joey
Revisado para usar aritmética de caracteres em vez de pesquisa de matriz.
LBushkin
@ mdm20: Você está certo. Eu tive um erro na tabela de pesquisa. Corrigido agora.
LBushkin
Bem, a décima segunda vez é o charme: * D
LBushkin
A quicky para salvar 5 caracteres: Menor do que lançando "magic"para object, seria implicitamente chamar ToString()em yadicionando "". Mas, porque +tem precedência maior do que ?:, você tem que colocá-lo na verdade parte em vez da falsa parte: x!=4?y+"":"magic".
P Daddy
6

Perl: 148 caracteres

(Perl: 233 181 212 206 200 199 198 185 179 149 148 caracteres)

  • Movido o hash de exceções para a matriz de unidade. Isso resultou na minha capacidade de cortar muitos caracteres :-)
  • mobrule apontou um bug desagradável. A solução rápida adiciona 31 caracteres, ouch!
  • Refatorado para zero caso especial, golfe moderado feito também.
  • Acesso direto à lista para uso único em vez de armazenamento na matriz? Claro que sim!
  • TANTO REFATORANTE para apenas UM personagem sangrento. Esta é, verdadeiramente, a vida de um jogador de golfe. :-(
  • Ops, fácil correção de espaço em branco. 198 agora.
  • Refatorou algum código redundante.
  • A última palavra-chave de retorno em ré desnecessária, cortou um pouco mais.
  • Refatoração massiva por comentários; infelizmente, só consegui chegar a 149 porque tive que consertar um bug que estava presente em meu código anterior e nas versões dos comentadores.
  • Tentando "mágica" de palavras nuas.

Vamos fazer a bola rolar com uma tentativa modesta em Perl.

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

Truques:

Muitos!

Platinum Azure
fonte
ACK! Como nunca testei isso nunca saberei.
Platinum Azure
Você tem algum código morto aí? Não estou vendo como o caso especial para zero é necessário quando $ u [0] é 4. Eu tenho uma versão aparentemente funcional do seu código @ 166 caracteres e acho que tem espaço para ficar um pouco mais curto do que isso.
hobbs
@hobbs: Bom ponto, vou olhar novamente. A história é que eu passei pela metade de algumas revisões e de repente as coisas quebraram (mais ou menos no ponto em que escolhi 4 -> 0). Mas acho que você está certo neste ponto :-)
Platinum Azure
Não me considero um grande programador Perl, mas você pode reduzir alguns caracteres: @u=split$x,'43350435543668877988';suas vírgulas usam 19 caracteres desnecessários, dividindo- undefse em divisões a cada caractere, eu uso $xcomo uma variável indefinida para tomar o lugar de `undef` - total economia: 11 caracteres. Além disso, remova o mem chompe você terá um outro personagem rapou a sua pontuação.
vol7ron
Fazendo melhor, mas você ainda pode economizar mais perdendo sub rtotalmente - você só usa isso uma vez e pode substituir tudo por um único ternário aninhado sem parênteses. Minha versão agora é 144 caracteres: gist.github.com/473289
hobbs
5

JavaScript 1.8 (SpiderMonkey) - 153 caracteres

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.')

Uso: echo 42 | js golf.js

Resultado:

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

Com bônus - 364 caracteres

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.')

Resultado:

noventa e nove são dez.
dez são três.
três são cinco.
cinco são quatro.
quatro é mágico.
gnarf
fonte
4

Haskell, 224 270 caracteres

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

E um pouco mais legível -

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
fonte
4

Versão C ++ Stdio, reduzida: 196 caracteres

#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");}

Versão C ++ Iostreams, reduzida: 195 caracteres

#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, sem redução: 344 caracteres

#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
fonte
Fixo. Também ficou um pouco mais curto.
Mike DeSimone
Bem feito. (Eu ri muito do enigma do padrão de 20 caracteres!)
Platinum Azure
Sim, aquele era um headbanger real, até que me ocorreu que #defineseria ainda mais curto, pois poderia substituir vários tokens.
Mike DeSimone
printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Não apenas mais curto, mas também mais rápido.
Ben Voigt
2
@Mike DeSimone: Acho que while(p!=4)poderia ser abreviado para while(p-4). Um personagem inteiro, eu sei, mas ainda assim. :-)
Platinum Azure
3

Delphi: 329 caracteres

Versão de linha única:

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.

Formado:

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.

Provavelmente espaço para mais apertos ... :-P

Jørn E. Angeltveit
fonte
3

C # 314 286 283 274 289 273 252 chars.

Esmagado:

252 

Normal:

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();
    }
}

Editar Dykam: Fez algumas inserções e alterações cuidadosas:

  • Alterou o l.ToString () em uma conversão objectde string "magic".
  • Criei uma variável temporária o, para que pudesse mover para breakfora do forloop, ou seja, resultando em a do-while.
  • Informei a oatribuição, assim como a vatribuição, continuando a inserir o cálculo de lnos argumentos da função por completo, eliminando a necessidade de l. Também incluiu a atribuição de m.
  • Removido um espaço em int[] x, também int[]xé legítimo.
  • Tentei transformar o array em uma transformação de string, mas using System.Linqera demais para fazer disso uma melhoria.

Editar 2 Dykam Alterado o array int para um array / string char, adicionado aritmia apropriada para corrigir isso.

mdm20
fonte
Sim, ficou mais curto do que a versão Java.
Dykam
3

Lua, 176 caracteres

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
fonte
3

C - sem palavras numéricas

180 175 * 172 167 caracteres

Todas as novas linhas são legíveis e podem ser removidas:

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.");}

Ligeiramente reduzido:

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.");
}

* A versão anterior errou o alvo em duas partes da especificação: não manipulava zero e recebia entrada na linha de comando em vez de stdin. Lidar com zero caracteres adicionados, mas usar stdin em vez de argumentos de linha de comando economizou ainda mais, resultando em uma economia líquida.

P papai
fonte
2

perl, 123 122 caracteres

Acabei de perceber que não há requisitos para a saída em STDOUT, então a saída em STDERR em vez disso e eliminar outro caractere.

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

E, uma versão que retorna números detalhados:

279 278 276 280 caracteres

@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/

Embora atenda às especificações, não está 100% bem formatado. Ele retorna um espaço extra após os números que terminam em zero. A especificação diz:

"Eu não me importo como você separa os tokens de palavras, embora eles devam ser separados"

Isso é uma espécie de doninha. Uma versão mais correta em

282 281 279 283 caracteres

@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
fonte
1

Pitão:

#!/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
fonte
4
Eu gosto disso. Você provavelmente poderia apertar um pouco embora.
Josh K
@Vlad: a entrada deve ser lida a partir de stdin ao invés dos argumentos. Isso significa que você pode apenas usar N = input()(ou raw_input()) e eliminar as syscoisas.
kennytm
Além disso, você poderia fazer com que as pequenas incluíssem adolescentes, então a instrução if seria apenas "if n <20: return Smalls [n]". Smalls ainda funcionaria para o caso> = 20, por causa do módulo em 10.
Jon Smock
5
Esta deve ser a primeira vez que vejo (totalmente opcional) she-bangem uma resposta de código de golfe ;-)
ChristopheD
Parece um bom começo ... Definitivamente aperte-o, mesmo Python não precisa de TODOS esses espaços em branco. :-) Além disso, como Ferruccio aponta, 0 não funciona, especificamente parece entrar em um loop infinito.
Platinum Azure
1

C ++, 171 caracteres (#include omitido)

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
fonte
Eu acho que se você considerar isso como C, você pode evitar a necessidade de #includeporque as funções serão apenas assumidas para receber intparâmetros. Você pode até salvar um traço fazendo o mainretorno int.
Gabe
1

Ruby, 164 caracteres

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."

decodificado:

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
fonte
Boa solução Ruby, mantendo-o simples. :-) (+1)
Platinum Azure
Manter as coisas simples não é desculpa para mantê-las excessivamente longas ;-)
Joey
Acho que você pode substituir 'if n == 0' por 'if! N'
Vincent
2
Em Ruby? Sempre pensei que todos os valores, exceto falso e nulo, avaliados como verdadeiros :-(
Platinum Azure
1

Lua 185 190 199

pontos adicionados, adicionado io.read, removido () na última impressão

 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.'

com quebras de linha

 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
fonte
Precisa de um n=io.read()(+11 caracteres) para cumprir a regra de leitura do número da entrada padrão. Mudar print('4 is magic.')para print'4 is magic.'salvará 2 caracteres. Remover ;depois )salvará 1 caractere. O printuso de vírgulas parece trapaça, mas as especificações não são claras. Pode muito bem mudar para print(n,'is',m,'.')para salvar 2 caracteres.
gwell
As vírgulas renderizadas como novas linhas em Lua são independentes? Já faz um tempo desde que eu usei.
Nick Van Brunt
As vírgulas são renderizadas como guias.
gwell
0

Código 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);  
}  

//////////// testing //////////////////

 $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';
    }

////// Resultados /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
Desenvolvedor
fonte
4
@wallacoloo: Uma solução mesquinha para uma linguagem mesquinha: D
Thomas Eding
5
Ou um número muito menor de 178 caracteres:$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
Boa piada. :-D Tão bem programado.
Tom Pažourek
0

Perl - 130 caracteres


5.12.1 (130 caracteres) 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 caracteres) 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/


Histórico de mudanças:

20100714:2223- reverti a mudança com a atenção do mobrule , mas ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), que é o mesmo # de caracteres, mas fiz isso no caso de alguém ver uma maneira de melhorar

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ removeu parênteses desnecessários
20100713:xxxx- $=<>;chop;$_=pop;- cortesia para mobrule


Nota: Eu estava cansado de melhorar as respostas dos outros nos comentários, então agora estou sendo ganancioso e posso apenas adicionar minhas alterações aqui :) Esta é uma divisão da resposta do Platinum Azure - crédito em parte para Hobbs , mobrule e Platinum Azure .

vol7ron
fonte
Quando você se livrou da $_%10&&...construção, quebrou a especificação das entradas 20,30,40, ...
mob
+1 Muito bem feito. Você saiu do stdin para o args :-(
Platinum Azure
Certo, substituído por ARGV, que é preenchido por STDIN:) ou .. echo bar | xargs perl foo.pl, tecnicamente canalizado de echo para args para perl :)
vol7ron
0

Shameless Perl com palavras numéricas (329 caracteres)

Adaptado diretamente do código C de P Daddy, com alguns ajustes para p()fazê-lo fazer a mesma coisa usando primitivos Perl em vez de C, e um mainloop quase reescrito. Veja a explicação dele. As novas linhas são opcionais.

@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

Nota lateral: é uma pena que o perl printapenas retorne verdadeiro / falso; se retornasse uma contagem, economizaria 7 golpes.

hobbs
fonte
0

Ruby, 141 caracteres:

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
fonte
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
user368038
fonte