Calculadora de numerologia


19

O objetivo desse desafio é calcular um tipo de dígito de numerologia a partir de strings contendo caracteres e números.

  • A entrada pode ser feita por qualquer método conveniente (entrada padrão, argumentos, arquivo separado).
  • A entrada pode conter quaisquer caracteres ASCII imprimível, mas apenas alfanumérico ( A-Z, a-z, e 0-9) têm de ser considerados.
  • A saída deve ser um dígito entre 1e 9ou uma estrela *se nenhuma letra e nenhum dígito foram encontrados ... (ou mesmo 0se a entrada contiver qualquer número 0 e nada mais, mas isso não importa).
  • Os valores das letras são mapeados desta maneira:

    1  2  3  4  5  6  7  8  9
    a  b  c  d  e  f  g  h  i
    j  k  l  m  n  o  p  q  r
    s  t  u  v  w  x  y  z
    
  • O dígito da numerologia é calculado adicionando cada valor da sequência e repita até que haja apenas um dígito. Amostra para 13579, Hello, world!, 00 0 00, !@#$%^&*();, e 3.141592:

    13579 => 1 + 3 + 5 + 7 + 9 = 25 => 2 + 5 = 7
    Hello, world! => 8 + 5 + 3 + 3 + 6 + 5 + 6 + 9 + 3 + 4 = 52 => 5 + 2 = 7
    00 0 00 => 0 + 0 + 0 + 0 + 0 = 0
    !@#$%^&*(); => *
      => *
    3.141592 => 3 + 1 + 4 + 1 + 5 + 9 + 2 = 25 => 2 + 5 = 7
    3.1415926535897932384 => 
     3 + 1 + 4 + 1 + 5 + 9 + 2 + 6 + 5 + 3 + 5 + 8 + 9 + 7 + 9 + 3 + 2 + 3 + 8 + 4
     = 97 => 9 + 7 = 16 => 1 + 6 = 7
    

    (Isso é ótimo, a maioria dessas amostras dá 7! Mas é apenas amostra;)

    Mais alguns testes:

    Bob  => 2 + 6 + 2 = 10 => 1 + 0 = 1
    Charlie => 3 + 8 + 1 + 9 + 3 + 9 + 5 = 38 => 3 + 8 = 11 => 1 + 1 = 2
    Anna => 1 + 5 + 5 + 1 = 12 => 1 + 2 = 3
    Fana => 6 + 1 + 5 + 1 = 13 => 1 + 3 = 4
    Gregory => 7 + 9 + 5 + 7 + 6 + 9 + 7 = 50 => 5 + 0 = 5
    Denis => 4 + 5 + 5 + 9 + 1 = 24 => 2 + 4 = 6
    Erik => 5 + 9 + 9 + 2 = 25 => 2 + 5 = 7
    Helen => 8 + 5 + 3 + 5 + 5 = 26 => 2 + 6 = 8
    Izis => 9 + 8 + 9 + 1 = 27 => 2 + 7 = 9
    

Este é um , então a resposta mais curta em bytes vence.

Menor por idioma


0 desaparecerá quando adicionado a qualquer outra coisa
F. Hauri

0 não é relevante! A saída relevante está entre 1e 9!
F. Hauri

Você poderia adicionar alguns exemplos sem caracteres alfanuméricos?
ETHproductions

11
Quero dizer algo como !@#$%^&*(); algo que deve retornar *.
ETHproductions

Tem sido muito difícil resistir a citar isso em algumas discussões de análise técnica na área de Money ...
;-p

Respostas:


6

Matlab, 121 bytes

s=[input('','s'),'*'];while nnz(s)>1;s=num2str(sum(mod([s(48<s&s<58)-4,s(96<s&s<123)+2,s(64<s&s<91)-2],9)+1));end;disp(s)

