aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-162/pokgopun/go/ch-1.go53
-rw-r--r--challenge-162/pokgopun/go/ch-2.go200
2 files changed, 253 insertions, 0 deletions
diff --git a/challenge-162/pokgopun/go/ch-1.go b/challenge-162/pokgopun/go/ch-1.go
new file mode 100644
index 0000000000..3c87b36686
--- /dev/null
+++ b/challenge-162/pokgopun/go/ch-1.go
@@ -0,0 +1,53 @@
+// Write a script to generate the check digit of given ISBN-13 code. Please refer wikipedia for more information.
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "regexp"
+ "strconv"
+)
+
+func main() {
+ isbns := []string{"978-0-306-40615-7"}
+ if len(os.Args) > 1 {
+ isbns = os.Args[1:]
+ }
+ for _, v := range isbns {
+ r, err := checkDigit(extractDigits(v))
+ var res string
+ if err != nil {
+ res = "not available due to " + fmt.Sprint(err)
+ } else {
+ res = strconv.Itoa(r)
+ }
+ fmt.Printf("ISBN-13 check digit for %q is %s\n", v, res)
+ }
+}
+
+func extractDigits(str string) (s []int, n int) {
+ str = regexp.MustCompile(`\D`).ReplaceAllLiteralString(str, "")
+ if len(str) > 0 {
+ for _, v := range str {
+ s = append(s, int(v-48))
+ }
+ return s, len(s)
+ }
+ return []int{}, 0
+}
+
+func checkDigit(s []int, n int) (r int, err error) {
+ if n < 12 || n > 13 {
+ return 0, errors.New("invalid input")
+ }
+ for i := 0; i < 12; i += 2 {
+ r += s[i] + 3*s[i+1]
+ }
+ r %= 10
+ r = 10 - r
+ if r == 10 {
+ r = 0
+ }
+ return r, nil
+}
diff --git a/challenge-162/pokgopun/go/ch-2.go b/challenge-162/pokgopun/go/ch-2.go
new file mode 100644
index 0000000000..e60a68d516
--- /dev/null
+++ b/challenge-162/pokgopun/go/ch-2.go
@@ -0,0 +1,200 @@
+package main
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+func main() {
+ pass1, msg1 := "playfair example", "hide the gold in the tree stump"
+ pf1, _ := New(pass1)
+ res1, err := pf1.Encrypt(msg1)
+ fmt.Printf("encrypt(%q, %q) = %q => %t, err => %v\n", pass1, msg1, res1, res1 == "bmodzbxdnabekudmuixmmouvif", err)
+
+ pass2, msg2 := "perl and raku", "siderwrdulfipaarkcrw"
+ pf2, _ := New(pass2)
+ res2, err := pf2.Decrypt(msg2)
+ fmt.Printf("encrypt(%q, %q) = %q => %t, err => %v\n", pass2, msg2, res2, res2 == "thewexeklychallengex", err)
+}
+
+func isLowercaseLetter(s string) bool {
+ re := regexp.MustCompile(`^[a-z]+$`)
+ return re.MatchString(s)
+}
+func lowerCaseAndRemoveSpace(s string) string {
+ return regexp.MustCompile(`\s`).ReplaceAllLiteralString(strings.ToLower(s), "")
+}
+
+func insertX(s string) string {
+ sep := "x"[0]
+ var b strings.Builder
+ var seen byte
+ for _, v := range []byte(s) {
+ if v == seen {
+ b.WriteByte(sep)
+ }
+ b.WriteByte(v)
+ seen = v
+ }
+ if b.Len()%2 != 0 {
+ b.WriteByte(sep)
+ }
+ return b.String()
+}
+
+type inputType int
+
+const (
+ passphrase inputType = iota
+ msg2encrypt
+ msg2decrypt
+)
+
+func (ipt inputType) String() string {
+ switch ipt {
+ case passphrase:
+ return "passphrase"
+ case msg2encrypt:
+ return "msg2encrypt"
+ case msg2decrypt:
+ return "msg2decrypt"
+ default:
+ return "unknown"
+ }
+}
+
+type input struct {
+ val string
+ t inputType
+}
+
+func newInput(t inputType, s string) (r input, err error) {
+ fname := "newInput"
+ r = input{lowerCaseAndRemoveSpace(s), t}
+ ok := isLowercaseLetter(r.val)
+ switch t {
+ case passphrase:
+ if !ok {
+ return input{}, fmt.Errorf("%v: %v can only contain english and space characters", fname, t)
+ }
+ case msg2encrypt:
+ if !ok {
+ return input{}, fmt.Errorf("%v: %v can only contain english and space characters", fname, t)
+ }
+ r.val = insertX(r.val)
+ case msg2decrypt:
+ if !isLowercaseLetter(strings.ToLower(s)) || len(s)%2 != 0 {
+ return input{}, fmt.Errorf("%v: %v not encrypted by playfair", fname, t)
+ }
+ default:
+ return input{}, fmt.Errorf("%v: inputType %v is not supported", fname, t)
+ }
+ return r, nil
+}
+
+type rowcol struct{ row, col int }
+
+type playfair struct {
+ char2rc map[byte]rowcol
+ chars [5][5]byte
+}
+
+func (pf playfair) String() (s string) {
+ var b strings.Builder
+ for _, r := range pf.chars {
+ for _, c := range r {
+ fmt.Fprintf(&b, "%2s%v", string(c), pf.char2rc[c])
+ }
+ b.WriteByte("\n"[0])
+ }
+ return b.String()
+}
+
+func (pf playfair) convert(m input) (string, error) {
+ fname := "convert"
+ var o int
+ switch m.t {
+ case msg2encrypt:
+ o = 1
+ case msg2decrypt:
+ o = 4
+ default:
+ return "", fmt.Errorf("%v: only msg2encrypt/msg2decrypt are processed", fname)
+ }
+ b := []byte(m.val)
+ var r strings.Builder
+ for i := 0; i < len(b); i += 2 {
+ x, y := pf.char2rc[b[i]], pf.char2rc[b[i+1]]
+ switch {
+ case x.row == y.row:
+ x.col = (x.col + o) % 5
+ y.col = (y.col + o) % 5
+ case x.col == y.col:
+ x.row = (x.row + o) % 5
+ y.row = (y.row + o) % 5
+ default:
+ x.col, y.col = y.col, x.col
+ }
+ r.Write([]byte{pf.chars[x.row][x.col], pf.chars[y.row][y.col]})
+ }
+ return r.String(), nil
+}
+
+func (pf playfair) Encrypt(s string) (string, error) {
+ msg, err := newInput(msg2encrypt, s)
+ if err != nil {
+ return "", fmt.Errorf("Encrypt: %w", err)
+ }
+ return pf.convert(msg)
+}
+
+func (pf playfair) Decrypt(s string) (string, error) {
+ msg, err := newInput(msg2decrypt, s)
+ if err != nil {
+ return "", fmt.Errorf("Decrypt: %w", err)
+ }
+ return pf.convert(msg)
+}
+
+func chars(start byte, end byte) string {
+ var sb strings.Builder
+ for i := start; i <= end; i++ {
+ sb.WriteByte(i)
+ }
+ return sb.String()
+}
+
+func New(s string) (pf playfair, err error) {
+ fname := "New"
+ pass, err := newInput(passphrase, s)
+ if err != nil {
+ return playfair{}, fmt.Errorf("%v: %w", fname, err)
+ }
+ pf.char2rc = make(map[byte]rowcol, 26)
+ var row, col int
+ for _, b := range []byte(pass.val + chars("a"[0], "z"[0])) {
+ _, ok := pf.char2rc[b]
+ if ok {
+ continue
+ }
+ if b == "i"[0] || b == "j"[0] {
+ for _, k := range []byte("ij") {
+ pf.char2rc[k] = rowcol{row, col}
+ }
+ } else {
+ pf.char2rc[b] = rowcol{row, col}
+ }
+ pf.chars[row][col] = b
+ if col < 4 {
+ col++
+ } else {
+ col = 0
+ row++
+ if row > 4 {
+ break
+ }
+ }
+ }
+ return pf, nil
+}