Task: Kolakoski sequence




Go: package main

import "fmt"

func nextInCycle(c []int, index int) int {
    return c[index % len(c)]
}

func kolakoski(c []int, slen int) []int {
    s := make([]int, slen)
    i, k := 0, 0
    for {
        s[i] = nextInCycle(c, k)
        if s[k] > 1 {
            for j := 1; j < s[k]; j++ {
                i++
                if i == slen {
                    return s
                }
                s[i] = s[i - 1]
            }
        }
        i++
        if i == slen {
            return s
        }
        k++
    }
}

func possibleKolakoski(s []int) bool {
    slen := len(s)
    rle := make([]int, 0, slen)
    prev := s[0]
    count := 1
    for i := 1; i < slen; i++ {
        if s[i] == prev {
            count++
        } else {
            rle = append(rle, count)
            count = 1
            prev = s[i]
        }
    }
    
    for i := 0; i < len(rle); i++ {
        if rle[i] != s[i] {
            return false
        }
    }
    return true
}

func printInts(ia []int, suffix string) {
    fmt.Print("[")
    alen := len(ia)
    for i := 0; i < alen; i++ {
        fmt.Print(ia[i])
        if i < alen - 1 {
            fmt.Print(", ")
        }
    }
    fmt.Printf("]%s\n", suffix)
}

func main() {
    ias := make([][]int, 4)
    ias[0] = []int{1, 2}
    ias[1] = []int{2, 1}
    ias[2] = []int{1, 3, 1, 2}
    ias[3] = []int{1, 3, 2, 1}
    slens := []int{20, 20, 30, 30}
    for i, ia := range ias {
        slen := slens[i]
        kol := kolakoski(ia, slen)
        fmt.Printf("First %d members of the sequence generated by ", slen)
        printInts(ia, ":")
        printInts(kol, "")
        p := possibleKolakoski(kol)
        poss := "Yes"
        if !p {
            poss = "No"
        }
        fmt.Println("Possible Kolakoski sequence?", poss, "\n")
    }
}





VB: Imports System.Runtime.CompilerServices
Imports System.Text

Module Module1

    Class Crutch
        Public ReadOnly len As Integer
        Public s() As Integer
        Public i As Integer

        Public Sub New(len As Integer)
            Me.len = len
            s = New Integer(len - 1) {}
            i = 0
        End Sub

        Public Sub Repeat(count As Integer)
            For j = 1 To count
                i += 1
                If i = len Then
                    Return
                End If
                s(i) = s(i - 1)
            Next
        End Sub
    End Class

    <Extension()>
    Public Function NextInCycle(self As Integer(), index As Integer) As Integer
        Return self(index Mod self.Length)
    End Function

    <Extension()>
    Public Function Kolakoski(self As Integer(), len As Integer) As Integer()
        Dim c As New Crutch(len)

        Dim k = 0
        While c.i < len
            c.s(c.i) = self.NextInCycle(k)
            If c.s(k) > 1 Then
                c.Repeat(c.s(k) - 1)
            End If
            c.i += 1
            If c.i = len Then
                Return c.s
            End If
            k += 1
        End While

        Return c.s
    End Function

    <Extension()>
    Public Function PossibleKolakoski(self As Integer()) As Boolean
        Dim rle(self.Length) As Integer
        Dim prev = self(0)
        Dim count = 1
        Dim pos = 0
        For i = 2 To self.Length
            If self(i - 1) = prev Then
                count += 1
            Else
                rle(pos) = count
                pos += 1

                count = 1
                prev = self(i - 1)
            End If
        Next
        REM no point adding final 
        For i = 1 To pos
            If rle(i - 1) <> self(i - 1) Then
                Return False
            End If
        Next
        Return True
    End Function

    <Extension()>
    Public Function AsString(self As Integer()) As String
        Dim sb As New StringBuilder("[")
        Dim it = self.GetEnumerator()
        If it.MoveNext Then
            sb.Append(it.Current)
        End If
        While it.MoveNext
            sb.Append(", ")
            sb.Append(it.Current)
        End While
        Return sb.Append("]").ToString
    End Function

    Sub Main()
        Dim ias()() As Integer = {New Integer() {1, 2}, New Integer() {2, 1}, New Integer() {1, 3, 1, 2}, New Integer() {1, 3, 2, 1}}
        Dim lens() As Integer = {20, 20, 30, 30}

        For i = 1 To ias.Length
            Dim len = lens(i - 1)
            Dim kol = ias(i - 1).Kolakoski(len)

            Console.WriteLine("First {0} members of the sequence by {1}: ", len, ias(i - 1).AsString)
            Console.WriteLine(kol.AsString)
            Console.WriteLine("Possible Kolakoski sequence? {0}", kol.PossibleKolakoski)
            Console.WriteLine()
        Next
    End Sub

End Module