Verallgemeinerter Gematria-Rechner

11

Erstellen Sie einen bidirektionalen Gematria-Rechner für eine bestimmte Folge von Unicode-Zeichen als Alphabet.

Gematri-was?

Gematria ist ein System zur Zuweisung numerischer Werte zu Symbolen, das von alten Griechen entwickelt und von alten Juden übernommen wurde. Es ist ähnlich wie ASCII oder Unicode, es ist nur nicht linear ... Siehe folgende Tabelle (die vollständige Tabelle finden Sie unter dem obigen Link):

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

           ...

Die Namen der Buchstaben sind nicht wichtig, nur ihr Index im "Array" des Alphabets und der jeweilige numerische Wert. Das hebräische Alphabet hat nur 22 Buchstaben (ohne "letzte" Buchstaben), daher beträgt der maximal verfügbare Wert 400.

Wenn wir dieses System dem englischen Alphabet (AZ) ausleihen, erhalten wir A = 1, B = 2 ... L = 30 ... U = 300 ... Z = 800.

Zwei Dinge müssen wir wissen.

  1. Eines der wichtigsten Merkmale dieses Systems ist die Berechnung des "Gematria-Werts" eines Wortes durch Aufsummieren der Buchstabenwerte. (Einige sagen, dass es eine mystische Verbindung zwischen Wörtern oder Phrasen gibt (wenn der Wert des Raums Null ist) - die denselben Gematria-Wert haben).

  2. Jede nicht negative Ganzzahl kann in Symbolen dargestellt werden. Zum Beispiel (und bleiben wir vorerst beim englischen Alphabet) ist der Wert von 32 LB (L = 30 + B = 2). Der Wert von 1024 ist ZTKD (800 + 200 + 20 + 4. Beachten Sie, dass ZSSKD ebenfalls 1024 ist, dies ist jedoch keine rechtliche Darstellung, da es komprimiert werden kann).

Die Herausforderung

Schreiben Sie ein Programm / eine Funktion / ein Code-Snippet in der Sprache Ihrer Wahl, das zuerst mit einem Alphabet eingerichtet wird (siehe API unten), und akzeptieren Sie dann ein Argument. Dieses Argument kann eine Ganzzahl oder ein Wort / eine Phrase sein. Wenn es sich um eine Ganzzahl handelt, sollte Ihr Programm seine Darstellung in den Alphabetsymbolen ausgeben / zurückgeben - die am stärksten komprimierte (siehe (2) oben). Wenn es sich um ein Wort oder eine Phrase handelt, sollte Ihr Programm den Gematria-Wert ausgeben / zurückgeben (indem Sie die Werte der Symbole summieren, ohne Leerzeichen zu zählen, siehe (1) oben).

API

Ihr Programm / Ihre Funktion sollte 3 Argumente akzeptieren. Sie können sie von STDIN abrufen oder als Funktionsargumente sogar davon ausgehen, dass es sich um Variablen handelt, die vor Ihrem Funktionsaufruf programmgesteuert initialisiert wurden.

  • Erstes Argument - das erste Zeichen (in Unicode) des Alphabets.
  • Zweites Argument - das letzte Zeichen (in Unicode) des Alphabets.
  • Drittes Argument - Eine Ganzzahl, die in Symbolen dargestellt werden soll, ODER eine Phrase, die durch das angegebene Alphabet erstellt wird.

Ausgabe- / Rückgabewert: Abhängig vom dritten Argument, wie oben erläutert.

Annahmen

  • Die ersten beiden Argumente sind immer jeweils ein Zeichen lang, und das zweite ist immer größer als das erste.
  • Die Sequenz (erste bis letzte, einschließlich) enthält niemals einen der Werte 30-39 (die die Ziffern 0-9 darstellen), andernfalls wird das dritte Argument mehrdeutig. BEARBEITEN: Es enthält auch kein Leerzeichen, da Leerzeichen in Phrasen als Nullen gezählt werden.
  • Das dritte Argument, falls es sich um eine Phrase handelt, darf nur Leerzeichen und Buchstaben des angegebenen Alphabets enthalten. Eine leere Zeichenfolge ist keine gültige Eingabe (Sie können davon ausgehen, dass sie nicht leer ist). Wenn es sich um eine Ganzzahl handelt, können Sie davon ausgehen, dass es sich um eine positive Ganzzahl handelt.

Beispiele

Input                Output

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

Wertung

