Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/ruby
- # A recursive function used elsewhere... not intended for direct use
- def target_through_shifts_rec(start, target, start_str, cur_depth, max_depth)
- to_return = start_str
- if ((start == 0) && (start != target))
- start += 1
- to_return += "I"
- end
- return to_return if (start == target)
- # Just finish the thing off once it reaches a certain depth...
- if (cur_depth >= max_depth)
- if (start < target)
- while ((start << 1) <= target)
- to_return += "L"
- start = start << 1
- end
- else
- while ((start >> 1) >= target)
- to_return += "R"
- start = start >> 1
- end
- if (start <= 0)
- to_return += "I"
- start += 1
- end
- end
- while (start < target)
- to_return += "I"
- start += 1
- end
- while (start > target)
- to_return += "D"
- start -= 1
- end
- return to_return
- end
- # Randomly shift or increment/decrement in the proper direction. Favor shifts
- # for the sake of variety.
- if (start > target)
- if (rand < 0.75)
- return target_through_shifts_rec(start >> 1, target, to_return + "R",
- cur_depth + 1, max_depth)
- end
- return target_through_shifts_rec(start - 1, target, to_return + "D",
- cur_depth + 1, max_depth)
- end
- if (rand < 0.75)
- return target_through_shifts_rec(start << 1, target, to_return + "L",
- cur_depth + 1, max_depth)
- end
- return target_through_shifts_rec(start + 1, target, to_return + "I",
- cur_depth + 1, max_depth)
- end
- # Returns a string describing increments and shifts: e.g. "RRRILLD" means shift
- # the start right by 3, increment, then shift left by 2, then decrement to
- # transform it to the target.
- def target_through_shifts(start, target)
- target_through_shifts_rec(start, target, "", 0, 20)
- end
- def translate_shifts_to_c(shift_str, var)
- cur_str = var
- elements = shift_str.scan(/[A-Z]/)
- elements.each do |op|
- if (op =~ /L/)
- cur_str = "(#{cur_str})<<1"
- elsif (op =~ /R/)
- cur_str = "(#{cur_str})>>1"
- elsif (op =~ /I/)
- cur_str = "1+(#{cur_str})"
- elsif (op =~ /D/)
- cur_str = "(#{cur_str})-1"
- end
- end
- cur_str
- end
- def build_c(str)
- return "" if (str.length == 0)
- header = "#define l putchar\n"
- header += "int main(void) {\n"
- prev_val = 64
- inner = "#{prev_val.to_s}"
- str.each_byte do |b|
- shifts = target_through_shifts(prev_val, b)
- prev_val = b
- new = translate_shifts_to_c(shifts, inner)
- inner = "l(#{new})"
- end
- shifts = target_through_shifts(prev_val, 0)
- new = translate_shifts_to_c(shifts, inner)
- inner = "return #{new};\n"
- to_return = header
- # Insert newlines 90 chars, don't break shift operators
- counter = 0
- inner.each_char do |c|
- to_return += c
- if ((c =~ /[l() +-]/) && (counter >= 90))
- counter = 0
- to_return += "\n"
- end
- counter += 1
- end
- # Remove trailing whitespace for cleanliness :)
- to_return.gsub!(/ +?\n/, "\n")
- to_return + "}"
- end
- str = ARGV.join(" ") + "\n"
- puts build_c(str)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement