2014-05-01 69 views
1

我需要解壓縮打包的ASCII字符的字符串。算法如下:在ruby中更加優雅的打包ASCII算法的實現

  1. 獲取3個打包的ASCII字節,將它們放入4個ASCII字節。 (3字節至4字節中的6 + 6 + 6 + 6位)
  2. 對於每個字節,將位6設置爲位5的補碼。
  3. 對於每個字節將位7復位爲零。
  4. 對下3個打包字節重複。

我是新來的Ruby,可能是有解決這個任務更正確,更優雅的方式,而我的代碼:

while i < pstr.length 
    parr = [pstr[0] & 0x3F, pstr[0]>>6 | ((pstr[1] << 2) & 0x3F), 
      pstr[1]>>4 | ((pstr[2] << 4) & 0x3F), 
      pstr[2]>>2] 
    parr.collect! { |a| a | (~(a << 1) & 0x20) }   
    parr.collect! { |a| a & 0x7F } 

    puts parr 

    i += 3 
end 

UPDATE1:THX用於收集校正。

+2

只是爲了澄清:您的代碼按預期工作(例如通過測試),但您希望獲得有關Ruby成語或快捷方式的幫助?你可以添加一些測試輸入和驗證輸出到問題,這將有所幫助。 –

+0

你看過'#unpack'嗎? http://www.ruby-doc.org/core-2.1.1/String.html#method-i-unpack –

+0

@UriAgassi當我在文檔中閱讀時,Ruby不支持打包/解壓縮打包的ASCII碼。 – Darkkey

回答

1

雖然紅寶石的Array#packString#unpack不直接支持ASCII包並解壓,他們通過pack('m')unpack('m')方式支持Base64編碼。這可以幫助解決涉及從每個保存8個相關位的3個字節到每個保存6個4個字節的位移。

這是一個開始的實現packunpack這是一個更紅寶石式的。 pack對字符串的操作是4的精確倍數,刪除任何餘數。相反地​​unpack每3個字符擴大到4

B64 = ('A'..'Z').to_a+('a'..'z').to_a+('0'..'9').to_a+%w(+ /) # Base64 alphabet 
H64 = Hash[B64.zip(0..63)] # Hash character to index 

# Translates every 4 characters to 3, drops any remainder 
def pack(ascii) 
    ascii.bytes.map { |b| B64[b&(b&0x40==0?0x3f:0x1f)] }.join.unpack('m')[0] 
end 

# Translates every 3 characters to 4 
def unpack(bstr) 
    [bstr].pack('m').chomp.split('').map do |c| 
     ((H64[c]|0x40) & (H64[c]&0x20==0?0x5f:0x3f)).chr 
    end.join 
end 

實例:

ascii_packed = pack('Hello World!') 
puts ascii_packed.length # => 9 
puts unpack(ascii_packed) # => "HELLO WORLD!" 

對於那些不熟悉的ASCII包,它是一個 「有損」 壓縮。在範圍0x20 <= x < 0x60以外的ASCII字符x被翻譯成該範圍內的字符。這就是爲什麼小寫字母在打包/解包時會大寫字母的原因。