Numerology Calculator


19

L'obiettivo di questa sfida è calcolare un tipo di cifra numerologica da stringhe contenenti caratteri e numeri.

  • L'input può avvenire tramite qualsiasi metodo conveniente (input standard, argomenti, file separato).
  • L'ingresso può contenere caratteri ASCII stampabili, ma solo alfanumerico ( A-Z, a-z, e 0-9) devono essere considerati.
  • L'uscita deve essere una cifra compresa tra 1e 9o una stella *, se nessuna lettera e nessun cifre in cui ha trovato ... (o anche 0se l'ingresso contenere qualsiasi numero di 0 e niente altro, ma questo non importa).
  • I valori delle lettere sono mappati in questo modo:

    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
    
  • La cifra numerologica viene calcolata aggiungendo ogni valore di stringa, quindi ripetere fino a quando non vi è una sola cifra. Esempio per 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
    

    (Questo è fantastico, la maggior parte di questi esempi danno 7! Ma è solo un campione;)

    Alcuni altri test:

    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
    

Questo è un , quindi vince la risposta più breve in byte.

Più breve per lingua


0 scompare quando viene aggiunto a qualsiasi altra cosa
F. Hauri,

0 non è rilevante! L'output pertinente è compreso tra 1e 9!
F. Hauri,

Potresti aggiungere alcuni esempi senza caratteri alfanumerici?
ETHproductions

1
Intendo qualcosa del genere !@#$%^&*(); qualcosa che dovrebbe tornare *.
ETHproductions

È stato molto difficile resistere citandolo in alcune delle discussioni di analisi tecnica sull'area Money ... ;-p
keshlam,

Risposte:


6

