fork download
  1. # [digits].my_digits(base)
  2. # [digits].my_digits([base]) # ex. [9,33,21,1428].undigits([24,60,60]) #=> 123456789
  3. # baseは数値または数値の配列
  4. # ty 0:baseは基数, 1:baseは |ビット数|
  5. class Array
  6. def undigits(base=10,ty=0)
  7. if base.is_a?(Array)
  8. case ty
  9. when 0
  10. bs = [*base,1]
  11. b = 1
  12. return self.inject(0){|r,i|
  13. if bs.empty?
  14. # raise ArgumentError
  15. return r
  16. else
  17. b *= bs.pop.abs
  18. next b * i + r if i.is_a?(Integer)
  19. # raise ArgumentError
  20. r
  21. end
  22. }
  23. when 1
  24. bs = base.dup
  25. b = 0
  26. return self.inject(0){|r,i|
  27. if bs.empty?
  28. # raise ArgumentError
  29. return r
  30. else
  31. ab = bs.pop.abs
  32. val = r | ((i & (1 << ab) - 1) << b)
  33. b += ab
  34. next val
  35. end
  36. }
  37. end
  38. raise ArgumentError, 'type'
  39. end
  40. raise( ArgumentError, 'base' ) if base.is_a?(Integer).!
  41. case ty
  42. when 0
  43. raise( ArgumentError, 'base' ) if base <= 1
  44. return self.reverse.inject(0){|r,i|
  45. next base * r + i if i.is_a?(Integer)
  46. # raise ArgumentError
  47. r
  48. }
  49. when 1
  50. raise( ArgumentError, 'base' ) if base == 0
  51. ab = base.abs
  52. msk = (1 << ab) - 1
  53. b = 0
  54. return self.inject(0){|r,i|
  55. # raise ArgumentError unles i.is_a?(Integer)
  56. next r unless i.is_a?(Integer)
  57. r += (i & msk) << b
  58. b += ab
  59. r
  60. }
  61. else
  62. raise ArgumentError
  63. end
  64. end
  65. alias_method :to_i, :undigits
  66. end
  67.  
  68. # baseは数値または数値の配列
  69. # ty 0:baseは基数, 1:baseはビット数、負のビット数は符号拡張する
  70. class Integer
  71. def my_digits(base=10,ty=0)
  72. v = self.to_i
  73. raise ArgumentError if v < 0
  74. if base.is_a?(Array)
  75. return [0] if v == 0
  76. case ty
  77. when 0
  78. bs = base.dup
  79. r = []
  80. while v > 0
  81. if bs.empty?
  82. r << v
  83. break
  84. else
  85. b = bs.pop
  86. v, n = v.divmod(b)
  87. r << n
  88. end
  89. end
  90. return r
  91. when 1
  92. bs = base.dup
  93. r = []
  94. while v > 0
  95. if bs.empty?
  96. # r << v
  97. break
  98. else
  99. b = bs.pop
  100. ab = b.abs
  101. bv = v & ((1 << ab) - 1)
  102. if b < 0
  103. xt = 1 << ab-1
  104. bv = (bv ^ xt) - xt
  105. end
  106. r << bv
  107. v >>= ab
  108. end
  109. end
  110. return r
  111. end
  112. raise ArgumentError
  113. end
  114. return [0] if v == 0
  115. raise( ArgumentError, 'base' ) if base.is_a?(Integer).! # || base <= 1
  116. ab = base.abs
  117. if ty == 0 && ab & (ab-1) == 0 # 2のべき乗?
  118. base = ab.bit_length - 1 # Math.log2(ab).round
  119. ty = 1
  120. ab = base # debug 2019/12/22 13:39 JST
  121. end
  122. r = []
  123. case ty
  124. when 0
  125. raise( ArgumentError, 'base' ) if base <= 1
  126. while v > 0
  127. v, n = v.divmod(base)
  128. r << n
  129. end
  130. return r
  131. when 1
  132. raise( ArgumentError, 'base' ) if base == 0
  133. msk = (1 << ab) - 1
  134. xt = 1 << ab - 1
  135. while v > 0
  136. r << ((base < 0)? ((v & msk) ^ xt) - xt : v & msk)
  137. v >>= ab
  138. end
  139. return r
  140. end
  141. raise ArgumentError
  142. end
  143. end
  144.  
  145. # Hash#bits( bitFieldHash ) -> Integer
  146. class Hash
  147. def bits( h )
  148. raise ArgumentError unless h.is_a?(Hash)
  149. h.keys.reverse.map{|k| self[k] || 0 }.undigits( h.values, 1 )
  150. end
  151. end
  152.  
  153. # Integer#unbit( bitFieldHash ) -> {bitValue}
  154. class Integer
  155. def unbits( h )
  156. raise ArgumentError unless h.is_a?(Hash)
  157. v = self.my_digits( h.values, 1 )
  158. v.push( *Array.new( h.size-v.size, 0 ) ) if v.size < h.size
  159. Hash[ *h.keys.map{|ky| [ky,v.pop || 0] }.flatten ]
  160. end
  161. end
  162.  
  163. #####################################################################
  164.  
  165. # test v2 2019/12/26
  166. module CheckRet_
  167. def self.check( f_verbose = false, f_lineNo = false )
  168. crb = Check_ret_bind_.new.instance_binding
  169. fl = (f_verbose.is_a?(Hash))? f_verbose[:lineno] : f_lineNo
  170. fv = (f_verbose.is_a?(Hash))? f_verbose[:verbose] : f_verbose
  171. fl &&= fv
  172. while buff = DATA.gets(chomp:true)
  173. print "%5d: " % DATA.lineno if fl
  174. case
  175. when /^\s*([^#].*?)#=>(.*)$/ =~ buff
  176. puts buff if fv
  177. syn = $1.strip
  178. val = $2.strip.sub(/\s*### .*$/,'')
  179. begin
  180. ans = eval( syn, crb )
  181. rescue
  182. puts "#{DATA.lineno}: #{$!}"
  183. end
  184. begin
  185. if ans != eval( val, crb )
  186. puts "*** Error : #{syn} #=> #{ans.inspect} != #{val} ***"
  187. end
  188. rescue
  189. puts "#{DATA.lineno}:#=> #{$!}"
  190. end
  191. when /^#---/ =~ buff
  192. puts if fl
  193. break if /^#---\s*END\b/i =~ buff
  194. when /^\s*#/ =~ buff
  195. puts buff if fv
  196. when buff != ''
  197. puts buff if fv
  198. begin
  199. eval( buff, crb )
  200. rescue
  201. puts "#{DATA.lineno}: #{$!}"
  202. end
  203. else
  204. puts buff if fv
  205. end
  206. end
  207. end
  208.  
  209. private; class Check_ret_bind_; def instance_binding; binding end end
  210. end
  211.  
  212. CheckRet_.check( lineno:true, verbose:true )
  213. puts "Done."
  214.  
  215. __END__
  216. [1, 1, 0, 1, 'hoge'].to_i(2) #=> 11
  217. 123456789.my_digits([24,60]) #=> [9, 21, 85733]
  218. 123456789.my_digits([24,60,60]) #=> [9,33,21,1428]
  219.  
  220. Bhms = [24,60,60]
  221. [9,33,21,1428,'d h:m:s'].undigits(Bhms) #=> 123456789
  222. 123456789.my_digits(Bhms).undigits(Bhms) #=> 123456789
  223. [9,33,21,1428, 9,9,9,9].undigits(Bhms) #=> 123456789
  224. [9,33,21].undigits(Bhms) #=> 77589
  225. [9,33].undigits(Bhms) #=> 1989
  226. [9].undigits(Bhms) #=> 9
  227.  
  228. # ==== bit field test ====
  229.  
  230. 0117.my_digits(8) #=> [7,1,1]
  231. 0117.my_digits(3,1) #=> [7,1,1] ### 上と同じ 8 == 2**3
  232.  
  233. [3,3,7].undigits(3,1).to_s(8) #=> "733"
  234. [1,3,7,8,0xFFFF,-1].undigits(3,1).to_s(8) #=> "770731"
  235.  
  236. 0b0011_100_01.my_digits([4,3,2],1) #=> [1,4,3]
  237. [1,4,3].undigits([4,3,2],1).to_s(2) #=> "1110001"
  238. 0b0011_100_01.my_digits([-4,-3,-2],1) #=> [1,-4,3] ### (-4:符号拡張)
  239. [1,-4,3].undigits([4,3,2],1).to_s(2) #=> "1110001"
  240. [1,-4,3].undigits([-4,-3,-2],1).to_s(2) #=> "1110001" ### (bit数は絶対値)
  241.  
  242. 0b001111_111_11.my_digits([-4,-3,-2],1) #=> [-1,-1,-1]
  243. 0b001110_110_10.my_digits([-4,-3,-2],1) #=> [-2,-2,-2]
  244. 0b001100_100_00.my_digits([-4,-3,-2],1) #=> [0,-4,-4]
  245.  
  246. 0b011111_111_11.my_digits([-4,-3,-2],1) #=> [-1,-1,-1] ### (範囲外のビットは無視)
  247. 0b011110_110_10.my_digits([-4,-3,-2],1) #=> [-2,-2,-2]
  248. 0b011100_100_00.my_digits([-4,-3,-2],1) #=> [0,-4,-4]
  249.  
  250. 0x0FFF.my_digits(-12,1) #=> [-1]
  251. 0x0FFF.my_digits([-12],1) #=> [-1]
  252. [3,3,7].undigits(-3,1).to_s(8) #=> "733"
  253. [9,33,21,1428].undigits([-24,-60,-60]) #=> 123456789 ### (これはraiseすべき?)
  254.  
  255.  
  256. BFset = { foo:2, bar:3, car:3 } # ビットフィールド名とビット数
  257. {}.bits( BFset ) #=> 0 ### 0b00_000_000
  258. { foo:1 }.bits( BFset ) #=> 0x40 ### 0b01_000_000
  259. { car:1, bar:2 }.bits( BFset ) #=> 17 ### 0b00_010_001
  260. bh = 17.unbits( BFset ) #=> {foo:0, bar:2, car:1}
  261. bh[ :foo ] = 3
  262. bh #=> {:foo=>3, :bar=>2, :car=>1}
  263. bh.bits( BFset ) #=> 209 ### 0b11_010_001
  264.  
  265. BFset2 = { foo:2, bar:-3, car:-3 }
  266. bh = 0xFF.unbits( BFset2 ) #=> {foo:3, bar:-1, car:-1}
  267. bh[ :car ] = 0
  268. bh.bits( BFset ) #=> 0xF8 ### 0b11_111_000
  269.  
Success #stdin #stdout 0.01s 6604KB
stdin
Standard input is empty
stdout
  215: 	[1, 1, 0, 1, 'hoge'].to_i(2)	#=> 11
  216: 	123456789.my_digits([24,60])	#=> [9, 21, 85733]
  217: 	123456789.my_digits([24,60,60])	#=> [9,33,21,1428]
  218: 
  219: 	Bhms = [24,60,60]
  220: 	[9,33,21,1428,'d h:m:s'].undigits(Bhms)		#=> 123456789
  221: 	123456789.my_digits(Bhms).undigits(Bhms)	#=> 123456789
  222: 	[9,33,21,1428, 9,9,9,9].undigits(Bhms)		#=> 123456789
  223: 	[9,33,21].undigits(Bhms) 	#=> 77589
  224: 	[9,33].undigits(Bhms)		#=> 1989
  225: 	[9].undigits(Bhms)			#=> 9
  226: 
  227: # ==== bit field test ====
  228: 
  229: 	0117.my_digits(8)		#=> [7,1,1]
  230: 	0117.my_digits(3,1)		#=> [7,1,1] ### 上と同じ 8 == 2**3
  231: 
  232: 	[3,3,7].undigits(3,1).to_s(8)	#=> "733"
  233: 	[1,3,7,8,0xFFFF,-1].undigits(3,1).to_s(8)	#=> "770731"
  234: 
  235: 	0b0011_100_01.my_digits([4,3,2],1)	#=> [1,4,3]
  236: 	[1,4,3].undigits([4,3,2],1).to_s(2)	#=> "1110001"
  237: 	0b0011_100_01.my_digits([-4,-3,-2],1)	#=> [1,-4,3] ### (-4:符号拡張)
  238: 	[1,-4,3].undigits([4,3,2],1).to_s(2)	#=> "1110001"
  239: 	[1,-4,3].undigits([-4,-3,-2],1).to_s(2)	#=> "1110001" ### (bit数は絶対値)
  240: 
  241: 	0b001111_111_11.my_digits([-4,-3,-2],1)	#=> [-1,-1,-1]
  242: 	0b001110_110_10.my_digits([-4,-3,-2],1)	#=> [-2,-2,-2]
  243: 	0b001100_100_00.my_digits([-4,-3,-2],1)	#=> [0,-4,-4]
  244: 
  245: 	0b011111_111_11.my_digits([-4,-3,-2],1)	#=> [-1,-1,-1] ### (範囲外のビットは無視)
  246: 	0b011110_110_10.my_digits([-4,-3,-2],1)	#=> [-2,-2,-2]
  247: 	0b011100_100_00.my_digits([-4,-3,-2],1)	#=> [0,-4,-4]
  248: 
  249: 	0x0FFF.my_digits(-12,1)			#=> [-1]
  250: 	0x0FFF.my_digits([-12],1)		#=> [-1]
  251: 	[3,3,7].undigits(-3,1).to_s(8)	#=> "733"
  252: 	[9,33,21,1428].undigits([-24,-60,-60])	#=> 123456789 ### (これはraiseすべき?)
  253: 
  254: 
  255: 	BFset = { foo:2, bar:3, car:3 }		# ビットフィールド名とビット数
  256: 	{}.bits( BFset )					#=> 0    ### 0b00_000_000
  257: 	{ foo:1 }.bits( BFset )				#=> 0x40 ### 0b01_000_000
  258: 	{ car:1, bar:2 }.bits( BFset )		#=> 17   ### 0b00_010_001
  259: 	bh = 17.unbits( BFset ) 			#=> {foo:0, bar:2, car:1}
  260: 	bh[ :foo ] = 3
  261: 	bh									#=> {:foo=>3, :bar=>2, :car=>1}
  262: 	bh.bits( BFset )					#=> 209  ### 0b11_010_001
  263: 
  264: 	BFset2 = { foo:2, bar:-3, car:-3 }
  265: 	bh = 0xFF.unbits( BFset2 ) 			#=> {foo:3, bar:-1, car:-1}
  266: 	bh[ :car ] = 0
  267: 	bh.bits( BFset )					#=> 0xF8  ### 0b11_111_000
Done.