diff --git a/archive/c/c-sharp/Baklava.cs b/archive/c/c-sharp/Baklava.cs index 300173c10..14458172f 100644 --- a/archive/c/c-sharp/Baklava.cs +++ b/archive/c/c-sharp/Baklava.cs @@ -1,21 +1,17 @@ -using System; +const int Height = 10; +const char Symbol = '*'; -class CSharp -{ - - static void Main (string[] args) - { - - for (SByte i = 0; i < 10; i++) - Console.WriteLine ( - new string (' ', (10 - i)) + new string ('*', (i * 2 + 1)) - ); +Span stars = stackalloc char[Height * 2 + 1]; +stars.Fill(Symbol); - for (SByte i = 10; -1 < i; i--) - Console.WriteLine ( - new string (' ', (10 - i)) + new string ('*', (i * 2 + 1)) - ); +static void PrintRow(int level, int height, ReadOnlySpan stars) +{ + Console.Write(new string(' ', height - level)); + Console.WriteLine(stars[..(level * 2 + 1)]); +} - } +for (int i = 0; i < Height; i++) + PrintRow(i, Height, stars); -} +for (int i = Height; i >= 0; i--) + PrintRow(i, Height, stars); diff --git a/archive/c/c-sharp/Base64EncodeDecode.cs b/archive/c/c-sharp/Base64EncodeDecode.cs index 60b05cdd6..64546e7b2 100644 --- a/archive/c/c-sharp/Base64EncodeDecode.cs +++ b/archive/c/c-sharp/Base64EncodeDecode.cs @@ -1,67 +1,34 @@ using System.Text; -public class Base64EncodeDecode +return args switch { - public static void Usage() - { - Console.WriteLine("Usage: please provide a mode and a string to encode/decode"); - Environment.Exit(1); - } + ["encode", var value] when !string.IsNullOrWhiteSpace(value) + => Encode(value), + ["decode", var value] when !string.IsNullOrWhiteSpace(value) + => Decode(value), - private static bool IsValidBase64(string input) - { - if (string.IsNullOrWhiteSpace(input) || input.Length % 4 != 0) - return false; + _ => Usage() +}; - foreach (char c in input) - { - if (!"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".Contains(c)) - return false; - } - - int padCount = input.EndsWith("==") ? 2 : - input.EndsWith('=') ? 1 : 0; - - int firstPadIndex = input.IndexOf('='); - return firstPadIndex == -1 || firstPadIndex >= input.Length - padCount; - } - - public static int Main(string[] args) - { - if (args.Length != 2) - { - Usage(); - return 1; - } - - string mode = args[0].ToLowerInvariant(); - string value = args[1]; - - if (string.IsNullOrWhiteSpace(mode) || string.IsNullOrWhiteSpace(value)) - { - Usage(); - return 1; - } +static int Encode(string value) +{ + Console.WriteLine(Convert.ToBase64String(Encoding.ASCII.GetBytes(value))); + return 0; +} - try - { - string result = mode switch - { - "encode" => Convert.ToBase64String(Encoding.UTF8.GetBytes(value)), - "decode" => IsValidBase64(value) - ? Encoding.UTF8.GetString(Convert.FromBase64String(value)) - : throw new ArgumentException("Input is not valid Base64."), - _ => throw new ArgumentException("Unknown mode. Use 'encode' or 'decode'.") - }; +static int Decode(string value) +{ + byte[] buffer = new byte[value.Length]; + if (!Convert.TryFromBase64String(value, buffer, out int written)) + return Usage(); - Console.WriteLine(result); - return 0; - } - catch - { - Usage(); - return 1; - } - } + Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, written)); + return 0; } + +static int Usage() +{ + Console.Error.WriteLine("Usage: please provide a mode and a string to encode/decode"); + return 1; +} \ No newline at end of file diff --git a/archive/c/c-sharp/BinarySearch.cs b/archive/c/c-sharp/BinarySearch.cs index 68411a55b..998b95593 100644 --- a/archive/c/c-sharp/BinarySearch.cs +++ b/archive/c/c-sharp/BinarySearch.cs @@ -1,58 +1,43 @@ -using System; -using System.Linq; using System.Collections.Generic; -public class BinarySearch +if (args is not [var input, var targetRaw] + || !int.TryParse(targetRaw, out int target) + || !TryParseSorted(input.AsSpan(), out var numbers)) { - public static bool Search(List list, int toFind) - { - int lowerBound = 0; - int upperBound = list.Count - 1; - while (lowerBound <= upperBound) - { - int midpoint = (lowerBound + upperBound) / 2; - if (list[midpoint] == toFind) - { - return true; - } - else if (list[midpoint] < toFind) - { - lowerBound = midpoint + 1; - } - else - { - upperBound = midpoint - 1; - } - } - return false; - } + return Usage(); +} - public static void ErrorAndExit() - { - Console.WriteLine("Usage: please provide a list of sorted integers (\"1, 4, 5, 11, 12\") and the integer to find (\"11\")"); - Environment.Exit(1); - } +Console.WriteLine(numbers.BinarySearch(target) >= 0); +return 0; + +static bool TryParseSorted(ReadOnlySpan span, out List numbers) +{ + numbers = new(span.Count(',') + 1); + + int last = int.MinValue; - public static void Main(string[] args) + while (!span.IsEmpty) { - try - { - var list = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - var toFind = Int32.Parse(args[1]); - - for (int i = 0; i < list.Count - 1; i++) - { - if (list[i] > list[i + 1]) - { - ErrorAndExit(); - } - } - - Console.WriteLine(Search(list, toFind)); - } - catch - { - ErrorAndExit(); - } + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n) || n < last) + return false; + + numbers.Add(n); + last = n; } + + return numbers.Count > 0; } + +static int Usage() +{ + Console.Error.WriteLine( + """Usage: please provide a list of sorted integers ("1, 4, 5, 11, 12") and the integer to find ("11")""" + ); + + return 1; +} \ No newline at end of file diff --git a/archive/c/c-sharp/BubbleSort.cs b/archive/c/c-sharp/BubbleSort.cs index 85693b3a1..5ea9e5c44 100644 --- a/archive/c/c-sharp/BubbleSort.cs +++ b/archive/c/c-sharp/BubbleSort.cs @@ -1,61 +1,62 @@ -using System; -using System.Linq; -using System.Collections.Generic; +using System.Runtime.InteropServices; -class CSharp +if (args is not [var input] || !TryParseList(input.AsSpan(), out var numbers)) + return Usage(); + +BubbleSort(numbers); + +Console.WriteLine(string.Join(", ", numbers)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - public static List BubbleSort(List xs) - { - var acc = xs.ToList(); - var last = acc.ToList(); - do - { - last = acc.ToList(); - acc = PassList(last.ToList()); - } - while(!acc.SequenceEqual(last)); - return acc; - } + numbers = new(span.Count(',') + 1); - public static List PassList(List xs) + while (!span.IsEmpty) { - if (xs.Count() <= 1) - return xs; - var x0 = xs[0]; - var x1 = xs[1]; - if (x1 < x0) - { - xs.RemoveAt(1); - return new List() {x1}.Concat(PassList(xs)).ToList(); - } - else - { - xs.RemoveAt(0); - return new List() {x0}.Concat(PassList(xs)).ToList(); - } - } - - public static void ErrorAndExit() - { - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); } - - public static void Main(string[] args) + + return numbers.Count > 1; +} + +static void BubbleSort(List list) +{ + Span span = CollectionsMarshal.AsSpan(list); + int n = span.Length; + + for (int i = 0; i < n - 1; i++) { - if (args.Length != 1) - ErrorAndExit(); - try - { - var xs = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - if (xs.Count() <= 1) - ErrorAndExit(); - var sortedXs = BubbleSort(xs); - Console.WriteLine(string.Join(", ", sortedXs)); - } - catch + bool swapped = false; + + for (int j = 0; j < n - i - 1; j++) { - ErrorAndExit(); + if (span[j] <= span[j + 1]) + continue; + + (span[j], span[j + 1]) = (span[j + 1], span[j]); + swapped = true; } + + if (!swapped) + return; } +} + + +static int Usage() +{ + Console.Error.WriteLine(""" +Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5" +""" + ); + return 1; } \ No newline at end of file diff --git a/archive/c/c-sharp/Capitalize.cs b/archive/c/c-sharp/Capitalize.cs index a6bee5da8..2726d71e2 100644 --- a/archive/c/c-sharp/Capitalize.cs +++ b/archive/c/c-sharp/Capitalize.cs @@ -1,20 +1,12 @@ -using System; -using System.Linq; - -namespace SamplePrograms +if (args is not [string input, ..] || string.IsNullOrWhiteSpace(input)) { - class Program - { - static void Main(string[] args) - { - if (!args.Any() || args[0] == "") - { - Console.WriteLine("Usage: please provide a string"); - return; - } - string input = args[0]; - string output = input.First().ToString().ToUpper() + input.Substring(1); - Console.WriteLine(output); - } - } + Console.Error.WriteLine("Usage: please provide a string"); + return; } + +char c = input[0]; + +if (char.IsLower(c)) + input = char.ToUpperInvariant(c) + input[1..]; + +Console.WriteLine(input); \ No newline at end of file diff --git a/archive/c/c-sharp/ConvexHull.cs b/archive/c/c-sharp/ConvexHull.cs index 1eeebc51f..878859149 100644 --- a/archive/c/c-sharp/ConvexHull.cs +++ b/archive/c/c-sharp/ConvexHull.cs @@ -1,135 +1,101 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Runtime.InteropServices; -public record Point(int X, int Y) : IComparable +if ( + args is not [var xInput, var yInput] + || !TryParsePoints(xInput.AsSpan(), yInput.AsSpan(), out var points) +) { - public int CompareTo(Point? other) - => other is null ? 1 : X != other.X ? X.CompareTo(other.X) : Y.CompareTo(other.Y); + return Usage(); +} - public override string ToString() => $"({X}, {Y})"; +points.Sort(); - public static bool operator <(Point left, Point right) => left.CompareTo(right) < 0; - public static bool operator >(Point left, Point right) => left.CompareTo(right) > 0; -} +var hull = BuildHull(CollectionsMarshal.AsSpan(points), out int size); +for (int i = 0; i < size; i++) + Console.WriteLine(hull[i]); + +return 0; -public static class ConvexHull +static bool TryParsePoints(ReadOnlySpan x, ReadOnlySpan y, out List points) { - private static void ShowUsage() + points = []; + + if (x.IsWhiteSpace() || y.IsWhiteSpace()) + return false; + + var list = new List(); + + while (true) { - Console.Error.WriteLine("Usage: please provide at least 3 x and y coordinates as separate lists (e.g. \"100, 440, 210\")"); + if (!TryNext(ref x, out int xVal) || !TryNext(ref y, out int yVal)) + break; + + points.Add(new(xVal, yVal)); } - private static List ParseIntegerList(string input) + return x.IsEmpty && y.IsEmpty && points.Count >= 3; + + static bool TryNext(ref ReadOnlySpan span, out int value) { - if (string.IsNullOrWhiteSpace(input)) - { - ShowUsage(); - Environment.Exit(1); - } - - var list = input - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Select(part => int.TryParse(part, out var val) - ? val - : throw new ArgumentException($"Invalid integer value: '{part}'")) - .ToList(); - - if (list.Count < 3) - { - ShowUsage(); - Environment.Exit(1); - } - - return list; + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + span = comma >= 0 ? span[(comma + 1)..] : []; + return int.TryParse(token, out value); } +} - - /// - /// Calculates the cross product of vectors OA and OB. - /// Positive result means counter-clockwise turn. - /// Negative result means clockwise turn. - /// Zero means points are colinear. - /// - private static long Cross(Point o, Point a, Point b) +static Point[] BuildHull(Span points, out int size) +{ + int numPoints = points.Length; + if (numPoints < 3) { - var (ox, oy) = (o.X, o.Y); - var (ax, ay) = (a.X, a.Y); - var (bx, by) = (b.X, b.Y); - return (long)(ax - ox) * (by - oy) - (long)(ay - oy) * (bx - ox); + size = numPoints; + return points.ToArray(); } + var hull = new Point[numPoints * 2]; + int h = 0; - /// - /// Constructs the convex hull using the Jarvis March algorithm. - /// - private static List BuildHull(List points) + for (int i = 0; i < numPoints; i++) { - int n = points.Count; - if (n < 3) return [.. points]; - - int startIndex = 0; - for (int i = 1; i < n; i++) - { - if (points[i] < points[startIndex]) - startIndex = i; - } + var p = points[i]; - var hull = new List(); - int currentIndex = startIndex; + while (h > 1 && Cross(hull[h - 2], hull[h - 1], p) <= 0) + h--; - do - { - hull.Add(points[currentIndex]); - int candidateIndex = (currentIndex + 1) % n; + hull[h++] = p; + } - for (int i = 0; i < n; i++) - { - if (Cross(points[currentIndex], points[i], points[candidateIndex]) > 0) - candidateIndex = i; - } + int lower = h; - currentIndex = candidateIndex; + for (int i = numPoints - 2; i >= 0; i--) + { + var p = points[i]; - } while (currentIndex != startIndex); + while (h > lower && Cross(hull[h - 2], hull[h - 1], p) <= 0) + h--; - return hull; + hull[h++] = p; } - public static int Main(string[] args) - { - if (args.Length != 2) - { - ShowUsage(); - return 1; - } - - try - { - var xCoords = ParseIntegerList(args[0]); - var yCoords = ParseIntegerList(args[1]); - if (xCoords.Count != yCoords.Count) - { - ShowUsage(); - return 1; - } - - if (xCoords.Count < 3) - { - ShowUsage(); - return 1; - } - - var points = xCoords.Zip(yCoords, (x, y) => new Point(x, y)).ToList(); - - BuildHull(points).ForEach(Console.WriteLine); - - return 0; - } - catch - { - ShowUsage(); - return 1; - } - } + size = h - 1; + return hull; + + static long Cross(Point o, Point a, Point b) => + (long)(a.X - o.X) * (b.Y - o.Y) - (long)(a.Y - o.Y) * (b.X - o.X); +} + +static int Usage() +{ + Console.Error.WriteLine( + """Usage: please provide at least 3 x and y coordinates as separate lists (e.g. "100, 440, 210")""" + ); + return 1; +} + +public readonly record struct Point(int X, int Y) : IComparable +{ + public int CompareTo(Point other) => X != other.X ? X.CompareTo(other.X) : Y.CompareTo(other.Y); + + public override string ToString() => $"({X}, {Y})"; } diff --git a/archive/c/c-sharp/DepthFirstSearch.cs b/archive/c/c-sharp/DepthFirstSearch.cs index 9a8813260..24c7f1ecc 100644 --- a/archive/c/c-sharp/DepthFirstSearch.cs +++ b/archive/c/c-sharp/DepthFirstSearch.cs @@ -1,152 +1,83 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -public record Node(int Id) +if (args is not [var matrixRaw, var verticesRaw, var targetRaw] || + !int.TryParse(targetRaw, out int target) || + !TryParseList(verticesRaw.AsSpan(), out var vertices) || + !TryParseList(matrixRaw.AsSpan(), out var matrix)) { - private readonly HashSet _childrenSet = new(); - private readonly List _children = new(); + return Usage(); +} - public IReadOnlyList Children => _children; +int n = vertices.Count; +if (matrix.Count != n * n) + return Usage(); - public void AddChild(int childId) - { - if (_childrenSet.Add(childId)) - _children.Add(childId); - } -} +List[] graph = new List[n]; +for (int i = 0; i < n; i++) + graph[i] = []; -public class Tree +for (int r = 0; r < n; r++) { - private readonly Dictionary _nodes = new(); - - public int RootId { get; } + int baseIdx = r * n; - public Tree(int rootId) => RootId = rootId; + for (int c = 0; c < n; c++) + if (matrix[baseIdx + c] != 0) + graph[r].Add(c); +} - public void AddNode(Node node) => _nodes[node.Id] = node; +Console.WriteLine( + DFS(graph, vertices, target).ToString().ToLowerInvariant() +); - public Node? GetNode(int id) => _nodes.TryGetValue(id, out var node) ? node : null; +return 0; - public bool ContainsNode(int id) => _nodes.ContainsKey(id); +static bool DFS(List[] graph, List values, int target) +{ + int n = values.Count; + var visited = new bool[n]; + var stack = new int[n]; + int sp = 0; - public IReadOnlyCollection Nodes => _nodes.Values; -} + stack[sp++] = 0; -public static class DepthFirstSearch -{ - private static void ShowUsage() + while (sp > 0) { - Console.Error.WriteLine("Usage: please provide a tree in an adjacency matrix form (\"0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0\") together with a list of vertex values (\"1, 3, 5, 2, 4\") and the integer to find (\"4\")"); + int v = stack[--sp]; + if (visited[v]) continue; + + visited[v] = true; + if (values[v] == target) return true; + + foreach (int next in graph[v]) + if (!visited[next]) + stack[sp++] = next; } - public static List ParseIntegerList(string input) - { - if (string.IsNullOrWhiteSpace(input)) - throw new ArgumentException("Input string is null or whitespace"); + return false; +} - var parts = input.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - var list = new List(parts.Length); +static bool TryParseList(ReadOnlySpan span, out List numbers) +{ + numbers = new(span.Count(',') + 1); - foreach (var part in parts) - { - if (!int.TryParse(part, out var val)) - throw new ArgumentException($"Invalid integer value: '{part}'"); - list.Add(val); - } + while (!span.IsEmpty) + { + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - if (list.Count < 1) - throw new ArgumentException("List must contain at least one integer"); + span = comma >= 0 ? span[(comma + 1)..] : []; - return list; - } + if (!int.TryParse(token, out int n)) + return false; - public static Tree CreateTree(List adjacencyMatrix, List vertices) - { - int n = vertices.Count; - - if (adjacencyMatrix.Count != n * n) - throw new ArgumentException("Adjacency matrix size does not match vertex count squared"); - - var tree = new Tree(vertices[0]); - - foreach (var v in vertices) - tree.AddNode(new Node(v)); - - for (int row = 0; row < n; row++) - { - var currentNode = tree.GetNode(vertices[row])!; - for (int col = 0; col < n; col++) - { - int matrixValue = adjacencyMatrix[row * n + col]; - if (matrixValue != 0) - { - int childId = vertices[col]; - if (!tree.ContainsNode(childId)) - throw new ArgumentException("Adjacency matrix references unknown vertex"); - currentNode.AddChild(childId); - } - } - } - - return tree; + numbers.Add(n); } - public static bool DFS(Tree tree, int target) - { - var visited = new HashSet(); - var stack = new Stack(); - stack.Push(tree.RootId); - - while (stack.Count > 0) - { - var current = stack.Pop(); - if (!visited.Add(current)) - continue; - - if (current == target) - return true; - - var node = tree.GetNode(current); - if (node is not null) - { - foreach (var child in node.Children) - stack.Push(child); - } - } - - return false; - } + return true; +} - public static int Main(string[] args) - { - if (args.Length != 3) - { - ShowUsage(); - return 1; - } - - try - { - var adjacencyMatrix = ParseIntegerList(args[0]); - var vertices = ParseIntegerList(args[1]); - - if (!int.TryParse(args[2], out var target)) - { - ShowUsage(); - return 1; - } - - var tree = CreateTree(adjacencyMatrix, vertices); - bool found = DFS(tree, target); - - Console.WriteLine(found.ToString().ToLowerInvariant()); - return 0; - } - catch - { - ShowUsage(); - return 1; - } - } -} \ No newline at end of file +static int Usage() +{ + Console.Error.WriteLine( + """Usage: please provide a tree in an adjacency matrix form ("0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0") together with a list of vertex values ("1, 3, 5, 2, 4") and the integer to find ("4")""" + ); + return 1; +} diff --git a/archive/c/c-sharp/Dijkstra.cs b/archive/c/c-sharp/Dijkstra.cs index 72177161d..f7c02c0b0 100644 --- a/archive/c/c-sharp/Dijkstra.cs +++ b/archive/c/c-sharp/Dijkstra.cs @@ -1,121 +1,81 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -public static class Program +if ( + args is not [var matrixRaw, var sourceRaw, var destRaw] + || !int.TryParse(sourceRaw, out int source) + || !int.TryParse(destRaw, out int dest) + || !TryParseList(matrixRaw.AsSpan(), out var matrix) +) + return Usage(); + +int n = (int)Math.Sqrt(matrix.Count); +if (n * n != matrix.Count || (uint)source >= n || (uint)dest >= n) + return Usage(); + +var graph = new List<(int, uint)>[n]; +for (int i = 0; i < n; i++) + graph[i] = []; + +for (int u = 0, k = 0; u < n; u++) + for (int v = 0; v < n; v++, k++) + if (matrix[k] != 0) + graph[u].Add((v, (uint)matrix[k])); + +uint result = Dijkstra(graph, source, dest); +if (result == uint.MaxValue) + return Usage(); + +Console.WriteLine(result); +return 0; + +static uint Dijkstra(List<(int to, uint w)>[] graph, int source, int destination) { - private const int INF = 0x3F3F3F3F; + var dist = new uint[graph.Length]; + Array.Fill(dist, uint.MaxValue); - private static void ShowUsage() - { - Console.Error.WriteLine("Usage: please provide three inputs: a serialized matrix, a source node and a destination node"); - Environment.Exit(1); - } + var pq = new PriorityQueue(); + pq.Enqueue(source, dist[source] = 0); - private static List ParseIntegerList(string input) + while (pq.TryDequeue(out int u, out uint d)) { - if (string.IsNullOrWhiteSpace(input)) - ShowUsage(); - - var list = input - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Select(s => - { - if (!int.TryParse(s, out var val) || val < 0) - ShowUsage(); - return val; - }) - .ToList(); - - if (list.Count == 0) - ShowUsage(); - - return list; - } - - private static int GetMatrixDimension(List matrix) - { - var length = matrix.Count; - var dimension = (int)Math.Sqrt(length); - return (dimension * dimension == length && dimension > 0) ? dimension : -1; - } + if (d != dist[u]) + continue; + if (u == destination) + return d; - private static int Dijkstra(List matrix, int dimension, int source, int destination) - { - var dist = Enumerable.Repeat(INF, dimension).ToArray(); - var visited = new bool[dimension]; - - dist[source] = 0; - - for (int _ = 0; _ < dimension; _++) + foreach (var (v, w) in graph[u]) { - int minDist = INF; - int minIndex = -1; - - for (int j = 0; j < dimension; j++) - { - if (!visited[j] && dist[j] < minDist) - { - minDist = dist[j]; - minIndex = j; - } - } - - if (minIndex == -1) - break; - - if (minIndex == destination) - return dist[minIndex]; - - visited[minIndex] = true; - - for (int j = 0; j < dimension; j++) - { - int weight = matrix[minIndex * dimension + j]; - if (!visited[j] && weight > 0 && dist[minIndex] + weight < dist[j]) - { - dist[j] = dist[minIndex] + weight; - } - } + uint newDist = d + w; + if (newDist < dist[v]) + pq.Enqueue(v, dist[v] = newDist); } - - return dist[destination] == INF ? -1 : dist[destination]; } - public static int Main(string[] args) - { - if (args.Length != 3) - { - ShowUsage(); - } - - var matrixStr = args[0].Trim(); - var sourceStr = args[1].Trim(); - var destinationStr = args[2].Trim(); - - if (string.IsNullOrEmpty(matrixStr) || string.IsNullOrEmpty(sourceStr) || string.IsNullOrEmpty(destinationStr)) - ShowUsage(); + return uint.MaxValue; +} - var matrix = ParseIntegerList(matrixStr); - int dimension = GetMatrixDimension(matrix); +static bool TryParseList(ReadOnlySpan span, out List numbers) +{ + numbers = new(span.Count(',') + 1); + while (!span.IsEmpty) + { + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - bool sourceParsed = int.TryParse(sourceStr, out int source); - bool destinationParsed = int.TryParse(destinationStr, out int destination); + span = comma >= 0 ? span[(comma + 1)..] : []; - if (dimension == -1 || !sourceParsed || !destinationParsed || - source < 0 || source >= dimension || - destination < 0 || destination >= dimension) - { - ShowUsage(); - } + if (!int.TryParse(token, out int n) || n < 0) + return false; - int shortestDistance = Dijkstra(matrix, dimension, source, destination); + numbers.Add(n); + } - if (shortestDistance == -1) - ShowUsage(); + return true; +} - Console.WriteLine(shortestDistance); - return 0; - } +static int Usage() +{ + Console.Error.WriteLine( + "Usage: please provide three inputs: a serialized matrix, a source node and a destination node" + ); + return 1; } diff --git a/archive/c/c-sharp/DuplicateCharacterCounter.cs b/archive/c/c-sharp/DuplicateCharacterCounter.cs index 14e64ace8..253c89e1e 100644 --- a/archive/c/c-sharp/DuplicateCharacterCounter.cs +++ b/archive/c/c-sharp/DuplicateCharacterCounter.cs @@ -1,39 +1,26 @@ -using System; -using System.Collections.Generic; - -public class DuplicateCharacterCounter +if (args is not [var input] || string.IsNullOrWhiteSpace(input)) { - public static void Main(string[] args) - { - if (args.Length == 0 || string.IsNullOrEmpty(args[0])) - { - Console.WriteLine("Usage: please provide a string"); - return; - } + Console.Error.WriteLine("Usage: please provide a string"); + return; +} - string input = args[0]; +Span freq = stackalloc int[128]; - Dictionary countMap = new Dictionary(); +foreach (char c in input) + if (c < 128) + freq[c]++; - foreach (char c in input) - { - if (countMap.ContainsKey(c)) - countMap[c]++; - else - countMap[c] = 1; - } +bool found = false; - string result = ""; +foreach (char c in input) +{ + if (c >= 128 || freq[c] < 2) + continue; - foreach (char c in input) - { - if (countMap[c] > 1) - { - result += $"{c}: {countMap[c]}\n"; - countMap[c] = 0; - } - } + Console.WriteLine($"{c}: {freq[c]}"); + freq[c] = 0; + found = true; +} - Console.WriteLine(string.IsNullOrEmpty(result) ? "No duplicate characters" : result.Trim()); - } -} \ No newline at end of file +if (!found) + Console.WriteLine("No duplicate characters"); \ No newline at end of file diff --git a/archive/c/c-sharp/EvenOdd.cs b/archive/c/c-sharp/EvenOdd.cs index fef8d255b..e4349408e 100644 --- a/archive/c/c-sharp/EvenOdd.cs +++ b/archive/c/c-sharp/EvenOdd.cs @@ -1,22 +1,7 @@ -using System; - -namespace SamplePrograms +if (args is not [var input] || !int.TryParse(input, out int n)) { - public class EvenOdd - { - public static void Main(string[] args) - { - try - { - int n = int.Parse(args[0]); - var result = n % 2 == 0 ? "Even" : "Odd"; - Console.WriteLine(result); - } - catch - { - Console.WriteLine("Usage: please input a number"); - Environment.Exit(1); - } - } - } + Console.Error.WriteLine("Usage: please input a number"); + return; } + +Console.WriteLine(n % 2 == 0 ? "Even" : "Odd"); \ No newline at end of file diff --git a/archive/c/c-sharp/Factorial.cs b/archive/c/c-sharp/Factorial.cs index a20f10e45..bb7d7c1a9 100644 --- a/archive/c/c-sharp/Factorial.cs +++ b/archive/c/c-sharp/Factorial.cs @@ -1,39 +1,24 @@ -using System; using System.Numerics; -namespace SamplePrograms +if (args is not [var input] || !BigInteger.TryParse(input, out var n) || n < 0) { - public class Factorial - { - public static BigInteger Fact(BigInteger n) - { - if (n <= 0) - return 1; - return n * Fact(n - 1); - } + Console.Error.WriteLine("Usage: please input a non-negative integer"); + return; +} + +Console.WriteLine(Factorial(n)); + +static BigInteger Factorial(BigInteger n) => n < 2 ? BigInteger.One : MultiplyRange(2, n); + +static BigInteger MultiplyRange(BigInteger lo, BigInteger hi) +{ + if (lo > hi) + return BigInteger.One; + if (lo == hi) + return lo; + if (hi - lo == 1) + return lo * hi; - public static void Main(string[] args) - { - try - { - var n = BigInteger.Parse(args[0]); - if (n > 4550) - { - Console.WriteLine(string.Format("{0}! is out of the reasonable bounds for calculation.", n)); - Environment.Exit(1); - } - else if (n < 0) { - Console.WriteLine("Usage: please input a non-negative integer"); - Environment.Exit(1); - } - var result = Fact(n); - Console.WriteLine(result); - } - catch - { - Console.WriteLine("Usage: please input a non-negative integer"); - Environment.Exit(1); - } - } - } + BigInteger mid = (lo + hi) / 2; + return MultiplyRange(lo, mid) * MultiplyRange(mid + 1, hi); } diff --git a/archive/c/c-sharp/Fibonacci.cs b/archive/c/c-sharp/Fibonacci.cs index 99cb2d8b4..ade30de17 100644 --- a/archive/c/c-sharp/Fibonacci.cs +++ b/archive/c/c-sharp/Fibonacci.cs @@ -1,30 +1,13 @@ -using System; - -namespace SamplePrograms +if (args is not [var input] || !int.TryParse(input, out int n) || n < 0) { - public class Fibonacci - { - public static void Main(string[] args) - { - try - { - int n = int.Parse(args[0]); - int first = 0; - int second = 1; - int result = 0; - for(int i = 1; i <= n; i++) - { - result = first + second; - first = second; - second = result; - Console.WriteLine(i + ": " + first); - } - } - catch(Exception) - { - Console.WriteLine("Usage: please input the count of fibonacci numbers to output"); - Environment.Exit(0); - } - } - } + Console.Error.WriteLine("Usage: please input the count of fibonacci numbers to output"); + return; } + +int a = 1, b = 1; + +for (int i = 1; i <= n; i++) +{ + Console.WriteLine($"{i}: {a}"); + (a, b) = (b, a + b); +} \ No newline at end of file diff --git a/archive/c/c-sharp/FileInputOutput.cs b/archive/c/c-sharp/FileInputOutput.cs index 8c83ff3ca..254bc1b28 100644 --- a/archive/c/c-sharp/FileInputOutput.cs +++ b/archive/c/c-sharp/FileInputOutput.cs @@ -1,20 +1,18 @@ -using System; using System.IO; -namespace SamplePrograms -{ - public class FileIO - { - public static void Write() => - File.WriteAllText("output.txt", "file contents"); - - public static string Read() => - File.ReadAllText("output.txt"); +const string Path = "output.txt"; +const string Content = """ +line 1 +line 2 +line 3 +"""; - public static void Main(string[] args) - { - Write(); - Console.WriteLine(Read()); - } - } +try +{ + File.WriteAllText(Path, Content); + Console.WriteLine(File.ReadAllText(Path)); +} +catch (IOException ex) +{ + Console.WriteLine($"IO error: {ex.Message}"); } \ No newline at end of file diff --git a/archive/c/c-sharp/FizzBuzz.cs b/archive/c/c-sharp/FizzBuzz.cs index 323d602f5..7257f4abb 100644 --- a/archive/c/c-sharp/FizzBuzz.cs +++ b/archive/c/c-sharp/FizzBuzz.cs @@ -1,32 +1,9 @@ -namespace FizzBuzz +for (int i = 1; i <= 100; i++) { - public class Program - { - public static string FizzBuzz(int number) - { - string temp = ""; - if (number % 3 == 0) - { - temp += "Fizz"; - } - if (number % 5 == 0) - { - temp += "Buzz"; - } - if (string.IsNullOrEmpty(temp)) - { - temp += number; - } - return temp; - } + string s = ""; - private static void Main(string[] args) - { - for (int i = 1; i <= 100; i++) - { - string line = FizzBuzz(i); - System.Console.WriteLine(line); - } - } - } -} + if (i % 3 == 0) s += "Fizz"; + if (i % 5 == 0) s += "Buzz"; + + Console.WriteLine(s.Length > 0 ? s : i); +} \ No newline at end of file diff --git a/archive/c/c-sharp/FractionMath.cs b/archive/c/c-sharp/FractionMath.cs index 5738389cb..f8a56e690 100644 --- a/archive/c/c-sharp/FractionMath.cs +++ b/archive/c/c-sharp/FractionMath.cs @@ -1,196 +1,83 @@ -using System; +if ( + args is not [var leftRaw, var op, var rightRaw] + || !Fraction.TryParse(leftRaw, out var a) + || !Fraction.TryParse(rightRaw, out var b) +) +{ + Console.Error.WriteLine("Usage: ./fraction-math operand1 operator operand2"); + return; +} + +Console.WriteLine( + op switch + { + "+" => (a + b).ToString(), + "-" => (a - b).ToString(), + "*" => (a * b).ToString(), + "/" => (a / b).ToString(), + "==" => (a == b ? 1 : 0), + "!=" => (a != b ? 1 : 0), + ">" => (a > b ? 1 : 0), + "<" => (a < b ? 1 : 0), + ">=" => (a >= b ? 1 : 0), + "<=" => (a <= b ? 1 : 0), + _ => "Error: Invalid operator", + } +); -namespace SamplePrograms +public readonly record struct Fraction(long N, long D) : IComparable { - public class FractionMath + public override string ToString() => $"{N}/{D}"; + + public static Fraction Create(long n, long d) + { + if (d == 0) + throw new DivideByZeroException(); + + long g = Gcd(n, d); + return new(n / g * Math.Sign(d), Math.Abs(d / g)); + } + + static long Gcd(long a, long b) + { + a = Math.Abs(a); + b = Math.Abs(b); + + while (b != 0) + (a, b) = (b, a % b); + + return a == 0 ? 1 : a; + } + + public static bool TryParse(ReadOnlySpan s, out Fraction f) { - private int numerator; - private int denominator; - - public FractionMath(int numerator = 0, int denominator = 1) - { - if (denominator == 0) - { - throw new ArgumentException("Denominator cannot be zero."); - } - - this.numerator = numerator; - this.denominator = denominator; - } - - // GCD method using the Euclidean algorithm in an iterative approach - // Orginal algorithm was found on GeeksforGeeks, modified for clarity: - // https://www.geeksforgeeks.org/program-to-find-gcd-or-hcf-of-two-numbers/# - private int GCD(int x, int y) - { - while (y != 0) - { - int z = x; - x = y; - y = z % y; - } - return x; - } - - private void Simplify() - { - int gcd = GCD(numerator, denominator); - numerator /= gcd; - denominator /= gcd; - - if (denominator < 0) - { - numerator = -numerator; - denominator = -denominator; - } - } - - public override string ToString() - { - Simplify(); - return $"{numerator}/{denominator}"; - } - - public static FractionMath Parse(string fractionString) - { - string[] numbers = fractionString.Split('/'); - if (numbers.Length != 2) - { - throw new FormatException("Invalid fraction. A format of 'numerator/denominator' is expected."); - } - - int numerator = int.Parse(numbers[0]); - int denominator = int.Parse(numbers[1]); - - return new FractionMath(numerator, denominator); - } - - public static FractionMath operator +(FractionMath f1, FractionMath f2) - { - int newNumerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator; - int newDenominator = f1.denominator * f2.denominator; - return new FractionMath(newNumerator, newDenominator); - } - - public static FractionMath operator -(FractionMath f1, FractionMath f2) - { - int newNumerator = f1.numerator * f2.denominator - f2.numerator * f1.denominator; - int newDenominator = f1.denominator * f2.denominator; - return new FractionMath(newNumerator, newDenominator); - } - - public static FractionMath operator *(FractionMath f1, FractionMath f2) - { - int newNumerator = f1.numerator * f2.numerator; - int newDenominator = f1.denominator * f2.denominator; - return new FractionMath(newNumerator, newDenominator); - } - - public static FractionMath operator /(FractionMath f1, FractionMath f2) - { - int newNumerator = f1.numerator * f2.denominator; - int newDenominator = f1.denominator * f2.numerator; - return new FractionMath(newNumerator, newDenominator); - } - - public static bool operator ==(FractionMath f1, FractionMath f2) - { - return f1.numerator * f2.denominator == f1.denominator * f2.numerator; - } - - public static bool operator !=(FractionMath f1, FractionMath f2) - { - return !(f1 == f2); - } - - public static bool operator >(FractionMath f1, FractionMath f2) - { - return f1.numerator * f2.denominator > f1.denominator * f2.numerator; - } - - public static bool operator <(FractionMath f1, FractionMath f2) - { - return f1.numerator * f2.denominator < f1.denominator * f2.numerator; - } - - public static bool operator >=(FractionMath f1, FractionMath f2) - { - return f1 > f2 || f1 == f2; - } - - public static bool operator <=(FractionMath f1, FractionMath f2) - { - return f1 < f2 || f1 == f2; - } - - public static void Main(string[] args) - { - if (args.Length != 3) - { - Console.WriteLine("Usage: ./fraction-math operand1 operator operand2"); - return; - } - - try - { - FractionMath operand1 = Parse(args[0]); - string operation = args[1]; - FractionMath operand2 = Parse(args[2]); - - FractionMath result; - bool comparisonResult; - - switch (operation) - { - case "+": - result = operand1 + operand2; - Console.WriteLine(result); - break; - case "-": - result = operand1 - operand2; - Console.WriteLine(result); - break; - case "*": - result = operand1 * operand2; - Console.WriteLine(result); - break; - case "/": - result = operand1 / operand2; - Console.WriteLine(result); - break; - case "==": - comparisonResult = operand1 == operand2; - Console.WriteLine(comparisonResult ? "1" : "0"); - break; - case "!=": - comparisonResult = operand1 != operand2; - Console.WriteLine(comparisonResult ? "1" : "0"); - break; - case ">": - comparisonResult = operand1 > operand2; - Console.WriteLine(comparisonResult ? "1" : "0"); - break; - case "<": - comparisonResult = operand1 < operand2; - Console.WriteLine(comparisonResult ? "1" : "0"); - break; - case ">=": - comparisonResult = operand1 >= operand2; - Console.WriteLine(comparisonResult ? "1" : "0"); - break; - case "<=": - comparisonResult = operand1 <= operand2; - Console.WriteLine(comparisonResult ? "1" : "0"); - break; - default: - Console.WriteLine($"Error: Invalid operator '{operation}'"); - break; - } - } - catch (Exception e) - { - Console.WriteLine($"Error: {e.Message}"); - } - } + f = default; + + int i = s.IndexOf('/'); + return i >= 0 + && long.TryParse(s[..i], out long n) + && long.TryParse(s[(i + 1)..], out long d) + && d != 0 + && (f = Create(n, d)) == f; } + + public static Fraction operator +(Fraction a, Fraction b) => + Create(a.N * b.D + b.N * a.D, a.D * b.D); + + public static Fraction operator -(Fraction a, Fraction b) => + Create(a.N * b.D - b.N * a.D, a.D * b.D); + + public static Fraction operator *(Fraction a, Fraction b) => Create(a.N * b.N, a.D * b.D); + + public static Fraction operator /(Fraction a, Fraction b) => Create(a.N * b.D, a.D * b.N); + + public static bool operator <(Fraction a, Fraction b) => a.N * b.D < b.N * a.D; + + public static bool operator >=(Fraction a, Fraction b) => !(a < b); + + public static bool operator >(Fraction a, Fraction b) => b < a; + + public static bool operator <=(Fraction a, Fraction b) => !(b < a); + + public int CompareTo(Fraction other) => (N * other.D).CompareTo(other.N * D); } diff --git a/archive/c/c-sharp/HelloWorld.cs b/archive/c/c-sharp/HelloWorld.cs index f4d785988..193a0edb9 100644 --- a/archive/c/c-sharp/HelloWorld.cs +++ b/archive/c/c-sharp/HelloWorld.cs @@ -1,10 +1 @@ -namespace SamplePrograms -{ - public class HelloWorld - { - static void Main() - { - System.Console.WriteLine("Hello, World!"); - } - } -} +Console.WriteLine("Hello, World!"); \ No newline at end of file diff --git a/archive/c/c-sharp/InsertionSort.cs b/archive/c/c-sharp/InsertionSort.cs index ad1bc192a..58388ea81 100644 --- a/archive/c/c-sharp/InsertionSort.cs +++ b/archive/c/c-sharp/InsertionSort.cs @@ -1,47 +1,65 @@ -using System; -using System.Linq; -using System.Collections.Generic; +using System.Runtime.InteropServices; -public class InsertionSort +if (args is not [var input] || !TryParseList(input.AsSpan(), out var numbers)) + return Usage(); + +InsertionSort(CollectionsMarshal.AsSpan(numbers)); + +Console.WriteLine(string.Join(", ", numbers)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - public static List Insertion(List xs) - { - var sorted = new List(); - foreach (var x in xs) - sorted = Insert(sorted, x); - return sorted; - } + numbers = new(span.Count(',') + 1); - public static List Insert(List xs, int x) + while (!span.IsEmpty) { - var index = 0; - while (index < xs.Count() && x > xs[index]) - index++; - xs.Insert(index > 0 ? index : 0, x); - return xs; - } + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - public static void ErrorAndExit() - { - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); } - - public static void Main(string[] args) + + return numbers.Count > 1; +} + +static void InsertionSort(Span xs) +{ + for (int i = 1; i < xs.Length; i++) { - if (args.Length != 1) - ErrorAndExit(); - try - { - var xs = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - if (xs.Count() <= 1) - ErrorAndExit(); - var sortedXs = Insertion(xs); - Console.WriteLine(string.Join(", ", sortedXs)); - } - catch + int x = xs[i]; + if (x >= xs[i - 1]) + continue; + + int lo = 0, + hi = i; + + while (lo < hi) { - ErrorAndExit(); + int mid = (lo + hi) >> 1; + + if (x >= xs[mid]) + lo = mid + 1; + else + hi = mid; } + + xs[lo..i].CopyTo(xs[(lo + 1)..]); + xs[lo] = x; } -} \ No newline at end of file +} + +static int Usage() +{ + Console.Error.WriteLine( + """ +Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5" +""" + ); + return 1; +} diff --git a/archive/c/c-sharp/JobSequencing.cs b/archive/c/c-sharp/JobSequencing.cs index e43edb2ae..f2f308f06 100644 --- a/archive/c/c-sharp/JobSequencing.cs +++ b/archive/c/c-sharp/JobSequencing.cs @@ -1,86 +1,87 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Runtime.InteropServices; -// shows a job with profit and deadline properties -class Job +if ( + args is not [var profitsRaw, var deadlinesRaw] + || !TryParseJobs(profitsRaw.AsSpan(), deadlinesRaw.AsSpan(), out var jobs, out int maxDeadline) +) { - public int Profit { get; set; } - public int Deadline { get; set; } + return Usage(); +} + +Console.WriteLine(MaxProfit(jobs, maxDeadline)); +return 0; + +static bool TryParseJobs( + ReadOnlySpan profits, + ReadOnlySpan deadlines, + out List jobs, + out int maxDeadline +) +{ + jobs = new(Math.Max(profits.Count(',') + 1, 0)); + maxDeadline = 0; + + while (!profits.IsEmpty && !deadlines.IsEmpty) + { + if (!TryNext(ref profits, out int profit) || !TryNext(ref deadlines, out int deadline)) + return false; - // constructor to initialize the job with profits and deadline - public Job(int profit, int deadline) + jobs.Add(new(profit, deadline)); + maxDeadline = Math.Max(maxDeadline, deadline); + } + + return profits.IsEmpty && deadlines.IsEmpty && jobs.Count > 0; + + static bool TryNext(ref ReadOnlySpan span, out int n) { - Profit = profit; - Deadline = deadline; + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + span = comma >= 0 ? span[(comma + 1)..] : []; + return int.TryParse(token, out n); } } -class JobSequencing +static long MaxProfit(List jobs, int maxDeadline) { - static void Main(string[] args) + jobs.Sort((a, b) => b.Profit.CompareTo(a.Profit)); + + int n = Math.Min(jobs.Count, maxDeadline); + + Span parent = n <= 1024 ? stackalloc int[n + 1] : new int[n + 1]; + + for (int i = 0; i <= n; i++) + parent[i] = i; + + long total = 0; + + foreach (ref readonly var j in CollectionsMarshal.AsSpan(jobs)) { - // check if 2 arugments are provided (lists of profits and deadlines) - if (args.Length < 2) - { - Console.WriteLine("Usage: please provide a list of profits and a list of deadlines"); - return; - } - - // parse the list of profits from the first arugment - var profitList = args[0].Split(',').Select(p => int.TryParse(p.Trim(), out int x) ? x : (int?)null).ToList(); - - // parse the list of profits from the second arugment - var deadlineList = args[1].Split(',').Select(d => int.TryParse(d.Trim(), out int x) ? x : (int?)null).ToList(); - - // Validate inputs - if (profitList.Contains(null) || deadlineList.Contains(null) || profitList.Count != deadlineList.Count) - { - Console.WriteLine("Usage: please provide a list of profits and a list of deadlines"); - return; - } - - // combine both profits and deadline sinto job objects - var jobs = profitList.Zip(deadlineList, (p, d) => new Job(p.Value, d.Value)).ToList(); - - // calculate the max profit - var result = GetMaxProfitJobSequence(jobs); - - // output of total profit - Console.WriteLine(result.Sum(job => job.Profit)); + int slot = Find(parent, Math.Min(j.Deadline, n)); + + if (slot == 0) + continue; + + total += j.Profit; + parent[slot] = Find(parent, slot - 1); } - // method to calculate the max profits - public static List GetMaxProfitJobSequence(List jobs) - { + return total; +} - // sort jobs in descending order - jobs.Sort((a, b) => b.Profit.CompareTo(a.Profit)); - - // find the max deadline of the time slots - int maxDeadline = jobs.Max(job => job.Deadline); - - // create voolean array to mark time taken of time slots - var timeSlots = new bool[maxDeadline]; - - // store the selected job sequence - var jobSequence = new List(); - - foreach (var job in jobs) - { - for (int i = job.Deadline - 1; i >= 0; i--) - { - // time slot is availble the scedule the job - if (!timeSlots[i]) - { - timeSlots[i] = true; - jobSequence.Add(job); - break; - } - } - } - - // return the selected jobs - return jobSequence; +static int Find(Span parent, int i) +{ + while (i != parent[i]) + { + parent[i] = parent[parent[i]]; + i = parent[i]; } + return i; +} + +static int Usage() +{ + Console.Error.WriteLine("Usage: please provide a list of profits and a list of deadlines"); + return 1; } + +readonly record struct Job(int Profit, int Deadline); diff --git a/archive/c/c-sharp/JosephusProblem.cs b/archive/c/c-sharp/JosephusProblem.cs index f99e08e68..12de35f2e 100644 --- a/archive/c/c-sharp/JosephusProblem.cs +++ b/archive/c/c-sharp/JosephusProblem.cs @@ -1,40 +1,19 @@ -using System; - -namespace JosephusProblem +if ( + args is not [var nText, var kText] + || !int.TryParse(nText, out int n) + || !int.TryParse(kText, out int k) + || n <= 0 + || k <= 0 +) { - class Program - { - const string Usage = "Usage: please input the total number of people and number of people to skip."; - - static void Main(string[] args) - { - if (args.Length < 2) - { - Console.WriteLine(Usage); - return; - } - - if (!int.TryParse(args[0], out int n) || !int.TryParse(args[1], out int k) || n <= 0 || k <= 0) - { - Console.WriteLine(Usage); - return; - } - - int survivor = FindJosephusPosition(n, k); - - Console.WriteLine(survivor); - } - - static int FindJosephusPosition(int n, int k) - { - int result = 0; + Console.Error.WriteLine( + "Usage: please input the total number of people and number of people to skip." + ); + return; +} - for (int m = 2; m <= n; m++) - { - result = (result + k) % m; - } +int survivor = 0; +for (int i = 2; i <= n; i++) + survivor = (survivor + k) % i; - return result + 1; - } - } -} +Console.WriteLine(survivor + 1); diff --git a/archive/c/c-sharp/LinearSearch.cs b/archive/c/c-sharp/LinearSearch.cs index 0fbed3acb..4b317deaf 100644 --- a/archive/c/c-sharp/LinearSearch.cs +++ b/archive/c/c-sharp/LinearSearch.cs @@ -1,38 +1,37 @@ -using System; -using System.Linq; -using System.Collections.Generic; +if ( + args is not [var input, var targetRaw] + || !int.TryParse(targetRaw, out int target) + || !TryParseList(input.AsSpan(), out var numbers) +) + return Usage(); -public class LinearSearch +Console.WriteLine(numbers.Contains(target)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - public static bool Search(List list, int toFind) - { - foreach (int value in list) - { - if (value == toFind) - { - return true; - } - } - return false; - } + numbers = new(span.Count(',') + 1); - public static void ErrorAndExit() + while (!span.IsEmpty) { - Console.WriteLine("Usage: please provide a list of integers (\"1, 4, 5, 11, 12\") and the integer to find (\"11\")"); - Environment.Exit(1); - } + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - public static void Main(string[] args) - { - try - { - var list = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - var toFind = Int32.Parse(args[1]); - Console.WriteLine(Search(list, toFind)); - } - catch - { - ErrorAndExit(); - } + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); } + + return numbers.Count > 0; +} + +static int Usage() +{ + Console.WriteLine( + """Usage: please provide a list of integers ("1, 4, 5, 11, 12") and the integer to find ("11")""" + ); + return 1; } diff --git a/archive/c/c-sharp/LongestCommonSubsequence.cs b/archive/c/c-sharp/LongestCommonSubsequence.cs index e40bf305e..1bc99de9c 100644 --- a/archive/c/c-sharp/LongestCommonSubsequence.cs +++ b/archive/c/c-sharp/LongestCommonSubsequence.cs @@ -1,39 +1,76 @@ -using System; using System.Collections.Generic; -using System.Linq; -namespace SamplePrograms +if ( + args is not [var raw1, var raw2] + || !TryParseList(raw1.AsSpan(), out var a) + || !TryParseList(raw2.AsSpan(), out var b) +) { - public class LongestCommonSubsequence + Console.WriteLine( + """ +Usage: please provide two lists in the format "1, 2, 3, 4, 5" +""" + ); + return; +} + +Console.WriteLine(string.Join(", ", LCS(a, b))); + +static bool TryParseList(ReadOnlySpan span, out List numbers) +{ + numbers = new(span.Count(',') + 1); + + while (!span.IsEmpty) { - private static IEnumerable LCS(IEnumerable list1, IEnumerable list2) - { - if (list1.Count() == 0 || list2.Count() == 0) - return new List(); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - if (list1.First().Equals(list2.First())) - return LCS(list1.Skip(1), list2.Skip(1)).Concat(new List() { list1.First() }); + span = comma >= 0 ? span[(comma + 1)..] : []; - return Longest(LCS(list1, list2.Skip(1)), LCS(list1.Skip(1), list2)); - } + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); + } + + return true; +} + +static List LCS(List a, List b) +{ + int n = a.Count, m = b.Count; + if (n == 0 || m == 0) return []; + + int[,] dp = new int[n + 1, m + 1]; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + dp[i, j] = a[i - 1] == b[j - 1] + ? dp[i - 1, j - 1] + 1 + : Math.Max(dp[i - 1, j], dp[i, j - 1]); - private static IEnumerable Longest(params IEnumerable[] lists) => - lists.OrderByDescending(l => l.Count()).First(); + var result = new List(dp[n, m]); - public static void Main(string[] args) + int i2 = n, j2 = m; + + while (i2 > 0 && j2 > 0) + { + if (a[i2 - 1] == b[j2 - 1]) { - try - { - var list1 = args[0].Split(',').Select(i => i.Trim()); - var list2 = args[1].Split(',').Select(i => i.Trim()); - var lcs = LCS(list1, list2).Reverse(); - Console.WriteLine(string.Join(", ", lcs)); - } - catch - { - Console.WriteLine("Usage: please provide two lists in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); - } + result.Add(a[i2 - 1]); + i2--; + j2--; + } + else if (dp[i2 - 1, j2] >= dp[i2, j2 - 1]) + { + i2--; + } + else + { + j2--; } } -} \ No newline at end of file + + result.Reverse(); + return result; +} diff --git a/archive/c/c-sharp/LongestPalindromicSubstring.cs b/archive/c/c-sharp/LongestPalindromicSubstring.cs index e1e077298..b097fe241 100644 --- a/archive/c/c-sharp/LongestPalindromicSubstring.cs +++ b/archive/c/c-sharp/LongestPalindromicSubstring.cs @@ -1,71 +1,74 @@ -using System; -using System.Text.RegularExpressions; +if (args is not { Length: > 0 }) + return Usage(); -namespace SamplePrograms +string result = LongestPalindrome(string.Join(' ', args)); + +if (result.Length < 2) + return Usage(); + +Console.WriteLine(result); +return 0; + +static string LongestPalindrome(string input) { - public class LongestPalindromicSubstring + int length = input.Length; + if (length < 2) + return ""; + + char[] transformed = new char[2 * length + 3]; + int[] radius = new int[transformed.Length]; + + int index = 0; + transformed[index++] = '^'; + + ReadOnlySpan source = input; + + foreach (char c in source) + { + transformed[index++] = '#'; + transformed[index++] = c; + } + + transformed[index++] = '#'; + transformed[index++] = '$'; + + int center = 0; + int rightBoundary = 0; + + int bestCenter = 0; + int bestRadius = 0; + + for (int i = 1; i < index - 1; i++) { - public static void Main(string[] args) - { - string input = string.Join(" ", args); - Console.WriteLine(LongestPalindrome(input)); - } - - public static string LongestPalindrome(string input) - { - if (string.IsNullOrEmpty(input) || !ContainsPalindrome(input)) - { - return "Usage: please provide a string that contains at least one palindrome"; - } - - int start = 0; - int end = 0; - - for (int i = 0; i < input.Length; i++) - { - int lengthOne = ExpandAroundCenter(input, i, i); - int lengthTwo = ExpandAroundCenter(input, i, i + 1); - int length = Math.Max(lengthOne, lengthTwo); - - if (length > end - start) - { - start = i - (length - 1) / 2; - end = i + length / 2; - } - } - return input.Substring(start, end - start + 1); - } - - private static int ExpandAroundCenter(string input, int left, int right) - { - while (left >= 0 && right < input.Length && input[left] == input[right]) - { - left--; - right++; - } - return right - left - 1; - } - - private static bool ContainsPalindrome(string input) - { - string[] words = input.Split(' '); - foreach (string word in words) - { - if (word.Length > 1 && word == Reverse(word)) - { - return true; - } - } - - string cleanedInput = input.Replace(" ", ""); - return cleanedInput.Length > 1 && cleanedInput == Reverse(cleanedInput); - } - - private static string Reverse(string input) - { - char[] charArray = input.ToCharArray(); - Array.Reverse(charArray); - return new string(charArray); - } + int mirror = 2 * center - i; + int R = radius[i]; + + if (i < rightBoundary) + R = Math.Min(rightBoundary - i, radius[mirror]); + + while (transformed[i + R + 1] == transformed[i - R - 1]) + R++; + + radius[i] = R; + int expandedRight = i + R; + + center = expandedRight > rightBoundary ? i : center; + rightBoundary = Math.Max(expandedRight, rightBoundary); + + bool isBest = R > bestRadius; + bestRadius = isBest ? R : bestRadius; + bestCenter = isBest ? i : bestCenter; } -} \ No newline at end of file + + if (bestRadius < 2) + return ""; + + int startIndex = (bestCenter - bestRadius) / 2; + return input.AsSpan(startIndex, bestRadius).ToString(); +} + +static int Usage() +{ + Console.Error.WriteLine("Usage: please provide a string that contains at least one palindrome"); + return 1; +} diff --git a/archive/c/c-sharp/LongestWord.cs b/archive/c/c-sharp/LongestWord.cs index 90fe895c8..bce049a5e 100644 --- a/archive/c/c-sharp/LongestWord.cs +++ b/archive/c/c-sharp/LongestWord.cs @@ -1,27 +1,26 @@ -using System; -using System.Linq; +if (args is not [var sentence] || string.IsNullOrWhiteSpace(sentence)) + return Usage(); -public class LongestWord +int max = 0, + cur = 0; + +foreach (char c in sentence) { - public static void Main(string[] args) + if (char.IsWhiteSpace(c)) { - // check for empty string or empty input - if (args.Length == 0 || args[0] == "") { - Console.WriteLine("Usage: please provide a string"); - } else { - // stores string from args - string sentence = args[0]; - - // split string by whitespace (these four special characters), removes empty entries - string[] words = sentence.Split(new[] {' ', '\t', '\n', '\r'}, StringSplitOptions.RemoveEmptyEntries); - - // sort array by length in descending order so longest string is first and returns is to array - words = words.OrderByDescending(word => word.Length).ToArray(); - - // log the length of longest word - Console.WriteLine(words[0].Length); - } + cur = 0; + continue; } + cur++; + max = Math.Max(cur, max); +} + +Console.WriteLine(max); +return 0; -} \ No newline at end of file +static int Usage() +{ + Console.Error.WriteLine("Usage: please provide a string"); + return 1; +} diff --git a/archive/c/c-sharp/MaximumArrayRotation.cs b/archive/c/c-sharp/MaximumArrayRotation.cs index 4eecb255b..eb2d01658 100644 --- a/archive/c/c-sharp/MaximumArrayRotation.cs +++ b/archive/c/c-sharp/MaximumArrayRotation.cs @@ -1,72 +1,58 @@ -using System; -using System.Collections.Generic; -using System.Linq; +if (args is not [var input] || !TryParseList(input.AsSpan(), out var numbers)) + return ExitWithUsage(); -public static class Program +Console.WriteLine(MaximumRotationSum(numbers)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - private static void ShowUsage() - { - Console.Error.WriteLine("Usage: please provide a list of integers (e.g. \"8, 3, 1, 2\")"); - Environment.Exit(1); - } + numbers = new(span.Count(',') + 1); - private static List ParseIntegerList(string input) + while (!span.IsEmpty) { - if (string.IsNullOrWhiteSpace(input)) - ShowUsage(); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - var list = input - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Select(s => - { - if (!int.TryParse(s, out var val) || val < 0) - ShowUsage(); - return val; - }) - .ToList(); + span = comma >= 0 ? span[(comma + 1)..] : []; - if (list.Count == 0) - ShowUsage(); + if (!int.TryParse(token, out int n)) + return false; - return list; + numbers.Add(n); } - private static int MaximumRotationSum(IList numbers) - { - int n = numbers.Count; - if (n == 0) - ShowUsage(); - - int totalSum = 0; - int currentWeightedSum = 0; - - for (int i = 0; i < n; i++) - { - totalSum += numbers[i]; - currentWeightedSum += numbers[i] * i; - } + return numbers.Count > 0; +} - int maxWeightedSum = currentWeightedSum; +static int MaximumRotationSum(List numbers) +{ + int n = numbers.Count; - for (int i = 1; i < n; i++) - { - currentWeightedSum = currentWeightedSum + totalSum - n * numbers[n - i]; - if (currentWeightedSum > maxWeightedSum) - maxWeightedSum = currentWeightedSum; - } + int totalSum = numbers[0]; + int rotationSum = 0; - return maxWeightedSum; + for (int i = 1; i < n; i++) + { + int v = numbers[i]; + totalSum += v; + rotationSum += v * i; } - public static int Main(string[] args) - { - if (args.Length != 1) - ShowUsage(); + int best = rotationSum; - var inputList = ParseIntegerList(args[0]); + for (int i = 1, last = n - 1; i < n; i++, last--) + { + rotationSum += totalSum - n * numbers[last]; + best = Math.Max(best, rotationSum); + } - Console.WriteLine(MaximumRotationSum(inputList)); + return best; +} - return 0; - } +static int ExitWithUsage() +{ + Console.WriteLine( + "Usage: please provide a list of integers (e.g. \"8, 3, 1, 2\")" + ); + return 1; } diff --git a/archive/c/c-sharp/MaximumSubarray.cs b/archive/c/c-sharp/MaximumSubarray.cs index 876e78395..a6afa6bfe 100644 --- a/archive/c/c-sharp/MaximumSubarray.cs +++ b/archive/c/c-sharp/MaximumSubarray.cs @@ -1,63 +1,52 @@ -using System; -using System.Collections.Generic; -using System.Linq; +if ( + args is not [var input] + || string.IsNullOrWhiteSpace(input) + || !TryParseList(input.AsSpan(), out var numbers) +) + return ExitWithUsage(); -public static class Program +Console.WriteLine(MaximumSubarraySum(numbers)); +return 0; + +static int MaximumSubarraySum(List numbers) { - private static void ShowUsage() - { - Console.Error.WriteLine("Usage: Please provide a list of integers in the format: \"1, 2, 3, 4, 5\""); - Environment.Exit(1); - } + int current = numbers[0]; + int best = numbers[0]; - private static List ParseIntegerList(string input) + for (int i = 1; i < numbers.Count; i++) { - if (string.IsNullOrWhiteSpace(input)) - ShowUsage(); - - var list = input - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Select(s => - { - if (!int.TryParse(s, out var val)) - ShowUsage(); - return val; - }) - .ToList(); - - if (list.Count == 0) - ShowUsage(); - - return list; + int v = numbers[i]; + current = Math.Max(v, current + v); + best = Math.Max(current, best); } - private static int MaximumSubarraySum(IReadOnlyList numbers) - { - if (numbers.Count == 0) - return 0; - - int currentSum = numbers[0]; - int maxSum = numbers[0]; - - for (int i = 1; i < numbers.Count; i++) - { - int number = numbers[i]; - currentSum = Math.Max(number, currentSum + number); - maxSum = Math.Max(maxSum, currentSum); - } + return best; +} - return maxSum; - } +static bool TryParseList(ReadOnlySpan span, out List numbers) +{ + numbers = new(span.Count(',') + 1); - public static int Main(string[] args) + while (!span.IsEmpty) { - if (args.Length != 1) - ShowUsage(); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; - var inputList = ParseIntegerList(args[0]); + span = comma >= 0 ? span[(comma + 1)..] : []; - Console.WriteLine(MaximumSubarraySum(inputList)); + if (!int.TryParse(token, out int n)) + return false; - return 0; + numbers.Add(n); } + + return true; +} + +static int ExitWithUsage() +{ + Console.Error.WriteLine( + "Usage: Please provide a list of integers in the format: \"1, 2, 3, 4, 5\"" + ); + return 1; } diff --git a/archive/c/c-sharp/MergeSort.cs b/archive/c/c-sharp/MergeSort.cs index c5230b306..41f915147 100644 --- a/archive/c/c-sharp/MergeSort.cs +++ b/archive/c/c-sharp/MergeSort.cs @@ -1,62 +1,96 @@ -using System; -using System.Linq; using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Buffers; -public class MergeSort +if (args is not [var input] || !TryParseList(input.AsSpan(), out var numbers)) + return ExitWithUsage(); + +Span span = CollectionsMarshal.AsSpan(numbers); +MergeSort(span); + +Console.WriteLine(string.Join(", ", numbers)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - public static List Sort(List xs) => Sort(xs.Select(x => new List() {x}).ToList()).First(); - public static List> Sort(List> xs) + numbers = new(span.Count(',') + 1); + + while (!span.IsEmpty) { - if (xs.Count <= 1) - return xs; - var x0 = xs[0]; - var x1 = xs[1]; - xs.RemoveAt(0); - xs.RemoveAt(0); - return Sort(new List>() - { - Merge(x0, x1) - }.Concat(Sort(xs).ToList()).ToList()); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); } - public static List Merge(List xs, List ys) + return numbers.Count > 1; +} + +// Bottom-up merge sort +static void MergeSort(Span span) +{ + int n = span.Length; + if (n <= 1) + return; + + int[] buffer = new int[n]; + + Span src = span; + Span dst = buffer; + + for (int width = 1; width < n; width *= 2) { - if (!xs.Any()) - return ys; - if (!ys.Any()) - return xs; - if (xs[0] < ys[0]) + for (int left = 0; left < n; left += width * 2) { - var x0 = xs[0]; - xs.RemoveAt(0); - return new List() {x0}.Concat(Merge(xs, ys)).ToList(); + int mid = Math.Min(left + width, n); + int right = Math.Min(left + width * 2, n); + + Merge( + src[left..mid], + src[mid..right], + dst[left..right] + ); } - var y0 = ys[0]; - ys.RemoveAt(0); - return new List() {y0}.Concat(Merge(xs, ys)).ToList(); - } - public static void ErrorAndExit() - { - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); + Span temp = src; + src = dst; + dst = temp; } - public static void Main(string[] args) + // if final data ended up in buffer, copy back + if (!src.Overlaps(span)) + src.CopyTo(span); +} + +static void Merge( + ReadOnlySpan left, + ReadOnlySpan right, + Span target) +{ + int li = 0; + int ri = 0; + int ti = 0; + + while (li < left.Length && ri < right.Length) { - if (args.Length != 1) - ErrorAndExit(); - try - { - var xs = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - if (xs.Count() <= 1) - ErrorAndExit(); - var sortedXs = Sort(xs); - Console.WriteLine(string.Join(", ", sortedXs)); - } - catch - { - ErrorAndExit(); - } + target[ti++] = left[li] <= right[ri] + ? left[li++] + : right[ri++]; } + + left[li..].CopyTo(target[ti..]); + right[ri..].CopyTo(target[ti..]); +} + +static int ExitWithUsage() +{ + Console.WriteLine( + "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\"" + ); + return 1; } diff --git a/archive/c/c-sharp/MinimumSpanningTree.cs b/archive/c/c-sharp/MinimumSpanningTree.cs index b35c5f22c..45314789d 100644 --- a/archive/c/c-sharp/MinimumSpanningTree.cs +++ b/archive/c/c-sharp/MinimumSpanningTree.cs @@ -1,108 +1,95 @@ -using System; -using System.Collections.Generic; -using System.Linq; +if (args is not [var input] || !TryParseMatrix(input.AsSpan(), out var matrix, out int n)) + return ExitWithUsage(); -public static class Program -{ - private static void ShowUsage() - { - Console.Error.WriteLine("Usage: please provide a comma-separated list of integers"); - Environment.Exit(1); - } - - private static List ParseIntegerList(string input) - { - if (string.IsNullOrWhiteSpace(input)) - ShowUsage(); - - var tokens = input - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); +int weight = MinimumSpanningTreeWeight(matrix, n); +if (weight < 0) + return ExitWithUsage(); - if (tokens.Length < 4) // Minimum size for a 2x2 matrix - ShowUsage(); +Console.WriteLine(weight); +return 0; - var numbers = new List(); - foreach (var token in tokens) - { - if (!int.TryParse(token, out int value)) - ShowUsage(); +static int MinimumSpanningTreeWeight(List matrix, int n) +{ + var inMst = new bool[n]; + var minEdge = new int[n]; - numbers.Add(value); - } + Array.Fill(minEdge, int.MaxValue); - int dim = (int)Math.Sqrt(numbers.Count); - if (dim * dim != numbers.Count) - ShowUsage(); + minEdge[0] = 0; - return numbers; - } + int total = 0; - private static int MinimumSpanningTreeWeight(List adjacencyMatrix, int dimension) + for (int added = 0; added < n; added++) { - var includedInMST = new bool[dimension]; - var minEdgeWeight = new int[dimension]; + int bestWeight = int.MaxValue; + int u = -1; - for (int i = 0; i < dimension; i++) + for (int i = 0; i < n; i++) { - minEdgeWeight[i] = int.MaxValue; - includedInMST[i] = false; + if (!inMst[i] && minEdge[i] < bestWeight) + { + bestWeight = minEdge[i]; + u = i; + } } - minEdgeWeight[0] = 0; - int totalWeight = 0; + if (u < 0) + return -1; - for (int count = 0; count < dimension; count++) + inMst[u] = true; + total += bestWeight; + + int row = u * n; + + for (int v = 0; v < n; v++) { - int currentMinWeight = int.MaxValue; - int currentNode = -1; + int w = matrix[row + v]; - for (int i = 0; i < dimension; i++) - { - if (!includedInMST[i] && minEdgeWeight[i] < currentMinWeight) - { - currentMinWeight = minEdgeWeight[i]; - currentNode = i; - } - } + if (w != 0 && !inMst[v] && w < minEdge[v]) + minEdge[v] = w; + } + } - if (currentNode == -1) - { - ShowUsage(); - } + return total; +} - includedInMST[currentNode] = true; - totalWeight += currentMinWeight; +static bool TryParseMatrix(ReadOnlySpan view, out List numbers, out int dimension) +{ + numbers = null!; + dimension = 0; - for (int adjacent = 0; adjacent < dimension; adjacent++) - { - int edgeWeight = adjacencyMatrix[currentNode * dimension + adjacent]; - if (!includedInMST[adjacent] && edgeWeight != 0 && edgeWeight < minEdgeWeight[adjacent]) - { - minEdgeWeight[adjacent] = edgeWeight; - } - } - } + if (view.IsWhiteSpace()) + return false; - return totalWeight; - } + int expected = view.Count(',') + 1; + if (expected < 4) return false; - public static int Main(string[] args) + var list = new List(expected); + + while (!view.IsEmpty) { - if (args.Length != 1) - ShowUsage(); + int i = view.IndexOf(','); + var token = i >= 0 ? view[..i] : view; - var inputList = ParseIntegerList(args[0]); + view = i >= 0 ? view[(i + 1)..] : []; - var numbers = ParseIntegerList(args[0]); - int dimension = (int)Math.Sqrt(numbers.Count); + if (!int.TryParse(token, out int v)) + return false; - int mstWeight = MinimumSpanningTreeWeight(numbers, dimension); + list.Add(v); + } - if (mstWeight == -1) - ShowUsage(); + int d = (int)Math.Sqrt(list.Count); + if (d * d != list.Count) + return false; - Console.WriteLine(mstWeight); + numbers = list; + dimension = d; + return true; +} - return 0; - } +static int ExitWithUsage() +{ + Console.Error.WriteLine("""Usage: please provide a comma-separated list of integers"""); + return 1; } diff --git a/archive/c/c-sharp/PalindromicNumber.cs b/archive/c/c-sharp/PalindromicNumber.cs index f67b5833d..389f481d3 100644 --- a/archive/c/c-sharp/PalindromicNumber.cs +++ b/archive/c/c-sharp/PalindromicNumber.cs @@ -1,51 +1,31 @@ -using System; -public class PalindromicNumber -{ - public static void Main(string[] args) - { +if (args is not [var raw] || !ulong.TryParse(raw.AsSpan(), out ulong number)) + return ExitWithUsage(); - try - { - long verifyInput = long.Parse(args[0]); +Console.WriteLine(IsPalindrome(number) ? "true" : "false"); +return 0; - if (verifyInput >= 0) - { - Console.WriteLine(palindrome(args[0])); - } - else - { - Console.WriteLine("Usage: please input a non-negative integer"); - } +static bool IsPalindrome(ulong value) +{ + if (value < 10) + return true; - } - catch - { - Console.WriteLine("Usage: please input a non-negative integer"); - } + if (value % 10 == 0) + return false; - } + ulong reversedHalf = 0; - public static string palindrome(string numString) + while (value > reversedHalf) { - char[] digits = numString.ToCharArray(); - - int backCount = digits.Length - 1; - - for (int i = 0; i < digits.Length; i++) - { - if (digits[i] != digits[backCount]) - { - return "false"; - } - else - { - backCount--; - } - - } - - return "true"; - + reversedHalf = reversedHalf * 10 + value % 10; + value /= 10; } + return value == reversedHalf || + value == reversedHalf / 10; +} + +static int ExitWithUsage() +{ + Console.WriteLine("Usage: please input a non-negative integer"); + return 1; } \ No newline at end of file diff --git a/archive/c/c-sharp/PrimeNumber.cs b/archive/c/c-sharp/PrimeNumber.cs index c10aa6666..bf57a166b 100644 --- a/archive/c/c-sharp/PrimeNumber.cs +++ b/archive/c/c-sharp/PrimeNumber.cs @@ -1,44 +1,31 @@ -using System; -using Math = System.Math; +if (args is not [var raw] || !ulong.TryParse(raw, out ulong number)) + return ExitWithUsage(); -namespace SamplePrograms +Console.WriteLine(IsPrime(number) ? "Prime" : "Composite"); +return 0; + +static bool IsPrime(ulong value) { - public class PrimeNumber - { - public static bool IsPrime(ulong x) - { - if (x <= 1) - return false; - if (x != 2 && x % 2 == 0) - return false; + if (value < 2) + return false; - for (ulong i = 3; i <= Convert.ToUInt64(Math.Sqrt(x)); i += 2) - { - if (x % i == 0) - return false; - } + if (value == 2) + return true; - return true; - } + if (value % 2 == 0) + return false; - public static void Main(string[] args) - { - try - { - var n = ulong.Parse(args[0]); - if (n > 18446744073709551615) // Max of a ulong in C# - { - Console.WriteLine(string.Format("{0} is out of the reasonable bounds for calculation.", n)); - Environment.Exit(1); - } - var result = IsPrime(n) ? "Prime" : "Composite"; - Console.WriteLine(result); - } - catch - { - Console.WriteLine("Usage: please input a non-negative integer"); - Environment.Exit(1); - } - } + for (ulong divisor = 3; divisor * divisor <= value; divisor += 2) + { + if (value % divisor == 0) + return false; } + + return true; +} + +static int ExitWithUsage() +{ + Console.WriteLine("Usage: please input a non-negative integer"); + return 1; } diff --git a/archive/c/c-sharp/QuickSort.cs b/archive/c/c-sharp/QuickSort.cs index 4c226494d..435fd2dff 100644 --- a/archive/c/c-sharp/QuickSort.cs +++ b/archive/c/c-sharp/QuickSort.cs @@ -1,43 +1,89 @@ -using System; -using System.Linq; using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Buffers; -public class QuickSort +if (args is not [var input] || !TryParseList(input.AsSpan(), out var numbers)) + return ExitWithUsage(); + +Span span = CollectionsMarshal.AsSpan(numbers); +QuickSort(span); + +Console.WriteLine(string.Join(", ", numbers)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - public static List Sort(List xs) - { - if (!xs.Any()) - return xs; - - var index = xs.Count() / 2; - var x = xs[index]; - xs.RemoveAt(index); - var left = Sort(xs.Where(v => v <= x).ToList()); - var right = Sort(xs.Where(v => v > x).ToList()); - return left.Append(x).Concat(right).ToList(); - } + numbers = new(span.Count(',') + 1); - public static void ErrorAndExit() + while (!span.IsEmpty) { - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); } - public static void Main(string[] args) + return numbers.Count > 1; +} + +static void QuickSort(Span span) +{ + if (span.Length <= 1) + return; + + int lo = 0; + int hi = span.Length - 1; + + Sort(span, lo, hi); + + static void Sort(Span s, int lo, int hi) { - if (args.Length != 1) - ErrorAndExit(); - try + while (lo < hi) { - var xs = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - if (xs.Count() <= 1) - ErrorAndExit(); - var sortedXs = Sort(xs); - Console.WriteLine(string.Join(", ", sortedXs)); + int p = Partition(s, lo, hi); + + // Tail recursion elimination: sort smaller side first + if (p - lo < hi - p) + { + Sort(s, lo, p - 1); + lo = p + 1; + } + else + { + Sort(s, p + 1, hi); + hi = p - 1; + } } - catch + } + + static int Partition(Span s, int lo, int hi) + { + int pivot = s[hi]; + int i = lo; + + for (int j = lo; j < hi; j++) { - ErrorAndExit(); + if (s[j] <= pivot) + { + (s[i], s[j]) = (s[j], s[i]); + i++; + } } + + (s[i], s[hi]) = (s[hi], s[i]); + return i; } } + +static int ExitWithUsage() +{ + Console.WriteLine( + "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\"" + ); + return 1; +} diff --git a/archive/c/c-sharp/RemoveAllWhitespace.cs b/archive/c/c-sharp/RemoveAllWhitespace.cs index 2a000cc9e..a926d02d5 100644 --- a/archive/c/c-sharp/RemoveAllWhitespace.cs +++ b/archive/c/c-sharp/RemoveAllWhitespace.cs @@ -1,31 +1,25 @@ -using System; -using System.Linq; +if (args is not [var input] || string.IsNullOrEmpty(input)) + return ExitWithError(); -class CSharp -{ - - public static void ExitWithError() - { - Console.WriteLine("Usage: please provide a string"); - Environment.Exit(1); - } +RemoveWhitespace(input.AsSpan()); +return 0; - public static void RemoveAllWhitespace(string str) { - Console.WriteLine( - new string( - str - .Where(c => !Char.IsWhiteSpace(c)) - .ToArray() - ) - ); - } +static void RemoveWhitespace(ReadOnlySpan input) +{ + char[] buffer = new char[input.Length]; + int j = 0; - static void Main (string[] args) + foreach (char c in input) { - if (!args.Any() || args[0] == "") { - ExitWithError(); - } - RemoveAllWhitespace(args[0]); + if (!char.IsWhiteSpace(c)) + buffer[j++] = c; } + Console.WriteLine(new string(buffer, 0, j)); } + +static int ExitWithError() +{ + Console.WriteLine("Usage: please provide a string"); + return 1; +} \ No newline at end of file diff --git a/archive/c/c-sharp/ReverseString.cs b/archive/c/c-sharp/ReverseString.cs index f3849fe14..3fdbbb3c0 100644 --- a/archive/c/c-sharp/ReverseString.cs +++ b/archive/c/c-sharp/ReverseString.cs @@ -1,22 +1,13 @@ -using System; +if (args is [var input] && !string.IsNullOrEmpty(input)) + Console.WriteLine(Reverse(input.AsSpan())); -namespace SamplePrograms +static string Reverse(ReadOnlySpan s) { - public class ReverseString - { - public static string Reverse(string input) - { - var charArray = input.ToCharArray(); - Array.Reverse(charArray); - return new string(charArray); - } + int n = s.Length; + char[] result = new char[n]; - public static void Main(string[] args) - { - if (args.Length > 0) - { - System.Console.WriteLine(Reverse(args[0])); - } - } - } -} + for (int i = 0; i < n; i++) + result[i] = s[n - 1 - i]; + + return new string(result); +} \ No newline at end of file diff --git a/archive/c/c-sharp/RomanNumeral.cs b/archive/c/c-sharp/RomanNumeral.cs index aebe5ab69..4bc47931e 100644 --- a/archive/c/c-sharp/RomanNumeral.cs +++ b/archive/c/c-sharp/RomanNumeral.cs @@ -1,53 +1,55 @@ -using System; -using System.Collections.Generic; +if (args is not [var input]) + return ExitWith("Usage: please provide a string of roman numerals"); -namespace SamplePrograms +if (!TryRomanToInt(input.AsSpan().Trim(), out int value)) + return ExitWith("Error: invalid string of roman numerals"); + +Console.WriteLine(value); +return 0; + +static bool TryRomanToInt(ReadOnlySpan roman, out int result) { - public class RomanNumeral + result = 0; + if (roman.Length == 0) + return true; + + int prev = 0; + + for (int i = roman.Length - 1; i >= 0; i--) { - private static readonly Dictionary RomanDecMapping = new Dictionary() - { - ['M'] = 1000, - ['D'] = 500, - ['C'] = 100, - ['L'] = 50, - ['X'] = 10, - ['V'] = 5, - ['I'] = 1, - }; - - private static int RomanToDecimal(string roman, int total=0) - { - if (roman.Length < 1) - return total; - var romanArray = roman.ToCharArray(); - if (romanArray.Length == 1) - return total + RomanDecMapping[romanArray[0]]; - - var romanVal = RomanDecMapping[romanArray[0]]; - var nextRomanVal = RomanDecMapping[romanArray[1]]; - if (romanVal < nextRomanVal) - return RomanToDecimal(roman.Substring(1), total - romanVal); - - return RomanToDecimal(roman.Substring(1), total + romanVal); - } - - public static void Main(string[] args) - { - if (args.Length < 1) - { - Console.WriteLine("Usage: please provide a string of roman numerals"); - Environment.Exit(1); - } - try - { - Console.WriteLine(RomanToDecimal(args[0].ToUpper())); - } - catch (KeyNotFoundException) - { - Console.WriteLine("Error: invalid string of roman numerals"); - Environment.Exit(1); - } - } + if (!TryGetValue(roman[i], out int current)) + return false; + + if (current < prev) + result -= current; + else + result += current; + + prev = current; } + + return true; } + +static bool TryGetValue(char c, out int value) +{ + value = char.ToUpper(c) switch + { + 'I' => 1, + 'V' => 5, + 'X' => 10, + 'L' => 50, + 'C' => 100, + 'D' => 500, + 'M' => 1000, + _ => 0 + }; + + return value != 0; +} + +static int ExitWith(string message) +{ + Console.WriteLine(message); + return 1; +} \ No newline at end of file diff --git a/archive/c/c-sharp/Rot13.cs b/archive/c/c-sharp/Rot13.cs index 19ff9784d..229627cb4 100644 --- a/archive/c/c-sharp/Rot13.cs +++ b/archive/c/c-sharp/Rot13.cs @@ -1,52 +1,29 @@ -using System; -using System.Collections.Generic; -using System.Linq; +if (args is not [var input] || string.IsNullOrEmpty(input)) + return ExitWithUsage(); -namespace SamplePrograms -{ - public class Rot13 - { - static List Lowers = "abcdefghijklmnopqrstuvwxyz".ToCharArray().ToList(); - static List Uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().ToList(); +Console.WriteLine(Rot13(input.AsSpan())); +return 0; - public static string Encrypt(string str) => - string.Join("", str.ToCharArray().Select(c => Encrypt(c))); +static string Rot13(ReadOnlySpan input) +{ + char[] result = new char[input.Length]; - public static Char Encrypt(char c) + for (int i = 0; i < input.Length; i++) + { + char c = input[i]; + result[i] = c switch { - List ltrs; - if (char.IsUpper(c)) - ltrs = Uppers; - else if (char.IsLower(c)) - ltrs = Lowers; - else - return c; - - var newIndex = (ltrs.IndexOf(c) + 13) % 26; - return ltrs[newIndex]; - - } + >= 'a' and <= 'z' => (char)('a' + (c - 'a' + 13) % 26), + >= 'A' and <= 'Z' => (char)('A' + (c - 'A' + 13) % 26), + _ => c, + }; + } - public static void ExitWithError() - { - Console.WriteLine("Usage: please provide a string to encrypt"); - Environment.Exit(1); - } + return new string(result); +} - public static void Main(string[] args) - { - try - { - var str = args[0]; - if (String.IsNullOrEmpty(str)) - ExitWithError(); - var result = Encrypt(str); - Console.WriteLine(result); - } - catch - { - ExitWithError(); - } - } - } +static int ExitWithUsage() +{ + Console.WriteLine("Usage: please provide a string to encrypt"); + return 1; } diff --git a/archive/c/c-sharp/SelectionSort.cs b/archive/c/c-sharp/SelectionSort.cs index e89da854a..e4b183629 100644 --- a/archive/c/c-sharp/SelectionSort.cs +++ b/archive/c/c-sharp/SelectionSort.cs @@ -1,40 +1,62 @@ -using System; -using System.Linq; using System.Collections.Generic; +using System.Runtime.InteropServices; -public class SelectionSort +if (args is not [var input] || !TryParseList(input.AsSpan(), out var numbers)) + return ExitWithUsage(); + +SelectionSort(numbers); + +Console.WriteLine(string.Join(", ", numbers)); +return 0; + +static bool TryParseList(ReadOnlySpan span, out List numbers) { - public static IEnumerable Selection(List xs) - { - while (xs.Any()) - { - var x = xs.Min(); - xs.Remove(x); - yield return x; - } - } + numbers = new(span.Count(',') + 1); - public static void ErrorAndExit() + while (!span.IsEmpty) { - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); + int comma = span.IndexOf(','); + var token = comma >= 0 ? span[..comma] : span; + + span = comma >= 0 ? span[(comma + 1)..] : []; + + if (!int.TryParse(token, out int n)) + return false; + + numbers.Add(n); } - public static void Main(string[] args) + return numbers.Count > 1; +} + +static void SelectionSort(List list) +{ + if (list.Count < 2) + return; + + Span span = CollectionsMarshal.AsSpan(list); + + int n = span.Length; + + for (int i = 0; i < n - 1; i++) { - if (args.Length != 1) - ErrorAndExit(); - try - { - var xs = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - if (xs.Count() <= 1) - ErrorAndExit(); - var sortedXs = Selection(xs); - Console.WriteLine(string.Join(", ", sortedXs)); - } - catch + int minIndex = i; + + for (int j = i + 1; j < n; j++) { - ErrorAndExit(); + if (span[j] < span[minIndex]) + minIndex = j; } + + if (minIndex != i) + (span[i], span[minIndex]) = (span[minIndex], span[i]); } -} \ No newline at end of file +} + +static int ExitWithUsage() +{ + Console.WriteLine( + "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\"" + ); + return 1; +} diff --git a/archive/c/c-sharp/TransposeMatrix.cs b/archive/c/c-sharp/TransposeMatrix.cs index 771caa416..7b993be46 100644 --- a/archive/c/c-sharp/TransposeMatrix.cs +++ b/archive/c/c-sharp/TransposeMatrix.cs @@ -1,68 +1,66 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Runtime.InteropServices; -public static class Program +if (args is not [var colsRaw, var rowsRaw, var matrixRaw] + || !int.TryParse(colsRaw, out int cols) + || !int.TryParse(rowsRaw, out int rows) + || cols <= 0 || rows <= 0 + || !TryParseMatrix(matrixRaw.AsSpan(), cols, rows, out var matrix) +) { - private static void ShowUsage() - { - Console.Error.WriteLine("Usage: please enter the dimension of the matrix and the serialized matrix"); - Environment.Exit(1); - } + return ExitWithUsage(); +} - private static List ParseIntegerList(string input) - { - if (string.IsNullOrWhiteSpace(input)) - ShowUsage(); +Console.WriteLine(string.Join(", ", Transpose(matrix, cols, rows))); +return 0; - var tokens = input - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); +static List Transpose(List m, int cols, int rows) +{ + var o = new List(m.Count); + for (int i = 0; i < m.Count; i++) o.Add(0); - var numbers = new List(); - foreach (var token in tokens) - { - if (!int.TryParse(token, out int value)) - ShowUsage(); + var src = CollectionsMarshal.AsSpan(m); + var dst = CollectionsMarshal.AsSpan(o); - numbers.Add(value); - } + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + dst[c * rows + r] = src[r * cols + c]; - return numbers; - } + return o; +} - static List TransposeMatrix(int cols, int rows, List input) - { - var result = new List(new int[rows * cols]); - - for (int i = 0; i < rows; ++i) - { - for (int j = 0; j < cols; ++j) - { - int index = j * rows + i; - result[index] = input[i * cols + j]; - } - } - - return result; - } +static bool TryParseMatrix(ReadOnlySpan view, int cols, int rows, out List numbers) +{ + numbers = new(cols * rows); + + if (view.IsWhiteSpace()) + return false; + + int expected = cols * rows; + int count = 0; - static int Main(string[] args) + while (!view.IsEmpty) { - if (args.Length != 3) - ShowUsage(); + int i = view.IndexOf(','); + var token = i >= 0 ? view[..i] : view; - if (!int.TryParse(args[0], out var cols)) - ShowUsage(); + view = i >= 0 ? view[(i + 1)..] : []; - if (!int.TryParse(args[1], out var rows)) - ShowUsage(); + if (!int.TryParse(token, out int v)) + return false; - var numbers = ParseIntegerList(args[2]); - if (numbers.Count != cols * rows) - ShowUsage(); + numbers.Add(v); - var transposed = TransposeMatrix(cols, rows, numbers); - Console.WriteLine(string.Join(", ", transposed)); - return 0; + if (++count > expected) + return false; } + + return count == expected; +} + +static int ExitWithUsage() +{ + Console.Error.WriteLine( + """Usage: please enter the dimension of the matrix and the serialized matrix""" + ); + return 1; } diff --git a/archive/c/c-sharp/Zeckendorf.cs b/archive/c/c-sharp/Zeckendorf.cs index 1cc82ac5b..fb9c41900 100644 --- a/archive/c/c-sharp/Zeckendorf.cs +++ b/archive/c/c-sharp/Zeckendorf.cs @@ -1,52 +1,61 @@ +using System; +using System.Collections.Generic; using System.Globalization; -public static class Zeckendorf +if (args is not [var raw] || + !long.TryParse(raw, out long n) || + n < 0) { - private static readonly long[] Fibs = GenerateFibs(); + return ExitWithUsage(); +} - private static long[] GenerateFibs() - { - var fs = new List { 1, 2 }; - while (long.MaxValue - fs[^1] >= fs[^2]) - { - fs.Add(fs[^1] + fs[^2]); - } - return [.. fs]; - } +if (n == 0) + return 0; + +ReadOnlySpan fibs = GenerateFibs(); +Span buffer = stackalloc long[fibs.Length]; + +int count = Decompose(n, fibs, buffer); +Console.WriteLine(string.Join(", ", buffer[..count].ToArray())); + +return 0; + +static int Decompose(long n, ReadOnlySpan fibs, Span result) +{ + int count = 0; - public static void Main(string[] args) + for (int i = fibs.Length - 1; i >= 0 && n > 0; i--) { - if (args.Length == 0 || !long.TryParse(args[0], NumberStyles.None, CultureInfo.InvariantCulture, out var n) || n < 0) + long f = fibs[i]; + + if (f <= n) { - Console.WriteLine("Usage: please input a non-negative integer"); - return; + result[count++] = f; + n -= f; } + } - if (n == 0) return; + return count; +} - Span terms = stackalloc long[Fibs.Length]; - int count = Decompose(n, terms); +static int ExitWithUsage() +{ + Console.WriteLine("Usage: please input a non-negative integer"); + return 1; +} - PrintResults(terms[..count]); - } +static long[] GenerateFibs() +{ + var list = new List { 1, 2 }; - private static int Decompose(long n, Span terms) + while (true) { - int count = 0; - int i = Array.BinarySearch(Fibs, n); - if (i < 0) i = ~i - 1; + long next = list[^1] + list[^2]; + if (next < 0 || next > long.MaxValue - list[^1]) + break; - for (; i >= 0 && n > 0; i--) - { - if (Fibs[i] <= n) - { - terms[count++] = Fibs[i]; - n -= Fibs[i]; - } - } - return count; + list.Add(next); } - private static void PrintResults(ReadOnlySpan terms) => - Console.WriteLine(string.Join(", ", terms.ToArray())); + return list.ToArray(); } \ No newline at end of file diff --git a/archive/c/c-sharp/testinfo.yml b/archive/c/c-sharp/testinfo.yml index 983415da1..56e5b0ca4 100644 --- a/archive/c/c-sharp/testinfo.yml +++ b/archive/c/c-sharp/testinfo.yml @@ -4,9 +4,20 @@ folder: container: image: "mcr.microsoft.com/dotnet/sdk" - tag: "9.0" + tag: "10.0" build: | - bash -c "dotnet new console --language 'C#' && \ - mv {{ source.name }}{{ source.extension }} Program.cs && \ - dotnet build --sc" - cmd: "dotnet run --sc --no-restore" + bash -c " + export DOTNET_CLI_TELEMETRY_OPTOUT=1 + export DOTNET_NOLOGO=true + + dotnet new console --no-restore --force -o . > /dev/null + rm Program.cs + + dotnet build -c Release \ + --no-self-contained \ + -p:UseSharedCompilation=false \ + -p:Deterministic=true \ + -p:Optimize=true \ + -o ./publish + " + cmd: "dotnet ./publish/src.dll" \ No newline at end of file