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
16 changes: 16 additions & 0 deletions hw2/BOR/BOR.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше 7.0, если нет веских оснований использовать LTS-версию (в реальной жизни LTS может быть лучше, потому что позволит отсрочить миграцию на новый .NET, в домашке — никто и так её мигрировать не будет).

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<Compile Remove="BorTests\**" />
<EmbeddedResource Remove="BorTests\**" />
<None Remove="BorTests\**" />
</ItemGroup>

</Project>
31 changes: 31 additions & 0 deletions hw2/BOR/BOR.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32825.248
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BOR", "BOR.csproj", "{BE1A97A4-739A-4A61-BC4A-1F10DED38B17}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BorTests", "BorTests\BorTests.csproj", "{7AD0402E-2599-43F3-BB95-4B81FBE278C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BE1A97A4-739A-4A61-BC4A-1F10DED38B17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE1A97A4-739A-4A61-BC4A-1F10DED38B17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE1A97A4-739A-4A61-BC4A-1F10DED38B17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE1A97A4-739A-4A61-BC4A-1F10DED38B17}.Release|Any CPU.Build.0 = Release|Any CPU
{7AD0402E-2599-43F3-BB95-4B81FBE278C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AD0402E-2599-43F3-BB95-4B81FBE278C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AD0402E-2599-43F3-BB95-4B81FBE278C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AD0402E-2599-43F3-BB95-4B81FBE278C1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EBD94A4-7C68-4EE5-9F63-D26F90FFEA6E}
EndGlobalSection
EndGlobal
167 changes: 167 additions & 0 deletions hw2/BOR/Bor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
Comment on lines +5 to +6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лишние using-и надо убирать, для чего и в Visual Studio, и в Rider есть рефакторинг, автоматически убирающий их из всего проекта

using System.Xml.Linq;

namespace Bor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Оно по-английски Trie, а не Bor. Никогда не пишите транслитом.
  • Используйте file-scoped namespaces

