Created
June 22, 2019 02:49
-
-
Save n4o847/310f9285376fec7ad5c4cdfc5b04c428 to your computer and use it in GitHub Desktop.
This file contains 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
class Hanoi | |
STACK = { :A => 0, :B => 1, :C => 2 } | |
BYTES = { :u8 => 0, :u16 => 1, :u32 => 2, :u64 => 3 } | |
def pair(x, y) | |
a, b = STACK[x], STACK[y] | |
raise "" if a == b | |
b -= 1 if a < b | |
[a, b] | |
end | |
{ | |
:add => 0b000, | |
:sub => 0b001, | |
:mul => 0b010, | |
:div => 0b011, | |
:mod => 0b100, | |
:or => 0b101, | |
:and => 0b110, | |
:xor => 0b111, | |
}.each do |name, xxx| | |
define_method(name) do |from, to, size = :u8| | |
yy, z = pair(from, to) | |
nn = BYTES[size] | |
@out << "001%03b%02b%01b%02b00000" % [xxx, yy, z, nn] | |
@ip += 1 | |
end | |
end | |
def copy(from, to, size = :u8) | |
xx, y = pair(from, to) | |
nn = BYTES[size] | |
@out << "0001%02b%01b%02b0000000" % [xx, y, nn] | |
@ip += 1 | |
end | |
def push(st, vvvvvvvv) | |
xx = STACK[st] | |
@out << "01%02b%08b0000" % [xx, vvvvvvvv] | |
@ip += 1 | |
end | |
def print(st) | |
xx = STACK[st] | |
@out << "00001%02b000000000" % [xx] | |
@ip += 1 | |
end | |
def pop(st, size = :u8) | |
xx = STACK[st] | |
nn = BYTES[size] | |
@out << "000000%02b%02b000000" % [xx, nn] | |
@ip += 1 | |
end | |
def goto(name) | |
@ip += 1 | |
@out << [name, @ip] | |
end | |
# def jmp(s, vvvvvvvvvvvvvv) | |
# @out << "1%01b%014b" % [s, vvvvvvvvvvvvvv] | |
# end | |
def iszero(st, size = :u8) | |
xx = STACK[st] | |
nn = BYTES[size] | |
@out << "000001%02b%02b000000" % [xx, nn] | |
@ip += 1 | |
end | |
def label(name) | |
@labels[name] = @ip | |
end | |
def exec(&block) | |
@out = [] | |
@ip = 0 | |
@labels = {} | |
instance_eval(&block) | |
data = @out.map {|op| | |
if op.is_a?(Array) | |
name, from = op | |
to = @labels[name] | |
s = to - from < 0 ? 1 : 0 | |
vvvvvvvvvvvvvv = (to - from).abs | |
op = "1%01b%014b" % [s, vvvvvvvvvvvvvv] | |
end | |
op.to_i(2) | |
}.pack("S<*") | |
File.write("./hanoi.txt", data) | |
puts "done: #{data.size} bytes" | |
end | |
end | |
Hanoi.new.exec do | |
pop :A, :u32 # [ 0 .. N | | ] | |
push :B, 50 # [ 0 .. N | 51 | ] | |
label :L5 | |
push :C, 84 # [ 0 .. N | x | 85 ] | |
sub :C, :A # [ 0 .. N | x (N-85) | 85 ] | |
pop :C # [ 0 .. N | x (N-85) | ] | |
iszero :B | |
goto :L1 | |
label :L2 | |
pop :B # [ 0 .. T | x | ] | |
push :C, 32 | |
print :C | |
pop :C | |
push :C, 1 # [ 0 .. T | x | 1 ] | |
sub :B, :C # [ 0 .. T (x-1) | x | 1 ] | |
pop :C # [ 0 .. T (x-1) | x | ] | |
pop :B # [ 0 .. T (x-1) | | ] | |
copy :A, :B # [ 0 .. T (x-1) | (x-1) | ] | |
copy :A, :B # [ 0 .. T (x-1) | (x-1) (x-1) | ] | |
pop :A # [ 0 .. T | (x-1) (x-1) | ] | |
iszero :B | |
goto :L2 | |
goto :L3 | |
label :L1 | |
pop :B # [ 0 .. N | x | ] | |
push :C, 1 # [ 0 .. N | x | 1 ] | |
sub :B, :C # [ 0 .. N (x-1) | x | 1 ] | |
pop :C # [ 0 .. N (x-1) | x | ] | |
pop :B # [ 0 .. N (x-1) | | ] | |
copy :A, :B # [ 0 .. N (x-1) | (x-1) | ] | |
pop :A # [ 0 .. N | (x-1) | ] | |
iszero :B | |
goto :L4 | |
pop :B | |
push :B, 51 # [ 0 .. N | 51 | ] | |
label :L4 | |
copy :A, :C # [ 0 .. N | (x-1) | N ] | |
pop :A # [ 0 .. N-1 | (x-1) | N ] | |
goto :L5 | |
label :L3 | |
pop :B # [ 0 .. T | 0 | ] | |
pop :B | |
push :B, 51 # [ .. N | 51 | .. M ] | |
push :B, 0 | |
label :L6 | |
pop :B | |
iszero :B | |
goto :L7 | |
pop :A | |
push :A, 35 | |
pop :B | |
push :B, 51 | |
label :L7 | |
print :A | |
copy :C, :A # [ .. N M | 51 | .. M ] | |
pop :C # [ .. M | 51 | .. L ] | |
push :C, 1 # [ .. M | x | .. L 1 ] | |
sub :B, :C # [ .. M (x-1) | x | .. L 1 ] | |
pop :C # [ .. M (x-1) | x | .. L ] | |
pop :B # [ .. M (x-1) | | .. L ] | |
copy :A, :B # [ .. M (x-1) | (x-1) | .. L ] | |
pop :A # [ .. M | (x-1) | .. L ] | |
push :C, 75 # [ .. M | (x-1) | .. L 75 ] | |
sub :C, :A # [ .. M | (x-1) (M-75) | .. L 75 ] | |
pop :C # [ .. M | (x-1) (M-75) | .. L ] | |
iszero :B | |
goto :L6 | |
pop :B | |
print :A | |
label :L8 | |
print :A | |
push :C, 1 | |
sub :B, :C | |
pop :C | |
pop :B | |
copy :A, :B | |
pop :A | |
iszero :B | |
goto :L8 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment