Calculadora Gematria Generalizada

11

Crie uma calculadora Gematria bidirecional, para qualquer sequência de caracteres Unicode, como o alfabeto.

Gematri-O que?

Gematria é um sistema de atribuição de valores numéricos a símbolos, desenvolvido por gregos antigos e adotado por judeus antigos. É semelhante ao ASCII ou Unicode, é apenas não linear ... Consulte a tabela a seguir (a tabela completa está disponível no link acima):

Index     Letter   Letter name  Value
--------------------------
  0         א         "Alef"     1
  1         ב         "Bet"      2

           ...

  8         ט         "Tet"      9
  9         י         "Yud"      10
 10         כ         "Kaf"      20

           ...

 17         צ        "Tsady"     90
 18         '        "Kuf"       100
 19         ר        "Resh"      200

           ...

Os nomes das letras não são importantes, apenas seu índice na "Matriz" do alfabeto e o respectivo valor numérico. O alfabeto hebraico possui apenas 22 letras (não incluindo as letras "finais"), portanto, o valor máximo disponível é 400.

Se emprestarmos esse sistema para o alfabeto inglês (AZ), terminaremos com A = 1, B = 2 ... L = 30 ... U = 300 ... Z = 800.

Duas coisas que precisamos saber.

  1. Uma das características mais importantes desse sistema é calcular o "valor da gematria" de uma palavra , resumindo os valores de suas letras. (Alguns dizem que há uma conexão mística entre palavras ou frases (quando o valor do espaço é zero) - que compartilham o mesmo valor da Gematria).

  2. Qualquer número inteiro não negativo pode ser representado em símbolos. Por exemplo (e vamos ficar com o alfabeto inglês por enquanto) o valor de 32 é LB (L = 30 + B = 2). O valor de 1024 é ZTKD (800 + 200 + 20 + 4. Observe que ZSSKD também é 1024, mas isso não é uma representação legal, pois pode ser compactado).

O desafio

Escreva um trecho de programa / função / código no idioma de sua escolha, primeiro configurado com um alfabeto (consulte API abaixo) e, em seguida, aceite um argumento. Esse argumento pode ser um número inteiro ou uma palavra / frase. Se for um número inteiro - seu programa deve gerar / retornar sua representação nos símbolos do alfabeto - o mais compactado (veja (2) acima). Se for uma palavra ou frase, seu programa deve gerar / retornar o valor da Gematria (somando os valores dos símbolos, sem contar os espaços em branco, consulte (1) acima).

API

Seu programa / função deve aceitar 3 argumentos. Você pode obtê-los no STDIN ou, como argumentos da função, pode até assumir que são variáveis ​​que foram inicializadas programaticamente antes da chamada da função.

  • Primeiro argumento - o primeiro caractere (em Unicode) do alfabeto.
  • Segundo argumento - o último caractere (em Unicode) do alfabeto.
  • Terceiro argumento - Um número inteiro, a ser representado em símbolos, OU uma frase que é criada pelo alfabeto fornecido.

Valor de saída / retorno: dependendo do terceiro argumento, conforme explicado acima.

Premissas

  • Os dois primeiros argumentos sempre terão um caractere cada, e o segundo sempre será maior do que o primeiro.
  • A sequência (do primeiro ao último, inclusive) nunca incluirá nenhum dos valores 30-39 (que representam os dígitos 0-9); caso contrário, o terceiro argumento será ambíguo. EDIT: também não conterá espaço, pois nas frases os espaços são contados como zeros.
  • O terceiro argumento, caso seja uma frase, pode conter apenas espaços e letras do alfabeto especificado. String vazia não é uma entrada válida (você pode assumir que não está vazia). Caso seja um número inteiro, você pode assumir que é um número inteiro positivo.

Exemplos

Input                Output

A Z CODE GOLF        175
a s 512              sssssjb
A B 7                BBBA
≐ ⊐ ≤≫ ≥            1700

Pontuação

Score = upvotes - length/100.0

Seu código deve ser curto, mas o mais importante é popular. Pontuações negativas também podem ser reproduzidas. O vencedor será a resposta com a pontuação mais alta em uma semana a partir de agora, 2014-11-29 19:20:00 UTC.

Jacob
fonte
Eu refiz sua pergunta novamente ao desafio geral do código, pois acho que a pontuação é suficientemente diferente do código de golfe ou de um concurso de popularidade padrão.
Martin Ender
Está bem. São muitas tags :) obrigado.
24414 Jacob
O espaço em si está incluído na lista de inclusão criada pelos dois primeiros caracteres?
Optimizer
Além disso, o que você quer dizer com a segunda suposição? O código ASCII para 0 não é 30.
Otimizador
1
@proudhaskeller Esse é um erro comum, pois você aprende no jardim de infância "peh tsady kuf resh", que soa como tsadik kuf ... Você pode confirmar isso com a Academia de Hebraico.
23414 Jacob Jacob

