Skip to content

Commit

Permalink
arbitrary text support
Browse files Browse the repository at this point in the history
  • Loading branch information
thevilledev committed May 18, 2023
1 parent be7a7c9 commit 67e58a9
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 5 deletions.
57 changes: 54 additions & 3 deletions thespine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@ package thespine

import (
"errors"
"strings"
"unicode/utf8"
)

// THE_SIZE represents the size of grouping used by the anagram encode/decode
const THE_SIZE = 3

// ErrInvalidString represents an error for invalid UTF-8 string
var ErrInvalidString = errors.New("invalid string")

// Decode takes a UTF-8 string as an input and decodes the anagram.
// Error returned in case of an invalid UTF-8 string.
func Decode(s string) (string, error) {
if !utf8.ValidString(s) {
return "", ErrInvalidString
}
sr := []rune(s)
l := len(sr)
if l <= THE_SIZE {
return s, nil
}

g := make([][]rune, 0)
gc := l / THE_SIZE
if l%THE_SIZE != 0 {
Expand All @@ -29,15 +38,21 @@ func Decode(s string) (string, error) {
gs := sr[si:ei]
g = append(g, gs)
}
return concat(g), nil
return runestring(g), nil
}

// Encode takes a UTF-8 string as an input and generates an anagram out of it.
// Error returned in case of an invalid UTF-8 string.
func Encode(s string) (string, error) {
if !utf8.ValidString(s) {
return "", ErrInvalidString
}
sr := []rune(s)
l := len(sr)
if l <= THE_SIZE {
return s, nil
}

g := make([][]rune, 0)
gc := l / THE_SIZE
if l%THE_SIZE != 0 {
Expand All @@ -55,10 +70,46 @@ func Encode(s string) (string, error) {
for i, j := 0, len(g)-1; i < j; i, j = i+1, j-1 {
g[i], g[j] = g[j], g[i]
}
return concat(g), nil
return runestring(g), nil
}

// EncodeText takes a UTF-8 string as an input, splits it by whitespace and runs an anagram for each word.
// Error returned in case of an invalid UTF-8 string.
func EncodeText(s string) (string, error) {
o := ""
ws := strings.Split(s, " ")
for i, w := range ws {
ew, err := Encode(w)
if err != nil {
return "", err
}
o += ew
if i != len(ws)-1 {
o += " "
}
}
return o, nil
}

// DecodeText takes a UTF-8 string as an input, splits it by whitespace and decodes each anagram word-by-word.
// Error returned in case of an invalid UTF-8 string.
func DecodeText(s string) (string, error) {
o := ""
ws := strings.Split(s, " ")
for i, w := range ws {
ew, err := Decode(w)
if err != nil {
return "", err
}
o += ew
if i < len(ws)-1 {
o += " "
}
}
return o, nil
}

func concat(r [][]rune) string {
func runestring(r [][]rune) string {
var s string
for _, r := range r {
s += string(r)
Expand Down
70 changes: 68 additions & 2 deletions thespine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func Test_Decode(t *testing.T) {
t.Fatalf("decode err wanted but got none")
}
if got != test.want {
t.Fatalf("decode got: %s\nwant: %s\n", got, test.want)
t.Fatalf("decode got: '%s'\nwant: '%s'\n", got, test.want)
}
})
}
Expand Down Expand Up @@ -106,7 +106,7 @@ func Test_Encode(t *testing.T) {
t.Fatalf("encode err wanted but got none")
}
if enc != test.want {
t.Fatalf("encode got: %s\nwant: %s\n", enc, test.want)
t.Fatalf("encode got: '%s'\nwant: '%s'\n", enc, test.want)
}
})
}
Expand All @@ -132,3 +132,69 @@ func FuzzEncode(f *testing.F) {
}
})
}

func Test_EncodeText(t *testing.T) {
tests := []struct {
str string
name string
want string
wantErr bool
}{
{
str: "meh noob",
name: "the noob",
want: "meh bnoo",
wantErr: false,
},
{
str: "The Putrefying Road In The 19th Extremity (...Somewhere Inside The Bowels Of The Endlessness...)",
name: "the noob2",
want: "The gyinrefPut dRoa In The h19t ityremExt ehermew.So(.. ideIns The elsBow Of The ..)ss.snelesEnd",
wantErr: false,
},
{
str: "\xf2",
name: "the invalid string",
want: "",
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
o, _ := EncodeText(test.str)
if o != test.want {
t.Fatalf("encode got: '%s'\nwant: '%s'\n", o, test.want)
}
})
}
}

func Test_DecodeText(t *testing.T) {
tests := []struct {
str string
name string
want string
wantErr bool
}{
{
str: "The gyinrefPut dRoa In The h19t ityremExt ehermew.So(.. ideIns The elsBow Of The ..)ss.snelesEnd",
name: "the puzzle",
want: "The Putrefying Road In The 19th Extremity (...Somewhere Inside The Bowels Of The Endlessness...)",
wantErr: false,
},
{
str: "\xf2",
name: "the invalid string",
want: "",
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
o, _ := DecodeText(test.str)
if o != test.want {
t.Fatalf("encode got: '%s'\nwant: '%s'\n", o, test.want)
}
})
}
}

0 comments on commit 67e58a9

Please sign in to comment.