Calculatrice de numérologie

19

Le but de ce défi est de calculer un type de chiffre de numérologie à partir de chaînes contenant des caractères et des nombres.

  • L'entrée peut se faire par n'importe quelle méthode pratique (entrée standard, arguments, fichier séparé).
  • L'entrée peut contenir des caractères ASCII imprimables, mais seulement alphanumérique ( A-Z, a-zet 0-9) doivent être pris en considération.
  • La sortie doit être un chiffre entre 1et 9ou une étoile *si aucune lettre et aucun chiffre ne sont trouvés ... (ou même 0si l'entrée contient un nombre quelconque 0 et rien d'autre, mais cela n'a pas d'importance).
  • Les valeurs des lettres sont mappées de cette manière:

    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
    
  • Le chiffre de numérologie est calculé en ajoutant chaque valeur de chaîne, puis répétez jusqu'à ce qu'il n'y ait qu'un seul chiffre. Exemple pour 13579, Hello, world!, 00 0 00, !@#$%^&*();, et 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
    

    (C'est super, la plupart de ces échantillons donnent 7! Mais ce n'est qu'un échantillon;)

    Quelques tests supplémentaires:

    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
    

Il s'agit d'un , donc la réponse la plus courte en octets l'emporte.

Le plus court par langue

F. Hauri
la source
0 disparaîtra lorsqu'il sera ajouté à autre chose
F. Hauri
0 n'est pas pertinent! La sortie pertinente se situe entre 1et 9!
F.Hauri
Pourriez-vous ajouter quelques exemples sans caractères alphanumériques?
ETHproductions
1
Je veux dire quelque chose comme !@#$%^&*(); quelque chose qui devrait revenir *.
ETHproductions
Il a été très difficile de résister à citer cela dans certaines des discussions d'analyse technique sur la zone monétaire ... ;-p
keshlam

Réponses:

6

Matlab, 121 octets

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 n'est tout simplement pas fait pour les chaînes = (

flawr
la source
3
Hé, au moins ce n'est pas aussi verbeux que Mma: P
LegionMammal978
mon +1, je ne pouvais pas faire mieux. btw, est-il nécessaire de mettre une dispdéclaration?
brainkz
@brainkz Peut-être, mais je pense généralement que c'est du bon côté
flawr
3

Mathematica, 174 168 163 octets

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]]&

Effectue la première étape, puis calcule la racine numérique.

LegionMammal978
la source
3

Ruby, 97 74 caractères

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

Exemple d'exécution:

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
homme au travail
la source
3

Perl, 91 89 76 74 octets

73 + 1 pour -pinterrupteur

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

Les tests

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

Merci @manatwork de m'avoir aidé à sauver 2 14 16 15 17 caractères !!

... J'ai réfléchi: N % 32 + Ypeut remplacer( N & 31 ) + Y !

F. Hauri
la source
1
Si vous capturez toute la sous-chaîne correspondante, $1est égal à $&. Il vaut donc mieux supprimer la capture et changer le nom de la variable.
manatwork
1
whilele bloc pourrait être $t="*";s/\d/$t+=$&/eg;$_=$t.
manatwork
1
Désolé, mais c'est en fait 1 caractère de plus, car vous devez inclure le -pcommutateur dans le nombre.
manatwork
1
Désolé à nouveau (cette fois un plus grand désolé), mais il échoue lors de la saisie d'un seul caractère autre qu'un mot, par exemple "!" Donne le même résultat "!". ( Semble fonctionner parce qu'avec la chaîne here-string, l'entrée est toujours passée avec un retour à la ligne, donc dans vos cas de test ne passe jamais l'entrée avec un seul caractère. Utilisez echo -n "$test" | perl -pe '…'pour voir ce que je veux dire.) Vous pouvez le résoudre en changeant la whilecondition en !/^[\d*]$/. Bien qu'il y ait, pour réduire la perte de score, vous pouvez remplacer tout whilece: $t="*",s/\d/$t+=$&/eg,$_=$t until/^[\d*]$/.
manatwork
1
Il y a une autre amélioration que vous pouvez faire. Comme &la priorité est inférieure à +, tandis que la valeur %est supérieure, changez &31%32et vous pouvez supprimer les parenthèses autour de cette sous-expression.
manatwork
3

ES6, 98 octets

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

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

Version 94 octets qui ne fonctionne que sur les chaînes courtes:

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

Utilisation match, mapet joins'est avéré être plus court que l'utilisation de replacedeux fois:

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

Testez-le ici: https://jsbin.com/zizosayisi/edit?js,console

Neil
la source
Cela ne fonctionne pas pour l'entrée00 0 00
rink.attendant.6
@ rink.attendant.6 Ah, le REPL que j'utilisais n'était que des impressions ["0"], 0donc je ne pouvais pas faire la différence.
Neil
Beaucoup, beaucoup mieux que la version @ rink.attendant.6! Astuces de golf intelligentes utilisées. Pourriez-vous expliquer > '@', & 31et || 9?
Pavlo
1
@Pavlo fait > '@'juste la distinction entre les lettres et les chiffres. & 31est un moyen utile d'ignorer la différence entre les codes de caractères majuscules et minuscules, car il associe également directement les codes de caractères en valeurs 1 à 26. || 9est utilisé car % 9retourne 0 pour des multiples de 9 mais l'ajout répété de chiffres renvoie 9 pour des multiples non nuls de 9. Dans le code golfé que j'utilise à la (t + 8) % 9 + 1place, ce qui revient à la même chose.
Neil
Le langage est communément appelé "JavaScript (ES6)"
edc65
2

Gema, 161 caractères

*=@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}}}

