QX

From Esolang
Jump to navigation Jump to search

QX is a minimal language made by User:↑.

QX logo
Logo.

Commands

Command What it does
Q [a] Increments the current value at pointer by a. Can decrement if a is negative
X [a] [b] If a <= previous item at pointer then go to previous item at pointer and jump to line b else go to next item at pointer.

Computational class

QX is Turing-complete by translation from unbounded brainfuck.

Command Translation
+ Q 1
- Q -1
> X ∞ 0
< X -∞ n, where n is the next line
[ X ∞ 0 X 1 s X -∞ e, where s is the next command and e is after the corresponding ]
] X ∞ 0 X 1 s X -∞ e, where s is after the corresponding [ and e is the next command

Note that this assumes infinity is a valid constant.

Examples

Infinite loop

X 0 1

A+B Problem

Q ?
Q ?

If A and B must start separate:

Q ?
X 1 0
Q ?
X 1 6
X 0 12
Q -1
X 1 0
Q 1
X ∞ 0
X 0 4 

Lua interpreter

Made by User:Aadenboy

assert(arg[1], "Argument 1 must be a file to interpret")
local file = io.open(arg[1], "r")
assert(file, "File not found")
local code = file:read("*a")
file:close()

local range = {1, 1}
local mem = {0}
local pointer = 1
local commands = {}
code = code:gsub("∞", "i")
for pos, qx, a, b in code:gmatch("()([QX])%s*([%d%-%?%.i]*)%s*([%d%-%?%.i]*)") do
  a = a == "?" and "?" or (a == "i" and math.huge or (a == "-i" and -math.huge or tonumber(a)))
  b = b == "?" and "?" or (b == "i" and math.huge or (a == "-i" and -math.huge or tonumber(b)))
  local line = ({code:sub(0, pos):gsub("\n", "")})[2] + 1
  local char = #code:sub(0, pos):match("\n?([^\n]+)$")
  assert(a, line..":"..char..": "..qx.." expects at least one integer")
  assert(qx == "Q" or b, line..":"..char..": X expects two integers")
  table.insert(commands, {qx = qx, a = a, b = qx == "X" and b})
end

local i = 1
local steps = 0
repeat
  steps = steps + 1
  local c = commands[i]
  local a = c.a == "?" and (tonumber(io.read()) or 0) or c.a
  local b = c.b == "?" and (tonumber(io.read()) or 0) or c.b
  if c.qx == "Q" then
    i = i + 1
    mem[pointer] = mem[pointer] + a
  else
    local pre = mem[pointer-1] or 0
    pointer = pointer + (a <= pre and -1 or 1)
    mem[pointer] = mem[pointer] or 0
    i = a <= pre and b or i + 1
  end
  range = {math.min(range[1], pointer), math.max(range[2], pointer)}
until i < 1 or i > #commands or steps >= (tonumber(arg[2]) or math.huge)

print(steps.." steps\nPointer at "..pointer.."\nMemory:")
for i=range[1], range[2] do
  print("\t["..i.."]: "..mem[i])
end