Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
using System.Text.RegularExpressions;
using CommunityToolkit.HighPerformance;

namespace CountingCharOccurences
{
Expand Down Expand Up @@ -59,10 +58,7 @@ public int CountCharsUsingIndex(string source, char toFind)
int n = 0;

while ((n = source.IndexOf(toFind, n) + 1) != 0)
{
n++;
count++;
}

return count;
}
Expand Down Expand Up @@ -130,7 +126,7 @@ public int CountCharsUsingReplace(string source, char toFind)
[ArgumentsSource(nameof(GenerateStringWithCharArgs))]
public int CountCharsUsingRegex(string source, char toFind)
{
return new Regex(Regex.Escape(toFind.ToString())).Matches(source).Count;
return Regex.Count(source, Regex.Escape(toFind.ToString()));
}

[Benchmark]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace CountingCharOccurences
{
public class CountSubstringsAndFrequencies
{
public int CountSubstringNonOverlapping(string source, string toFind)
{
return source.AsSpan().Count(toFind);
}

public int CountSubstringOverlapping(string source, string toFind)
{
var count = 0;

for (var n = 0; (n = source.IndexOf(toFind, n, StringComparison.Ordinal)) != -1; n++)
count++;

return count;
}

public Dictionary<char, int> CountEveryCharUsingLinq(string source)
{
return source.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count());
}

public Dictionary<char, int> CountEveryCharUsingLoop(string source)
{
var counted = new Dictionary<char, int>();

foreach (var c in source)
counted[c] = counted.GetValueOrDefault(c) + 1;

return counted;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.0.0" />
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
</ItemGroup>

<ItemGroup>
<None Remove="CommunityToolkit.HighPerformance" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
using BenchmarkDotNet.Running;
using CountingCharOccurences;

namespace CountingCharOccurences
{
internal class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<CountChars>();
}
}
}
BenchmarkRunner.Run<CountChars>();
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using CountingCharOccurences;

namespace Test
{
public class CountSubstringsAndFrequenciesTest
{
private static readonly CountSubstringsAndFrequencies _counter = new CountSubstringsAndFrequencies();

[Fact]
public void WhenCountSubstringNonOverlappingThenMatchesDoNotOverlap()
{
string main = "aaaa";
string toFind = "aa";

int actual = _counter.CountSubstringNonOverlapping(main, toFind);

Assert.Equal(2, actual);
}

[Fact]
public void WhenCountSubstringOverlappingThenMatchesOverlap()
{
string main = "aaaa";
string toFind = "aa";

int actual = _counter.CountSubstringOverlapping(main, toFind);

Assert.Equal(3, actual);
}

[Fact]
public void WhenCountEveryCharUsingLinqThenReturnFrequencyOfEachChar()
{
string main = "hello world";

var actual = _counter.CountEveryCharUsingLinq(main);

Assert.Equal(3, actual['l']);
Assert.Equal(2, actual['o']);
}

[Fact]
public void WhenCountEveryCharUsingLoopThenReturnSameFrequenciesAsLinq()
{
string main = "hello world";

var actual = _counter.CountEveryCharUsingLoop(main);

Assert.Equal(_counter.CountEveryCharUsingLinq(main), actual);
}
}
}
11 changes: 11 additions & 0 deletions strings-csharp/CountingCharOccurences/Test/Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ public void WhenSearchCharUsingIndexThenReturnNumberOfOccurences()
Assert.Equal(2, actual);
}

[Fact]
public void WhenSearchCharWithAdjacentOccurencesThenReturnNumberOfOccurences()
{
string main = "LLama LLama";
char toFind = 'L';

int actual = _countChars.CountCharsUsingIndex(main, toFind);

Assert.Equal(4, actual);
}

[Fact]
public void WhenSearchCharUsingForThenReturnNumberOfOccurences()
{
Expand Down
10 changes: 5 additions & 5 deletions strings-csharp/CountingCharOccurences/Test/Test.csproj
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PackageReference Include="coverlet.collector" Version="10.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Loading