May 3, 2014 by Daniel P. Clark

Code Golf Challenge Unique Base 64 Incrementor

The goal is to write a script that will use your (Base 64) numbering system and never repeat any character within the string while incrementing.

When you rollover a big number that jumps to the next place value you need to substitute it with the next unique in place… example (in Base 10) 0985,0986,0987 jumps to 1023, 1024, 1025 to avoid repetition. Note: Rollovers are when you hit the top place value like 0999 and roll over to the next place value 1000

So increment all 12 character unique strings without wasting CPU cycles on skip loops.

Rules

  • No like characters within the 12 character string.
  • No skip/next command in loop from “0985”,”0986″,”0987″ to “1023” (Base 10 example), use substitution. This is a rollover. Rollovers are no skip zones.
  • All down counts of any length (starting from the highest value character towards the next +11 characters) get substituted on rollover Example: if Z was highest value character in the base and Y was next then YXWVUTSRQPON will roll over to Z0123456789a

Criterion

Pass 5 test cases with different position rollover cases (when the next place position increments).

About Number Bases

Our numbering system is (Base 10). That includes 0-9. Binary is (Base 2), that’s only >1’s and 0’s. Hex is (Base 16) (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F). A hexadecimal “F” has a >(Base 10) value of 15.

In Binary, a string of two binary characters can have only two unique states. Like ’10’ >and ’01’. In this challenge Binary is not a possible choice since you can’t have any more >unique amount of characters then two since you only have 1 and 0.

(Base 64) has 64 individual characters which would translate in value in (Base 10) from >between 0 to 63. See here for more on (Base 64) http://en.wikipedia.org/wiki/Base_64

Logic Insights

Your incrementor function will increment to the next ‘not in string’ character on the right end until it gets to the highest character. Once it get’s to the last character then it passes on to the swap task.

The swap task then looks for the chunk to jump to eg: in (Base 10) to go from 00987 to the next level would be 01234. So seeing 00987 is the set to replace we have the 0 which “can” be incremented, and then the 987 which is a counting down sequence 9, 8, 7. So we then increment the first number to the left so 0 turns to 1, and then substitute the 987 with the smallest unused numbers from left to right, which is 234.

Here is a working long answer written in Ruby:

The order of the (base 64) used in this code and output is as is defined on Wikipedia

class B64
    def initialize(string, lngth=12)
        @b64 = (
            ("A".."Z").to_a + ("a".."z").to_a + ("0".."9").to_a + ["+","/"]
        ).each_with_index.map {|x,i| {x=>i} }.inject(:update)
        @string = string
        @max = lngth.times.map { |i| @b64.invert[@b64.length-i-1] }.join("")
        @start = lngth.times.map { |i| @b64.invert[i] }.join("")
    end

    def next
        # this is where everything moves forward
        unless inc(@string)
            swapper
        end
        @string
    end

    def inc(s)
        # increment last item in string or false
        unless @b64[s[-1]] == @b64.length-1
            unless s == @max
                if first_non(s,s[-1])
                    s[-1] = first_non(s,s[-1])
                elsif not first_non(s,s[-2])
                    s[-1] = first_non(s)
                    if first_non(s,s[-2])
                        s[-2] = first_non(s,s[-2])
                    else
                        swapper
                    end
                else
                    swapper
                end
            else
                swapper
            end
        else
            return false
        end
        return true
    end

    def seek_high(s)
        # select with index highest number
        val = s.split("").map { |x| @b64[x] }
        return val.index(val.compact.max)
    end

    def swapper
        if @string == @max
            @string = @start
        else
            # save loop cycles by substituting with next unique charcter set
            val = @string[0..seek_high(@string)-1]
            inc(val)
            count = @string[seek_high(@string)..-1].length
            count.times do
                val += first_non(val)
            end
            @string = val
        end
    end

    def first_non(s,start = @b64.invert[0])
        # find the lowest not used character in base
        (@b64[start][email protected]).each do |p|
            unless !!s[@b64.invert[p]]
                return @b64.invert[p]
            end
        end
        return false
    end
end

# Pass 5 test cases with rollovers
["ABCDEFGHIJK9","ABCD/9876542","ABCDEF+/9875","ABCDEFG+/985","A+/987654320"].each do |val|
    test = B64.new(val)
    puts " ******** TEST FOR ROLLOVER SEQUENCE #{val} ******** "
    5.times do
        print test.next + ", "
    end
    puts
    puts
end

And here is it’s output.

 ******** TEST FOR ROLLOVER SEQUENCE ABCDEFGHIJK9 ******** 
ABCDEFGHIJK+, ABCDEFGHIJK/, ABCDEFGHIJLK, ABCDEFGHIJLM, ABCDEFGHIJLN, 

 ******** TEST FOR ROLLOVER SEQUENCE ABCD/9876542 ******** 
ABCD/9876543, ABCD/987654+, ABCD/98765+E, ABCD/98765+F, ABCD/98765+G, 

 ******** TEST FOR ROLLOVER SEQUENCE ABCDEF+/9875 ******** 
ABCDEF+/9876, ABCDEF/GHIJK, ABCDEF/GHIJL, ABCDEF/GHIJM, ABCDEF/GHIJN, 

 ******** TEST FOR ROLLOVER SEQUENCE ABCDEFG+/985 ******** 
ABCDEFG+/986, ABCDEFG+/987, ABCDEFG/HIJK, ABCDEFG/HIJL, ABCDEFG/HIJM, 

 ******** TEST FOR ROLLOVER SEQUENCE A+/987654320 ******** 
A+/987654321, A/BCDEFGHIJK, A/BCDEFGHIJL, A/BCDEFGHIJM, A/BCDEFGHIJN,

Submission

Please head over to github and fork and send a pull request and name your file as follows golfb64-<yourname>.xxx for your golf answers and longb64-<yourname>.xxx for your long answer versions. Use any promming language you’d like. I’ve included my long version longb64-danielpclark.rb

To see other people’s submissions you can check here as well.

Please comment, share, subscribe to my RSS Feed,and follow me on twitter @6ftdan!

God Bless! – Daniel P. Clark

#base 64#challenge#code golf#programming

Comments

  1. Daniel P. Clark
    May 10, 2014 - 2:49 am

    The challenge has finally been reopened at codegolf.stackexchange.com!

Leave a Reply

Your email address will not be published / Required fields are marked *