Calculadora de Numerología

19

El objetivo de este desafío es calcular un tipo de dígito de numerología a partir de cadenas que contienen caracteres y números.

  • La entrada puede ser a través de cualquier método conveniente (entrada estándar, argumentos, archivo separado).
  • La entrada puede contener cualquier caracteres ASCII imprimibles, pero sólo alfanumérico ( A-Z, a-zy 0-9) tiene que ser considerado.
  • La salida debe ser un dígito entre 1y / 9o una estrella *si no se encuentra ninguna letra y ningún dígito ... (o incluso 0si la entrada contiene cualquier número 0 y nada más, pero esto no importa).
  • Los valores de las letras se asignan de esta manera:

    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
    
  • El dígito de numerología se calcula sumando cada valor de cadena, luego repítelo hasta que solo haya un dígito. De la muestra para 13579, Hello, world!, 00 0 00, !@#$%^&*();, y 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
    

    (¡Esto es genial, la mayoría de estas muestras dan 7! Pero es solo una muestra;)

    Algunas pruebas más:

    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 es un , por lo que gana la respuesta más corta en bytes.

Más corto por idioma

F. Hauri
fuente
0 desaparecerá cuando se agregue a cualquier otra cosa
F. Hauri
¡0 no es relevante! La salida relevante es entre 1y 9!
F. Hauri
¿Podría agregar algunos ejemplos sin caracteres alfanuméricos?
ETHproductions
1
Me refiero a algo como !@#$%^&*(); algo que debe devolver *.
ETHproductions
Ha sido muy difícil resistirse a citar esto en algunas de las discusiones de análisis técnico sobre el área de Money ... ;-p
keshlam

Respuestas:

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)

Matlab simplemente no está hecho para cadenas = (

falla
fuente
3
Hola, al menos no es tan detallado como Mma: P
LegionMammal978
mi +1, no podría hacerlo mejor. por cierto, ¿es necesario poner dispdeclaración?
brainkz
@brainkz Quizás, pero por lo general considero que es seguro
falla
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]]&

Realiza el primer paso, luego calcula la raíz digital.

LegionMammal978
fuente
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||?*}

Ejecución de muestra:

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
hombre trabajando
fuente
3

Perl, 91 89 76 74 bytes

73 + 1 para -pinterruptor

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

Pruebas

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

¡Gracias @manatwork por ayudarme a ahorrar 2 14 16 15 17 caracteres!

... He pensado en: N % 32 + Ypuede reemplazar( N & 31 ) + Y !

F. Hauri
fuente
1
Si captura toda la subcadena coincidente, $1es igual a $&. Así que mejor elimine la captura y cambie el nombre de la variable.
manatwork
1
whileEl bloqueo podría ser $t="*";s/\d/$t+=$&/eg;$_=$t.
manatwork
1
Lo sentimos, pero en realidad es 1 carácter más, ya que debe incluir el -pinterruptor en el recuento.
manatwork
1
Lo siento de nuevo (esta vez lo siento más), pero falla en la entrada de caracteres sin palabras, por ejemplo, "!" Resulta igual "!". ( Parece funcionar porque con here-string la entrada siempre se pasa con una nueva línea final, por lo que en sus casos de prueba nunca pasa la entrada de un solo carácter. Use echo -n "$test" | perl -pe '…'para ver a qué me refiero). Puede resolverlo cambiando la whilecondición a !/^[\d*]$/. Una vez allí, para reducir la pérdida puntuación, es posible reemplazar la totalidad whilecon esto: $t="*",s/\d/$t+=$&/eg,$_=$t until/^[\d*]$/.
manatwork
1
Hay una mejora más que puedes hacer. Como &tiene una precedencia menor que +, mientras que %tiene mayor, cambie &31%32y puede eliminar los paréntesis alrededor de esa subexpresión.
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:'*'

Sin golf:

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

Versión de 94 bytes que solo funciona en cadenas cortas:

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, mapy joinresultó ser más corto que usar replacedos veces:

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

Pruébelo aquí: https://jsbin.com/zizosayisi/edit?js,console

Neil
fuente
Esto no funciona para la entrada00 0 00
rink.attendant.6
@ rink.attendant.6 Ah, el REPL que estaba usando solo imprime ["0"], 0así que no pude notar la diferencia.
Neil
¡Mucho, mucho mejor que la versión @ rink.attendant.6! Hacks inteligentes de golf utilizados. Podría explicar > '@', & 31y || 9?
Pavlo
1
@Pavlo > '@'solo distingue entre letras y números. & 31es una forma útil de ignorar la diferencia entre los códigos de caracteres en mayúsculas y minúsculas, ya que también asigna de forma conveniente los códigos de caracteres directamente en valores de 1..26. || 9se usa porque % 9devuelve 0 para múltiplos de 9, pero la adición repetida de dígitos devuelve 9 para múltiplos distintos de cero de 9. En el código de golf que uso, en (t + 8) % 9 + 1cambio, se trata de lo mismo.
Neil
El lenguaje se denomina comúnmente "JavaScript (ES6)"
edc65
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 solo para probar si las llamadas de dominio recursivo funcionan).

