From 48a1e121a369934d8803ee733ab20b5bb36cfaf0 Mon Sep 17 00:00:00 2001 From: DimVlas Date: Sat, 13 Apr 2024 11:38:55 +0300 Subject: [PATCH] =?UTF-8?q?hw02=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hw02_unpack_string/unpack.go | 64 +++++++++++++++++++++++++++++-- hw02_unpack_string/unpack_test.go | 25 +++++++++++- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/hw02_unpack_string/unpack.go b/hw02_unpack_string/unpack.go index 41f003d..f5746c1 100644 --- a/hw02_unpack_string/unpack.go +++ b/hw02_unpack_string/unpack.go @@ -2,11 +2,67 @@ package hw02unpackstring import ( "errors" + "fmt" + "slices" + "strconv" + "strings" ) -var ErrInvalidString = errors.New("invalid string") +var ( + ErrInvalidString = errors.New("invalid string") -func Unpack(_ string) (string, error) { - // Place your code here. - return "", nil + nums = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} + + numZero = '0' +) + +// True - если руна является цифрой. +func IsDigit(r rune) bool { + return slices.Contains(nums, r) +} + +func Unpack(text string) (string, error) { + if text == "" { // с пустой строкой ничего не делаем + return "", nil + } + + runes := []rune(text) + + if IsDigit(runes[0]) { // если первая руна цифра + return "", ErrInvalidString + } + + var res strings.Builder + + lenRunes := len(runes) + for i := 0; i < lenRunes; i++ { + if IsDigit(runes[i]) { + return "", ErrInvalidString + } + + if i == lenRunes-1 { // это последний символ + res.WriteRune(runes[i]) + break + } + if !IsDigit(runes[i+1]) { // следующий символ не цифра + res.WriteRune(runes[i]) + continue + } + if IsDigit(runes[i+1]) { // следующий символ цифра + if runes[i+1] == numZero { // следующий символ '0' + i++ + continue + } + n, err := strconv.Atoi(string(runes[i+1])) + if err != nil { + return "", fmt.Errorf("error converting rune '%q' to number: %w", runes[i+1], err) + } + + res.WriteString(strings.Repeat(string(runes[i]), n)) + i++ + continue + } + } + + return res.String(), nil } diff --git a/hw02_unpack_string/unpack_test.go b/hw02_unpack_string/unpack_test.go index 9799e18..73dfe8c 100644 --- a/hw02_unpack_string/unpack_test.go +++ b/hw02_unpack_string/unpack_test.go @@ -13,6 +13,9 @@ func TestUnpack(t *testing.T) { expected string }{ {input: "a4bc2d5e", expected: "aaaabccddddde"}, + {input: "a4bc2d5e3", expected: "aaaabccdddddeee"}, + {input: "a4bc2d5e0", expected: "aaaabccddddd"}, + {input: "a+3b", expected: "a+++b"}, {input: "abccd", expected: "abccd"}, {input: "", expected: ""}, {input: "aaa0b", expected: "aab"}, @@ -34,7 +37,7 @@ func TestUnpack(t *testing.T) { } func TestUnpackInvalidString(t *testing.T) { - invalidStrings := []string{"3abc", "45", "aaa10b"} + invalidStrings := []string{"3abc", "45", "aaa10b", "aaa+b10"} for _, tc := range invalidStrings { tc := tc t.Run(tc, func(t *testing.T) { @@ -43,3 +46,23 @@ func TestUnpackInvalidString(t *testing.T) { }) } } + +func TestIsDigit(t *testing.T) { + tests := []struct { + input rune + expected bool + }{ + {input: 'a', expected: false}, + {input: '5', expected: true}, + {input: '!', expected: false}, + {input: '\n', expected: false}, + } + + for _, tc := range tests { + tc := tc + t.Run(string(tc.input), func(t *testing.T) { + result := IsDigit(tc.input) + require.Equal(t, tc.expected, result) + }) + } +}