using System;
class Kata{
static int stringCounter(string s1, string s2)
{
bool b_n = s1.Contains(s2);
int count;
if ( !b_n )
return 0;
int index, length;
do
{
length = s2.Length;
index = s1.IndexOf(s2);
s1 = s1.Remove(index,length);
count++;
}
while (b_n);
return count;
}
static void Main() {
string ControL = "тук-тук!";
Console.WriteLine(ControL);
Console.Write($"\"тук\" is {stringCounter(ControL, "тук")} times...")
Console.ReadKey();
}
}
о синтаксических ошибкахнасколько помню, та строка, на которую он указывал, была не той искомой строкой. Или просто бывает ведь, что всегда ставишь все точки-запятые, а тут глядишь и не замечаешь.
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace Occurrences
{
class Program
{
static int method1(string source, string pattern)
=> new Regex(pattern).Matches(source).Count;
static int method2(string source, string pattern)
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Count() - 1;
static void Main(string[] args)
{
var src = "тук - тук!";
var ptn = "тук";
Console.WriteLine($"'{ptn}' found on '{src}' use 'method1' {method1(src, ptn)} times...");
Console.WriteLine($"'{ptn}' found on '{src}' use 'method2' {method2(src, ptn)} times...");
}
}
}
if (index == -1)
break;
static int StringCounter(string s1, string s2)
{
int count = 0;
int index;
while (true)
{
index = s1.IndexOf(s2);
if (index == -1)
return count;
s1 = s1.Substring(index + s2.Length);
count++;
}
}
while (true)
Кроме того вместо метода Remove можно использовать метод Substring. Здесь большой разницы в использовании между ними нет, то лично мне кажется что название Substring лучше отражает суть происходящего. Но тут уже дело вкуса.согласен что лучше отражает. мало того, это обычно приоритет в современном корпоративе - читаемость (а значит сопровождаемость кода)
а вот по F# я пока только "слюнки пускал"..
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Occurrences
{
static class Program
{
static int useSubString(this string source, string pattern)
{
int count = 0;
int index;
while (true)
{
index = source.IndexOf(pattern);
if (index == -1)
return count;
source = source.Substring(index + pattern.Length);
count++;
}
}
static int useRemove(this string source, string pattern)
{
int count = 0;
int index;
while (true)
{
index = source.IndexOf(pattern);
if (index == -1)
return count;
source = source.Remove(index, pattern.Length);
count++;
}
}
static int useSplit(this string source, string pattern)
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Count() - 1;
static int useRegexp(this string source, string pattern)
=> new Regex(pattern).Matches(source).Count;
static void sample()
{
var src = "тук - тук!";
var ptn = "тук";
$"'{ptn}' found on '{src}' use 'useSubString'\t {useSubString(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRemove'\t {useRemove(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useSplit'\t {useSplit(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRegexp'\t {useRegexp(src, ptn)} times...".print();
}
static Random rnd = new Random();
static string pattren = genPattern();
static string genPattern()
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var i = 0; i < l; i++)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
return sb.ToString();
}
static List<string> sources = new List<string>();
static void fill(int n)
{
for (var i = 0; i < n; i++)
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var j = 0; j < l; j++)
if (rnd.Next(0, 7) % 3 != 0)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
else
sb.Append(pattren);
sources.Add(sb.ToString());
}
}
static void bench(int n)
{
// массивы что бы убрать влияние динамического создания объектов
var uss = new int[n];
var urm = new int[n];
var usp = new int[n];
var urx = new int[n];
var sw = new Stopwatch();
sw.Start();
fill(n);
var tsf = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uss[i] = sources[i].useSubString(pattren);
var tss = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urm[i] = sources[i].useRemove(pattren);
var trm = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
usp[i] = sources[i].useSplit(pattren);
var tsp = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urx[i] = sources[i].useRegexp(pattren);
var trx = sw.Elapsed;
sw.Stop();
// весь вывод выносим за пределы замера
$"fill\t {tsf.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSubString\t {tss.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRemove\t {trm.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSplit\t {tsp.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRegexp\t {trx.ToString(@"hh\:mm\:ss\.fffff")}".print();
// вывод размерности массивов, что бы сборщик мусора не успел возбудиться ))
$"{uss.Length} {urm.Length} {usp.Length} {urx.Length}".print();
}
static void Main(string[] args)
{
sample();
var n = 1_000_000;
bench(n);
}
static void print(this string s) => Console.WriteLine(s);
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Occurrences
{
static class Program
{
static int useSubString(this string source, string pattern)
{
int count = 0;
int index;
while (true)
{
index = source.IndexOf(pattern);
if (index == -1)
return count;
source = source.Substring(index + pattern.Length);
count++;
}
}
static int useRemove(this string source, string pattern)
{
int count = 0;
int index;
while (true)
{
index = source.IndexOf(pattern);
if (index == -1)
return count;
source = source.Remove(index, pattern.Length);
count++;
}
}
static int useSplit(this string source, string pattern)
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Count() - 1;
static int useRegexp(this string source, string pattern)
=> new Regex(pattern).Matches(source).Count;
static void sample()
{
var src = "тук - тук!";
var ptn = "тук";
$"'{ptn}' found on '{src}' use 'useSubString'\t {useSubString(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRemove'\t {useRemove(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useSplit'\t {useSplit(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRegexp'\t {useRegexp(src, ptn)} times...".print();
}
static Random rnd = new Random();
static string pattren = genPattern();
static string genPattern()
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var i = 0; i < l; i++)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
return sb.ToString();
}
static List<string> sources = new List<string>();
static void fill(int n)
{
for (var i = 0; i < n; i++)
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var j = 0; j < l; j++)
if (rnd.Next(0, 7) % 3 != 0)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
else
sb.Append(pattren);
sources.Add(sb.ToString());
}
}
static void bench(int n, bool check = true)
{
// массивы что бы убрать влияние динамического создания объектов
var uss = new int[n];
var urm = new int[n];
var usp = new int[n];
var urx = new int[n];
var sw = new Stopwatch();
sw.Start();
fill(n);
var tsf = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uss[i] = sources[i].useSubString(pattren);
var tss = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urm[i] = sources[i].useRemove(pattren);
var trm = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
usp[i] = sources[i].useSplit(pattren);
var tsp = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urx[i] = sources[i].useRegexp(pattren);
var trx = sw.Elapsed;
sw.Stop();
// весь вывод выносим за пределы замера
//Console.WriteLine(tsf.ToString(@"dddd\.hh\:mm\:ss\.fffffff"));
$"fill\t {tsf.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSubString\t {tss.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRemove\t {trm.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSplit\t {tsp.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRegexp\t {trx.ToString(@"hh\:mm\:ss\.fffff")}".print();
// выод размерности массивов, или чек, что бы сборщик мусора не успел возбудиться ))
if (check)
$"{chk(urm)} {chk(usp)} {chk(urx)}".print();
else
$"{uss.Length} {urm.Length} {usp.Length} {urx.Length}".print();
bool chk(int[] x)
{
for (var i = 0; i < x.Length; i++)
if (uss[i] != x[i])
return false;
return true;
}
}
static void Main(string[] args)
{
sample();
var n = 1_000_000;
bench(n);
}
static void print(this string s) => Console.WriteLine(s);
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Occurrences
{
static class Program
{
static int useSubString(this string source, string pattern)
{
int count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Substring(index + pattern.Length);
count++;
}
}
static int useRemove(this string source, string pattern)
{
int count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Remove(index, pattern.Length);
count++;
}
}
static int useSplit(this string source, string pattern)
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Count() - 1;
static int useRegexp(this string source, string pattern)
=> new Regex(pattern).Matches(source).Count;
static void sample(string src = "тук - тук!", string ptn = "тук")
{
$"'{ptn}' found on '{src}' use 'useSubString'\t {useSubString(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRemove'\t {useRemove(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useSplit'\t {useSplit(src, ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRegexp'\t {useRegexp(src, ptn)} times...".print();
}
static Random rnd = new Random();
static string pattren = genPattern();
static string genPattern()
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var i = 0; i < l; i++)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
return sb.ToString();
}
static List<string> sources = new List<string>();
static void fill(int n)
{
for (var i = 0; i < n; i++)
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var j = 0; j < l; j++)
if (rnd.Next(0, 7) % 3 != 0)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
else
sb.Append(pattren);
sources.Add(sb.ToString());
}
}
static void bench(int n = 1_000_000, bool check = true)
{
// массивы что бы убрать влияние динамического создания объектов
var uss = new int[n];
var urm = new int[n];
var usp = new int[n];
var urx = new int[n];
var sw = new Stopwatch();
sw.Start();
fill(n);
var tsf = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uss[i] = sources[i].useSubString(pattren);
var tss = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urm[i] = sources[i].useRemove(pattren);
var trm = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
usp[i] = sources[i].useSplit(pattren);
var tsp = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urx[i] = sources[i].useRegexp(pattren);
var trx = sw.Elapsed;
sw.Stop();
// весь вывод выносим за пределы замера
$"fill\t\t {tsf.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSubString\t {tss.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRemove\t {trm.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSplit\t {tsp.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRegexp\t {trx.ToString(@"hh\:mm\:ss\.fffff")}".print();
// выод размерности массивов, или чек, что бы сборщик мусора не успел возбудиться ))
if (check)
$"{chk(urm)} {chk(usp)} {chk(urx)}".print();
else
$"{uss.Length} {urm.Length} {usp.Length} {urx.Length}".print();
bool chk(int[] x)
{
for (var i = 0; i < x.Length; i++)
if (uss[i] != x[i])
return false;
return true;
}
}
static void Main(string[] args)
{
sample();
bench();
}
static void print(this string s) => Console.WriteLine(s);
}
}
но вот что сплит всех уделает "как бог черепаху" искренне не ожидал ))
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Occurrences
{
static class Program
{
static int useSubString(this string source, string pattern)
{
var count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Substring(index + pattern.Length);
count++;
}
}
static int useRemove(this string source, string pattern)
{
var count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Remove(index, pattern.Length);
count++;
}
}
static int useIndex(this string source, string pattern)
{
var count = 0;
var pos = 0;
var len = pattern.Length;
while (true)
{
var index = source.IndexOf(pattern, pos);
if (index < 0)
return count;
pos = index + len;
count++;
}
}
static int useSplit(this string source, string pattern)
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Count() - 1;
static int useRegexp(this string source, string pattern)
=> new Regex(pattern).Matches(source).Count;
static void sample(string src = "тук - тук!", string ptn = "тук")
{
$"'{ptn}' found on '{src}' use 'useSubString'\t {src.useSubString(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRemove'\t {src.useRemove(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useIndexOf'\t {src.useIndex(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useSplit'\t {src.useSplit(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRegexp'\t {src.useRegexp(ptn)} times...".print();
}
static Random rnd = new Random();
static string pattren = genPattern();
static string genPattern()
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var i = 0; i < l; i++)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
return sb.ToString();
}
static List<string> sources = new List<string>();
static void fill(int n)
{
for (var i = 0; i < n; i++)
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var j = 0; j < l; j++)
if (rnd.Next(0, 7) % 3 != 0)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
else
sb.Append(pattren);
sources.Add(sb.ToString());
}
}
static void bench(int n = 1_000_000, bool check = true)
{
// массивы что бы убрать влияние динамического создания объектов
var uss = new int[n];
var urm = new int[n];
var uio = new int[n];
var usp = new int[n];
var urx = new int[n];
var sw = new Stopwatch();
sw.Start();
fill(n);
var tsf = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uss[i] = sources[i].useSubString(pattren);
var tss = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urm[i] = sources[i].useRemove(pattren);
var trm = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uio[i] = sources[i].useIndex(pattren);
var tio = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
usp[i] = sources[i].useSplit(pattren);
var tsp = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urx[i] = sources[i].useRegexp(pattren);
var trx = sw.Elapsed;
sw.Stop();
// весь вывод выносим за пределы замера
$"fill\t\t {tsf.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSubString\t {tss.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRemove\t {trm.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useIndexOf\t {tio.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSplit\t {tsp.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRegexp\t {trx.ToString(@"hh\:mm\:ss\.fffff")}".print();
// выод размерности массивов, или чек, что бы сборщик мусора не успел возбудиться ))
if (check)
$"{chk(urm)} {chk(usp)} {chk(uio)} {chk(urx)}".print();
else
$"{uss.Length} {urm.Length} {usp.Length} {urx.Length}".print();
bool chk(int[] x)
{
for (var i = 0; i < x.Length; i++)
if (uss[i] != x[i])
return false;
return true;
}
}
static void Main(string[] args)
{
sample();
bench();
}
static void print(this string s) => Console.WriteLine(s);
}
}
static int useIndex(this string source, string pattern)
{
var count = 0;
var index = 0;
while (true)
{
index = source.IndexOf(pattern, index);
if (index < 0)
return count;
index += pattern.Length;
count++;
}
}
static int useIndex(this string source, string pattern)
{
var count = 0;
var index = 0;
while (true)
if ((index = source.IndexOf(pattern, index)) < 0)
return count;
else
{
index += pattern.Length;
count++;
}
}
static int useIndex(this string source, string pattern)
{
for (int count = 0, index = 0; ; count++)
if ((index = source.IndexOf(pattern, index)) < 0)
return count;
else
index += pattern.Length;
}
ухожу, ухожу, ухожу ... (с)
если будут вопросы по F# с радостью отвечу, если смогу, конечно.а переписать на F# мой "бенчмарк".. хлопотно? было бы любопытно ))
class Program
{
static void Main() => BenchmarkRunner.Run<Benchmark>();
}
[MemoryDiagnoser]
public class Benchmark
{
static Random rnd = new Random();
static string GenPattern()
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var i = 0; i < l; i++)
sb.Append((char)('A' + rnd.Next(0, 26)));
return sb.ToString();
}
static string GenSource(string pattern)
{
var l = rnd.Next(100, 200);
var sb = new StringBuilder();
for (var j = 0; j < l; j++)
if (rnd.Next(0, 7) % 3 != 0)
sb.Append((char)('A' + rnd.Next(0, 26)));
else
sb.Append(pattern);
return sb.ToString();
}
[IterationSetup]
public void Setup()
{
pattern = GenPattern();
source = GenSource(pattern);
}
string source;
string pattern;
[Benchmark]
public int UseSubstring()
{
var count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Substring(index + pattern.Length);
count++;
}
}
[Benchmark]
public int UseRemove()
{
var count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Remove(index, pattern.Length);
count++;
}
}
[Benchmark]
public int UseIndex()
{
int c = 0, i = -pattern.Length;
while ((i = source.IndexOf(pattern, i + pattern.Length)) > -1) ++c;
return c;
}
[Benchmark]
public int UseSplit()
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Length - 1;
[Benchmark]
public int UseRegexp()
=> new Regex(pattern).Matches(source).Count;
[Benchmark]
public int UseReplace()
=> (source.Length - source.Replace(pattern, "").Length) / pattern.Length;
}
а переписать на F# мой "бенчмарк".. хлопотно? было бы любопыт
В итоге побеждает Replace - изящное и, на мой взгляд, далеко не очевидное решение.тоже интересный прием..
смогу написать только ближе к понедельникуне вопрос, даже если и не сложится. но если сложится - мне проще заходить на "новые территории" сравнивая решения задачи, которая уже решена знакомым способом. как наверное и всем ))
Replaceи
Splitимеют минимальные простые обертки, к низкоуровневым реализациям. наверняка аналоги давно есть в рантаймах типа user32.dll, или где то рядом ))
open System
open System.Text.RegularExpressions
open System.Text
open System.Diagnostics
module String =
let print = printfn "%s"
let useSubString x (pattern:string) =
let rec loop (source:string) count =
let index = source.IndexOf pattern
if source.IndexOf pattern < 0 then count
else
count + 1 |> loop (source.Substring (index + pattern.Length))
loop x 0
let useRemove x (pattern:string) =
let rec loop (source:string) count =
let index = source.IndexOf pattern
if source.IndexOf pattern < 0 then count
else
count + 1 |> loop (source.Remove(index, pattern.Length))
loop x 0
let useSplit (x:string) (pattern:string) =
x.Split([| pattern |], StringSplitOptions.None).Length - 1
let useRegexp x (pattern:string) = Regex(pattern).Matches(x).Count
let sample() =
let src = "тук - тук!"
let ptn = "тук"
[
"useSubString", String.useSubString
"useRemove", String.useRemove
"useSplit", String.useSplit
"useRegexp", String.useRegexp
]
|> List.map(fun (n,f) ->
f src ptn |> sprintf "'%s' found on '%s' use '%s'\t %i times..." ptn src n
)
|> List.iter String.print
let rnd = Random()
let genPattern() =
let l = rnd.Next(10, 20)
(StringBuilder(), [0..l - 1])
||> List.fold (fun sb _ -> sb.Append('A').Append(rnd.Next 26))
let pattren = genPattern().ToString()
let fill n =
Array.init n (fun _ ->
let l = rnd.Next(10, 20)
(StringBuilder(), [0..l - 1])
||> List.fold (fun sb _ ->
if (rnd.Next(0, 7) % 3 <> 0) then
sb.Append('A').Append(rnd.Next 26)
else
sb.Append pattren
)
|> fun sb -> sb.ToString()
)
let bench() =
let n = 1_000_000
// массивы что бы убрать влияние динамического создания объектов
let uss = Array.zeroCreate n
let urm = Array.zeroCreate n
let usp = Array.zeroCreate n
let urx = Array.zeroCreate n
let sw = Stopwatch()
sw.Start()
let sources = fill(n)
let tsf = sw.Elapsed
sw.Reset()
sw.Start()
for i in 0..n-1 do
uss.[i] <- String.useSubString sources.[i] pattren
let tss = sw.Elapsed
sw.Reset()
sw.Start()
for i in 0..n-1 do
urm.[i] <- String.useRemove sources.[i] pattren
let trm = sw.Elapsed
sw.Reset()
sw.Start()
for i in 0..n-1 do
usp.[i] <- String.useSplit sources.[i] pattren
let tsp = sw.Elapsed
sw.Reset()
sw.Start()
for i in 0..n-1 do
urx.[i] <- String.useRegexp sources.[i] pattren
let trx = sw.Elapsed
sw.Stop()
// весь вывод выносим за пределы замера
[
sprintf "fill\t\t %s" <| tsf.ToString(@"hh\:mm\:ss\.fffff")
sprintf "useSubString\t %s" <| tss.ToString(@"hh\:mm\:ss\.fffff")
sprintf "useRemove\t %s" <| trm.ToString(@"hh\:mm\:ss\.fffff")
sprintf "useSplit\t %s" <| tsp.ToString(@"hh\:mm\:ss\.fffff")
sprintf "useRegexp\t %s" <| trx.ToString(@"hh\:mm\:ss\.fffff")
] |> List.iter String.print
// выод размерности массивов, или чек, что бы сборщик мусора не успел возбудиться ))
printfn "%i %i %i %i" uss.Length urm.Length usp.Length urx.Length
sample()
bench()