Talk:EnScript

From Esolang
Jump to navigation Jump to search

The ENC Command

Hey, just want to know if I've understood the ENC command correctly. Is the following example correct?

LDA A, 13425
LDA B, 53241
ENC A, B
  • The look-up table
Key Value
1 5
2 3
3 2
4 4
5 1

is created (I guess that means that accumulator B is 1-indexed rather than 0-indexed)

  • The first digit of A (1) is replaced with a 5
  • The second digit of A (3) is replaced with a 2
  • The third digit of A (4) is replaced with a 4
  • The fourth digit of A (2) is replaced with a 3
  • The fifth digit of A (5) is replaced with a 1

Consequently, accumulator A ends up holding the value 52431.JonoCode9374 (talk) 07:22, 4 June 2019 (UTC)

Also, if the lookup table contains digits that aren't unique (e.g. 1233), does that mean that the string cant be encrypted? JonoCode9374 (talk) 07:33, 4 June 2019 (UTC)

By the way, watch out! The lookup table is not sorted!

You are getting the ideas right. However, I would like to describe that "look-up table". Every element in a "lookup-table" exists and is unique. For example, if the command ENC A, B was executed, with LDA A, 111 and LDA B,222 is executed, this "lookup-table" will be created:

Key Value
2 1
2 1
2 1

Also, since every element should be unique, the lookup-table will change to:

Key Value
2 1

The rest of the numbers map to 0:

Key Value
1 0
2 1
3 0
4 0
5 0
6 0
7 0
8 0
9 0

All elements inside A will be changed to 0(resulting a 000). Then, it will change to 0, as all preceding zeroes are deleted automatically after a number.

And back to the problem you specified:

LDA A, 13425
LDA B, 53241
ENC A, B

For simplicity, all mappings to 0 will be skipped in the table.
The encryption will happen on A, so B will be the key and A will be the value(sorry if I messed up a bit in the spec):

  • The lookup table
Key Value
5 1
4 3
3 4
2 2
1 5

So, A will be converted into:54321. Please note that it is reversed.

Sorry if this is bothering you; I tried to make it as unique as possible.

(PS. If this language runs as what you specified, it would just be nonsense to specify this much. It will be a command that copies another accumulator's value to this accumulator. The example that you just made is a result of messing up with the lookup table, as you have mis-replaced the numbers and got a different result.)--A (talk) 10:55, 4 June 2019 (UTC)

No worries, it's not bothering me at all - - just trying to make an interpreter for it, and needed to know the exact sleds. JonoCode9374 (talk) 12:03, 4 June 2019 (UTC)
If you have a partial interpreter, please put it here; I might know how to fix it. --A (talk) 10:23, 5 June 2019 (UTC)
Sure, I'll put it on tomorrow when I have my computer... Editing things on my phone isn't exactly easy! JonoCode9374 (talk) 11:33, 5 June 2019 (UTC)

The CHS Command

Also, could someone clarify the CHS command? What I want to know is how the amount of places each number is shifted is determined. Is it based upon the index of the character upon time of shifting, or is there something else I'm missing? JonoCode9374 (talk) 07:42, 4 June 2019 (UTC)

No, that is invalid. What I mean is just inserting a number into that digit and delete the number before insertion. Find a position, which is specified by the number itself. Then, insert that number into the number list. It has nothing to do with shifting. Make sure that all numbers have inserted once, and then CHS will be done.--A (talk) 11:02, 4 June 2019 (UTC)

Partial Interpreter

#EnScript Esolang Interpreter
#No rights reserved

#Usage:
#python3 enscript.py file.en --mode [lazy|strict]

def is_isogram(string):
    for char in string:
        if string.count(char) > 1:
            return False
    return True

class Interpreter:
    def __init__(self, code):
        self.lines = code.split("\n")
        self.accs = {} #Accumulator list starts empty
        self.ip = -1

    def step(self):
        #Move to the next command
        self.ip += 1

        for acc in self.accs:
            if self.accs[acc][0] == "9":
                self.ip = -1
                return False
        
        if self.ip > len(self.lines):
            self.ip = 0

        return True

    def _encrypt(self, source, acc_table):
        if not is_isogram(self.accs[acc_table]):
            return

        table = dict()

        for char in self.accs[source]:
            if self.accs[acc_table].find(char) == -1:
                return
            else:
                table[char] = self.accs[acc_table].index(char) + 1

        temp = ""

        for char in self.accs[source]:
            temp += table[char]

        self.accs[acc_source] = temp

    
    def _chase(self):
        pass

    def _rev(self, source, location):
        self.accs[location] = self.accs[source][::-1]

    def _increment(self, source, location):
        temp = ""
        for char in self.accs[source]:
            if char == 9:
                temp += 0
            else:
                temp += str(int(char) + 1)
        self.accs[location] = temp

    
    def _load(self, location, value):
        self.accs[location] = value


    def execute(self):
        while self.step():
            cmd, values = self.lines[self.ip].split(" ", 1)
            values = values.split(", ")

            if cmd == "ENC":
                fn = self._encrypt

            elif cmd == "CHS":
                fn = self._chase

            elif cmd == "REV":
                fn = self._rev

            elif cmd == "INC":
                fn = self._increment

            elif cmd == "LDA":
                fn = self._load

            elif cmd == "INP":
                self.accs[values[0]] = input()
                continue
            
            elif cmd == "OUT":
                print(self.accs[values[0]], end="")
                continue

            fn(values[0], values[1])
            
if __name__ == "__main__":
    x = Interpreter('''
    Code here
    ''')

    x.execute()
 

Uh-oh, what you left out is the CHS command, which is the only command that I don't know how to implement. --A (talk) 04:05, 6 June 2019 (UTC)

I didn't know how to implement it either. JonoCode9374 (talk) 06:48, 6 June 2019 (UTC)

The first thing that comes to my mind is to implement a queue, but I haven't wrote queues before, and writing them is very difficult(personally). (That should be an interesting golfing exercise though.) I should try to write a program that puts things into a queue and then pops them first.--A (talk) 08:12, 6 June 2019 (UTC)

Here is my code for deques (does not support pop_back, but should be fine for implementing queues; credits https://blog.csdn.net/NFR413/article/details/78448954):

def push_back(x,item):
    x.insert(0,item)

def pop_front(x):
    x.pop()

def front(x):
    return x[-1]

def back(x):
    return x[0]

def push_front(x,item):
    x.append(item)

I think the algorithm will be:

  • Create another queue marking whether the item has been chased. If every item in that queue has became 1, stop the algorithm.
  • While every item in the marking queue has not became 1:
    • Remove the item in the back of the main queue and use it as a while loop
    • While this item in its number form is larger than 0:
      • Pop the back of the main queue
      • Push the popped value of the main queue back to the front of the main queue
      • Decrement this item by 1
    • Push the item before decrementing back to the back of the main queue
    • Mark that this number has been chased

I discovered this implementation:

# Index to shift, Times remaining
def Shift(i, t):
    if t<1:L[i][1]=0;return
    if i+1<len(L):
        L[i],L[i+1]=L[i+1],L[i]
        Shift(i+1,t-1)
    else:
        L.insert(0,L.pop())
        Shift(0,t-1)
L=[[c,1]for c in input()]
while 1:
    t=[x for x in L if x[1]]or exit("".join(x[0]for x in L))
    i=L.index(min(t,key=lambda x:x[0]))
    Shift(i,int(L[i][0]))