Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hw02 unpack string #2

Merged
merged 6 commits into from
Apr 14, 2024
Merged
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
Empty file removed hw02_unpack_string/.sync
Empty file.
2 changes: 1 addition & 1 deletion hw02_unpack_string/go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/fixme_my_friend/hw02_unpack_string
module github.com/DimVlas/otus_hw/hw02_unpack_string

go 1.19

Expand Down
82 changes: 78 additions & 4 deletions hw02_unpack_string/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,85 @@ package hw02unpackstring

import (
"errors"
"fmt"
"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'

bslash = '\\'
)

// True - если руна является цифрой.
func IsDigit(r rune) bool {
for _, num := range nums {
if num == r {
return true
}
}
return false
}
Comment on lines +21 to +28
Copy link
Collaborator

Choose a reason for hiding this comment

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

Думаю, что можно использовать функцию стандартной библиотеки https://pkg.go.dev/unicode#IsDigit


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++ {
Comment on lines +43 to +44
Copy link
Collaborator

Choose a reason for hiding this comment

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

Удобнее и проще будет использовать цикл range. Это позволит на каждой итерации получать текущий символ, при необходимости запоминать предыдущий и не обращаться к элементам по индексу

if IsDigit(runes[i]) {
return "", ErrInvalidString
}

if runes[i] == bslash { // текущий символ слэш
if i == lenRunes-1 { // это последний символ
return "", ErrInvalidString
}

if !IsDigit(runes[i+1]) && runes[i+1] != bslash { // следующий символ не цифра и не слэш
return "", ErrInvalidString
}

i++ // нужно обработать следующий символ как обычный
}

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
}
33 changes: 28 additions & 5 deletions hw02_unpack_string/unpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ 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"},
// uncomment if task with asterisk completed
// {input: `qwe\4\5`, expected: `qwe45`},
// {input: `qwe\45`, expected: `qwe44444`},
// {input: `qwe\\5`, expected: `qwe\\\\\`},
// {input: `qwe\\\3`, expected: `qwe\3`},
{input: `qwe\4\5`, expected: `qwe45`},
{input: `qwe\45`, expected: `qwe44444`},
{input: `qwe\\5`, expected: `qwe\\\\\`},
{input: `qwe\\\3`, expected: `qwe\3`},
}

for _, tc := range tests {
Expand All @@ -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", `aaaa\`, `aaa\\\b`}
for _, tc := range invalidStrings {
tc := tc
t.Run(tc, func(t *testing.T) {
Expand All @@ -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)
})
}
}
Loading