BlockSorting を Squeak Smalltalk で


BlockSorting - 西尾泰和のはてなダイアリー 経由で http://homepage3.nifty.com/DO/blocksorting.htmSqueak Smalltalk で書いてみる。

| encode decode |

encode := [:src |
    | srcsrc vars code |
    srcsrc := src, src.
    vars := (1 to: src size)
        collect: [:idx | srcsrc copyFrom: idx to: idx + src size - 1].
    code := vars sort collect: [:each | each last].
    {code as: String. vars indexOf: src}].

decode := [:args |
    | code pos pairs sorted |
    code := args first. pos := args second.
    pairs := code asArray collectWithIndex: [:each :idx | {each. idx}].
    sorted := pairs sortBy: [:a :b | a first < b first
        or: [a first = b first and: [a second < b second]]].
    String streamContents: [:ss | sorted size timesRepeat: [
        ss nextPut: (sorted at: pos) first.
        pos := (sorted at: pos) second]]].

^decode value: (encode value: 'abracadabra')   "=> 'abracadabra' "


どうしてこれで復号できるのか(理屈は分かっても)不思議な感じ。



マイブームの Rubinius Ruby でも直訳っぽく。

class Array; def second; self[1] end end
module Enumerable
  def collect_with_index; i = -1; collect{|ea| yield(ea, i+=1)} end
end

def encode(src)
  srcsrc = src + src
  vars = (0..src.size-1).collect{|idx| srcsrc[idx, src.size]}
  code = vars.sort!.collect{|e| e.split(//).last}
  [code, vars.index(src)]
end

def decode(code, pos)
  pairs = code.to_a.collect_with_index{|ea,idx| [ea, idx]}
  sorted = pairs.sort
  result = []
  sorted.size.times{
    result << sorted[pos].first
    pos = sorted[pos].second}
  result.join
end

p decode(*encode("abracadabra"))   #=> "abracadabra"