Distância para quatro

13

Este desafio é baseado neste vídeo . Eu recomendo que você assista antes de tentar este desafio.

Primeiro, definimos uma função. Esta função ( OEIS ) recebe um número inteiro n como entrada e gera o número de letras na representação em inglês de n (sem espaços ou hífens). Por exemplo, "três" tem 5 letras, portanto, 3 mapeia para 5.

Conforme demonstrado no vídeo, iniciando com qualquer número que se repita, esse processo resultará em quatro, que serão mapeados para si mesmos para sempre.

Aqui está um gráfico direcionado bruto mostrando as órbitas dos números menores que 16:

  12 11
    \|      
15 2 6 1 10 14 13
  \ \|/ /  /  /
   7 3-/  8--/
    \|   /
 9 0 5--/
  \ \|
   \-4

Seu desafio é determinar o número de etapas que um número executará (ou o número de vezes que essa função deve ser aplicada a um número) antes de atingir quatro (ou seja, o nível no gráfico direcionado na foto).

Formando números em inglês

Aqui está uma breve explicação de como se deve formar palavras em inglês para este desafio:

Os números de um a dezenove são:

um, dois, três, quatro, cinco, seis, sete, oito, nove, dez, onze, doze, treze, quatorze, quinze, dezesseis, dezessete, dezoito, dezenove

Para números maiores que dezenove, o processo é o seguinte:

Se o número tiver centenas, comece com o nome do dígito na casa das centenas e "cem".

por exemplo

100 -> "onehundred"

Se o restante for menor que vinte, acrescente a representação em inglês do restante.

por exemplo

714 -> "sevenhundredfourteen"

Caso contrário, se o dígito das dezenas não for zero, acrescente a representação adequada:

2-> twenty
3-> thirty
4-> forty
5-> fifty
6-> sixty
7-> seventy
8-> eighty
9-> ninety

por exemplo

470 -> "fourhundredseventy"

Finalmente, se houver um dígito, acrescente sua representação

por exemplo

681 -> "sixhundredeightyone"

Outras estipulações

  • Para números maiores que cem, você deve deixar de lado o "e" ao contar o número de letras. Por exemplo, 577 é "quinhentos e sete até sete", que tem 23 letras.

  • Seu programa deve aceitar todos os números inteiros maiores que 0 e menores que 1.000 como entrada por métodos padrão.

  • Seu programa deve gerar o número de etapas necessárias para os métodos de saída padrão.

  • Este é um codegolf, e a solução com o menor número de bytes vence.

Casos de teste

1 -> 3
4 -> 0
7 -> 2
23 -> 5
577 -> 6
600 -> 4 
Post Rock Garf Hunter
fonte
1
Relacionada Eu pensei que este era um ingênuo, mas eu não posso encontrá-lo.
James
O que aconteceu com "e"? Ou melhor, por que deixar de fora e ?!
Jonathan Allan
@JonathanAllan cuz 'Murica
LegionMammal978

Respostas:

5

JavaScript (ES6), 106 bytes

f=(n,a="03354435543668877998")=>n-4&&1+f(7*(n>99)-(-a[n/100|0]-(a[n%=100]||a[n%10])-"0066555766"[n/10|0]))

As strings parecem ser a melhor maneira de codificar o comprimento, apesar da sobrecarga de conversão numérica.

Neil
fonte
Puxa, isso é quase exatamente o que minha resposta (quase postada) parecia, apenas 11 bytes mais curta.
ETHproductions 10/09/16
@ETHproductions Ainda bem que joguei 16 bytes antes de publicá-lo!
Neil
2

Python, com num2words, 97 113 115 94 93 92 bytes

+16 bytes (esqueceu o hifenação que num2words aplica-se que na verdade não alterar os resultados de qualquer um dos casos de teste, embora 23e 577cada um tem um hífen)
+2 bytes (esqueceu de incluir f=embora recursiva)
-20 bytes (uso re)
-8 bytes graças ao @Wheat Wizard (use ~, substitua n!=4por n-4e ... importação de uma linha> _ <)
-1 byte graças a @Cyoce (espaço de 4 and)

import re,num2words as w
f=lambda n:n-4and-~f(len(re.sub('\W|and','',w.num2words(n))))

Apenas conta o número de etapas; também funciona para números inteiros grandes e negativos ( \Wencontra os espaços, vírgulas e hífens no resultado num2words):

>>> for test in (1,4,7,23,577,600,-1*2**96,3**96):
...     print('test: {0}  ->  {1}'.format(test, f(test)))
...
test: 1  ->  3
test: 4  ->  0
test: 7  ->  2
test: 23  ->  5
test: 577  ->  6
test: 600  ->  4
test: -79228162514264337593543950336  ->  4
test: 6362685441135942358474828762538534230890216321  ->  5

Aqui está o último caso, passo a passo:

sixquattuordecillionthreehundredsixtytwotredecillionsixhundredeightyfiveduodecillionfourhundredfortyoneundecilliononehundredthirtyfivedecillionninehundredfortytwononillionthreehundredfiftyeightoctillionfourhundredseventyfourseptillioneighthundredtwentyeightsextillionsevenhundredsixtytwoquintillionfivehundredthirtyeightquadrillionfivehundredthirtyfourtrilliontwohundredthirtybillioneighthundredninetymilliontwohundredsixteenthousthreehundredtwentyone
fourhundredfiftyone
nineteen
eight
five
Jonathan Allan
fonte
1
Você não precisa de um f=antes de sua função lambda
post rock Garf Hunter
1
Tente em import re,num2words as rvez das duas declarações diferentes.
Post Rock Garf Hunter
1
n-4é a mesma coisa quen!=4
Post Rock Garf Hunter 10/09/16
1
@WheatWizard num2wordsé w, reainda é re- nota que tanto o módulo e função são chamadosnum2words
Jonathan Allan
1
Último Ok, and 1+pode ser substituído por and-~salvar um byte
post rock Garf Hunter
1

Pitão - 54 bytes

Tentará refatorar.

KjC"Y©åláóê¤"Ttl.u?<NyT@KNs+V@LKJ_jNT[Z@jC"Ckg"ThtJ7

Conjunto de Teste .

Maltysen
fonte
1

Mathematica, 89 bytes

Length@FixedPointList[StringLength@StringReplace[IntegerName@#,{" "->"","-"->""}]&,#]-2&

Mathematica típico: funções internas boas, nomes longos de funções ruins. FixedPointListaplica seu primeiro argumento (uma função) ao segundo argumento repetidamente até a resposta não mudar, listando todos os resultados; os resultados incluem a entrada original e duas cópias da saída repetida, daí a -2no final. O built-in do Mathematica IntegerNamecontém espaços e hífens, por isso precisamos nos livrar deles manualmente.

Irritantemente, IntegerNamea saída de contém o caractere "-" (Unicode # 8208) em vez de hífens normais; é por isso que esse envio é de 89 bytes em vez de 88. (E eu não poderia preceder o código acima com quatro espaços e aceitar o caractere Unicode - alguma ajuda? -, o código acima não funcionará exatamente se for recortado e colado .)

Greg Martin
fonte
1

Python 2.7, 344 216 208 bytes:

x=`input()`;c=0;y=lambda v:dict(zip(range(0,10),[0]+v));l=[3,3,5,4,4,3,5,5,4];d=y(l);e=y([3,6,6,6,5,5,7,7,6]);f=y([i+7for i in l])
while x!='4':x=`sum([q[int(r)]for q,r in zip([d,e,f],x[::-1])])`;c+=1
print c

Não usa bibliotecas externas, ao contrário de outras respostas do Python. Leva a entrada stdine a saída para stdout.

Repl.it com todos os casos de teste!

Explicação

Primeiro, cria 3 dicionários, cada um emparelhando o comprimento das representações da palavra em inglês de cada número com o número que representa no intervalo fechado, [1,9]no local unidades, dezenas e centenas, respectivamente. Por exemplo, a primeira entrada no dicionário dé 1:3como 1está escrita oneem inglês e tem 3letras.

Em seguida, cada local de dígitos em alguma entrada de sequência xé atribuído ao seu dicionário correspondente, após o qual cada número em cada local é correspondido com seu valor no dicionário correspondente. Por exemplo, suponha que o número de entrada seja 23. O local 20na casa das dezenas seria emparelhado com o dicionário e, no qual ele é correspondido 6, e o 3local na casa seria emparelhado com o dicionário d, no qual ele é correspondido 5. Esses dígitos correspondentes são então adicionados juntos para representar o comprimento da representação em inglês do número, que é atribuído xcomo uma string e, x!='4'enquanto o loop while continuar, incrementando cem1cada vez para representar o número de etapas realizadas até agora. Portanto, 23corresponderia a 11, o que por sua vez corresponderia a 6qual se voltaria para 3e depois para 5e finalmente para 4, resultando em 5etapas totais.

Finalmente, uma vez que o loop termina, a csaída é stdoutpara representar a "Distância para quatro", que nesse caso seria 5.

R. Kap
fonte
1

Java, 556 295 bytes

Obrigado a @KevinCruijssen por salvar 261 bytes

  void int(n) {int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,9,8,6,9,9,11,10,6,6,5,5,7,7,6};int c=0,t=(int)Math.pow(10,(int)Math.log10(n)),v=1;while(n>0){if(n/100>0)c+=(s[n/100]+7);else {if(n>0&n<25){c+=s[n];break;}else{c+=s[(n/10)+22];}}n=n%t;t=t/10;}while(c!=4){v++;c=s[c];}System.out.print(v);}


Ungolfed:

  void int(n) {

    int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,9,8,6,9,9,11,10,6,6,5,5,7,7,6};
     int c=0,t=(int)Math.pow(10,(int)Math.log10(n)),v=1;
         while(n>0){
            if(n/100>0)
                c+=(s[n/100]+7);
            else {if(n>0&n<25){
                c+=s[n];
            break;
            }
            else{
                c+=s[(n/10)+22];

            }
            }
            n=n%t;
            t=t/10;
        }

        while(c!=4)
        {
            v++;
        c=s[c];
        }
System.out.print(v);
}
Numberknot
fonte
Acho que você tem um erro no seu código, porque s++não é possível em uma corda-array ..: S
Kevin Cruijssen
@KevinCruijssen Declaro S (contador) como INT e STRING também .... o java automaticamente decide que é um INT.
Numberknot
Bem, se eu executar o código em ideone ou o meu Eclipse IDE falhar porque você tem dois s.. Btw, você pode golfe o seu código por uma quantidade bastante grande assim:int c(int n){int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8,6,9,9,11,10,6,5,5,5,7,6,6},c=0,t=(int)Math.pow(10,(int)Math.log10(n)),x=1;while(n>0)if(n/100>0)c+=s[n/100]+7;else{if(n>0&n<25){c+=s[n];break;}else c+=s[(n/10)+22];}n%=t;t/=10;}for(;c!=4;x++,c=s[c]);return x;}
Kevin Cruijssen
Estou chocado ...... o que aconteceu com o meu código e obrigado @ KevinCruijssen..e estou corrigindo ... Obrigado novamente.
Numberknot 12/09/16
Np :) Eu acho que pode ser jogado de alguma forma sem usar o if-else e entrar lá (mas deixarei isso para outra pessoa), mas seu código inicial foi uma excelente base para enfrentar o desafio, então +1 de mim.
Kevin Cruijssen