Skip to content

Commit

Permalink
HW2
Browse files Browse the repository at this point in the history
(cherry picked from commit f59425ac23dea20b40c10dee09b627a1e1068b77)
  • Loading branch information
timersha committed Nov 11, 2024
1 parent 5e1ffa6 commit f92c90e
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 11 deletions.
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/timersha/golang-tests/hw02_unpack_string

go 1.22

Expand Down
93 changes: 90 additions & 3 deletions hw02_unpack_string/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,98 @@ package hw02unpackstring

import (
"errors"
"math"
"strconv"
"unicode"
)

var ErrInvalidString = errors.New("invalid string")

func Unpack(_ string) (string, error) {
// Place your code here.
return "", nil
func Unpack(input *[]rune, result *[]rune) error {
inputIndex := 0
resultIndex := 0
backslash := '\\'
inputLen := len(*input) - 1

// validate length
if inputLen == 0 {
return nil
}

for inputIndex <= inputLen {
r := (*input)[inputIndex]

// starts with digit
if unicode.IsDigit(r) && inputIndex == 0 {
return ErrInvalidString
}

inputNextIndex := nextIndex(input, inputIndex)
nextR := (*input)[inputNextIndex]
// finds number
if inputLen != inputNextIndex && unicode.IsDigit(r) && unicode.IsDigit(nextR) {
return ErrInvalidString
}

// escaped symbol is valid
isValidForEscape := unicode.IsDigit(nextR) || nextR == backslash
if r == backslash && isValidForEscape {
*result = append(*result, nextR)
resultIndex++
inputIndex += 2
continue
}

// escaped symbol is not valid
if r == backslash && !isValidForEscape {
return ErrInvalidString
}

// repeatedly add rune
isDigit := unicode.IsDigit(r)
if isDigit {
shift := appendRune(result, (*result)[previousIndex(result, resultIndex)], r)
resultIndex += shift
inputIndex++
continue
}

// don't append current rune
vl, err := strconv.Atoi(string(nextR))
if err == nil && vl == 0 {
inputIndex++
continue
}

// simple append
*result = append(*result, r)
resultIndex++
inputIndex++
}

return nil
}

func appendRune(res *[]rune, rn rune, count rune) int {
value, err := strconv.Atoi(string(count))
if err != nil {
return 0
}

for range value - 1 {
*res = append(*res, rn)
}
return value
}

func nextIndex(sl *[]rune, index int) int {
slLen := math.Max(0, float64(len(*sl)-1))
nextIndex := index + 1
return int(math.Min(float64(slLen), float64(nextIndex)))
}

func previousIndex(sl *[]rune, index int) int {
slLen := math.Max(0, float64(len(*sl)-1))
previousIndex := index - 1
return int(math.Min(float64(slLen), math.Max(0, float64(previousIndex))))
}
18 changes: 11 additions & 7 deletions hw02_unpack_string/unpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,32 @@ func TestUnpack(t *testing.T) {
{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 {
var res = make([]rune, 0, 100)

Check failure on line 27 in hw02_unpack_string/unpack_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed (gofumpt)
tc := tc
t.Run(tc.input, func(t *testing.T) {
result, err := Unpack(tc.input)
runes := []rune(tc.input)
err := Unpack(&runes, &res)
require.NoError(t, err)
require.Equal(t, tc.expected, result)
require.Equal(t, tc.expected, string(res))
})
}
}

func TestUnpackInvalidString(t *testing.T) {
invalidStrings := []string{"3abc", "45", "aaa10b"}
var res = make([]rune, 0, 100)

Check failure on line 40 in hw02_unpack_string/unpack_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed (gofumpt)
for _, tc := range invalidStrings {
tc := tc
t.Run(tc, func(t *testing.T) {
_, err := Unpack(tc)
runes := []rune(tc)
err := Unpack(&runes, &res)
require.Truef(t, errors.Is(err, ErrInvalidString), "actual error %q", err)
})
}
Expand Down

0 comments on commit f92c90e

Please sign in to comment.