Respostas:

4

CJam, 80 75 70 bytes, Upvotes - 0,7

Arc:Irc\-):N,f#{9,:)f*~}%N<lS-_A,s&{i{1${1$)<},)\,I+o-}h;;}{If-\f=:+}?

Teste aqui.

Este é um programa completo, que recebe a entrada de STDIN e imprime o resultado em STDOUT.

Não tenho muita certeza de como devo buscar popularidade aqui, então estou simplesmente jogando golfe, na esperança de obter um tamanho de código razoavelmente impressionante. ;)

Acredito que a conversão int-to-string ainda pode ser melhorada, mas não a vejo no momento.

Obrigado ao Optimizer por me lembrar sobre a interseção de conjuntos e que matrizes vazias são falsas.

A                                   "Push integer 10.";
 rc:I                               "Read token, convert to character, save in I.";
     rc                             "Read token, convert to character.";
       \-)                          "Swap, subtract, increment.";
          :N                        "Store number of characters in N.";
            ,                       "Turn into range [0 1 2 ... N-1].";
             f#                     "Map 10^i onto that range.";
               {       }%           "Map this block onto the powers of 10.";
                9,                  "Create range [0 1 2 ... 8].";
                  :)                "Increment each element.";
                    f*              "Multiply each by the current power of 10.";
                      ~             "Unwrap/dump the resulting array.";
                                    "Now we've got the values of the first 9N digits.";
                         N<         "That's too much, so truncate to the first N.";
                           l        "Read the rest of the line.";
                            S-      "Remove spaces.";
                              _     "Duplicate string and get first character.";
                               A,   "Create range [0 1 2 ... 9].";
                                 s  "Turn into string '0123456789'.";
                                  & "Intersection of characters.";

{                      }{        }? "If/else depending on whether the result is empty.";
                                    "If it was a digit...";
 i                                  "Convert string to integer.";
  {                }h               "While that integer isn't zero...";
   1$                               "Copy digit values.";
     {    },                        "Filter digit values.";
      1$                            "Copy remaining integer.";
        )<                          "Increment, compare.";
                                    "This discards values greater than the integer.";
            )\                      "Slice off last digit value, and swap with list.";
              ,I+                   "Get length of list and add to I.";
                 o                  "Print character.";
                  -                 "Subtract digit value from integer.";
                     ;;             "Empty stack.";
                                    "If the string was not a number...";
                         I          "Push initial character.";
                          f-        "Subtract it from each character in string.";
                            \       "Swap differences and digit values.";
                             f=     "Use differences to index into the values.";
                               :+   "Sum up all the values.";

No segundo caso, o resultado é deixado na pilha, que é impressa automaticamente no final do programa.

Martin Ender
fonte
5

Java 7, Pontuação = Upvotes - 3.97

Yay!!! Java!!! O idioma de golfe favorito do mundo. O que, você pode realmente jogar golfe em java ??? Bem, é como usar um trator para arremessar.

aé esperado que contenha o primeiro caractere. bé esperado que contenha o último caractere. cé esperado que tenha a sequência de entrada.

Aqui está a função golfed:

int d=0;try{d=Integer.parseInt(c);}catch(Exception e){}int l=b-a+1;char[]f=new char[l];int[]g=new int[l];int h=1;int i=1;g[0]=1;f[0]=a;int j;for(j=1;j<b-a+1;){g[j]=(h+=i);f[j]=(char)(f[j++-1]+1);i*=h==10*i?10:1;}if(d==0){h=0;for(char k:c.toCharArray()){for(j=0;j<l;j++){if(f[j]==k){h+=g[j];}}}System.out.println(h);}else{c="";for(j=l;j>0;){if(g[--j]<=d){c+=f[j];d-=g[j++];}}System.out.println(c);}

Aqui está recuado com o código de estrutura:

public class G{

    public static void main(String[] args){
        new G(args);
    }

    public G(String[] args){
        a = args[0].charAt(0);
        b = args[1].charAt(0);
        for (int i = 2; i < args.length; i++){
            c += args[i];
        }
        function();
    }

    char a;

    char b;

    String c = "";

