How to resolve the algorithm De Bruijn sequences step by step in the Ruby programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm De Bruijn sequences step by step in the Ruby programming language

Table of Contents

Problem Statement

The sequences are named after the Dutch mathematician   Nicolaas Govert de Bruijn.

A note on Dutch capitalization:   Nicolaas' last name is   de Bruijn,   the   de   isn't normally capitalized unless it's the first word in a sentence.   Rosetta Code (more or less by default or by fiat) requires the first word in the task name to be capitalized.

In combinatorial mathematics,   a   de Bruijn sequence   of order   n   on a   size-k   alphabet (computer science)   A   is a cyclic sequence in which every possible   length-n   string (computer science, formal theory)   on   A   occurs exactly once as a contiguous substring. Such a sequence is denoted by   B(k, n)   and has length   kn,   which is also the number of distinct substrings of length   n   on   A;     de Bruijn sequences are therefore optimally short. There are: distinct de Bruijn sequences   B(k, n).

For this Rosetta Code task,   a   de Bruijn   sequence is to be generated that can be used to shorten a brute-force attack on a   PIN-like   code lock that does not have an "enter" key and accepts the last   n   digits entered.

Note:   automated teller machines (ATMs)   used to work like this,   but their software has been updated to not allow a brute-force attack.

A   digital door lock   with a 4-digit code would have B (10, 4) solutions,   with a length of   10,000   (digits). Therefore, only at most     10,000 + 3     (as the solutions are cyclic or wrap-around)   presses are needed to open the lock. Trying all 4-digit codes separately would require   4 × 10,000   or   40,000   presses.

(The last requirement is to ensure that the verification tests performs correctly.   The verification processes should list any and all missing PIN codes.) Show all output here, on this page.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm De Bruijn sequences step by step in the Ruby programming language

The provided Ruby code defines two methods, deBruijn and validate, to generate and validate a de Bruijn sequence.

deBruijn Method:

  • The deBruijn method takes two parameters:

    • k: The number of symbols in the alphabet (in this case, 10 digits).
    • n: The length of the desired de Bruijn sequence.
  • It initializes:

    • alphabet as a string containing the digits "0123456789".
    • @a as an array of size k * n filled with zeros.
    • @seq as an empty array.
  • It defines a nested method db:

    • db takes four parameters:
      • k: The number of symbols in the alphabet.
      • n: The length of the desired de Bruijn sequence.
      • t: The current position in the sequence.
      • p: The period of the sequence.
    • It checks if t is greater than n. If so, it checks if n is divisible by p. If it is, it concatenates the first p elements of @a to @seq.
    • If t is not greater than n, it sets @a[t] to @a[t - p]. It then calls db recursively with k, n, t + 1, and p.
    • It sets j to @a[t - p] + 1 and loops while j is less than k. Within the loop, it sets @a[t] to j, calls db recursively with k, n, t + 1, and t, and increments j.
  • Finally, the deBruijn method calls db with k, n, 1, and 1 to generate the de Bruijn sequence.

validate Method:

  • The validate method takes a string db as a parameter.

  • It initializes:

    • le to the length of db.
    • found as an array of 10000 zeros.
    • errs as an empty array.
  • It iterates over all substrings of length 4 in db and checks if they consist only of digits. If so, it converts the substring to an integer and increments the corresponding element in the found array.

  • After the iteration, it checks each element in found. If an element is 0, it adds an error message to the errs array indicating that the corresponding PIN number is missing. If an element is greater than 1, it adds an error message indicating that the PIN number occurs multiple times.

  • If errs is empty, it prints "No errors found." Otherwise, it prints the number of errors found and lists the error messages.

Usage:

The code demonstrates the usage of deBruijn and validate methods. It generates a de Bruijn sequence of length 10^4, prints its first and last 130 digits, and then validates the sequence. It also overlays the sequence with a dot character at position 4443 and re-validates it to showcase error detection.

Source code in the ruby programming language

def deBruijn(k, n)
    alphabet = "0123456789"
    @a = Array.new(k * n, 0)
    @seq = []

    def db(k, n, t, p)
        if t > n then
            if n % p == 0 then
                temp = @a[1 .. p]
                @seq.concat temp
            end
        else
            @a[t] = @a[t - p]
            db(k, n, t + 1, p)
            j = @a[t - p] + 1
            while j < k do
                @a[t] = j # & 0xFF
                db(k, n, t + 1, t)
                j = j + 1
            end
        end
    end
    db(k, n, 1, 1)

    buf = ""
    for i in @seq
        buf <<= alphabet[i]
    end
    return buf + buf[0 .. n-2]
end

def validate(db)
    le = db.length
    found = Array.new(10000, 0)
    errs = []
    # Check all strings of 4 consecutive digits within 'db'
    # to see if all 10,000 combinations occur without duplication.
    for i in 0 .. le-4
        s = db[i .. i+3]
        if s.scan(/\D/).empty? then
            found[s.to_i] += 1
        end
    end
    for i in 0 .. found.length - 1
        if found[i] == 0 then
            errs <<= ("    PIN number %04d missing" % [i])
        elsif found[i] > 1 then
            errs <<= ("    PIN number %04d occurs %d times" % [i, found[i]])
        end
    end
    if errs.length == 0 then
        print "  No errors found\n"
    else
        pl = (errs.length == 1) ? "" : "s"
        print "  ", errs.length, " error", pl, " found:\n"
        for err in errs
            print err, "\n"
        end
    end
end

db = deBruijn(10, 4)
print "The length of the de Bruijn sequence is ", db.length, "\n\n"
print "The first 130 digits of the de Bruijn sequence are: ", db[0 .. 129], "\n\n"
print "The last 130 digits of the de Bruijn sequence are: ", db[-130 .. db.length], "\n\n"

print "Validating the de Bruijn sequence:\n"
validate(db)
print "\n"

db[4443] = '.'
print "Validating the overlaid de Bruijn sequence:\n"
validate(db)


  

You may also check:How to resolve the algorithm Arbitrary-precision integers (included) step by step in the Go programming language
You may also check:How to resolve the algorithm Abbreviations, automatic step by step in the Tcl programming language
You may also check:How to resolve the algorithm Loops/For with a specified step step by step in the TUSCRIPT programming language
You may also check:How to resolve the algorithm Null object step by step in the Babel programming language
You may also check:How to resolve the algorithm HTTPS step by step in the Frink programming language