ROL ROR

  • C#
  • .NET (FX) 1.0–2.0

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von wolfi_bayern.

    Heyyo

    Ich habe ein byte[] mit n Elementen.
    Ich möchte nun eine ROL (RotateLeft) bzw ROR (RotateRight) operation durchführen.
    Das heißt die element nach rechts bzw lniks verschieben. Das ganze soll aber circular sein, d.h. dass das letzte byte wieder
    am anfang drangepackt wird.
    Gibt es da evtl eine default Funktion vom Framework oder muss ich es per hand mit einem for loop machen?


    C# Developer
    Learning C++
    Hi
    es gibt zwei Lösungsmöglichkeiten: Mit zusätzlichem Array der Größe k, es wird um k rotiert, oder ohne. Im ersten Fall ist es trivial (hier nur die Linksrotation, rechts ist analog): Kopiere die Einträge 0 bis k-1 in den Puffer, kopiere die Einträge k bis n (= Zahl der Elemente - 1) im Ziel an die Stellen 0 bis n-k und kopiere dann aus dem Puffer zurück an die Stellen n-k+1 bis n.

    Ohne Puffer ist's komplizierter: Wähle ein beliebiges l mit 0 <= l < n, n ist hier nicht der maximale Index, sondern die Länge des Arrays.
    Wiederhole für m=0..k-1: Merke dir v=l+m. Setze i auf v.
    Wiederhole: Merke dir den Wert an j=(-k+n+i)%n (Vorsicht Überlauf möglich) und kopiere den i-ten Wert an j. Setze i auf i-k. Wenn j < v, beende die Schleife (sind übrigens im Durchschnitt n/k Durchläufe)

    Jetzt sollte eigentlich alles passen.

    Mein Algo ließe sich auch auf den Puffer übertragen. Unter Verwendung des ThreadStaticAttribute-Attributs ließe sich zudem ein solcher Puffer wiederverwenden. Er muss halt hinreichend groß sein (d.h., die Länge des Puffers muss mindestens k sein), ansonsten musst du den Algorithmus auf Puffer anwenden ;)

    Edit: Gerade gemerkt, dass es mit dem Algorithmus ohne Puffer gar nicht funktionieren kann, wenn n%k=0. Man muss solange iterieren, bis man ein bereits besuchtes Element erreicht und dann ein nicht besuchtes wählen.
    Es muss also gelten, dass (x*n) % k = 0, dann wird im der x-ten Runde abgebrochen und ein nicht verschobenes Element gewählt. Verschoben wurden dann im letzten Durchlauf alle ((v % k)*p)%k=0-Werte, wobei p eine Zahl zwischen 1 und x (oder x-1, ist mir grad zu spät) ist. Also wählt man als nächstes einen Wert für v, für den ((v%k)*p)% 0 für alle bisherigen v nicht zutrifft. Das sollte eigentlich einfach in seiner Bestimmung sein, aber dafür bin ich zu müde.

    Viele Grüße
    ~blaze~

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    @Rikudo

    Für primitive Datentypnen gibt es die buffer.BlockCopy

    Sollte Funktioniere ungetestet

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Module Module1
    4. Public Function shiftLeft(ByVal b As Byte(), ByVal n As Integer) As Byte()
    5. Dim dst(b.Length - 1) As Byte
    6. Buffer.BlockCopy(b, n, dst, 0, b.Length - n)
    7. Buffer.BlockCopy(b, 0, dst, b.Length - n, n)
    8. Return dst
    9. End Function
    10. Public Function shiftRight(ByVal b As Byte(), ByVal n As Integer) As Byte()
    11. Dim dst(b.Length - 1) As Byte
    12. Buffer.BlockCopy(b, 0, dst, n, b.Length - n)
    13. Buffer.BlockCopy(b, b.Length - n, dst, 0, n)
    14. Return dst
    15. End Function
    16. Sub Main()
    17. Dim b As Byte() = {1, 2, 3, 4, 5, 6, 7, 8}
    18. Dim bResR As Byte() = shiftRight(b, 1)
    19. Dim bResL As Byte() = shiftLeft(b, 1)
    20. End Sub
    21. End Module



    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Hallo Community

    Hab heute abend noch kurz Zeit gefunden für einen Test. Wollte wissen, wie die Zeiten sind.
    Ich vermute mal, dass es bei den String-Varianten sogar noch bessere Methoden gibt. Über den Stringbuilder jedoch nicht .?

    Hier meine Zeitergebnisse

    Quellcode

    1. Enter für die Zeitmessung Byte - blockCopy vs. array.copy
    2. Zeit für n = 1000000: 387 ms
    3. Zeit für n = 1000000: 452 ms
    4. Differenz: -65 ms
    5. Enter für die Zeitmessung Byte - skip/take Enumerable
    6. Zeit für n = 1000000: 10055 ms
    7. Differenz: -9668 ms
    8. Enter für die Zeitmessung Char vs. String array.copy
    9. Zeit für n = 1000000: 664 ms
    10. Zeit für n = 1000000: 639 ms
    11. Differenz: 25 ms


    und hier noch den TestCode
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Module Module1
    4. Public Function shiftLeft(ByVal b As String, ByVal n As Integer, Optional ByVal _rot As Boolean = True) As String
    5. Dim dst() As Char = (New String("0"c, b.Length)).ToCharArray
    6. If _rot Then
    7. Dim nn As Integer = n Mod b.Length
    8. b.CopyTo(nn, dst, 0, b.Length - nn)
    9. b.CopyTo(0, dst, b.Length - nn, nn)
    10. ElseIf n < b.Length Then
    11. b.CopyTo(n, dst, 0, b.Length - n)
    12. End If
    13. Return dst
    14. End Function
    15. Public Function shiftRight(ByVal b As String, ByVal n As Integer, Optional ByVal _rot As Boolean = True) As String
    16. Dim dst() As Char = (New String("0"c, b.Length)).ToCharArray
    17. If _rot Then
    18. Dim nn As Integer = n Mod b.Length
    19. b.CopyTo(0, dst, nn, b.Length - nn)
    20. b.CopyTo(b.Length - nn, dst, 0, nn)
    21. ElseIf n < b.Length Then
    22. b.CopyTo(0, dst, n, b.Length - n)
    23. End If
    24. Return dst
    25. End Function
    26. Public Function shiftLeft(ByVal b As Char(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Char()
    27. Dim dst() As Char = (New String("0"c, b.Length)).ToCharArray
    28. If _rot Then
    29. Dim nn As Integer = n Mod b.Length
    30. Array.Copy(b, nn, dst, 0, b.Length - nn)
    31. Array.Copy(b, 0, dst, b.Length - nn, nn)
    32. ElseIf n < b.Length Then
    33. Array.Copy(b, n, dst, 0, b.Length - n)
    34. End If
    35. Return dst
    36. End Function
    37. Public Function shiftRight(ByVal b As Char(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Char()
    38. Dim dst() As Char = (New String("0"c, b.Length)).ToCharArray
    39. If _rot Then
    40. Dim nn As Integer = n Mod b.Length
    41. Array.Copy(b, 0, dst, nn, b.Length - nn)
    42. Array.Copy(b, b.Length - nn, dst, 0, nn)
    43. ElseIf n < b.Length Then
    44. Array.Copy(b, 0, dst, n, b.Length - n)
    45. End If
    46. Return dst
    47. End Function
    48. Public Function shiftLeft(ByVal b As Byte(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Byte()
    49. Dim dst(b.Length - 1) As Byte
    50. If _rot Then
    51. Dim nn As Integer = n Mod b.Length
    52. Buffer.BlockCopy(b, nn, dst, 0, b.Length - nn)
    53. Buffer.BlockCopy(b, 0, dst, b.Length - nn, nn)
    54. ElseIf n < b.Length Then
    55. Buffer.BlockCopy(b, n, dst, 0, b.Length - n)
    56. End If
    57. Return dst
    58. End Function
    59. Public Function shiftRight(ByVal b As Byte(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Byte()
    60. Dim dst(b.Length - 1) As Byte
    61. If _rot Then
    62. Dim nn As Integer = n Mod b.Length
    63. Buffer.BlockCopy(b, 0, dst, nn, b.Length - nn)
    64. Buffer.BlockCopy(b, b.Length - nn, dst, 0, nn)
    65. ElseIf n < b.Length Then
    66. Buffer.BlockCopy(b, 0, dst, n, b.Length - n)
    67. End If
    68. Return dst
    69. End Function
    70. Public Function shiftL(ByVal b As Byte(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Byte()
    71. Dim dst(b.Length - 1) As Byte
    72. If _rot Then
    73. Dim nn As Integer = n Mod b.Length
    74. Array.Copy(b, nn, dst, 0, b.Length - nn)
    75. Array.Copy(b, 0, dst, b.Length - nn, nn)
    76. ElseIf n < b.Length Then
    77. Array.Copy(b, n, dst, 0, b.Length - n)
    78. End If
    79. Return dst
    80. End Function
    81. Public Function shiftR(ByVal b As Byte(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Byte()
    82. Dim dst(b.Length - 1) As Byte
    83. If _rot Then
    84. Dim nn As Integer = n Mod b.Length
    85. Array.Copy(b, 0, dst, nn, b.Length - nn)
    86. Array.Copy(b, b.Length - nn, dst, 0, nn)
    87. ElseIf n < b.Length Then
    88. Array.Copy(b, 0, dst, n, b.Length - n)
    89. End If
    90. Return dst
    91. End Function
    92. Public Function shiftR2(ByVal b As Byte(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Byte()
    93. Dim dst(b.Length - 1) As Byte
    94. If _rot Then
    95. Dim list = b.ToList()
    96. Dim nn As Integer = n Mod b.Length
    97. Return list.Skip(b.Length - nn).Concat(list.Take(b.Length - nn)).ToArray()
    98. ElseIf n < b.Length Then
    99. Buffer.BlockCopy(b, 0, dst, n, b.Length - n)'Gib's da ev. andere Möglichkeit über Enumerable
    100. End If
    101. Return Nothing
    102. End Function
    103. Public Function shiftL2(ByVal b As Byte(), ByVal n As Integer, Optional ByVal _rot As Boolean = True) As Byte()
    104. Dim dst(b.Length - 1) As Byte
    105. If _rot Then
    106. Dim list = b.ToList()
    107. Dim nn As Integer = n Mod b.Length
    108. Return list.Skip(nn).Concat(list.Take(nn)).ToArray()
    109. ElseIf n < b.Length Then
    110. Buffer.BlockCopy(b, n, dst, 0, b.Length - n)'Gib's da ev. andere Möglichkeit über Enumerable
    111. End If
    112. Return dst
    113. End Function
    114. Sub Main()
    115. Dim cnt As Integer = 5
    116. 'Dim b = New Byte() {1, 2, 3, 4, 5, 6, 7, 8}
    117. Dim b(62 - 1) As Byte
    118. For i As Byte = 0 To 62 - 1 : b(i) = i : Next
    119. Console.WriteLine("Enter für die Zeitmessung Byte - blockCopy vs. array.copy")
    120. Console.ReadKey()
    121. Dim nn As Integer = 1000000
    122. Dim bResR() As Byte, bResL() As Byte
    123. Dim StartZeit As Date = System.DateTime.Now
    124. For i As Integer = 0 To nn
    125. bResR = shiftRight(b, cnt)
    126. bResL = shiftLeft(bResR, cnt)
    127. Next
    128. Dim EndZeit As Integer = CInt(System.DateTime.Now.Subtract(StartZeit).TotalMilliseconds)
    129. Console.WriteLine("Zeit für n = " & nn & ": " & EndZeit.ToString & " ms")
    130. StartZeit = System.DateTime.Now
    131. For i As Integer = 0 To nn
    132. bResR = shiftR(b, cnt)
    133. bResL = shiftL(bResR, cnt)
    134. Next
    135. Dim EndZeit2 As Integer = CInt(System.DateTime.Now.Subtract(StartZeit).TotalMilliseconds)
    136. Console.WriteLine("Zeit für n = " & nn & ": " & EndZeit2.ToString & " ms")
    137. Console.WriteLine("Differenz: " & EndZeit - EndZeit2 & " ms")
    138. Console.WriteLine() : Console.WriteLine()
    139. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    140. Console.WriteLine("Enter für die Zeitmessung Byte - skip/take Enumerable")
    141. Console.ReadKey()
    142. StartZeit = System.DateTime.Now
    143. For i As Integer = 0 To nn
    144. bResR = shiftR2(b, cnt)
    145. bResL = shiftL2(bResR, cnt)
    146. Next
    147. EndZeit2 = CInt(System.DateTime.Now.Subtract(StartZeit).TotalMilliseconds)
    148. Console.WriteLine("Zeit für n = " & nn & ": " & EndZeit2.ToString & " ms")
    149. Console.WriteLine("Differenz: " & EndZeit - EndZeit2 & " ms")
    150. Console.WriteLine() : Console.WriteLine()
    151. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    152. Console.WriteLine("Enter für die Zeitmessung Char vs. String array.copy")
    153. Console.ReadKey()
    154. 'Dim s As String = "abcdefgh"
    155. Dim s As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    156. Dim c() As Char = s.ToCharArray
    157. Dim cR() As Char = shiftRight(c, cnt)
    158. Dim cL() As Char = shiftLeft(cR, cnt)
    159. Dim cRO() As Char = shiftRight(c, cnt, False)
    160. Dim cLO() As Char = shiftLeft(c, cnt, False)
    161. StartZeit = System.DateTime.Now
    162. For i As Integer = 0 To nn
    163. cR = shiftRight(c, cnt)
    164. cL = shiftLeft(cR, cnt)
    165. Next
    166. EndZeit = CInt(System.DateTime.Now.Subtract(StartZeit).TotalMilliseconds)
    167. Console.WriteLine("Zeit für n = " & nn & ": " & EndZeit.ToString & " ms")
    168. Dim sR As String = shiftRight(s, cnt)
    169. Dim sL As String = shiftLeft(sR, cnt)
    170. Dim sRO As String = shiftRight(s, cnt, False)
    171. Dim sLO As String = shiftLeft(s, cnt, False)
    172. StartZeit = System.DateTime.Now
    173. For i As Integer = 0 To nn
    174. sR = shiftRight(s, cnt)
    175. sL = shiftLeft(sR, cnt)
    176. Next
    177. EndZeit2 = CInt(System.DateTime.Now.Subtract(StartZeit).TotalMilliseconds)
    178. Console.WriteLine("Zeit für n = " & nn & ": " & EndZeit2.ToString & " ms")
    179. Console.WriteLine("Differenz: " & EndZeit - EndZeit2 & " ms")
    180. Console.WriteLine() : Console.WriteLine()
    181. Console.ReadKey()
    182. End Sub
    183. End Module


    Freundliche Grüsse

    exc-jdbi
    Moin!

    ich hätts so gemacht:

    VB.NET-Quellcode

    1. Public Function shiftLeft(array As Byte()) As Byte()
    2. Dim arraylist As New List(Of Byte)(array.ToList)
    3. Dim temp As Byte = arraylist.First
    4. arraylist.RemoveAt(0)
    5. arraylist.Add(temp)
    6. Return arraylist.ToArray
    7. End Function
    8. Public Function shiftright(array As Byte()) As Byte()
    9. Dim arraylist As New List(Of Byte)(array.ToList)
    10. Dim temp As Byte = arraylist.Last
    11. arraylist.RemoveAt(arraylist.Count - 1)
    12. arraylist.Insert(0, temp)
    13. Return arraylist.ToArray
    14. End Function
    Der Beitrag wurde aus 100% wiederverwendbaren Elektronen erstellt!