Ejecución de muestra:

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
hombre trabajando
fuente
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(_)}

Todavía trato de buscar una forma de utilizar el retorno implícito en la función externa.

Sin golf + sin minificar

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. Elimina todos los caracteres no alfanuméricos
  2. Llama a una función de forma recursiva para reducir los caracteres a sus valores respectivos mientras la cadena tiene más de 1 carácter.
    1. Convierte la cadena en mayúsculas para trabajar fácilmente con códigos ASCII
    2. Convierte a matriz usando el operador de propagación y ejecuta un acumulador
    3. Use la isNaNfunción global (que emite su entrada) para verificar si no es un número
      • Si no es así, conviértalo a código ASCII y mod 9 para obtener su valor respectivo
      • Si es un número, tíralo
  3. Si la longitud es 0, no hay caracteres alfanuméricos presentes (devuelve un asterisco); de lo contrario, devuelve la salida de la función recursiva.
rink.attendant.6
fuente
Esta regla de ruptura 00 0 00, salida en *lugar de 0!
F. Hauri
@ F.Hauri fijo.
rink.attendant.6
Puede evitar el retorno explícito utilizando el operador de comando: _=>{expr;return expr}=>_=>(expr,expr)
Pavlo
@Pavlo ¿Cómo lo aplico en mi caso?
rink.attendant.6
No funciona para mí, lanza 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".

les una tabla de búsqueda de caracteres para la lista de enteros (lista única, si se encuentra char, de lo contrario, la lista está vacía). fbusca cada carácter de su argumento y aplana la lista de listas devuelta en una lista simple de enteros y llamadas gpara verificar la condición final (lista vacía (-> *) o entero único) o para llamar fcon la suma de la lista para otra ronda.

nimi
fuente
1

MATL , 64 bytes

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

Esto usa la versión actual (4.0.0) del lenguaje.

Tengo la sensación de que podría acortarse ...

Casos de prueba

>> 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
Luis Mendo
fuente
Desafortunadamente, no pude analizar tu muestra. Publique casos de prueba completos, incluidas las pruebas agregadas recientemente (lo siento).
F. Hauri
@ F.Hauri Sí, necesitarías a Matlab para probarlos. Lo siento, todavía no hay compilador en línea. He agregado los casos de prueba
Luis Mendo
1

En serio, 50 bytes

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

Hex Dump:

2c24973ba331d1df2b3b237058bb402d402d3b5960272a2e7f
60ce5831575860bda13b73392a402575604de4243b6c445758

Pruébalo en línea

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
quintapia
fuente
@ F.Hauri Haga clic en "Pruébelo en línea". ingrese sus casos de prueba en el cuadro de entrada.
quintopia
1

Pyth, 39 bytes

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

Pruébalo en línea

Solo estoy haciendo esto porque no puedo dormir. Quizás lo explique mañana ...

quintapia
fuente
1

Golpe pura, 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:-*}"

(el segundo salto de línea es solo para evitar la barra de desplazamiento)

Regla de prueba:

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
F. Hauri
fuente
1

JavaScript (ES6), 78 83

Solución recursiva. Siendo la recursividad de la cola, las variables t y r no tienen que ser locales.

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

Fragmento de prueba

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>

edc65
fuente
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"*"
Kieran Hunt
fuente
Esta prueba fallida con 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,"*"]&

Un poco diferente de LegionMammal978 de arriba. Mi función convierte todo en un código de caracteres, luego filtra los elementos no alfanuméricos (reemplazándolos con cadenas vacías). Si no hay caracteres alfanuméricos, devuelve *, de lo contrario toma la raíz digital. Esto podría ser significativamente (~ 15B) más corto si no tuviera que lidiar con el caso de cadena de todos ceros. Así es la vida.

La magia de Mathematica, para los no iniciados: foo//.a_:>Tr@IntegerDigits@aes un reemplazo repetido: reemplaza cualquier número aen foo con la suma de sus dígitos, luego lo reemplaza nuevamente hasta que alcanza un punto fijo, es decir, adeja de cambiar bajo reemplazo.

Pruebas:

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}
hYPotenuser
fuente
Desafortunadamente, no pude analizar tu muestra. Por favor, publique los casos de prueba
F. Hauri
En camino. Al armar las pruebas, también encontré algunos errores tipográficos para corregir. Gracias;)
hYPotenuser