{
public class Bor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужны комментарии ко всем классам и public-методам (свойствам и т.п.)

{
private class BorNode
{
internal Dictionary<char, BorNode> nexts = new ();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private, объемлющий класс всё равно имеет к этим полям доступ.

internal bool isTerminate { get; set; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Свойства всегда именуются с заглавной. И интересно, почему nexts не свойство, а остальные — свойства

internal int WordsWithSamePrefix { get; set; }
public BorNode()
{
isTerminate = false;
WordsWithSamePrefix = 0;
Comment on lines +20 to +21

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это не надо, .NET гарантирует, что после создания класса все его поля заполнены нулями

}
}
private BorNode root;
Comment on lines +23 to +24

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут бы пустую строку

public int Size { get; private set; }
private bool IsEmptyStringContained;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А поля всегда именуются со строчной (константы иногда с заглавной, но это не тот случай)


public Bor()
{
IsEmptyStringContained = false;
root = new BorNode();
Size = 0;
}
/// <summary>
Comment on lines +33 to +34

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Надо пустую строку между методами

/// Добавляет строку в дерево. возвращает true, если такой строки ещё не было, работает за O(|element|)
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
Comment on lines +37 to +39

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Пустые тэги с комментариями не нужны. Надо либо написать комментарий, либо удалить их вовсе

public bool Add (string element)
{
if (element == null)
{
throw new ArgumentNullException();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new ArgumentNullException();
throw new ArgumentNullException(nameof(element));

Тут аргумент один, так что нетрудно догадаться, какой аргумент плохой, но всё же.

}
if (element == "")
{
if (IsEmptyStringContained) return false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (IsEmptyStringContained) return false;
if (IsEmptyStringContained)
{
return false;
}

Это местное правило, официальный стайлгайд разрешает писать как Вы, но это хуже в плане быстрого восприятия структуры программы.

else
{
IsEmptyStringContained = true;
Size++;
return true;
}
}
if (Contains(element))
{
return false;
}
var CurrentNode = root;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Локальные переменные точно именуются со строчной всегда

for (int i = 0; i < element.Length; i++)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут кажется, что сам i нигде не нужен, так что можно переписать через foreach

{
if (!CurrentNode.nexts.ContainsKey(element[i]))
{
CurrentNode.nexts[element[i]] = new BorNode();
}
CurrentNode.WordsWithSamePrefix++;
CurrentNode = CurrentNode.nexts[element[i]];
}
CurrentNode.WordsWithSamePrefix++;
CurrentNode.isTerminate = true;
Size++;
return true;
}
/// <summary>
/// Возвращает true, если элемент содержится в дереве. работает за O(|element|)
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public bool Contains(string element)
{
if (element == null)
{
throw new ArgumentNullException();
}
if (element == "")
{
return IsEmptyStringContained;
}
var CurrentNode = root;
for (int i = 0; i < element.Length; i++)
{
if (!CurrentNode.nexts.ContainsKey(element[i]))
{
return false;
}
CurrentNode = CurrentNode.nexts[element[i]];
}
if (CurrentNode.isTerminate == false) return false;
return true;
Comment on lines +100 to +101

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (CurrentNode.isTerminate == false) return false;
return true;
return CurrentNode.isTerminate;

}
/// <summary>
/// Удаляет элемент из дерева.возвращает true, если элемент реально был в дереве, работает за O(|element|)
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public bool Remove(string element)
{
if (element == null)
{
throw new ArgumentNullException();
}
if (element == "")
{
if (!IsEmptyStringContained) return false;
else
{
IsEmptyStringContained = false;
return true;
}
}
if (!Contains(element))
{
return false;
}
var CurrentNode = root;
for (int i = 0; i < element.Length; i++)
{
CurrentNode = CurrentNode.nexts[element[i]];
CurrentNode.WordsWithSamePrefix--;
}
CurrentNode.isTerminate = false;
Size--;
return true;
}
/// <summary>
/// Возвращает количество строк в дереве начинающихся с этого префикса. работает за O(|prefix|). если prefix == "" бросает исключение.
/// </summary>
/// <param name="prefix"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="Exception"></exception>
public int HowManyStartsWithPrefix(string prefix)
{
if (prefix == null)
{
throw new ArgumentNullException();
}
if (prefix == "")
{
throw new Exception();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему нет, это просто количество строк в дереве. Вообще, Exception, как мы теперь знаем, бросать нельзя.

}
var CurrentNode = root;
for (int i = 0; i < prefix.Length; i++)
{
if (!CurrentNode.nexts.ContainsKey(prefix[i]))
{
return 0;
}
CurrentNode = CurrentNode.nexts[prefix[i]];
}
return CurrentNode.WordsWithSamePrefix;
}
}
}
87 changes: 87 additions & 0 deletions hw2/BOR/BorTests/BorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

namespace Bor.Tests
{
public class Tests
{
[Test]
public void AddUncontainedStringShouldAddAndReturnTrue()
{
Bor bor = new Bor();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Bor bor = new Bor();
var bor = new Bor();

Assert.IsTrue(bor.Add("NewString"));
Assert.IsTrue(bor.Add("NewStr"));
Assert.That(bor.Size, Is.EqualTo(2));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Надо пустые строки между методами

[Test]
public void AddContainedStringShouldReturnFalse()
{
Bor bor = new Bor();
Assert.IsTrue(bor.Add("NewString"));
Assert.IsFalse(bor.Add("NewString"));
Assert.That(bor.Size, Is.EqualTo(1));
}
[Test]
public void AddEmptyString()
{
var bor = new Bor();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Создание бора можно вынести в метод с атрибутом SetUp, если объявить бор как поле тестового класса

Assert.IsTrue(bor.Add(""));
Assert.IsFalse(bor.Add(""));
Assert.That(bor.Size, Is.EqualTo(1));
}
[Test]
public void AddNullStringShouldThrowException()
{
Bor bor = new();
Assert.Catch<ArgumentNullException>(() => bor.Add(null));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Assert.Catch<ArgumentNullException>(() => bor.Add(null));
Assert.Throws<ArgumentNullException>(() => bor.Add(null));

Мы же знаем, какое именно исключение должно быть брошено

}
[Test]
public void RemoveContainedStringShouldRemoveAndReturnTrue()
{
Bor bor = new Bor();
bor.Add("Element");
Assert.IsTrue(bor.Remove("Element"));
Assert.That(bor.Size, Is.EqualTo(0));
}
[Test]
public void RemoveUncontainedStringShouldReturnFalse()
{
var bor = new Bor();
bor.Add("NewElement");
Assert.IsFalse(bor.Remove("Element"));
}
[Test]
public void RemoveNullStringShouldThrowException()
{
Bor bor = new();
Assert.Catch<ArgumentNullException>(() => bor.Remove(null));
}
[Test]
public void Contains()
{
var bor = new Bor();
bor.Add("Str101");
Assert.IsTrue(bor.Contains("Str101"));
Assert.IsFalse(bor.Contains("Str"));
}
[Test]
public void ContainsNullShouldThrowException()
{
var bor = new Bor();
Assert.Catch<ArgumentNullException>(() => bor.Contains(null));
}
[Test]
public void HowManyStartsWithPrefix()
{
var bor = new Bor();
bor.Add("1");
bor.Add("12");
bor.Add("1234");
bor.Add("12345");
Assert.That(bor.HowManyStartsWithPrefix("1"), Is.EqualTo(4));
Assert.That(bor.HowManyStartsWithPrefix("12"), Is.EqualTo(3));
Assert.That(bor.HowManyStartsWithPrefix("123"), Is.EqualTo(2));
Assert.That(bor.HowManyStartsWithPrefix("12345"), Is.EqualTo(1));
Assert.That(bor.HowManyStartsWithPrefix("00"), Is.EqualTo(0));
}

}
}
23 changes: 23 additions & 0 deletions hw2/BOR/BorTests/BorTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

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

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

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BOR.csproj" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions hw2/BOR/BorTests/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using NUnit.Framework;
12 changes: 12 additions & 0 deletions hw2/BOR/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Program
{
public class Program
{
public static void Main()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это вообще не надо, собирайте бор как библиотеку

{

}
}
}