    void function(){
        int d=0;
        try{
            d=Integer.parseInt(c);
        }catch(Exception e){}
        int l=b-a+1;
        char[]f=new char[l];
        int[]g=new int[l];
        int h=1;
        int i=1;
        g[0]=1;
        f[0]=a;
        int j;
        for(j=1;j<b-a+1;){
            g[j]=(h+=i);
            f[j]=(char)(f[j++-1]+1);
            i*=h==10*i?10:1;
        }
        if(d==0){
            h=0;
            for(char k:c.toCharArray()){
                for(j=0;j<l;j++){
                    if(f[j]==k){
                        h+=g[j];
                    }
                }
            }
            System.out.println(h);
        }else{
            c="";
            for(j=l;j>0;){
                if(g[--j]<=d){
                    c+=f[j];
                    d-=g[j++];
                }
            }
            System.out.println(c);
        }
    }
}

Aqui está completamente expandido:

public class Generator{

    public static void main(String[] args){
        beginning = args[0].charAt(0);
        end = args[1].charAt(0);
        for (int i = 2; i < args.length; i++){
            phrase += args[i];
        }
        function();
    }

    static char beginning;

    static char end;

    static String phrase = "";

    static void function(){
        int convertTo = 0;
        try{
             convertTo = Integer.parseInt(phrase);
        } catch (Exception e){}
        char[] alphabet = new char[end - beginning + 1];
        int[] values = new int[alphabet.length];
        int value = 1;
        int base = 1;
        values[0] = 1;
        alphabet[0] = beginning;
        int i;
        for (i = 1; i < values.length;){
            values[i] = (value += base);
            alphabet[i] = (char)(alphabet[i++-1]+1);
            base*=value==10*base?10:1;
        }
        if(convertTo==0){
            value = 0;
            for (char character : phrase.toCharArray()){
                for (i = 0; i < alphabet.length;i++){
                    if (alphabet[i] == character){
                        value += values[i];
                    }
                }
            }
            System.out.println(value);


        } else {
            phrase = "";
            for (i = values.length;i > 0;){
                if (values[--i] <= convertTo){
                    phrase += alphabet[i];
                    convertTo -= values[i++];
                }
            }
            System.out.println(phrase);

        }
    }
}
O número um
fonte
2

APL (votações positivas - 1.05)

{U←⎕UCS⋄A←V↑∊(10*0,⍳⌊9÷⍨V←1+|-/U⍺)∘.×⍳9⋄⍬≢0↑⍵:+/A[1+(U⍵~' ')-U⊃⍺]⋄U(U⊃⍺)+{⍵≤0:⍬⋄(¯1+A⍳T),∇⍵-T←⊃⌽A/⍨⍵≥A}⍵}

Esta é uma função que leva os dois caracteres à esquerda e o argumento a ser convertido à direita:

      'A' 'Z'{U←⎕UCS⋄A←V↑∊(10*0,⍳⌊9÷⍨V←1+|-/U⍺)∘.×⍳9⋄⍬≢0↑⍵:+/A[1+(U⍵~' ')-U⊃⍺]⋄U(U⊃⍺)+{⍵≤0:⍬⋄(¯1+A⍳T),∇⍵-T←⊃⌽A/⍨⍵≥A}⍵}'CODE GOLF'
175
      gematria←{U←⎕UCS⋄A←V↑∊(10*0,⍳⌊9÷⍨V←1+|-/U⍺)∘.×⍳9⋄⍬≢0↑⍵:+/A[1+(U⍵~' ')-U⊃⍺]⋄U(U⊃⍺)+{⍵≤0:⍬⋄(¯1+A⍳T),∇⍵-T←⊃⌽A/⍨⍵≥A}⍵}
      'A' 'Z' gematria 'CODE GOLF'
175
      'a' 's' gematria 512
sssssjb
      'A' 'B' gematria 7
BBBA
      '≐' '⊐' gematria '≤≫ ≥'
1700

Versão não destruída:

gematria←{
   ⍝ get Unicode values for characters
   first last←⎕UCS¨⍺
   amount←1+last-first
   ⍝ find the value for each character in the alphabet
   alphabet←amount↑∊(10*0,⍳⌊amount÷9)∘.×⍳9

   ⍝ right arg is string: calculate number
   ⍬≢0↑⍵: +/ alphabet[1+(⎕UCS ⍵~' ')-first]

   ⍝ otherwise, right arg is number: find string
   ⎕UCS first+{
      ⍝ number ≤ 0? empty string
      ⍵≤0:⍬

      ⍝ find highest value we can subtract
      val←⊃⌽(⍵≥alphabet)/alphabet

      ⍝ return it, followed by the conversion of the rest of the number
      (¯1+alphabet⍳val), ∇⍵-val
   }⍵
}
marinus
fonte
2

Haskell, 188 bytes; Upvotes - 1,88

Este é um programa completo de STDIN para STDOUT, muito jogado. EDIT: Agora em menos de 200 bytes! EDIT2: salvou um byte com a sugestão do @ proudhaskeller.

x=[1..9]++map(*10)x
f(a:_:b:_:z@(u:_))|u>'/'&&u<':'=w$read z|1<2=show.sum$map v z where v ' '=0;v c=x!!(length[a..c]-1);w 0="";w n=(\c->c:w(n-v c))$last[d|d<-[a..b],v d<=n]
main=interact$f

Ele constrói a lista infinita de valores x = [1,2,3,4,5,6,7,8,9,10,20,30,..]na primeira linha e executa E / S na terceira linha. O valor de uma letra c, dado o intervalo [a..b], é então o valor na posição length [a..c] - 1de x. Na segunda linha, ramificamos a primeira letra udo terceiro argumento e somamos seus valores de gematria (se unão for um dígito) ou construímos avidamente uma palavra com o valor fornecido (se ufor um dígito).

Versão ungolfed com nomes de variáveis ​​mais legíveis:

values = [1..9] ++ map (*10) values
f (low:_:high:_:rest@(first:_))
  | first > '/' && first < ':' = construct $ read rest
  | otherwise                  = show . sum $ map value rest
  where value ' '   = 0
        value c     = values !! (length [low..c] - 1)
        construct 0 = ""
        construct n = (\c -> c : construct (n - value c)) $
                      last [d | d <- [low..high], value d <= n]
main = interact $ f
Zgarb
fonte
você pode remover a {}partir da cláusula WHERE para um ganho de um byte
haskeller orgulhoso
1

CJam, 70 bytes, #Upvotes - 0,7

{{_9%)A@9/#*}%}:M;rcrc),\i>:QlS-_@&{Qf#M:+}{i{Q,,M{1$)<},)Q@,=@@-}h;}?

Isso pressupõe que uma entrada válida será passada. Recebe a entrada de STDIN como a especificação da API diz e imprime o resultado em STDOUT.

Exemplos:

Input                Output

A Z CODE GOLF        175
a s 512              sssssjb
A B 7                BBBA
≐ ⊐ ≤≫ ≥            1700

Experimente online aqui

Bloquear explicação sábia :

{{_9%)A@9/#*}%}:M;
{             }:M;              "Define a function M which takes an input array of"
                                "indeces and calculates the Gematri number for them";
 {          }%                  "Run this code block for each element of the array";
  _9%)                          "Copy the number, take modulus by 9 and increment it";
      A@                        "Put 10 on stack, and rotate to get the number on top";
        9/                      "Integer divide the number by 9";
          #                     "Calculate 10 to the power the above quotient";
           *                    "Multiply the above result by modulus 9";

rcrc),\i>:QlS-_@&
rcrc                            "Read the first two characters, representing the lower"
                                "and upper end of the character list";
    ),                          "Increment the upper end and get a list of U to ASCII 0"
                                "characters where U is the upper limit";
      \i                        "Swap and convert the lower limit to its ASCII number";
        >:Q                     "Slice the character list to get our desired character"
                                "list range and store it in Q";
           lS-                  "Read the rest of the line as string and remove spaces";
              _@&               "Take a copy, get Q on top of stack and take"
                                "intersection with the input string. If the resulting"
                                "string is empty, then the third input was a number";
                 {...}{...}?    "First code block is for string input and second for"
                                "number input based on the above intersected string";

{Qf#M:+}
 Qf#                            "For each character of input string, calculate its"
                                "position in Q";
    M                           "Get the Gematri numbers for these inceces";
     :+                         "Sum them all to get the final Gematri number for the"
                                "input string"

{i{Q,,M{1$)<},)Q@,=@@-}h;}
 i                              "Convert the input number string to integer";
  {                   }h        "Run the code block till we get 0 on top of stack";
   Q,,M                         "Get the first length(Q) Gematri numbers";
       {1$)<},                  "Filter and take only which are less than input number";
              )                 "Pop the last number from the filtered array. This is"
                                "The maximum Gematri number that can be deducted";
               Q@               "Put Q on stack and rotate the remaining filtered array"
                                "to top of stack";
                 ,              "Calculate the length of that array, which is also the"
                                "index of the Gematri number used.";
                  =             "Get the corresponding character to that Gematri number";
                   @@-          "Put the number and Gematri number on top and subtract."
                                "The next loop runs on the above result now";
                        ;       "Pop the resedual 0 from stack. The remaining stack now"
                                "contains just the Gematri characters."
Optimizer
fonte