On Fri, Mar 05, 2004 at 06:09:43PM +0900, illocutionist wrote:

> # An opposite to .succ! Or, a predecessor method for String.

>

> # This little thing is for my own use, and entertainment.

> # There are those that might recoil from by beginners drivel, but I

> # need a little help...

>

> # I keep getting 'out of range' error no matter what I try

> # when "a".pred!

>

> class String

>

> def pred!

> begin

> # get the ascii value of the last element in string and decrement it...

> self[self.size - 1] = (self[self.size - 1] - 1)

>

> if self[self.size - 1] == 96 # 'a' is the last char we want

> self.chop! # when 'a'.pred! .chop char

> self[self.size - 1] = 122 # set new last element to 'z'

> end

> return self

> end while self.size > 0 # hmmmm...

> end

> end

>> "abcd".my_pred_alpha
=> "abcc"

>> "abcd".my_succ_alpha
=> "abce"

>> "z".my_succ_alpha
=> "00"

>> "00".my_pred_alpha
=> "z"

batsman@tux-chan:/tmp$ ruby /tmp/yy.rb

Loaded suite /tmp/yy

Started

.....

Finished in 1.525721 seconds.

5 tests, 20011 assertions, 0 failures, 0 errors

class String

ALPHA = [('0'..'9'), ('A'..'Z'), ('a'..'z')].

inject([]){|a,b| a + b.to_a}.map{|x| x[0]}

def my_succ_alpha

vals = self.unpack("C*")

carry = (vals.size-1).downto(0) do |idx|

if (i = ALPHA.index(vals[idx])) < ALPHA.size - 1

vals[idx] = ALPHA[i+1]

break false

else

vals[idx] = ALPHA[0]

end

end

vals.unshift(ALPHA[0]) if carry

vals.pack("C*")

end

def my_pred_alpha # breaks for "0"

vals = self.unpack("C*")

carry = (vals.size-1).downto(0) do |idx|

if (i = ALPHA.index(vals[idx])) > 0

vals[idx] = ALPHA[i-1]

break false

else

vals[idx] = ALPHA[-1]

end

end

vals.shift if carry

vals.pack("C*")

end

def my_succ # just operating on byte values

vals = self.unpack("C*")

carry = (vals.size-1).downto(0) do |idx|

if vals[idx] < 255

vals[idx] += 1

break false

else

vals[idx] = 0

end

end

vals.unshift(0) if carry

vals.pack("C*")

end

def my_pred # 'reverse' of my_succ

vals = self.unpack("C*")

carry = (vals.size-1).downto(0) do |idx|

if vals[idx] > 0

vals[idx] -= 1

break false

else

vals[idx] = 255

end

end

vals.shift if carry

vals.pack("C*")

end

end

require 'test/unit'

class TC_my_succ < Test::Unit::TestCase

def arr_succ(a)

a.pack("C*").my_succ.unpack("C*")

end

def arr_pred(a)

a.pack("C*").my_pred.unpack("C*")

end

def test_rand

5000.times do

txt = (0..rand(20)).map{rand(255)}.pack("C*")

assert_equal(txt, txt.my_succ.my_pred)

assert_equal(txt, txt.my_pred.my_succ)

end

end

def test_rand_alpha

5000.times do

txt = (0..rand(20)).inject("") do |a,b|

a << String::ALPHA[rand(String::ALPHA.size)]

end

next if txt == "0" # my_pred_alpha is undefined

assert_equal(txt, txt.my_succ_alpha.my_pred_alpha)

assert_equal(txt, txt.my_pred_alpha.my_succ_alpha)

end

end

def test_my_pred_alpha

assert_equal("aa", "ab".my_pred_alpha)

assert_equal("aZ", "aa".my_pred_alpha)

assert_equal("z", "00".my_pred_alpha)

assert_equal("0", "1".my_pred_alpha)

assert_equal("00", "01".my_pred_alpha)

assert_equal("9", "A".my_pred_alpha)

end

def test_my_succ

assert_equal("ab", "aa".my_succ)

assert_equal("a:", "a9".my_succ)

assert_equal([0, 0], arr_succ([255]))

assert_equal([?b, 0], arr_succ([?a, 255]))

end

def test_my_pred

assert_equal("aa", "ab".my_pred)

assert_equal("a9", "a:".my_pred)

assert_equal([0, 255], arr_pred([1,0]))

assert_equal([255], arr_pred([0,0]))

assert_equal([?a, 255], arr_pred([?b, 0]))

end

end

--

Running Debian GNU/Linux Sid (unstable)

batsman dot geo at yahoo dot com

*** PUBLIC flooding detected from erikyyy

<lewnie> THAT's an erik, pholx....

-- Seen on #LinuxGER