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

    • VB.NET

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

      Warum packt Ihr da überall so ein tolles fixed-Statements rein? Ich glaube kaum, dass das sonderlich viel bringt. Im Gegenteil: Die CLR kann den Speicher nicht optimieren, weil die Daten da irgendwo angepinnt rumhängen.
      Warum ein Struct? Das wird ein einziges mal instanziiert, da hat man mit einem Struct wahrscheinlich einen Geschwindigkeitsvorteil von ca. 0%.


      Übrigens:

      dotnetperls schrieb:

      Performance optimization
      The fixed statement does generate certain intermediate language instructions when used, which impact performance. Often, for this reason, unsafe code and pointer manipulation is slower than managed C# code.

      So:
      This indicates that, in the .NET Framework, it is typically better to use exclusively managed code.

      Also:
      Older languages that do not rely on the .NET Framework will benefit more from pointer manipulation optimizations.
      Einfach für alles Pointer verwenden, weil "is ja schnell und so" ist also nicht der Beste weg. Der JIT/NGen/GC optimiert da oft einfach besser.

      Müsste man trotzdem mal testen.

      Edit:
      Mal ganz davon abgesehen, dass der Unsafe-Kram oft auch die Portabilität auf andere Plattformen/Programmiersprachen extrem einschränkt. Aber darum geht's hier ja nicht.
      Von meinem iPhone gesendet

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

      Ich hab Win7 :D
      Hab nicht auf die FW Version geachtet.
      @nikeee13
      Geht nicht um die Matrix, nur um den Algo. Fixxed is da nirgens drin. Ob nun Struct oder Klasse ist egal, die verhalen sich nicht anders in diesem Fall.
      Dateien
      Es ging auch so, ich konnte es einfach auf 4.5 runtersetzen. ;)
      Allerdings funktioniert diese Zeile bei mir nicht:

      C-Quellcode

      1. byte* color = &((byte*)sourceData.Scan0)[Clamp(sourceY, 0, height - 1) * sourceData.Stride + Clamp(sourceX, 0, width - 1) * 4];
      Man kann keine Referenz eines dereferenzierten Pointers abgreifen. Ich hab das so geändert:

      C-Quellcode

      1. byte* color = (byte*)sourceData.Scan0 + Clamp(sourceY, 0, height - 1) * sourceData.Stride + Clamp(sourceX, 0, width - 1) * 4;
      Also das läuft bei dir? Sicher, dass dus nicht mit C++ verwechselst. :P Du hast vermutlich 2013, oder?
      Ich hab ProcessingKernel auch mal zu ner Klasse gemacht, das fixed-Zeugs war ja nur drin, weil man bei ner Struct das Array nicht initialisieren kann.
      Habs zum testen rausgenommen, damit mir die richtige Exception geschmissen wird ^^ Kann gern wieder rein. Durch Offset und Faktor hat man mehr Möglichkeiten für Filter. Bei manchen Filtern werden die Pixelwerte negativ, dann kann man n Offset dazu addieren. Der Faktor dient auch dazu um den Range zwischen 0 und 255 zu halten.

      Pfade relativ ausgeben

      hier schoma die nächste Aufgabe:
      Gegeben sind viele absolute Pfade.
      die sollen nun relativ zu einem bestimmten Pfad ausgegeben werden, also

      Input schrieb:

      C:\Programming\DotNet\VS10\VB08\_WithDataset\VokabelTrainer
      C:\Programming\DotNet\VS10\VB10\_WithDataset\WithCheckbox
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0DatasetTemplate\A0DatasetTemplate\bin\Release
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0DatasetTemplate\A0DatasetTemplate\obj\Debug
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0DatasetTemplate\A0DatasetTemplate\obj\Debug\TempPE
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0EbcTemplate
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0EbcTemplate\A0EbcTemplate
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0EbcTemplate\A0EbcTemplate\obj

      käme raus als:

      Output schrieb:

      ..\..\..\VB08\_WithDataset\VokabelTrainer
      ..\WithCheckbox
      ..\A0DatasetTemplate\A0DatasetTemplate\bin\Release
      ..\A0DatasetTemplate\A0DatasetTemplate\obj\Debug
      ..\A0DatasetTemplate\A0DatasetTemplate\obj\Debug\TempPE
      .
      A0EbcTemplate
      A0EbcTemplate\obj
      eben relativ zu
      C:\Programming\DotNet\VS10\VB10\_WithDataset\A0EbcTemplate

      Signatur-Vorschlag:

      VB.NET-Quellcode

      1. Function GetRelPathes(currentPath As String, fullPathes As IEnumerable(Of String)) As String()
      2. Return (From fp In fullPathes Select "..\.." & fp.Substring(15)).ToArray
      3. End Function


      Nicht erschrecken: Die TestAnwendung ist "Fat-Ware" ;)
      Dateien
      • PathResolver.zip

        (232,44 kB, 67 mal heruntergeladen, zuletzt: )

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

      Habs:
      Spoiler anzeigen

      C-Quellcode

      1. public static bool IsAbsolutePath(string path, out char driveLetter)
      2. {
      3. driveLetter = default(char);
      4. if (string.IsNullOrEmpty(path))
      5. return false;
      6. driveLetter = path[0];
      7. return path.Length >= 2 && char.IsLetter(driveLetter) && path[1] == ':' && (path.Length < 3 || path[2] == '\\');
      8. }
      9. public static string GetRelativePath(string currentPath, string path)
      10. {
      11. char driveLetter1, driveLetter2;
      12. if (currentPath == null)
      13. throw new ArgumentNullException("currentPath");
      14. if (!IsAbsolutePath(currentPath, out driveLetter1))
      15. throw new ArgumentException("The path has to be absolute.", "currentPath");
      16. if (path == null)
      17. throw new ArgumentNullException("path");
      18. if (!IsAbsolutePath(path, out driveLetter2))
      19. throw new ArgumentException("The path has to be absolute.", "path");
      20. if (driveLetter1 != driveLetter2)
      21. throw new InvalidOperationException("The drive letters are not allowed to be different.");
      22. if (string.Equals(currentPath, path, StringComparison.OrdinalIgnoreCase))
      23. return ".";
      24. string[] currentPathParts = currentPath.Split('\\');
      25. string[] pathParts = path.Split(new[] { '\\' }, currentPathParts.Length);
      26. for (int i = 0; i < currentPathParts.Length; i++)
      27. {
      28. if (pathParts.Length <= i)
      29. return string.Concat(Enumerable.Repeat("..", currentPathParts.Length - i)) + pathParts[pathParts.Length - 1];
      30. if (!string.Equals(currentPathParts[i], pathParts[i], StringComparison.OrdinalIgnoreCase))
      31. return string.Concat(Enumerable.Repeat("..", currentPathParts.Length - i)) + string.Join("", pathParts.Skip(i));
      32. }
      33. return pathParts[pathParts.Length - 1];
      34. }
      35. public static string[] GetRelativePaths(string currentPath, IEnumerable<string> paths)
      36. {
      37. return paths.Select(path => GetRelativePath(currentPath, path)).ToArray();
      38. }
      Ich habs mit deinen Testpfaden getestet und es gab das richtige Ergebnis.

      Edit: der Editor hat wieder Backslashes verschluckt. X(
      Da kommt das bei raus:

      Quellcode

      1. ..\..\..\..\..\..\VB08\_WithDataset\VokabelTrainer
      2. ..\..\..\..\WithCheckbox
      3. .
      4. ..\..\obj\Debug
      5. ..\..\obj\Debug\TempPE
      6. ..\..\..\..\A0EbcTemplate
      7. ..\..\..\..\A0EbcTemplate\A0EbcTemplate
      8. ..\..\..\..\A0EbcTemplate\A0EbcTemplate\obj
      Ist das das, was du sehen wolltest?
      ists ein Fehler im CodeConverter? bei mir kommt

      VB.NET-Quellcode

      1. ............VB08_WithDatasetVokabelTrainer
      2. ........WithCheckbox
      3. .
      4. ....objDebug
      5. ....objDebug\TempPE
      6. ........A0EbcTemplate
      7. ........A0EbcTemplateA0EbcTemplate
      8. ........A0EbcTemplateA0EbcTemplateobj


      nö - der Fehler ist wohl Zeile#39, das string.Join()

      nö - zB noch mehr Fehler, bei Eingabe von

      VB.NET-Quellcode

      1. C:\Programming\DotNet\VS10\VB10\_WithDataset\BindingSourceBug\HelpersDll\obj\x86\Debug\TempPE
      2. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip
      3. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BlindStromKompensation
      4. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\Helpers
      5. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation
      6. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\BlindStromKompensation
      7. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\Helpers
      8. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\BlindStromKompensation\My Project
      9. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\Helpers\My Project
      10. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BlindStromKompensation\bin
      11. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BlindStromKompensation\My Project
      und currentDir

      VB.NET-Quellcode

      1. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\BlindStromKompensation\My Project
      bekomme ich

      VB.NET-Quellcode

      1. ..\..\..\..\..\BindingSourceBug\HelpersDll\obj\x86\Debug\TempPE
      2. ......BackZip
      3. ..\..\..\..\BlindStromKompensation
      4. ..\..\..\..\Helpers
      5. ....BlindStromKompensation
      6. ..BlindStromKompensation
      7. ..\..\Helpers
      8. .
      9. ..\..\Helpers\My Project
      10. ..\..\..\..\BlindStromKompensation\bin
      11. ..\..\..\..\BlindStromKompensation\My Project
      Aber da hab ich schon versucht, was auszubügeln. :(

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

      Ich hab ja gesagt, der Editor hat Backslashes verschluckt, weshalb die jetzt in der Ausgabe alle fehlen.
      In den Zeilen 36 und 39 gehört jeweils hinter die zwei Punkte ( das ist der String in Enumerable.Repeat()) ein Backslash (bzw. in C# zwei wegen Escaping). Das selbe gilt in Zeile 39 für den Seperator-Char in string.Join().
      So sollte das eigentlich aussehen:
      ups - schwer überlesen. Und schwerer Forum-Bug.
      So ist ein SourceCode-Austausch natürlich unbrauchbar.

      Also ich weiß einfach nicht, ob ichs nu richtig teste, aber bei Eingabe

      VB.NET-Quellcode

      1. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BlindStromKompensation
      2. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\Helpers
      3. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation
      4. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\BlindStromKompensation
      5. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\Helpers
      6. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\BlindStromKompensation\My Project
      7. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\Helpers\My Project
      8. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BlindStromKompensation\bin
      9. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BlindStromKompensation\My Project
      currentPath

      VB.NET-Quellcode

      1. C:\Programming\DotNet\VS10\VB10\_WithDataset\BlindStromKompensation\BackZip\BlindStromKompensation\BlindStromKompensation\My Project
      failts noch ein bisserl:

      VB.NET-Quellcode

      1. ..\..\..\BackZip
      2. ..\..\..\..\BlindStromKompensation
      3. ..\..\..\..\Helpers
      4. ..\..\BlindStromKompensation
      5. ..\BlindStromKompensation
      6. ..\..\Helpers
      7. .
      8. ..\..\Helpers\My Project
      9. ..\..\..\..\BlindStromKompensation\bin
      10. ..\..\..\..\BlindStromKompensation\My Project
      (#4 sollte ..\.. sein.)
      Und ich nehme an, das dadrunter sollte auch nur ..\ sein.
      Probier mal die Zeilen 35/36 durch das hier zu ersetzen (fehlende Backslashes beachten):

      C-Quellcode

      1. if (pathParts.Length == i)
      2. return string.Concat(Enumerable.Repeat("..", currentPathParts.Length - i));
      Ich bin mir bei der Behandlung dieses Sonderfalls nicht ganz sicher, aber so kam da zumindest das richtige Ergebnis raus.

      Edit: bzw. wenn du die Backslashes am Ende nicht haben willst gehts auch so (hier sind die Backslashes vorne im Join, nicht nach den Punkten):

      C-Quellcode

      1. if (pathParts.Length == i)
      2. return string.Join("", Enumerable.Repeat("..", currentPathParts.Length - i));
      Aufgabe: Zähle Zeile
      Challengetyp: "I can do that in one line!"

      Lösungen bitte ausschließlich als Einzeiler.
      Wer noch eine kleine extra Challenge haben will: auf unnötige Konvertierungen zwischen Reihungen verzichten! (z.B. toList())
      Ergänze folgenden Funktionsrumpf:

      VB.NET-Quellcode

      1. ''' <summary>
      2. ''' Gibt die Summe aller Zeilen der Dateien in dem angegebenen Verzeichnis zurück.
      3. ''' </summary>
      4. ''' <param name="path">Eine Zeichenfolge, die den Pfad angibt, in dem gesucht werden soll.</param>
      5. ''' <param name="searchPattern">Die Suchzeichenfolge. Das Standardmuster ist "*", wobei alle Dateien gefunden werden.</param>
      6. ''' <param name="searchOption">Einer der Enumerationswerte, der angibt, ob nur das aktuelle Verzeichnis oder auch alle Unterverzeichnisse durchsucht werden sollen. Der Standardwert ist TopDirectoryOnly.</param>
      7. ''' <returns></returns>
      8. ''' <remarks></remarks>
      9. Public Shared Function countLines(path As String, Optional searchPattern As String = "*", Optional searchOption As SearchOption = IO.SearchOption.TopDirectoryOnly) As Integer
      10. Return 42
      11. End Function
      Als Einzeiler ist das vllt. nicht unbedingt sinnvoll, aber hab' ihn trotzdem angehängt:

      VB.NET-Quellcode

      1. Shared Function CountLines(
      2. directory As DirectoryInfo,
      3. Optional searchPattern As String = "*",
      4. Optional searchOption As SearchOption = IO.SearchOption.TopDirectoryOnly) As Integer
      5. If directory Is Nothing Then
      6. If searchOption = IO.SearchOption.TopDirectoryOnly Then
      7. Return 0
      8. Else
      9. Return System.IO.DriveInfo.GetDrives().Sum(Function(p)
      10. If Not p.IsReady Then Return 0
      11. Return CountLinesHelper(p.RootDirectory, searchPattern, searchOption)
      12. End Function)
      13. End If
      14. Else
      15. Return CountLinesHelper(directory, searchPattern, searchOption)
      16. End If
      17. End Function
      18. Private Shared Function CountLinesHelper(
      19. directory As DirectoryInfo,
      20. Optional searchPattern As String = "*",
      21. Optional searchOption As SearchOption = IO.SearchOption.TopDirectoryOnly) As Integer
      22. Try
      23. Return If(searchOption = IO.SearchOption.AllDirectories, directory.EnumerateDirectories(). _
      24. Select(AddressOf CountLinesHelper).Sum(), 0) + _
      25. directory.GetFiles().Select(Function(p) File.ReadAllLines(p.FullName).Length).Sum()
      26. Catch ex As FileNotFoundException
      27. Return 0
      28. 'TODO: add security fail exception handling
      29. End Try
      30. End Function
      31. Shared Function CountLinesPrimitive(
      32. directory As String,
      33. Optional searchPattern As String = "*",
      34. Optional searchOption As SearchOption = IO.SearchOption.TopDirectoryOnly) As Integer
      35. Return IO.Directory.EnumerateFiles(directory, searchPattern, searchOption).Select(Function(file) IO.File.ReadAllLines(file).Length).Sum()
      36. End Function

      Exception-Handling fällt dann halt weg, da directory nicht Nothing sein darf, es sei denn, du störst dich nicht an einem Zweizeiler.

      Gruß
      ~blaze~