Last active
September 9, 2022 18:56
-
-
Save saman3d/79598f2565a0e566e1f0f15416b9c28f to your computer and use it in GitHub Desktop.
Xulu v1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bufio" | |
| "errors" | |
| "fmt" | |
| "os" | |
| "regexp" | |
| "strings" | |
| ) | |
| // var rawStatement = "abcd abcd aabbc ab a c ccd dede dede cccd cd ascd aaabbcccee aaeeedd dede eeddd ddeeccc cccaabbb ddeeccaa aabbdd ddeeccaa" | |
| var reAlphabet = regexp.MustCompile(`^[a-e]+$`) | |
| var reVerb = regexp.MustCompile(`^(abcd|bcde|dede)$`) | |
| type verb int | |
| const ( | |
| v_ADD verb = -3 + iota | |
| v_SUB | |
| v_MUL | |
| ) | |
| var textToVerb = map[string]verb{ | |
| "abcd": v_ADD, | |
| "bcde": v_SUB, | |
| "dede": v_MUL, | |
| } | |
| var scanner = bufio.NewScanner(os.Stdin) | |
| func main() { | |
| fmt.Println(" Xulu v1 \n Author: saman koushki \n Enter your sentence bellow") | |
| for { | |
| fmt.Print("> ") | |
| scanner.Scan() | |
| raw := scanner.Text() | |
| answer, err := CompileXulu(raw) | |
| if err != nil { | |
| fmt.Println(err.Error()) | |
| } else { | |
| fmt.Println(answer) | |
| } | |
| } | |
| } | |
| // Xulu language is a simple language for writing simple nesting calculations | |
| // Xulu alphabete consists of 5 letters: a b c d e | |
| // with compositing this letters with each other you can represent numbers | |
| // a = 1, b = 2, c = 3, d = 4, e = 5 | |
| // here is how: | |
| // each sequence of repeated letters are added to each other. then we calculate mod 5 of them and raise them | |
| // to the power of 2. then sum them up. | |
| // Example: | |
| // aabbcccca | |
| // | |
| // - break this number to its repeated alphabets: | |
| // aa , bb , cccc , a | |
| // | |
| // - now compute its equivalents for every part | |
| // aa = 1 + 1 = 2 | |
| // bb = 2 + 2 = 4 | |
| // cccc = 3 + 3 + 3 + 3 = 12 | |
| // a = 1 | |
| // | |
| // - compute mod 5 of each set : | |
| // aa mod 5 = 2 | |
| // bb mod 5 = 4 | |
| // cccc mod 5 = 2 | |
| // a mod 5 = 1 | |
| // | |
| // - Now sqaure each number and add them up: | |
| // (2^2) + (4^2) + 2^2 +1 ^ 2 = 25 | |
| // | |
| // nouns have no meaning by them selves so they come up with a verb | |
| // which determines the operation that should be done on the nouns to | |
| // reach the answer. there are 3 verbs: | |
| // abcd = addition | |
| // bcde = subtraction | |
| // dede = multiplication | |
| // | |
| // the syntax consists of sentences. sentences are verbs followed by n > 1 number of nouns | |
| // when a verb comes after nother verb it starts a sentence on lower level. | |
| // 3 verbs cannot come after each other. | |
| // a verb cannot come after n < 2 number of nouns | |
| // example: | |
| // v v n n v n n v v n n v n n | |
| // is presented as tree: | |
| // v | |
| // ├── v | |
| // │ ├── n | |
| // │ └── n | |
| // ├── v | |
| // │ ├── n | |
| // │ └── n | |
| // └── v | |
| // ├── v | |
| // │ ├── n | |
| // │ └── n | |
| // └── v | |
| // ├── n | |
| // └── n | |
| func CompileXulu(s string) (int, error) { | |
| // 1. read statement | |
| statement := strings.Split(s, " ") | |
| // 2. validate statement | |
| err := validteStatement(statement) | |
| if err != nil { | |
| return 0, err | |
| } | |
| // 3. calculate statement | |
| return calculateStatementS(statement), nil | |
| } | |
| // translates a Xulu noun to int | |
| func translateNumber(s string) (number int) { | |
| var cache int | |
| for i, v := range []byte(s) { | |
| if i == 0 || s[i-1] == v { | |
| // 1. cache repeated alphabet till we rich another alphabet | |
| cache += int(v - 96) | |
| } else { | |
| // 2. calculate the cache and add to number | |
| cache = (cache % 5) | |
| cache = cache * cache | |
| number += cache | |
| cache = int(v - 96) | |
| } | |
| } | |
| // 3. calculate once more for the last sequence | |
| cache = (cache % 5) | |
| cache = cache * cache | |
| number += cache | |
| return | |
| } | |
| // validates Xulu statement syntax | |
| func validteStatement(s []string) error { | |
| var level int | |
| var c = map[int]int{0: 0} // counting each level children | |
| // the first token should always be a verbs | |
| if !isTokenVerb(s[0]) { | |
| return errors.New("failed to validate statement. invalid token at 0, statements should always start with a verb") | |
| } | |
| for i := 1; i < len(s); i++ { | |
| // -- validate token | |
| if !isTokenValid(s[i]) { | |
| return errors.New("failed to validate statement. invalid token at position " + fmt.Sprint(i)) | |
| } | |
| // -- check if token is verb | |
| if isTokenVerb(s[i]) { | |
| // -- check if previous token was verb | |
| if isTokenVerb(s[i-1]) { | |
| // -- increment level members | |
| c[level]++ | |
| // -- increment 1 level | |
| level++ | |
| c[level] = 0 | |
| // -- check if level-2 has more than 2 members cause we're not going back there anymore | |
| if level > 1 && c[level-2] < 2 { | |
| return errors.New("failed to validate statement. invalid syntax at position " + fmt.Sprint(i)) | |
| } | |
| } else if level > 0 { | |
| // -- increment level members | |
| c[level-1]++ | |
| // -- check if level has more than 2 members | |
| if c[level] < 2 { | |
| return errors.New("failed to validate statement. invalid syntax at position " + fmt.Sprint(i)) | |
| } | |
| // -- reset member count | |
| c[level] = 0 | |
| } else { | |
| // at the first level there should be no more than one verb wich is the first token | |
| return errors.New("sytax error at position " + fmt.Sprint(i) + ". cannot start another sentence outside a composite sentence.") | |
| } | |
| } else { | |
| // -- increment level members | |
| c[level]++ | |
| } | |
| } | |
| // in case we finished and missed to check the previous levels | |
| for l := level; l >= 0; l-- { | |
| if c[l] < 2 { | |
| return errors.New("syntax error invalid nesting.") | |
| } | |
| } | |
| return nil | |
| } | |
| // checks if a token is made of Xulu alphabet using regex | |
| func isTokenValid(s string) bool { | |
| return reAlphabet.Match([]byte(s)) | |
| } | |
| // checks if a token is one of (abcd, bcde, dede) | |
| func isTokenVerb(s string) bool { | |
| return reVerb.Match([]byte(s)) | |
| } | |
| // calculates Xulu statement using a single stack | |
| func calculateStatementS(s []string) int { | |
| var stack = []int{} | |
| var reserved = 0 | |
| // loop in reverse order (there should always be a noun at the end) | |
| // and since there are no closures in the syntax the last sentence is the leaf | |
| for i := len(s) - 1; i >= 0; i-- { | |
| if isTokenVerb(s[i]) { | |
| if isTokenVerb(s[i+1]) { | |
| // we are going one level up so we should sum up the whole stack and reset reserved | |
| // in another words we should sum up the answers of lower level sentences | |
| // therefore one answer remains which is the answer of top level sentence | |
| stack[0] = calculateSentence(textToVerb[s[i]], stack) | |
| stack = stack[:1] | |
| reserved = 0 | |
| } else { | |
| // calculate the sentence answer till reserved spot and remove the remaining | |
| // increment reserved so the answer will be preserved for the upper level sentence | |
| stack[len(stack)-reserved-1] = calculateSentence(textToVerb[s[i]], stack[:len(stack)-reserved]) | |
| stack = stack[len(stack)-reserved-1:] | |
| reserved++ | |
| } | |
| } else { | |
| // append to stack if its a noun | |
| stack = prepend(stack, translateNumber(s[i])) | |
| } | |
| } | |
| return stack[0] | |
| } | |
| // calculates Xulu statement using 2 stacks, one for local stack of only numbers | |
| // the second one is for the main sentences answers | |
| // depricated lol | |
| func calculateStatement(s []string) int { | |
| var mstack = []int{} | |
| var tstack = []int{} | |
| // loop in reverse order (there should always be a noun at the end) | |
| // and since there are no closures in the syntax the last sentence is the leaf | |
| for i := len(s) - 1; i >= 0; i-- { | |
| if isTokenVerb(s[i]) { | |
| if isTokenVerb(s[i+1]) { | |
| // we are going one level up so we should sum up the main stack | |
| // in another words we should sum up the answers of lower level sentences | |
| // therefore one answer remains which is the answerof top level sentence | |
| mstack[0] = calculateSentence(textToVerb[s[i]], mstack) | |
| mstack = mstack[:1] | |
| } else { | |
| // append the sentence answer to main stack and empty the temp stack | |
| // this way level answers are stored in main stack and temp stack is | |
| // ready to take neighbor nouns | |
| mstack = prepend(mstack, calculateSentence(textToVerb[s[i]], tstack)) | |
| tstack = tstack[:0] | |
| } | |
| } else { | |
| // append to temp stack if its a noun | |
| tstack = prepend(tstack, translateNumber(s[i])) | |
| } | |
| } | |
| return mstack[0] | |
| } | |
| // calculates answer of nouns using a given verb | |
| func calculateSentence(v verb, values []int) (o int) { | |
| o = values[0] | |
| values = values[1:] | |
| switch v { | |
| case v_ADD: | |
| for _, r := range values { | |
| o += r | |
| } | |
| break | |
| case v_MUL: | |
| for _, r := range values { | |
| o *= r | |
| } | |
| break | |
| case v_SUB: | |
| for _, r := range values { | |
| o -= r | |
| } | |
| break | |
| } | |
| return | |
| } | |
| // adds to the first of int list | |
| // important for order concerns when subtracting | |
| func prepend(l []int, i int) []int { | |
| l = append(l, 0) | |
| copy(l[1:], l) | |
| l[0] = i | |
| return l | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment