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