Angepinnt [Sammelthread] Knobel-Aufgaben, knifflige Algorithmen, elegante Lösungen

    • VB.NET

    Es gibt 178 Antworten in diesem Thema. Der letzte Beitrag () ist von Thunderbolt.

      Hab es doch hinbekommen, hat mir keine ruhe gelassen. Hab zwar nicht die Points sortiert, aber richtig geadded. Zwar unschön, aber gelößt. Bin mal auf die weiteren Lösungen gespannt.
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
      2. pList = New List(Of Point)
      3. For i = -1000 To 0
      4. For ii = -1000 To 0
      5. Dim res As Integer = CInt(i ^ 2 + ii ^ 2)
      6. If res > 490 And res < 510 Then
      7. pList.Add(New Point(i + 100, ii + 100))
      8. End If
      9. Next
      10. Next
      11. For i = 0 To 1000
      12. For ii = -1000 To 0
      13. Dim res As Integer = CInt(i ^ 2 + ii ^ 2)
      14. If res > 490 And res < 510 Then
      15. pList.Add(New Point(i + 100, ii + 100))
      16. End If
      17. Next
      18. Next
      19. For i = 1000 To 0 Step -1
      20. For ii = -0 To 1000
      21. Dim res As Integer = CInt(i ^ 2 + ii ^ 2)
      22. If res > 490 And res < 510 Then
      23. pList.Add(New Point(i + 100, ii + 100))
      24. End If
      25. Next
      26. Next
      27. For i = 0 To -1000 Step -1
      28. For ii = 1000 To 0 Step -1
      29. Dim res As Integer = CInt(i ^ 2 + ii ^ 2)
      30. If res > 490 And res < 510 Then
      31. pList.Add(New Point(i + 100, ii + 100))
      32. End If
      33. Next
      34. Next
      35. e.Graphics.DrawPolygon(Pens.Black, pList.ToArray)
      36. End Sub

      Bilder
      • Unbenannt.JPG

        8,53 kB, 57×61, 1.300 mal angesehen

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

      iwie einen Sonderpreis hast du dafür schon verdient! :thumbsup:

      aber ma ehrlich:

      VB.NET-Quellcode

      1. For i = 0 To 1000
      2. For ii = -1000 To 0
      Dir ist schon klar, dass das > 1 Mio Durchläufe sind (genau: 1002001)?

      Ansonsten denke ich, dass der Bresenham absolut nicht zu toppen ist.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

      Ja ist schon sehr viel, hätte ich mich mal etwas mehr mit IComparer beschäftigt, wäre das besser geworden, da ich die Points dann hätte sortieren können. Ich weiss nun auch schon was ich in den nächsten Tagen machen werde. Mir ging es nicht darum es möglichst performant zu lösen, sondern es überhaupt zu schaffen.
      Na ja hab das schon ungünstig gemacht, der Mittelpunkt wäre 0 daher auch beim Point zur Liste adden beide Achsen +100. Den radius hab ich etwas, ich sag mal ausgedehnt "res > 490 And res < 510", im nachhinein hab ich den fix auf die hälfte der Breite des Kreises gemacht, und die größe des Kreises verringert wodurch es dann auch nicht mehr ganz so eierig aussah.

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

      ErfinderDesRades schrieb:

      ist mir zu schwierig
      Isses nicht, ich hab solch etwa 1985 auf einem ZX81 implementiert.

      Derfuhr schrieb:

      "res > 490 And res < 510"
      ist nicht von Nöten, die Lösung ist exakt.
      Mal in 3 Sätzen ohne Code:
      Aufgrund der Symmetrie kann der Kreis in 8 Achtel zerlegt werden (@Artentus:).
      Ich fange oben an und gehe nach rechts, aufgrund der Symmetrie werden die anderen 7 Segmente entsprechend befüllt.
      Da ich oben bin, kann ich nur nach rechts oder rechts-unten geneb (waagerecht bzw. diagonal).
      Es wird für beide Punkte der Pytagoras berechnet und die Diagonale mit dem Radius-Quadrat verglichen.
      Der Punkt, der näher dran ist, ist der richtige.
      Nun wieder nach rechts / rechts unten ...
      Das Ende ist erreicht, wenn die Diagonale erreicht ist.
      Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
      Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
      Ein guter .NET-Snippetkonverter (der ist verfügbar).
      Programmierfragen über PN / Konversation werden ignoriert!

      Numerierung für Backup-Dateien generieren

      Dieses scheint eine nur kleine Knobelei:
      Aus dieser Fragestellung folgt folgendes Problem:
      Gegeben ein Backup-Verzeichnis, wo etwa verzippte Ordner als .zip-Dateien reinkommen sollen.
      Da soll ein neues Backup ja nicht immer das vorherige überschreiben, also hängt man eine Nummer an den Dateinamen an. Aber damit ist die Extension demoliert, und die Datei nicht mehr etwa für WinRar registriert. Also müssen Backup-Namen erzeugt werden ala:

      Output schrieb:

      C:\Programming\DotNet\VS10\Cs10\FileSplitter\Backups\FileSplitter_00.zip
      C:\Programming\DotNet\VS10\Cs10\FileSplitter\Backups\FileSplitter_01.zip
      C:\Programming\DotNet\VS10\Cs10\FileSplitter\Backups\FileSplitter_02.zip
      C:\Programming\DotNet\VS10\Cs10\FileSplitter\Backups\FileSplitter_03.zip
      C:\Programming\DotNet\VS10\Cs10\FileSplitter\Backups\FileSplitter_04.zip


      Input etwa obiger Ausgabe wäre

      Input schrieb:

      Source-File: C:\Programming\DotNet\VS10\Cs10\FileSplitter.zip
      Dest-Folder: C:\Programming\DotNet\VS10\Cs10\FileSplitter\Backups
      Dabei muss immer die höchste "Versionsnummer" erhöht werden, damit man die Backups einfach nach Name sortieren kann, und das letzte ist dann auch das neueste.
      Also Lücken in der Durchnumerierung dürfen nicht durch neue Dateien geschlossen werden - (allenfalls wäre die Durchnumerierung komplett neu zu machen, wenn man auf Lückenlosigkeit besteht).

      Vorschlag Methodensignatur:

      VB.NET-Quellcode

      1. Public Function AppendNumber(sourceFile as FileInfo, destFolder As DirectoryInfo) As FileInfo
      Hm, und warum scheint es nur eine kleine Knobelei?

      Filenamen vom Sourcefile nehmen, alle Files aus destFolder auflisten, nur die holen, die mit dem Namen anfangen, die Zahlen abtrennen, nach der höchsten Nummer suchen, die Zahl erhöhen, den File speichern. Wenn noch keine drin waren, dann 00 dranhängen.
      @sonne75:
      Hab die Falle bei der Aufgabe auch noch nicht aufgeschnappt.
      Um die höchste Zahl auszulesen könnte man sowas hier benutzen.

      VB.NET-Quellcode

      1. Public r As New System.Text.RegularExpressions.Regex("_\d+")
      2. Public Function AppendNumber(sourceFile As FileInfo, destFolder As DirectoryInfo) As FileInfo
      3. Dim vale = (From fi As FileInfo In destFolder.GetFiles() Select Integer.Parse(r.Match(fi.Name).Groups("value").Value)).Max()
      4. 'Hier der andere Kram
      5. End Function

      Müsste man halt noch ein bisschen bzgl. Validität anpassen.
      Done.

      C-Quellcode

      1. public FileInfo AppendNumber(FileInfo sourceFile, DirectoryInfo destFolder)
      2. {
      3. int w = 0;
      4. var files = destFolder.EnumerateFiles().Select(item => new { File = item, Name = Path.GetFileNameWithoutExtension(item.Name) }).Where(item => item.Name.StartsWith(Path.GetFileNameWithoutExtension(sourceFile.Name)) && item.Name.Contains('_') && item.File.Extension == sourceFile.Extension).Select(item => new { File = item.File, Name = item.Name, Number = int.Parse(item.Name.Split('_').Last()) }).OrderByDescending(item => item.Number);
      5. if (files.Any())
      6. {
      7. w = files.First().Number;
      8. }
      9. return new FileInfo(Path.Combine(destFolder.FullName, Path.GetFileNameWithoutExtension(sourceFile.Name) + "_" + (w + 1).ToString("00")) + sourceFile.Extension);
      10. }

      Einzeiler verbessert:
      Spoiler anzeigen
      (muss ohne Code-Tag sein, sonst wird's unschön)
      return new FileInfo(Path.Combine(destFolder.FullName, Path.GetFileNameWithoutExtension(sourceFile.Name) + "_" + (destFolder.EnumerateFiles().Select(item => new { File = item, Name = Path.GetFileNameWithoutExtension(item.Name) }).Where(item => item.Name.StartsWith(Path.GetFileNameWithoutExtension(sourceFile.Name)) && item.Name.Contains('_') && item.File.Extension == sourceFile.Extension).Select(item => new { File = item.File, Name = item.Name, Number = int.Parse(item.Name.Split('_').Last()) }).OrderByDescending(item => item.Number).Select(item => item.Number).FirstOrDefault() + 1).ToString("00")) + sourceFile.Extension);

      Ohne Einzeiler:
      Spoiler anzeigen

      C-Quellcode

      1. public FileInfo AppendNumber(FileInfo sourceFile, DirectoryInfo destFolder)
      2. {
      3. var s = destFolder.EnumerateFiles().Select(item => new { File = item, Name = Path.GetFileNameWithoutExtension(item.Name) });
      4. var t = s.Where(item => item.Name.StartsWith(Path.GetFileNameWithoutExtension(sourceFile.Name)) && item.Name.Contains('_') && item.File.Extension == sourceFile.Extension);
      5. var u = t.Select(item => new { File = item.File, Name = item.Name, Number = int.Parse(item.Name.Split('_').Last()) });
      6. var v = u.OrderByDescending(item => item.Number);
      7. int w = 0;
      8. if (v.Any())
      9. {
      10. w = v.First().Number;
      11. }
      12. return new FileInfo(Path.Combine(destFolder.FullName, Path.GetFileNameWithoutExtension(sourceFile.Name) + "_" + (w + 1).ToString("00")) + sourceFile.Extension);
      13. }

      Fehler aus Post #36 behoben.

      Link mit ordentlichem Highlighting: gist.github.com (Revisionen beachten!)

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „AliveDevil“ ()

      Ich hätte es halt in einem deutlich leserlichen Code (also ohne "Where", "Select" und anderen Inline-Kram) gemacht...

      Aber wie das immer so ist: wenn man weiß, wie es gemacht werden soll, fehlt die Herausforderung das Ganze in einem Code auszuschreiben (zumal der trivial zu sein scheint, ist nur Fleißarbeit).
      ich hänge mal eine Test-Anwendung an - bisher ist ja noch nix funktionsfähiges eingegangen (naja - c# mussich erst noch testen - jou - fail):

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class frmFileSaver
      3. Private _srcFile As New FileInfo("..\..\Test.txt")
      4. Private _destFolder As New DirectoryInfo("..\..\Backups")
      5. Private Sub btSaveFile_Click(sender As System.Object, e As System.EventArgs) Handles btSaveFile.Click
      6. _srcFile.CopyTo(AppendNumber(_srcFile, _destFolder))
      7. End Sub
      8. Public Shared Function AppendNumber(sourceFile As FileInfo, destFolder As DirectoryInfo) As String
      9. Return Path.Combine(destFolder.FullName, "JoUndHierNu...")
      10. End Function
      11. End Class
      (hab auch die Signatur bischen geändert - Rückgabe braucht kein FileInfo zu sein)
      Dateien
      • FileSaver00.zip

        (12,87 kB, 263 mal heruntergeladen, zuletzt: )
      Okay. Ich habs nochmal durch einen Konverter gejagt und kurz getestet:

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class frmFileSaver
      3. Private _srcFile As New FileInfo("..\..\Test.txt")
      4. Private _destFolder As New DirectoryInfo("..\..\Backups")
      5. Private Sub btSaveFile_Click(sender As System.Object, e As System.EventArgs) Handles btSaveFile.Click
      6. _srcFile.CopyTo(AppendNumber(_srcFile, _destFolder))
      7. End Sub
      8. Public Shared Function AppendNumber(sourceFile As FileInfo, destFolder As DirectoryInfo) As String
      9. Return Path.Combine(destFolder.FullName, Path.GetFileNameWithoutExtension(sourceFile.Name) + "_" + (destFolder.EnumerateFiles().[Select](Function(item) New With { _
      10. Key .File = item, _
      11. Key .Name = Path.GetFileNameWithoutExtension(item.Name) _
      12. }).Where(Function(item) item.Name.StartsWith(Path.GetFileNameWithoutExtension(sourceFile.Name)) AndAlso item.Name.Contains("_"c) AndAlso item.File.Extension = sourceFile.Extension).[Select](Function(item) New With { _
      13. Key .File = item.File, _
      14. Key .Name = item.Name, _
      15. Key .Number = Integer.Parse(item.Name.Split("_"c).Last()) _
      16. }).OrderByDescending(Function(item) item.Number).[Select](Function(item) item.Number).FirstOrDefault() + 1).ToString("00")) + sourceFile.Extension
      17. End Function
      18. End Class

      (Fehler aus Post #36 in Zeile 12 behoben)
      Funktioniert bestens.

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

      Na ja, ein bisschen Select war doch da und ja, ich weiß, ziemlich unübersichtlich noch.

      Aber gab es nicht Eigenschaft "NameWithoutExtension"? Oder war es nur bei FileSystemInfo?

      VB.NET-Quellcode

      1. Public Class frmFileSaver
      2. Private _srcFile As New FileInfo("..\..\Test.txt")
      3. Private _destFolder As New DirectoryInfo("..\..\Backups")
      4. Private Sub btSaveFile_Click(sender As System.Object, e As System.EventArgs) Handles btSaveFile.Click
      5. _srcFile.CopyTo(AppendNumber(_srcFile, _destFolder))
      6. End Sub
      7. Public Shared Function AppendNumber(ByVal sourceFile As FileInfo, ByVal destFolder As DirectoryInfo) As String
      8. Dim newNmb = 0
      9. Dim lst As New List(Of Integer)
      10. Dim NewName As String
      11. Dim filename= sourceFile.Name.Substring(0, filename.IndexOf("."c))
      12. Dim backfilesNmb = From f In destFolder.GetFiles Where f.Name.StartsWith(filename) Select f.Name.Split("_"c)(1)
      13. If backfilesNmb.Count > 0 Then
      14. For Each nmb In backfilesNmb
      15. Dim n = 0
      16. Integer.TryParse(nmb.Substring(0, nmb.IndexOf(".")), n)
      17. lst.Add(n)
      18. Next
      19. newNmb = lst.Max() + 1
      20. End If
      21. NewName = filename & "_" & newNmb.ToString("D2") & ".zip"
      22. Return Path.Combine(destFolder.FullName, NewName)
      23. End Function
      24. End Class
      @sonne75:
      Finde deine Lösung total übersichtlich. Ich weiß nicht was du hast :D
      Das einzige, was nicht so schick ist, ist die Maximumsuche mit einer Liste.
      Sowas finde ich da besser Link
      Aber gab es nicht Eigenschaft "NameWithoutExtension"? Oder war es nur bei FileSystemInfo?
      Gibt es glaube ich nicht, aber man könnte einfach FileInfo.Extension aus FileInfo.Name replacen.
      Hier mal mein Vorschlag :)

      VB.NET-Quellcode

      1. Public Function AppendNumber(sourceFile As FileInfo, destFolder As DirectoryInfo) As FileInfo
      2. Dim lst = destFolder.GetFiles("*" & Path.GetFileNameWithoutExtension(sourceFile.Name) & "*").Reverse.ToList
      3. Dim filename = Path.GetFileNameWithoutExtension(sourceFile.Name)
      4. For Each item In lst
      5. Dim s = item.Name.Replace(filename & "_", "")
      6. Dim s2 = (Integer.Parse(Path.GetFileNameWithoutExtension(s)) + 1).ToString("D2")
      7. Dim newfile = Path.Combine(destFolder.FullName, filename & "_" & s2 & ".zip")
      8. sourceFile.CopyTo(newfile, True)
      9. Next
      10. Dim newBackupFile As New FileInfo(Path.Combine(destFolder.FullName, filename & "_00.zip"))
      11. sourceFile.CopyTo(newBackupFile.FullName, True)
      12. Return newBackupFile
      13. End Function


      lg
      ScheduleLib 0.0.1.0
      Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten

      LaMiy schrieb:

      aber man könnte einfach FileInfo.Extension aus FileInfo.Name replacen.

      Stimmt, das wäre auch gut. Das Ungetüm

      VB.NET-Quellcode

      1. Path.GetFileNameWithoutExtension(sourceFile.Name)


      habe ich auch schon entdeckt, aber die Schreibweise ist mir beim besten Willen viel zu lang.

      @fichz
      Wieso kopierst du alle Files in der Schleife? Man braucht doch nur einen neuen Zip-File mit der nächsten Nummer.