Matlab, 121 byte

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 non è creato per stringhe = (


3
Ehi, almeno non è così prolisso come Mma: P
LegionMammal978,

il mio +1, non potrei fare di meglio. a proposito, è necessario mettere una dispdichiarazione?
brainkz,

@brainkz Forse, ma di solito lo inculo per essere sul sicuro
flawr

3

Mathematica, 174 168 163 byte

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

Fa il primo passo, quindi calcola la radice digitale.


3

Rubino, 97 74 caratteri

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

Esecuzione di esempio:

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 byte

73 + 1 per -pinterruttore

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

test

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

Grazie @manatwork per avermi aiutato a salvare 2 14 16 15 17 caratteri !!

... Ci ho pensato: N % 32 + Ypuò sostituire( N & 31 ) + Y !


1
Se acquisisci l'intera sottostringa abbinata, $1è uguale a $&. Quindi meglio rimuovere l'acquisizione e cambiare il nome della variabile.
arte

1
whileIl blocco potrebbe essere $t="*";s/\d/$t+=$&/eg;$_=$t.
arte

1
Siamo spiacenti, ma in realtà è più lungo di 1 carattere, poiché dovresti includere l' -popzione nel conteggio.
arte

1
Scusa di nuovo (questa volta una scusa più grande), ma fallisce con l'inserimento di singoli caratteri non di parole, ad esempio "!" Risulta lo stesso "!". ( Sembra funzionare perché con here-string l'input viene sempre passato con una nuova riga finale, quindi nei casi di test non passa mai l'immissione di un singolo carattere. Utilizzare echo -n "$test" | perl -pe '…'per vedere cosa intendo.) È possibile risolverlo modificando la whilecondizione in !/^[\d*]$/. Mentre era lì, per ridurre la perdita punteggio, è possibile sostituire l'intero whilecon questo: $t="*",s/\d/$t+=$&/eg,$_=$t until/^[\d*]$/.
arte

1
C'è un ulteriore miglioramento che puoi fare. Poiché &ha una precedenza inferiore rispetto a +, mentre %è maggiore, cambia &31%32e puoi rimuovere le parentesi attorno a quella sottoespressione.
arte

3

ES6, 98 byte

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

Versione a 94 byte che funziona solo su stringhe brevi:

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

Utilizzando match, mape joinsi è rivelato essere più breve di utilizzare replacedue volte:

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

Provalo qui: https://jsbin.com/zizosayisi/edit?js,console


Questo non funziona per l'input00 0 00
rink.attendant.6

@ rink.attendant.6 Ah, il REPL stavo usando solo le stampe ["0"]come 0quindi non ho potuto dire la differenza.
Neil,

Molto, molto meglio della versione @ rink.attendant.6! Hack da golf intelligenti utilizzati. Potresti spiegare > '@', & 31e || 9?
Pavlo,

1
@Pavlo > '@'distingue solo tra lettere e numeri. & 31è un modo utile per ignorare la differenza tra i codici di caratteri maiuscoli e minuscoli, poiché consente di mappare comodamente i codici di caratteri in valori 1..26. || 9viene utilizzato perché % 9restituisce 0 per multipli di 9, ma aggiungendo ripetutamente cifre restituisce 9 per multipli diversi da zero di 9. Nel codice golfizzato uso (t + 8) % 9 + 1invece che arriva alla stessa cosa.
Neil,

La lingua viene comunemente denominata "JavaScript (ES6)"
edc65,

2

Gema, 161 caratteri

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

(Scritto solo per provare se le chiamate di dominio ricorsive funzionano.)

Esecuzione di esempio:

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 byte

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

Sto ancora cercando un modo per usare il ritorno implicito nella funzione esterna.

Ungolfed + nonminified

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 tutti i caratteri non alfanumerici
  2. Chiama una funzione ricorsivamente per ridurre i caratteri ai rispettivi valori mentre la stringa è più lunga di 1 carattere.
    1. Converte la stringa in maiuscolo per lavorare facilmente con i codici ASCII
    2. Converti in array usando l'operatore spread ed esegui un accumulatore
    3. Usa la isNaNfunzione globale (che lancia il suo input) per verificare se non è un numero
      • In caso contrario, converti in codice ASCII e mod 9 per ottenere il rispettivo valore
      • Se è un numero, lancialo
  3. Se la lunghezza è 0, non erano presenti caratteri alfanumerici (restituisce un asterisco), altrimenti restituisce l'output della funzione ricorsiva.

Questa regola di interruzione 00 0 00, output *invece di 0!
F. Hauri,

@ F.Hauri Fixed.
rink.attendant.6,

Puoi evitare il ritorno esplicito usando l'operatore comune: _=>{expr;return expr}=>_=>(expr,expr)
Pavlo

@Pavlo Come posso applicarlo nel mio caso?
rink.attendant.6,

Non funziona per me, genera SyntaxError: jsbin.com/havotusoqa/1/edit?js,console
Pavlo,

1

Haskell, 126 byte

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

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

lè una tabella di ricerca per i caratteri in un elenco di numeri interi (elenco singleton, se viene trovato il carattere, altrimenti elenco vuoto). fcerca ogni carattere dell'argomento e appiattisce l'elenco restituito di elenchi in un semplice elenco di numeri interi e chiamate gper verificare la condizione finale (elenco vuoto (-> *) o intero singolo) o per chiamare fcon la somma dell'elenco per un altro giro.


1

MATL , 64 byte

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

Questo utilizza la versione corrente (4.0.0) della lingua.

Ho la sensazione che potrebbe essere abbreviato ...

Casi 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

Sfortunatamente, non ho potuto testare il tuo campione. Si prega di inviare interi casi di test, compresi i test aggiunti di recente (scusate).
F. Hauri,

@ F.Hauri Sì, avresti bisogno di Matlab per testarli. Spiacente, nessun compilatore online ancora. Ho aggiunto i casi di test
Luis Mendo il

1

Scherzi a parte, 50 byte

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

Dump esadecimale:

2c24973ba331d1df2b3b237058bb402d402d3b5960272a2e7f
60ce5831575860bda13b73392a402575604de4243b6c445758

Provalo online

Ha spiegato:

,$ù                                               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 Fai clic su "Provalo online". inserisci i casi di test nella casella di input.
Quintopia,

1

Pyth, 39 byte

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

Provalo online

Lo sto solo facendo perché non riesco a dormire. Forse lo spiegherò domani ...


1

Bash puro, 199 194 byte

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

(l'interruzione della seconda riga serve solo per evitare la barra di scorrimento)

Regola di prova:

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

Soluzione ricorsiva. Essendo ricorsione della coda, le variabili ter non devono essere locali.

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

spiegato

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 di prova

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 byte

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

Questo test fallito con 00 0 00!
F. Hauri,

0

Mathematica, 133 byte

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 po 'diverso da quello di LegionMammal978 sopra. La mia funzione trasforma tutto in un codice carattere, quindi filtra le cose non alfanumeriche (sostituendole con stringhe vuote). Se non ci sono alfanumerici, restituisce *, altrimenti prende la radice digitale. Questo potrebbe essere significativamente più breve (~ 15 B) se non dovessi occuparmi del caso delle stringhe a zero zeri. È la vita.

La magia di Mathematica, per i non iniziati: foo//.a_:>Tr@IntegerDigits@aè una sostituzione ripetuta: sostituisce tutti i numeri ain foo con la somma delle loro cifre, quindi sostituisce di nuovo fino a quando non raggiunge un punto fisso, cioè asmette di cambiare in sostituzione.

test:

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}

Sfortunatamente, non ho potuto testare il tuo campione. Si prega di inviare casi di test
F. Hauri il

Sulla mia strada. Nel mettere insieme i test, ho anche trovato alcuni errori di battitura da risolvere. Grazie;)
hYPotenuser il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.