KEMURI/str2kemuri.rb

From Esolang
Jump to navigation Jump to search

Back to KEMURI

A simple script to take a string from stdin and generate a KEMURI program to output such string. Works with mruby 3.4.0 (2025-04-20).

Warning: generates verbose program.

#!/use/bin/env ruby

class String2Kemuri
  def initialize
    @basic_table = Hash.new
    @table = Array.new(256)
    make_basic_table
    make_table
  end

  def make_basic_table
    #"Hello, world!"の各文字
    @basic_table[32] = %q{`^^^^^"^^'^"^^'^"^^'^"^^}
    @basic_table [?!.ord] = %q{`^^^^^^^^^^^"^^}
    @basic_table [?,.ord] = %q{`^^^^"^^'^"^^'^"^^'^"^^"'^"^^}
    @basic_table [?H.ord] = %q{`'^"^^'^"^^'^"^^'^"^^'^"^^'^"^^}
    @basic_table [?d.ord] = %q{`^^^^^^^^^^"^''^"^^}
    @basic_table [?e.ord] = %q{`"^^'^"^^'^"^^'^"^^'^"^^'^"^^"'^"^^}
    @basic_table [?l.ord] = %q{`^^^^^^^^^"^''^"^^"'^"^^}
    @basic_table [?o.ord] = %q{`^^^^^^^"^^'^"^^'^"^^}
    @basic_table [?r.ord] = %q{`^^^^^^^^"^''^"^^'^"^^}
    @basic_table [?w.ord] = %q{`^^^^^^"^^'^"^^'^"^^"'^"^^}

    # '0'
    @basic_table [0] = @basic_table [?H.ord] + @basic_table [?H.ord] + "^"

    # xor 255
    @basic_table .each do |k,v|
      @basic_table [k^255] ||= v + "~"
    end

    @basic_table .each do |k,v|
      @table[k] = v
    end
  end

  def make_table
    # 基本文字を4つ使えば、0..256まで埋まるみたい
    cs = @basic_table.keys
    cs.each do |i|
      cs.each do |j|
        cs.each do |k|
          cs.each do |l|
            x = i ^ j ^ k ^ l
            @table[x] ||= compile([i,j,k,l])
          end
        end
      end
    end
  end

  def compile(ary)
    # 無駄な文字を省く
    # HdHe => de
    ary.sort!
    for i in 1..(ary.size)
      if ary[i-1] == ary[i]
        ary[i-1] = nil
        ary[i] = nil
      end
    end
    ary.delete_if{|e|
      e==nil || e == 0 # a ^ 0 == a
    }

    # KEMURIに変換する
    ary.map!{|ch|
      @basic_table[ch]
    }
    ary.join("") + ("^" * (ary.size-1))
  end

  def to_kemuri(str)
    str.unpack("C*").map{|c| @table[c]}.reverse.join("") + "|"
  end
end

if $0 == __FILE__
  s2k = String2Kemuri.new
  print s2k.to_kemuri($stdin.read)
end