KEEP K.I.S.S.

tk's blog

安装jekyll后一个无法使用的问题解决

Ruby环境是安装在C:\Program Files目录下面的,而不是默认的根目录。

安装Jekyll后,无法使用jekyll命令,会提示如下错误

'""c:\program' 不是内部或外部命令,也不是可运行的程序 或批处理文件

应该是路径处理有问题。

用记事本打开Ruby安装位置的bin目录下的jekyll.bat文件,会发现调用Ruby可执行程序的部分代码中双引号不配对,开头命令"@"符号后多用了一个双引号,共有两行,去掉后就好了。可能需要管理员权限打开记事本编辑再保存。

Ruby 的小角度7参数转换简单描述

小角度7参数转换的 Ruby 使用 Matrix的简单描述

小角度的7参数坐标系转换可以化简原本的转换参数公式,最后如下图片描述

 

 

这是一段根据3个点对的坐标来求解转换额外一点的对应坐标的 Ruby代码,使用了Ruby标准库里的 Matrix,很方便的:

 

require 'matrix'

def buildBUnit(*p)
  a = []
  a[0, 7] = 1, 0, 0, p[0], 0, -p[2], p[1]
  a[7, 7] = 0, 1, 0, p[1], p[2], 0, -p[0]
  a[14, 7] = 0, 0, 1, p[2], -p[1], p[0], 0
  a
end

def cutDown(*p, count)
  a = []
  row = 0
  while row < (p.count.to_f / count).ceil
    a << p[row * count, count]
    row += 1
  end
  a
end

def buildB(*p)
  a = []
  p.each {|point| a += buildBUnit(*point) }
  Matrix[*(cutDown(*a, 7))]
end

def buildA(*p)
  Matrix.column_vector(p.flatten)
end

m = [[ 30.55876333, 117.2395818, 13.09], [30.55882632, 117.23958408, 13.188], [ 30.55876333, 117.23968333, 13.09]]
p = [[13.127, -3.579, 10.143], [13.090, 3.434, 10.200], [3.127, -3.579, 10.143]]
B = buildB(*p)
A = buildA(*m)

BT = B.transpose
temp = BT * B
X = temp.inv * BT * A

bas = [47.850, -0.020, 3.399]
trans = Matrix[*cutDown(*buildBUnit(*bas), 7)]
MM = trans * X
p MM

#够简单的。。。。

Ruby的字节操作

一个字节其实也就是一个整数,如果用十六进制表示的话,正好是两个十六进制数,用字符串表示就是 “HH”这样的表示。

Ruby的字节操作主要是靠两个方法来实现,String#unpack 和 Array#pack,两个类的实例方法,参数均为单一字符串。

举一个例子来讲解。

一般的 32位 Little-endian 机器上的单精度浮点数 float的一个实例: f = 88.888,得到它的字节表示 =>

因为字节操作需要 Array 类的 pack 操作,所以先把 f 放入一个数组实例中

 

irb(main):001:0> f = 88.888
=> 88.888
irb(main):002:0> s = []
=> []
irb(main):003:0> s << f
=> [88.888]
irb(main):004:0>

然后需要 pack 得到字符串表示

 

irb(main):004:0> s.pack("F")
=> "\xA8\xC6\xB1B"

也许会奇怪这个字符串为什么会这样,其实这里是 "\xA8\xC6\B1\x42",因为 \x42 正好是ASCII码表中 'B' 的十六进制代码,所以这里会显示成这样连着的。

然后我们得到字节的数值表示和十六进制表示:

 

irb(main):005:0> s.pack("F").unpack("C*")
=> [168, 198, 177, 66]
irb(main):006:0> s.pack("F").unpack("H*")
=> ["a8c6b142"]

还有一种方式:

 

irb(main):007:0> s.pack("F").unpack("C*").collect {|x| x.to_s(16) }
=> ["a8", "c6", "b1", "42"]

其实难点在于 pack 和 unpack 的操作,这个参数会很多,理解起来也有点难度,我觉得还是多用用就比较好理解了。

Ruby 转换 Hex文本文件为二进制文件

用串口调试助手接受哦串口数据,貌似没找到怎么直接存储为二进制文件,所以用文本框显示十六进制字节流表示,然后存储(如果直接显示二进制会乱码,而且转换会丢失数据)。然后就写了个Ruby脚本来还原这个十六进制文本流。

 

filename = ARGV[0]
bytes = []
File.open(filename, "r") do |file|
  while str = file.gets
    bytes += str.split.map {|byte| byte.hex}
  end
end

puts bytes.count

newfilename = filename + ".bin"
File.open(newfilename, "wb") do |file|
  file.write bytes.pack("C*")
end

Euler Project Problem 14 with Ruby

看题

 


The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.

 

Ruby 代码 这个速度还算可以了 4秒之内出结果

 

#!/d/ruby192/bin/ruby
#coding:utf-8

# get the next num of the chain
def next_num(num)
  if num.even?
    num/2
  else
    num*3+1
  end
end

$cache = Hash.new(0)

def get_len(num)
  if $cache.include?(num)
    res = $cache[num]
  else
    res = get_len(next_num(num))+1
    $cache[num] = res
  end
  res
end
$cache[1] = 1
$cache[2] = 2
$cache[4] = 3

$max,$most = 1,1
# from 1 to 1 million, so that the $cache may be used the most
(1...1_000_000).each do |num|
  if $max < get_len(num)
    $max = get_len(num)
    $most = num
  end
end  
puts $most,$max