Score = upvotes - length/100.0

Ihr Code sollte kurz, aber vor allem beliebt sein. Negative Ergebnisse können ebenfalls mitspielen. Der Gewinner ist die Antwort mit der höchsten Punktzahl in einer Woche, 29.11.2014 19:20:00 UTC.

Jakob
quelle
Ich habe Ihre Frage auf die Catch-All- Code-Challenge zurückgeführt, da ich denke, dass sich die Wertung ausreichend von Code-Golf oder einem Standard-Beliebtheitswettbewerb unterscheidet.
Martin Ender
In Ordnung. Das sind viele Tags :) danke.
Jacob
Was ist Leerzeichen selbst in der Einschlussliste enthalten, die von den ersten beiden Zeichen erstellt wurde?
Optimierer
Was meinst du mit der zweiten Annahme? ASCII-Code für 0 ist nicht 30.
Optimizer
1
@proudhaskeller Dies ist ein häufiger Fehler, da Sie im Kindergarten "peh tsady kuf resh" lernen, was wie tsadik kuf klingt ... Sie können dies gerne mit der Akademie für Hebräisch bestätigen.
Jacob

Antworten:

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=:+}?

Testen Sie es hier.

Dies ist ein vollständiges Programm, das Eingaben von STDIN entgegennimmt und das Ergebnis an STDOUT druckt.

Ich bin mir nicht sicher, wie ich hier auf Popularität schießen soll, also spiele ich einfach Golf und hoffe, stattdessen eine einigermaßen beeindruckende Codegröße zu erhalten. ;)

Ich glaube, dass die Int-zu-String-Konvertierung noch verbessert werden kann, aber ich sehe es momentan nicht.

Vielen Dank an Optimizer, der mich an die festgelegte Schnittmenge erinnert hat und dass leere Arrays falsch sind.

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

Im zweiten Fall verbleibt das Ergebnis auf dem Stapel, der am Ende des Programms automatisch gedruckt wird.

Martin Ender
quelle
5

Java 7, Score = Upvotes - 3.97

Yay!!! Java!!! Die weltweit beliebteste Golfsprache. Was, du kannst tatsächlich in Java Golf spielen ??? Nun, es ist so, als würde man einen Bulldozer zum Putten verwenden.

awird voraussichtlich das erste Zeichen enthalten. bwird voraussichtlich das letzte Zeichen enthalten. cwird voraussichtlich die Eingabezeichenfolge haben.

Hier ist die Funktion Golf:

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

Hier wird es mit Strukturcode eingerückt:

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

Hier ist es komplett erweitert:

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

        }
    }
}
Die Nummer eins
quelle
2

APL (positive Stimmen - 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}⍵}

Dies ist eine Funktion, die die beiden Zeichen links und das zu konvertierende Argument rechts verwendet:

      '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

Ungolfed Version:

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
quelle
2

Haskell, 188 Bytes; Upvotes - 1.88

Dies ist ein ausgewachsenes STDIN-to-STDOUT-Programm, das stark im Golfsport spielt. EDIT: Jetzt in weniger als 200 Bytes! EDIT2: Ein Byte mit @ stolzhaskellers Vorschlag gespeichert.

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

Es erstellt die unendliche Liste von Werten x = [1,2,3,4,5,6,7,8,9,10,20,30,..]in der ersten Zeile und führt E / A in der dritten Zeile aus. Der Wert eines Buchstabens cist angesichts des Bereichs [a..b]der Wert an der Position length [a..c] - 1von x. In der zweiten Zeile verzweigen wir in den ersten Buchstaben udes dritten Arguments und summieren entweder seine Gematria-Werte (wenn ues sich nicht um eine Ziffer handelt) oder konstruieren gierig ein Wort mit dem angegebenen Wert (wenn ues sich um eine Ziffer handelt).

Ungolfed Version mit besser lesbaren Variablennamen:

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
quelle
Sie könnten die {}aus der where-Klausel für einen Ein-Byte-Gewinn entfernen
stolzer Haskeller
1

CJam, 70 Bytes, #Upvotes - 0.7

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

Dies setzt voraus, dass eine gültige Eingabe übergeben wird. Übernimmt Eingaben von STDIN wie in der API-Spezifikation angegeben und druckt das Ergebnis an STDOUT.

Beispiele:

Input                Output

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

Probieren Sie es hier online aus

Blockweise Erklärung :

{{_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."
Optimierer
quelle