O Matlab não é feito apenas para strings = (


3
Ei, pelo menos não é tão detalhado quanto o Mma: P
LegionMammal978

meu +1, eu não poderia fazer melhor. btw, é necessário colocar dispdeclaração?
brainkz

@brainkz Talvez, mas eu normalmente incude-lo para estar no lado seguro
flawr

3

Mathematica, 174 168 163 bytes

Catch[#-9Floor[Max[#-1,1]/9]&@If[(a=Tr[Characters@#/.{(b=a_String)?DigitQ:>FromDigits@a,b?LetterQ:>LetterNumber@a~Mod~9,b->0}])<1&&#~StringFreeQ~"0",Throw@"*",a]]&

Executa o primeiro passo e depois calcula a raiz digital.


3

Ruby, 97 74 caracteres

n=->s{(t=eval s.tr('a-z9A-Z','1-9'*6).scan(/\d/)*?+)&&t>9?n[t.to_s]:t||?*}

Exemplo de execução:

2.1.5 :001 > n=->s{(t=eval s.tr('a-z9A-Z','1-9'*6).scan(/\d/)*?+)&&t>9?n[t.to_s]:t||?*}
 => #<Proc:0x00000001b4b3f0@(irb):4 (lambda)> 

2.1.5 :002 > puts ['13579', 'Hello, world!', '00 0 00', '!@#$%^&*();', ' ', '3.141592', '3.1415926535897932384', 'Bob', 'Charlie', 'Anna', 'Izis'].map{|s|'%s : %s'%[n[s],s]}
7 : 13579
7 : Hello, world!
0 : 00 0 00
* : !@#$%^&*();
* :  
7 : 3.141592
7 : 3.1415926535897932384
1 : Bob
2 : Charlie
3 : Anna
9 : Izis

3

Perl, 91 89 76 74 bytes

73 + 1 para -p switch

s/[a-z]/(ord($&)%32-1)%9+1/eig;$t="*",s/\d/$t+=$&/eg,$_=$t until/^[*\d]$/

Testes

for test in '13579' 'Hello, world!' '00 0 00' '!@#$%^&*();' ' ' \
    '3.141592' '3.1415926535897932384' \
    Bob Charlie Anna Fana Gregory Denis Erik Helen Izis ;do  
    perl -pe '
      s/[a-z]/(ord($&)%32-1)%9+1/eig;$t="*",s/\d/$t+=$&/eg,$_=$t until/^[*\d]$/
      ' < <(echo -n "$test")
    echo "  $test"
done
7  13579
7  Hello, world!
0  00 0 00
*  !@#$%^&*();
*   
7  3.141592
7  3.1415926535897932384
1  Bob
2  Charlie
3  Anna
4  Fana
5  Gregory
6  Denis
7  Erik
8  Helen
9  Izis

Obrigado @manatwork por me ajudar a economizar 2 14 16 15 17 caracteres !!

... Eu pensei sobre: N % 32 + Ypode substituir( N & 31 ) + Y !


11
Se você capturar toda a substring correspondente, $1é igual a $&. Portanto, remova melhor a captura e altere o nome da variável.
manatwork

11
whilebloco pode ser $t="*";s/\d/$t+=$&/eg;$_=$t.
manatwork

11
Desculpe, mas na verdade é 1 caractere a mais, pois você deve incluir a -popção na contagem.
manatwork

11
Desculpe novamente (desta vez, sinto muito mais), mas falha na entrada de um caractere que não seja uma palavra, por exemplo "!" Resulta da mesma forma "!". ( Parece funcionar porque, com a cadeia de caracteres here, a entrada é sempre passada com uma nova linha à direita, portanto, nos seus casos de teste, nunca passa uma entrada de caractere único. Use echo -n "$test" | perl -pe '…'para ver o que quero dizer.) Você pode resolvê-lo alterando a whilecondição para !/^[\d*]$/. Enquanto estava lá, para reduzir a perda de pontuação, você pode substituir o todo whilecom este: $t="*",s/\d/$t+=$&/eg,$_=$t until/^[\d*]$/.
manatwork

11
Há mais uma melhoria que você pode fazer. Como &tem precedência mais baixa do que +, enquanto %tem maior, altere &31%32e você pode remover os parênteses em torno dessa subexpressão.
manatwork

3

ES6, 98 bytes

s=>(m=s.match(/[1-9a-z]/gi))?(t=8,m.map(c=>t+=c>'@'?c.charCodeAt()&31:+c),t%9+1):/0/.test(s)?0:'*'

Ungolfed:

function(s) {
    var m = s.match(/[1-9a-z]/gi);
    if (m) {
        var t = 0;
        for (var i = 0; i < m.length; i++) {
            if (m[i] > '@')
                t += m[i].charCodeAt(0) & 31;
            else
                t += parseInt(m[i]);
        }
        return t % 9 || 9;
    }
    return /0/.test(s) ? 0 : "*";
}

Versão de 94 bytes que funciona apenas em cadeias curtas:

s=>(m=s.match(/[1-9a-z]/gi))?m.map(c=>c>'@'?c.charCodeAt()&31:c).join``%9||9:/0/.test(s)?0:'*'

Usando match, mape joinacabou por ser mais curto do que usar replaceduas vezes:

s=>(m=s.replace(/[^1-9a-z]/gi,''))?m.replace(/[a-z]/gi,c=>c.charCodeAt()&31)%9||9:/0/.test(s)?0:'*'

Teste aqui: https://jsbin.com/zizosayisi/edit?js,console


Isso não funciona para a entrada00 0 00
rink.attendant.6

@ rink.attendant.6 Ah, o REPL que eu estava usando apenas imprime ["0"], 0para não saber a diferença.
Neil

Muito, muito melhor que a versão @ rink.attendant.6! Hacks de golfe inteligentes usados. Você poderia explicar > '@', & 31e || 9?
Pavlo

11
@ Pavlo > '@'apenas distingue entre letras e números. & 31é uma maneira útil de ignorar a diferença entre códigos de caracteres maiúsculos e minúsculos, pois também mapeia diretamente os códigos de caracteres em valores de 1 a 26. || 9é usado porque % 9retorna 0 para múltiplos de 9, mas a adição repetida de dígitos retorna 9 para múltiplos diferentes de zero de 9. No código de golfe, eu uso o (t + 8) % 9 + 1que vem à mesma coisa.
Neil

O idioma é geralmente chamado de "JavaScript (ES6)"
edc65 27/12/2015

2

Gema, 161 caracteres

*=@n{*}
n:\A=@set{t;};<L1>=@set{t;@add{$t;@add{@mod{@sub{@mod{@char-int{$0};32};1};9};1}}};<D1>=@set{t;@add{$t;$0}};?=;\Z=@cmps{$t;;;\*;@cmpn{$t;9;$t;$t;@n{$t}}}

(Escrito apenas para tentar se as chamadas de domínio recursivas funcionam.)

Exemplo de execução:

bash-4.3$ for input in '13579' 'Hello, world!' '00 0 00' '!@#$%^&*();' ' ' '3.141592' '3.1415926535897932384'; do
>     echo -n "'$input' : "
>     gema '*=@n{*};n:\A=@set{t;};<L1>=@set{t;@add{$t;@add{@mod{@sub{@mod{@char-int{$0};32};1};9};1}}};<D1>=@set{t;@add{$t;$0}};?=;\Z=@cmps{$t;;;\*;@cmpn{$t;9;$t;$t;@n{$t}}}' <<< "$input"
>     echo
> done
'13579' : 7
'Hello, world!' : 7
'00 0 00' : 0
'!@#$%^&*();' : *
' ' : *
'3.141592' : 7
'3.1415926535897932384' : 7

1

JavaScript (ES6), 162 159 157 bytes

f=_=>{for(_=_.replace(/\W+/g,''),g=$=>''+[...$.toUpperCase()].reduce((p,a)=>isNaN(a)?p+(a.charCodeAt()-64)%9:+a+p,0);1<(l=_.length);_=g(_));return!l?'*':g(_)}

Ainda tentando procurar uma maneira de usar retorno implícito na função externa.

Ungolfed + unminified

f = str => {
  str = str.replace(/\W+/g, '');
  recursiveFunc = $ => String([...$.toUpperCase()].reduce(
    (prev, val) => isNaN(val) ? prev + (val.charCodeAt() - 64) % 9 : Number(val) + prev,
    0
  ));
  while (1 < (len = str.length)) {
    str = recursiveFunc(str);
  }
  return len === 0 ? '*' : recursiveFunc(str)
}
  1. Retira todos os caracteres não alfanuméricos
  2. Chama uma função recursivamente para reduzir os caracteres para seus respectivos valores enquanto a cadeia tem mais de 1 caractere.
    1. Converte a string em maiúscula para trabalhar facilmente com códigos ASCII
    2. Converta em array usando o operador spread e execute um acumulador
    3. Use a isNaNfunção global (que lança sua entrada) para verificar se não é um número
      • Caso contrário, converta para o código ASCII e mod 9 para obter seu respectivo valor
      • Se for um número, transmita-o
  3. Se o comprimento for 0, nenhum caractere alfanumérico estava presente (retorne um asterisco); caso contrário, retorne a saída da função recursiva.

Esta regra de quebra 00 0 00, produz em *vez de 0!
F. Hauri

@ F.Hauri Fixed.
rink.attendant.6

Você pode evitar o retorno explícito usando o operador comman: _=>{expr;return expr}=>_=>(expr,expr)
Pavlo

@ Pavo Como aplico isso no meu caso?
rink.attendant.6

Não funciona para mim, lança SyntaxError: jsbin.com/havotusoqa/1/edit?js,console
Pavlo

1

Haskell, 126 bytes

l x=[n|(c,n)<-zip(['0'..'9']++['a'..'z']++'\0':['A'..'Z'])$0:cycle[1..9],c==x]
g[]="*"
g[x]=show x
g x=f$show$sum x
f=g.(l=<<)

Uso: f "Hello, world!"-> "7".

lé uma tabela de pesquisa para caracteres na lista de números inteiros (lista singleton, se char for encontrado, lista vazia caso contrário). fpesquisa cada caractere do argumento e torna a lista de listas retornada em uma lista simples de números inteiros e chamadas gpara verificar a condição final (lista vazia (-> *) ou inteiro único) ou para chamar fcom a soma da lista para outra rodada.


1

MATL , 64 bytes

jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']

Isso usa a versão atual (4.0.0) do idioma.

Tenho a sensação de que poderia ser reduzido ...

Casos de teste

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> 13579
7

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> Hello, world!
7

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> 00 0 00
0

>> matl 
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> !@#$%^&*();
*

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> 3.141592
7

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> 3.1415926535897932384
7

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> Bob
1

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> Charlie
2

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> Anna
3

>> matl
 > jk42ht`YUt'[a-z]'XXY}3+w'[1-9]'XXY}6+h,9X\st9>]w2Y24Y2h!=~?x'*']
 > 
> Izis
9

Infelizmente, não pude testar sua amostra. Poste casos de teste completos, incluindo testes adicionados recentemente (desculpe).
F. Hauri

@ F.Hauri Sim, você precisaria do Matlab para testá-los. Desculpe por isso, nenhum compilador online ainda. Eu adicionei os casos de teste
Luis Mendo

1

Sério, 50 bytes

,$ù;ú1╤▀+;#pX╗@-@-;Y`'*.`╬X1WX`╜í;s9*@%u`MΣ$;lDWX

Hex Dump:

2c24973ba331d1df2b3b237058bb402d402d3b5960272a2e7f
60ce5831575860bda13b73392a402575604de4243b6c445758

Experimente Online

Explicado:

,$ù                                               Read input, make it a string, lowercase
    ú                                             Push lowercase alphabet
     1╤▀+                                         Prepend base 10 digits.
         ;#pX╗                                    Remove "0" from a copy and stash in reg0
   ;          @-                                  Remove alphanumerics from input copy
                @-                                Remove nonalphanumerics from input
                  ;Y                              Push 1 if string is empty, else 0
                    `'*.`╬                        If top is truthy, output * and halt
                          X                       Discard boolean
                           1                      Push 1 to enter loop
                            WX                 WX Loop while top of stack is truthy
                              `         `M        Map this function over the string
                               ╜                  Push alphanumeric string from reg0
                                í                 Push index of this char in it
                                 ;s9*             Push 9 if found, else -9
                                     @%u          Take index mod previous: this yields the
                                                  correct conversion from the numerology
                                          Σ       Sum the resulting digits.
                                           $      Convert the sum to a string.
                                            ;lD   push 1 less than its length

@ F.Hauri Clique em "Experimente Online". insira seus casos de teste na caixa de entrada.
quintopia 27/12/15

1

Pitão, 39 bytes

IK@J+jkUTGrz0WtK=K`smh%xtJd9-K\0)K).?\*

Experimente Online

Só estou fazendo isso porque não consigo dormir. Talvez eu explique amanhã ...


1

Pure bash, 199 194 bytes

eval a+={a..z};r="$1";while [ "${r:1}" ];do o=;for ((i=0;i<${#r};i++));do
l=${r:i:1};case $l in [a-zA-Z])d=${a%${l,}*};((o+=$((${#d}%9+1))));;[0-9])
((o+=l));;esac;done;r="$o";done;echo "${o:-*}"

(a quebra de segunda linha é apenas para evitar a barra de rolagem)

Regra de teste:

numerology() {
    eval a+={a..z};
    r="$1";
    while [ "${r:1}" ]; do
        o=;
        for ((i=0; i<${#r}; i++))
        do
            l=${r:i:1};
            case $l in 
                [a-zA-Z])
                    d=${a%${l,}*};
                    ((o+=$((${#d}%9+1))))
                ;;
                [0-9])
                    ((o+=l))
                ;;
            esac;
        done;
        r="$o";
    done;
    echo "${o:-*}"
}

for test in '13579' 'Hello, world!' '00 0 00' '!@#$%^&*();' ' ' \
            '3.141592' '3.1415926535897932384'\
            Bob Charlie Anna Fana Gregory Denis Erik Helen Izis ;do
    echo "$(numerology "$test")" $test
done
7 13579
7 Hello, world!
0 00 0 00
* !@#$%^&*();
*
7 3.141592
7 3.1415926535897932384
1 Bob
2 Charlie
3 Anna
4 Fana
5 Gregory
6 Denis
7 Erik
8 Helen
9 Izis

1

JavaScript (ES6), 78 83

Solução recursiva. Sendo recursão da cauda, ​​as variáveis ​​t e r não devem ser locais.

f=x=>(t=r=0,x.replace(/\w/g,d=>t+=1+~-parseInt(d,r=36)%9),t>9?f(''+t):r?t:'*')

Explicado

f=x=>(
  t = 0, // set initial value of counter to 0 
  r = 0, // flag to verify that we found at last one alphanumeric chars
  x.replace(/\w/g, d => ( // execute the following for each alphanumeric character
    // t += 1 + ~-parseInt(d,r=36) % 9 explained below
    r = 36, // set flag, could be any nonzero value
    d = parseInt(d,36), // convert to numeric. a..z -> 10..25, case insensitive.
    d = 1 + (d-1) % 9, // this is the arithmetic conversion required (
                       // works also with 0 because the strange implementation of % in javascript for negative numbers
    t = t + d // add to global counter
  ) ), 
  t > 9 // if t > 9 then we found some alphanumeric char, but we must repeat the loop on t
    ? f(''+t) // recursive call, t is numeric and must become a string
    : r // check flag r 
      ? t // if alphanumeric found, return t 
      : '*' // else return '*'
)

Snippet de teste

f=x=>(t=r=0,x.replace(/\w/g,d=>t+=1+~-parseInt(d,r=36)%9),t>9?f(''+t):r?t:'*')

console.log=x=>O.textContent+=x+'\n';

;[['13579',7],['Hello, world!',7],['00 0 00',0],['!@#$%^&*();','*'],
['3.141592',7],['3.1415926535897932384',7],
['Bob', 1],['Charlie', 2],['Anna', 3],['Fana', 4],['Gregory', 5],
['Denis', 6],['Erik', 7],['Helen', 8],['Izis', 9]]
.forEach(t=>{
  i=t[0]+''
  k=t[1]
  r=f(i)
  console.log(i+' -> ' + r + (k==r? ' OK':' Fail - expected '+k))
  })
<pre id=O></pre>


0

Python, 154 bytes

def A(S):
 D=lambda x:int(x)if x.isdigit()else (ord(x.lower())-6)%9
 while len(S)>1:S=str(sum([D(c)for c in S if c.isalnum()]))
 print S if int(S)else"*"

Este teste falhou com 00 0 00!
F. Hauri

0

Mathematica, 133 bytes

f[s_]:= ToCharacterCode@ToUpperCase@s-64/.{a_/;17>-a>6:>a+16,b_/;b<1||b>26:>""}//If[Or@@NumberQ/@#,Tr@#/.""->0//.a_:>Tr@IntegerDigits@a,"*"]&

Um pouco diferente do LegionMammal978 acima. Minha função transforma tudo em um código de caractere e filtra as coisas não alfanuméricas (substituindo-as por seqüências de caracteres vazias). Se não houver alfanuméricos, ele retornará *, caso contrário, será a raiz digital. Isso poderia ser significativamente (~ 15B) mais curto se eu não tivesse que lidar com o caso com todas as zeros. É a vida.

Magia Mathematica, para os não iniciados: foo//.a_:>Tr@IntegerDigits@aé uma substituição repetida: substitui qualquer númeroa em foo pela soma de seus dígitos, depois substitui novamente até atingir um ponto fixo, ou seja, apara de mudar sob substituição.

Testes:

f /@ {"13579", "Hello,world!", "00 0 00", "!@#$%^&*()", "3.141592","3.1415926535897932384"}
     => {7, 7, 0, "*", 7, 7}
f /@ {"Bob", "Charlie", "Anna", "Fana", "Gregory", "Denis", "Erik",  "Helen", "Izis"}
     => {1, 2, 3, 4, 5, 6, 7, 8, 9}

Infelizmente, não pude testar sua amostra. Poste casos de teste
F. Hauri

No meu caminho. Ao montar os testes, também encontrei alguns erros de digitação para corrigir. Obrigado;)
hYPotenuser
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.