challenge 全ての組み合わせ

2個以上のリストlist1, list2, list3...が与えられたときに、 その複数個のリストの中の要素を一つずつとりだして組にする方法の全通りのリストを返すコードを書いてください。

Pythonで表現すると下のようになります。

>>> c = CrossProduct([1,2,3,4], "abc")
>>> list(c.all())
[[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'],
 [2, 'b'], [2, 'c'], [3, 'a'], [3, 'b'],
 [3, 'c'], [4, 'a'], [4, 'b'], [4, 'c']]

>>> c = CrossProduct([0, 1], "ab", ["Foo", "Bar"])
>>> list(c.all())
[[0, 'a', 'Foo'], [0, 'a', 'Bar'], [0, 'b', 'Foo'], [0, 'b', 'Bar']
 [1, 'a', 'Foo'], [1, 'a', 'Bar'], [1, 'b', 'Foo'], [1, 'b', 'Bar']]
順番はこの通りでなくても構いません。返すものはリストと書きましたが、 なんらかの「一度に全部をメモリ上に作成しないリスト状のモノ」がある言語ではそちらを使う方がおすすめです。 数値や文字列を一つのリストに混在させるのがやっかいな言語では整数のリストに限定しても構いません。

このお題はZIGOROuさんとのやりとりにヒントを得て作りました。 (しまった、先にブログで公開されてしまった→Yet Another Hackadelic - 直積の導出と考えうる全ての値を網羅したハッシュの生成)

追記:サンプル出力が間違っていたのでoceanさんの解答を使って出力し直しました。

Posted feedbacks - VB.net

長い…が、
VBならこんなもんなのかな?
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Module Module1

    Sub Main()
        Dim li As Integer() = New Integer() {1, 2, 3, 4, 5}
        Dim ls As Char() = New Char() {"a"c, "b"c, "c"c}

        Dim cpg As New CrossProductGenerator(li, ls)
        Dim e As IEnumerator(Of Object()) = cpg.GetEnumerator

        While e.MoveNext
            For i As Integer = 0 To e.Current.Length - 1
                Console.Write(e.Current(i))
            Next
            Console.WriteLine()
        End While

    End Sub

End Module

Public Class CrossProductGenerator
    Implements IEnumerable(Of Object())
    Private _list As IEnumerable()

    Public Sub New(ByVal ParamArray list() As IEnumerable)
        _list = list
    End Sub

    Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of Object()) Implements IEnumerable(Of Object()).GetEnumerator
        Return New Enumerator(_list)
    End Function

    Private Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
        Return New Enumerator(_list)
    End Function

    Private Class Enumerator
        Implements IEnumerator(Of Object())

        Private _enumerators As IEnumerator()
        Private _current As Object()
        Private _state As Integer

        Public Sub New(ByVal list As IEnumerable())
            _enumerators = New IEnumerator(list.Length - 1) {}
            For i As Integer = 0 To _enumerators.Length - 1
                _enumerators(i) = list(i).GetEnumerator()
            Next
            _state = -1
            _current = Nothing
        End Sub

        Public Sub Reset() Implements System.Collections.IEnumerator.Reset
            For i As Integer = 0 To _enumerators.Length - 1
                _enumerators(i).Reset()
            Next
            _state = -1
            _current = Nothing
        End Sub

        Public ReadOnly Property Current() As Object() Implements System.Collections.Generic.IEnumerator(Of Object()).Current
            Get
                Return _current
            End Get
        End Property

        Private ReadOnly Property Current1() As Object Implements System.Collections.IEnumerator.Current
            Get
                If _state <> 0 Then Throw New InvalidOperationException()
                Return _current
            End Get
        End Property

        Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
            If _state > 0 Then Return False

            If _state < 0 Then
                For i As Integer = 0 To _enumerators.Length - 1
                    If Not _enumerators(i).MoveNext() Then
                        _state = 1
                        _current = Nothing
                        Return False
                    End If
                Next
                _state = 0
            Else
                Dim i As Integer = 0
                While i < _enumerators.Length
                    If _enumerators(i).MoveNext Then Exit While
                    _enumerators(i).Reset()
                    _enumerators(i).MoveNext()
                    i += 1
                End While
                If i >= _enumerators.Length Then
                    _state = 1
                    _current = Nothing
                    Return False
                End If
            End If

            _current = New Object(_enumerators.Length - 1) {}
            For i As Integer = 0 To _enumerators.Length - 1
                _current(i) = _enumerators(i).Current
            Next

            Return True
        End Function

        Public Sub Dispose() Implements IDisposable.Dispose
        End Sub

    End Class

End Class

Index

Feed

Other

Link

Pathtraq

loading...