(Écrit uniquement pour essayer de savoir si les appels de domaine récursifs fonctionnent.)

Exemple d'exécution:

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
homme au travail
la source
1

JavaScript (ES6), 162 159 157 octets

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

Toujours en train de chercher un moyen d'utiliser le retour implicite dans la fonction externe.

Non golfé + non minifié

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. Supprime tous les caractères non alphanumériques
  2. Appelle une fonction récursivement pour réduire les caractères à leurs valeurs respectives alors que la chaîne est supérieure à 1 caractère.
    1. Convertit la chaîne en majuscules pour travailler facilement avec les codes ASCII
    2. Convertir en tableau à l'aide de l'opérateur d'étalement et exécuter un accumulateur
    3. Utilisez la isNaNfonction globale (qui transforme son entrée) pour vérifier si ce n'est pas un nombre
      • Si ce n'est pas le cas, convertissez-le en code ASCII et mod 9 pour obtenir sa valeur respective
      • Si c'est un nombre, lancez-le
  3. Si la longueur est 0, aucun caractère alphanumérique n'était présent (retourner un astérisque), sinon retourner la sortie de la fonction récursive.
rink.attendant.6
la source
Cette règle de rupture 00 0 00, sortie *au lieu de 0!
F.Hauri
@ F.Hauri Fixed.
rink.attendant.6
Vous pouvez éviter un retour explicite en utilisant l'opérateur comman: _=>{expr;return expr}=>_=>(expr,expr)
Pavlo
@Pavlo Comment appliquer cela dans mon cas?
rink.attendant.6
Ne fonctionne pas pour moi, lance SyntaxError: jsbin.com/havotusoqa/1/edit?js,console
Pavlo
1

Haskell, 126 octets

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

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

lest une table de recherche de caractères pour lister des entiers (liste singleton, si char est trouvé, liste vide sinon). frecherche chaque caractère de son argument et aplatit la liste de listes retournée en une simple liste d'entiers et appelle gpour vérifier la condition de fin (liste vide (-> *) ou entier simple) ou pour appeler favec la somme de la liste pour un autre tour.

nimi
la source
1

MATL , 64 octets

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

Cela utilise la version actuelle (4.0.0) de la langue.

J'ai le sentiment que cela pourrait être raccourci ...

Cas de test

>> 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
la source
Malheureusement, je n'ai pas pu tester votre échantillon. Veuillez publier des cas de test entiers, y compris des tests récemment ajoutés (désolé).
F. Hauri
@ F.Hauri Oui, vous auriez besoin de Matlab pour les tester. Désolé, pas encore de compilateur en ligne. J'ai ajouté les cas de test
Luis Mendo
1

Sérieusement, 50 octets

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

Vidage hexadécimal:

2c24973ba331d1df2b3b237058bb402d402d3b5960272a2e7f
60ce5831575860bda13b73392a402575604de4243b6c445758

Essayez-le en ligne

Expliqué:

,$ù                                               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
quintopie
la source
@ F.Hauri Cliquez sur "Essayez-le en ligne". entrez vos cas de test dans la zone de saisie.
quintopie
1

Pyth, 39 octets

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

Essayez-le en ligne

Je fais juste ça parce que je ne peux pas dormir. Peut-être que je l'expliquerai demain ...

quintopie
la source
1

Pure bash, 199 194 octets

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

(le deuxième saut de ligne sert uniquement à éviter la barre de défilement)

Règle de test:

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
la source
1

JavaScript (ES6), 78 83

Solution récursive. Étant la récursivité de queue, les variables t et r ne doivent pas être locales.

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

Expliqué

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

Extrait de test

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
la source
0

Python, 154 octets

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
la source
Ce test d'échec avec 00 0 00!
F.Hauri
0

Mathematica, 133 octets

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 peu différent de LegionMammal978 ci-dessus. Ma fonction transforme tout en un code de caractère, puis filtre les éléments non alphanumériques (en les remplaçant par des chaînes vides). S'il n'y a pas de caractères alphanumériques, il renvoie *, sinon il prend la racine numérique. Cela pourrait être significativement (~ 15B) plus court si je n'avais pas à gérer le cas des chaînes entièrement zéros. C'est la vie.

Mathematica magic, pour les non-initiés: foo//.a_:>Tr@IntegerDigits@aest un remplacement répété: il remplace tous les nombres adans foo par la somme de leurs chiffres, puis il remplace à nouveau jusqu'à ce qu'il atteigne un point fixe, c'est-à-dire qu'il acesse de changer en cours de remplacement.

Tests:

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
la source
Malheureusement, je n'ai pas pu tester votre échantillon. Veuillez poster les cas de test
F. Hauri
Sur mon chemin. Lors de la mise en place des tests, j'ai également trouvé quelques fautes de frappe à corriger. Merci;)
hYPotenuser