How to resolve the algorithm Non-continuous subsequences step by step in the Julia programming language

Published on 22 June 2024 08:30 PM

How to resolve the algorithm Non-continuous subsequences step by step in the Julia programming language

Table of Contents

Problem Statement

Consider some sequence of elements. (It differs from a mere set of elements by having an ordering among members.) A subsequence contains some subset of the elements of this sequence, in the same order. A continuous subsequence is one in which no elements are missing between the first and last elements of the subsequence. Note: Subsequences are defined structurally, not by their contents. So a sequence a,b,c,d will always have the same subsequences and continuous subsequences, no matter which values are substituted; it may even be the same value.

Task: Find all non-continuous subsequences for a given sequence.

For the sequence   1,2,3,4,   there are five non-continuous subsequences, namely:

There are different ways to calculate those subsequences. Demonstrate algorithm(s) that are natural for the language.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Non-continuous subsequences step by step in the Julia programming language

Code Overview: The provided code generates and explores non-consecutive subsequences (NC subsequences) of a given length. A non-consecutive subsequence is a subsequence where no two consecutive elements are adjacent in the original sequence.

NCSubSeq: The NCSubSeq struct represents a non-consecutive subsequence. It stores the length (n) of the original sequence from which subsequences will be generated.

NCSubState: The NCSubState mutable struct represents the state of an iterator over NC subsequences. It holds two fields:

  • m: An integer representing the current subsequence being generated.
  • m2s: A function that maps an integer m to the corresponding NC subsequence.

Iterator Implementation: The iterate method for NCSubSeq implements a stateful iterator. It generates NC subsequences in ascending order until reaching the end of the sequence. The iterator maintains the NCSubState and updates it for each subsequence generation.

iscontseq Function: iscontseq checks if a given integer n represents a non-consecutive subsequence. It does so by ensuring that the count of zeros in the binary representation of n matches the sum of leading and trailing zeros.

makeint2seq Function: makeint2seq creates a closure function that maps an integer m to its corresponding NC subsequence. It calculates the binary digits of m with a fixed number of digits (based on the input argument n). The subsequence is then extracted by selecting the indices where the binary digits are 1.

Example Usage: The code demonstrates:

  • Generating NC subsequences for a 4-item sequence and printing them.
  • Generating the first and last 10 NC subsequences of the string "Rosetta".
  • Generating the first and last 10 NC subsequences of integer sequences of varying lengths.

Additional Features:

  • The Base.IteratorSize and Base.length methods are implemented for NCSubSeq to indicate that it can be used in for loops and its length can be obtained.
  • The @sprintf and @printf macros are used for string formatting.

Source code in the julia programming language

using Printf, IterTools

import Base.IteratorSize, Base.iterate, Base.length 

iscontseq(n::Integer) = count_zeros(n) == leading_zeros(n) + trailing_zeros(n)
iscontseq(n::BigInt)  = !ismatch(r"0", rstrip(bin(n), '0'))
 
function makeint2seq(n::Integer)
    idex = collect(1:n)
    function int2seq(m::Integer)
        d = digits(m, base=2, pad=n)
        idex[d .== 1]
    end
    return int2seq
end
 
struct NCSubSeq{T<:Integer}
    n::T
end
 
mutable struct NCSubState{T<:Integer}
    m::T
    m2s::Function
end
 
Base.IteratorSize(::NCSubSeq) = Base.HasLength()
Base.length(a::NCSubSeq) = 2 ^ a.n - a.n * (a.n + 1) ÷ 2 - 1
function Base.iterate(a::NCSubSeq, as::NCSubState=NCSubState(5, makeint2seq(a.n)))
    if 2 ^ a.n - 3 < as.m
        return nothing
    end
    s = as.m2s(as.m)
    as.m += 1
    while iscontseq(as.m)
        as.m += 1
    end
    return (s, as)
end
 
n = 4
println("Testing NCSubSeq for ", n, " items:\n ", join(NCSubSeq(n), " "))
 
s = "Rosetta"
cs = split(s, "")
m = 10
n = length(NCSubSeq(length(cs))) - m
println("\nThe first and last ", m, " NC sub-sequences of \"", s, "\":")
for (i, a) in enumerate(NCSubSeq(length(s)))
    i <= m || n < i || continue
    println(@sprintf "%6d %s" i join(cs[a], ""))
    i == m || continue
    println("    .. ......")
end

println("\nThe first and last ", m, " NC sub-sequences of \"", s, "\"")
for x in IterTools.Iterators.flatten([1:10; 20:10:40; big.(50:50:200)])
    @printf "%7d → %d\n" x length(NCSubSeq(x))
end


  

You may also check:How to resolve the algorithm Continued fraction step by step in the Go programming language
You may also check:How to resolve the algorithm Catalan numbers/Pascal's triangle step by step in the Groovy programming language
You may also check:How to resolve the algorithm Determine if a string is collapsible step by step in the MATLAB / Octave programming language
You may also check:How to resolve the algorithm Erdös-Selfridge categorization of primes step by step in the Rust programming language
You may also check:How to resolve the algorithm Angle difference between two bearings step by step in the Swift programming language