Reputation: 43
Recently I have been working on making a Python program that iterates over a string. I'm making an ESOLANG with this, but I've run into a big issue. This question is quite long, and I apologize for this. Here is the basic syntax, which you'll need to know to answer this.
e
sets the current value to the next character, so eA
sets current value to A
and eB
sets it to B
.p
prints the current value, so eFpeopp
prints Foo
.v
sets a variable. Running eAvB
will set the variable B
to A
.g
gets the value for a variable. The interpolator comes with a default variable (?
) which returns the version. So evpg?p
will print v2
. Use gc
to get the variable with the same name as the current value.(
starts a loop and )
ends a loop. You can specify the amount of times the loop will run with (n)
with n as the number from 0-9. You can use a bigger number with c
which will use the current value (ascii number)+
and -
increase and decrease the current value.f
generates a factorial. The variable 0
will be set to the length of the output, so 5
will make 0
to 3
because the factorial of 5
is 120
which is 3
digits. Then variables 1
-3
will have the results because there are three letters. So this program sets current value to 5 and prints the factorial of it. +++++fg1pg2pg3p
. In this example, the length (3) is hard coded, so another number wont work. Another flaw is that input is only 1 number. This can be fixed with loops.
There are some other characters, but they are not related to this. If you are interested, you can use this Discord bot.
Now, my problem. I am trying to get the factorial working, but I can't get it to work. This is my code (yes it is very long):from math import factorial
def parse(code, currentValue=0, varis={"?":"2"}, getCurrent=False):
# Copyright (c) UCYT5040
# minlang - A minimal language
output = ""
outputNext = False
getNext = False
setNext = False
valNext = False
appendNext = False
getLoopAmount = False
inLoop = False
loopCode = ""
runMoreTimes = 0
openLoops = 0
for i in code:
if valNext:
currentValue = ord(i)
valNext = False
continue
if appendNext:
currentValue += ord(i)
appendNext = False
continue
if getNext:
if i == "c":
currentValue = ord(varis[chr(currentValue)])
else:
currentValue = ord(varis[i])
getNext = False
continue
if outputNext:
output += chr(i)
outputNext = False
continue
if setNext:
varis[i] = chr(currentValue)
setNext = False
continue
dontDoThis = False
if inLoop:
if i == "(": openLoops+=1
if i == ")" and openLoops != 0:
openLoops -= 1
if openLoops == 0:
inLoop = False
dontDoThis = True
if not dontDoThis:
loopCode += i
continue
if getLoopAmount:
if i == "c": runMoreTimes = currentValue
else: runMoreTimes = int(i)
getLoopAmount = False
inLoop = True
while runMoreTimes > 0:
if not inLoop:
runMoreTimes -= 1
output += parse(loopCode, currentValue, varis)
currentValue = parse(loopCode, currentValue, varis, getCurrent=True)
else: break
if runMoreTimes == 0 and not inLoop:
loopCode = ""
if i == "e": # Sets the current value to the next character
valNext = True
if i == "a": # Adds the next character to the current value
appendNext = True
if i == "p": # Print current value
output += chr(currentValue)
if i == "g": # Get the value of a variable
getNext = True
if i == "v": # Set a variable
setNext = True
if i == "(":
getLoopAmount = True
openLoops += 1
if i == "-":
currentValue -= 1
if i == "+":
currentValue += 1
if i == "i":
currentValue = ord(input("Enter only 1 character of input: "))
if i == "?":
if varis["%"] == varis["!"]:
output += chr(currentValue)
if i == "&":
if not varis["%"] == varis["!"]:
break
if i == "f":
fact = str(factorial(currentValue))
varis["0"] = str(len(fact))
for ii in range(len(fact)):
f = fact[ii]
print(type(f),f,"fact")
varis[str(ii+1)] = f
print(varis["0"])
if getCurrent:
return currentValue
return output
print(parse(input("Enter code to run: ")))
Here are a few of my attempts to get it working.
UCYT5040: min run +++++fg1pg2pg3p
BOT > Minlang Runner: 120
This was successful, but the following are not.
UCYT5040: min run va++++f g0(cga+vagcp)
Command raised an exception: KeyError: '\x01'
Expanation: Set var a to 0. Get the factorial of 4. Get the value of 0, and run a loop of its length. Edit var a to get each digit. Get the value of the 1st digit (var 1). --ERROR: Trying to get var \x01 rather than 1.--
Why is \x01 passed?
Upvotes: 3
Views: 75
Reputation: 747
I think you need to replace chr()
and ord()
with the simple str()
and int()
in the getNext
function's if
branch, i.e.,
currentValue = ord(varis[chr(currentValue)])
Why:
using currentValue = 1
and assuming factorial has been calculated
chr(1) = '\x01'
so when you try to access varis['\x01']
the key doesn't exist in the dictionary [since inside the factorial you store it using str(ii+1)...
not chr()
Instead,
str(1) = '1'
, so you will access varis['1']
, which will result in '2'
and int('2') = 2
.
Upvotes: 1