Calculatrice de gématrie généralisée

11

Créez une calculatrice Gematria bidirectionnelle, pour n'importe quelle séquence donnée de caractères Unicode comme l'alphabet.

Gematri-Quoi?

La gématrie est un système d'attribution de valeurs numériques aux symboles, développé par les anciens Grecs et adopté par les anciens Juifs. C'est d'une manière comme ASCII ou Unicode, c'est juste non linéaire ... Voir le tableau suivant (le tableau complet est disponible dans le lien ci-dessus):

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

           ...

Les noms des lettres ne sont pas importants, seulement leur index dans le "tableau" de l'alphabet et la valeur numérique respective. L'alphabet hébreu ne compte que 22 lettres (sans compter les lettres "finales"), la valeur maximale disponible est donc de 400.

Si nous empruntons ce système à l'alphabet anglais (AZ), nous nous retrouverons avec A = 1, B = 2 ... L = 30 ... U = 300 ... Z = 800.

Deux choses que nous devons savoir.

  1. L'une des caractéristiques les plus importantes de ce système est le calcul de la "valeur en gématrie" d'un mot , en additionnant les valeurs de ses lettres. (Certains disent qu'il existe un lien mystique entre des mots ou des phrases (lorsque la valeur de l'espace est nulle) - qui partagent la même valeur de Gematria).

  2. Tout entier non négatif peut être représenté par des symboles. Par exemple (et restons avec l'alphabet anglais pour l'instant), la valeur de 32 est LB (L = 30 + B = 2). La valeur de 1024 est ZTKD (800 + 200 + 20 + 4. Notez que ZSSKD est également 1024, mais ce n'est pas une représentation légale, car il peut être compacté).

Le défi

Écrivez un programme / une fonction / un extrait de code dans la langue de votre choix, qui est d'abord configuré avec un alphabet (voir API ci-dessous), puis acceptez un argument. Cet argument peut être un entier ou un mot / une phrase. S'il s'agit d'un nombre entier - votre programme devrait afficher / renvoyer sa représentation dans les symboles de l'alphabet - le plus compact (voir (2) ci-dessus). S'il s'agit d'un mot ou d'une phrase, votre programme doit générer / renvoyer la valeur de Gematria (en additionnant les valeurs des symboles, sans compter les espaces, voir (1) ci-dessus).

API

Votre programme / fonction doit accepter 3 arguments. Vous pouvez les obtenir à partir de STDIN, ou en tant qu'arguments de fonction, vous pouvez même supposer que ce sont des variables qui ont été initialisées par programme avant l'invocation de votre fonction.

  • Premier argument - le premier caractère (en Unicode) de l'alphabet.
  • Deuxième argument - le dernier caractère (en Unicode) de l'alphabet.
  • Troisième argument - Un entier, à représenter en symboles, OU une phrase qui est créée par l'alphabet donné.

Valeur de sortie / retour: selon le troisième argument, comme expliqué ci-dessus.

Hypothèses

  • Les deux premiers arguments auront toujours un caractère chacun, et le second sera toujours plus gracieux que le premier.
  • La séquence (du premier au dernier inclus) n'inclura jamais aucune des valeurs 30-39 (qui représentent les chiffres 0-9), sinon elle rendra le troisième argument ambigu. EDIT: Il ne contiendra pas d'espace non plus, car dans les phrases, les espaces sont comptés comme des zéros.
  • Le troisième argument, s'il s'agit d'une phrase, ne peut contenir que des espaces et des lettres de l'alphabet donné. Une chaîne vide n'est pas une entrée valide (vous pouvez supposer qu'elle n'est pas vide). Dans le cas où il s'agit d'un entier, vous pouvez supposer qu'il s'agit d'un entier positif.

Exemples

Input                Output

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

Notation

Score = upvotes - length/100.0

Votre code doit être court, mais surtout populaire. Les scores négatifs peuvent également jouer. Le gagnant sera la réponse avec le score le plus élevé dans une semaine à partir de maintenant, 2014-11-29 19:20:00 UTC.

Jacob
la source
J'ai repensé votre question au défi du code fourre-tout car je pense que le score est suffisamment différent du code golf ou d'un concours de popularité standard.
Martin Ender
D'accord. Cela fait beaucoup de balises :) merci.
Jacob
Qu'est-ce que l'espace lui-même est inclus dans la liste d'inclusion créée par les deux premiers caractères?
Optimizer
Aussi, que voulez-vous dire par la deuxième hypothèse? Le code ASCII pour 0 n'est pas 30.
Optimizer
1
@proudhaskeller c'est une erreur courante puisque vous apprenez à la maternelle "peh tsady kuf resh" qui sonne comme tsadik kuf ... Vous êtes invités à le confirmer avec l'Académie pour l'hébreu.
Jacob

Réponses:

4

CJam, 80 75 70 octets, votes positifs - 0,7

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

Testez-le ici.

Il s'agit d'un programme complet, qui prend les données de STDIN et imprime le résultat dans STDOUT.

Je ne sais pas vraiment comment je suis censé tirer pour la popularité ici, alors je joue simplement au golf en espérant obtenir une taille de code assez impressionnante à la place. ;)

Je crois que la conversion int-to-string peut encore être améliorée, mais je ne la vois pas pour le moment.

Merci à Optimizer de m'avoir rappelé l'intersection définie et que les tableaux vides sont faux.

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.";

Dans le second cas, le résultat est laissé sur la pile, qui est imprimée automatiquement à la fin du programme.

Martin Ender
la source
5

Java 7, Score = Votes - 3,97

Yay!!! Java!!! La langue de golf préférée du monde dans le monde. Quoi, vous pouvez réellement jouer au golf en java ??? Eh bien, c'est un peu comme utiliser un bulldozer pour putter.

adevrait contenir le premier caractère. bdevrait contenir le dernier caractère. cdevrait avoir la chaîne d'entrée.

Voici la fonction jouée:

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);}

Ici, il est en retrait avec le code de structure:

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);
        }
    }
}

Ici, il est complètement développé:

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

        }
    }
}
Le numéro un
la source
2

APL (votes positifs - 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}⍵}

Il s'agit d'une fonction qui prend les deux caractères à gauche et l'argument à convertir à droite:

      '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

Version non golfée:

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

Haskell, 188 octets; Upvotes - 1,88

Il s'agit d'un programme complet de STDIN à STDOUT, fortement golfé. EDIT: maintenant en moins de 200 octets! EDIT2: enregistré un octet avec la suggestion de @ 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

Il construit la liste infinie de valeurs x = [1,2,3,4,5,6,7,8,9,10,20,30,..]sur la première ligne et effectue des E / S sur la troisième ligne. La valeur d'une lettre c, compte tenu de la plage [a..b], est alors la valeur à la position length [a..c] - 1de x. Sur la deuxième ligne, nous nous branchons sur la première lettre udu troisième argument, et soit additionnons ses valeurs de gématrie (si ce un'est pas un chiffre), soit construisons avidement un mot avec la valeur donnée (si uc'est un chiffre).

Version non golfée avec des noms de variables plus lisibles:

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
la source
vous pouvez supprimer la {}clause where pour un gain d'un octet
fier haskeller
1

CJam, 70 octets, # Upvotes - 0,7

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

Cela suppose qu'une entrée valide sera transmise. Prend l'entrée de STDIN comme le spécifie l'API et imprime le résultat sur STDOUT.

Exemples:

Input                Output

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

Essayez-le en ligne ici

Explication sage :

{{_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."
Optimiseur
la source