add: strings and projects
This commit is contained in:
57
19-strings-runes-bytes/01-bytes-runes-strings-basics/main.go
Normal file
57
19-strings-runes-bytes/01-bytes-runes-strings-basics/main.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "hey"
|
||||||
|
bytes := []byte{104, 101, 121}
|
||||||
|
|
||||||
|
// same as: []byte("hey")
|
||||||
|
fmt.Printf(`"hey" as bytes : %d`+"\n", []byte(str))
|
||||||
|
|
||||||
|
// same as: string([]byte{104, 101, 121})
|
||||||
|
fmt.Printf("bytes as string : %q\n", string(bytes))
|
||||||
|
|
||||||
|
// runes are unicode codepoints (numbers)
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf("%c : %[1]d\n", 'h')
|
||||||
|
fmt.Printf("%c : %[1]d\n", 'e')
|
||||||
|
fmt.Printf("%c : %[1]d\n", 'y')
|
||||||
|
|
||||||
|
// a rune literal is typeless
|
||||||
|
// you can put it in any numeric type
|
||||||
|
var (
|
||||||
|
anInt int = 'h'
|
||||||
|
anInt8 int8 = 'h'
|
||||||
|
anInt16 int16 = 'h'
|
||||||
|
anInt32 int32 = 'h'
|
||||||
|
|
||||||
|
// rune literal's default type is: rune
|
||||||
|
// so, you don't need to specify it.
|
||||||
|
// aRune rune = 'h'
|
||||||
|
aRune = 'h'
|
||||||
|
|
||||||
|
// and so on...
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf("rune literals are typeless:\n\t%T %T %T %T %T\n",
|
||||||
|
anInt, anInt8, anInt16, anInt32, aRune)
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// all are the same rune
|
||||||
|
|
||||||
|
// beginning with go 1.13 you can type: 0b0110_1000 instead
|
||||||
|
// fmt.Printf("%q as binary: %08[1]b\n", 0b0110_1000)
|
||||||
|
fmt.Printf("%q in decimal: %[1]d\n", 104)
|
||||||
|
fmt.Printf("%q in binary : %08[1]b\n", 'h')
|
||||||
|
fmt.Printf("%q in hex : 0x%[1]x\n", 0x68)
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var start, stop int
|
||||||
|
|
||||||
|
if args := os.Args[1:]; len(args) == 2 {
|
||||||
|
start, _ = strconv.Atoi(args[0])
|
||||||
|
stop, _ = strconv.Atoi(args[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if start == 0 || stop == 0 {
|
||||||
|
start, stop = 'A', 'Z'
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%-10s %-10s %-10s %-12s\n%s\n",
|
||||||
|
"literal", "dec", "hex", "encoded",
|
||||||
|
strings.Repeat("-", 45))
|
||||||
|
|
||||||
|
for n := start; n <= stop; n++ {
|
||||||
|
fmt.Printf("%-10c %-10[1]d %-10[1]x % -12x\n", n, string(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
EXAMPLE UNICODE BLOCKS
|
||||||
|
|
||||||
|
1 byte
|
||||||
|
------------------------------------------------------------
|
||||||
|
asciiStart = '\u0001' -> 32
|
||||||
|
asciiStop = '\u007f' -> 127
|
||||||
|
|
||||||
|
upperCaseStart = '\u0041' -> 65
|
||||||
|
upperCaseStop = '\u005a' -> 90
|
||||||
|
|
||||||
|
lowerCaseStart = '\u0061' -> 97
|
||||||
|
lowerCaseStop = '\u007a' -> 122
|
||||||
|
|
||||||
|
|
||||||
|
2 bytes
|
||||||
|
------------------------------------------------------------
|
||||||
|
latin1Start = '\u0080' -> 161
|
||||||
|
latin1Stop = '\u00ff' -> 255
|
||||||
|
|
||||||
|
|
||||||
|
3 bytes
|
||||||
|
------------------------------------------------------------
|
||||||
|
dingbatStart = '\u2700' -> 9984
|
||||||
|
dingbatStop = '\u27bf' -> 10175
|
||||||
|
|
||||||
|
|
||||||
|
4 bytes
|
||||||
|
------------------------------------------------------------
|
||||||
|
emojiStart = '\U0001f600' -> 128512
|
||||||
|
emojiStop = '\U0001f64f' -> 128591
|
||||||
|
*/
|
@ -0,0 +1,72 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unicode/utf8"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "Yūgen ☯ 💀"
|
||||||
|
|
||||||
|
// can't change a string
|
||||||
|
// a string is a read-only byte-slice
|
||||||
|
// str[0] = 'N'
|
||||||
|
// str[1] = 'o'
|
||||||
|
|
||||||
|
bytes := []byte(str)
|
||||||
|
|
||||||
|
// can change a byte slice
|
||||||
|
// bytes[0] = 'N'
|
||||||
|
// bytes[1] = 'o'
|
||||||
|
|
||||||
|
str = string(bytes)
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", str)
|
||||||
|
fmt.Printf("\t%d bytes\n", len(str))
|
||||||
|
fmt.Printf("\t%d runes\n", utf8.RuneCountInString(str))
|
||||||
|
fmt.Printf("% x\n", bytes)
|
||||||
|
fmt.Printf("\t%d bytes\n", len(bytes))
|
||||||
|
fmt.Printf("\t%d runes\n", utf8.RuneCount(bytes))
|
||||||
|
|
||||||
|
// fmt.Println()
|
||||||
|
// for i, r := range str {
|
||||||
|
// fmt.Printf("str[%2d] = % -12x = %q\n", i, string(r), r)
|
||||||
|
// }
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf("1st byte : %c\n", str[0]) // ok
|
||||||
|
fmt.Printf("2nd byte : %c\n", str[1]) // not ok
|
||||||
|
fmt.Printf("2nd rune : %s\n", str[1:3]) // ok
|
||||||
|
fmt.Printf("last rune : %s\n", str[len(str)-4:]) // ok
|
||||||
|
|
||||||
|
// disadvantage: each one is 4 bytes
|
||||||
|
runes := []rune(str)
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf("%s\n", str)
|
||||||
|
fmt.Printf("\t%d bytes\n", int(unsafe.Sizeof(runes[0]))*len(runes))
|
||||||
|
fmt.Printf("\t%d runes\n", len(runes))
|
||||||
|
|
||||||
|
fmt.Printf("1st rune : %c\n", runes[0])
|
||||||
|
fmt.Printf("2nd rune : %c\n", runes[1])
|
||||||
|
fmt.Printf("first five : %c\n", runes[:5])
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
word := "öykü"
|
||||||
|
fmt.Printf("%q in runes: %c\n", word, []rune(word))
|
||||||
|
fmt.Printf("%q in bytes: % [1]x\n", word)
|
||||||
|
|
||||||
|
fmt.Printf("%s %s\n", word[:2], []byte{word[0], word[1]}) // ö
|
||||||
|
fmt.Printf("%c\n", word[2]) // y
|
||||||
|
fmt.Printf("%c\n", word[3]) // k
|
||||||
|
fmt.Printf("%s %s\n", word[4:], []byte{word[4], word[5]}) // ü
|
||||||
|
}
|
46
19-strings-runes-bytes/04-rune-decoding/01/main.go
Normal file
46
19-strings-runes-bytes/04-rune-decoding/01/main.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
const text = `Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.
|
||||||
|
|
||||||
|
Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
|
||||||
|
|
||||||
|
Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.`
|
||||||
|
|
||||||
|
r, size := utf8.DecodeRuneInString("öykü")
|
||||||
|
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
|
||||||
|
|
||||||
|
r, size = utf8.DecodeRuneInString("ykü")
|
||||||
|
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
|
||||||
|
|
||||||
|
r, size = utf8.DecodeRuneInString("kü")
|
||||||
|
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
|
||||||
|
|
||||||
|
r, size = utf8.DecodeRuneInString("ü")
|
||||||
|
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
|
||||||
|
|
||||||
|
// for range loop automatically decodes the runes
|
||||||
|
// but it gives you the position of the current rune
|
||||||
|
// instead of its size.
|
||||||
|
|
||||||
|
// for _, r := range text {}
|
||||||
|
for i := 0; i < len(text); {
|
||||||
|
r, size := utf8.DecodeRuneInString(text[i:])
|
||||||
|
fmt.Printf("%c", r)
|
||||||
|
|
||||||
|
i += size
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Let's run this program to see the speed differences.
|
||||||
|
|
||||||
|
benchDecoder 30000000 46.2 ns/op --> BEST
|
||||||
|
benchForRange 30000000 53.0 ns/op --> MEDIOCRE
|
||||||
|
benchConcater 20000000 93.7 ns/op --> WORST
|
||||||
|
*/
|
||||||
|
|
||||||
|
var word = []byte("öykü")
|
||||||
|
|
||||||
|
func decoder(w []byte) {
|
||||||
|
_, size := utf8.DecodeRune(word)
|
||||||
|
copy(w[:size], bytes.ToUpper(w[:size]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func forRange(w []byte) {
|
||||||
|
var size int
|
||||||
|
for i := range string(w) {
|
||||||
|
if i > 0 {
|
||||||
|
size = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(w[:size], bytes.ToUpper(w[:size]))
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalString string
|
||||||
|
|
||||||
|
func concater(w []byte) {
|
||||||
|
runes := []rune(string(w))
|
||||||
|
runes[0] = unicode.ToUpper(runes[0])
|
||||||
|
globalString = string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bench(technique func([]byte)) testing.BenchmarkResult {
|
||||||
|
return testing.Benchmark(func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
technique(word)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("benchDecoder", bench(decoder))
|
||||||
|
fmt.Println("benchForRange", bench(forRange))
|
||||||
|
fmt.Println("benchConcater", bench(concater))
|
||||||
|
}
|
43
19-strings-runes-bytes/04-rune-decoding/02/main.go
Normal file
43
19-strings-runes-bytes/04-rune-decoding/02/main.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
word := []byte("öykü")
|
||||||
|
fmt.Printf("%s = % [1]x\n", word)
|
||||||
|
|
||||||
|
// how to make the first rune uppercase?
|
||||||
|
|
||||||
|
// you need to find the starting and ending position of the first rune
|
||||||
|
|
||||||
|
// 1st way: `for range`
|
||||||
|
// you can't get the runes by range overing a byte slice
|
||||||
|
// first, you need to convert it to a string
|
||||||
|
var size int
|
||||||
|
for i := range string(word) {
|
||||||
|
if i > 0 {
|
||||||
|
size = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2nd way: let's do it using the utf8 package's DecodeRune function
|
||||||
|
_, size = utf8.DecodeRune(word)
|
||||||
|
|
||||||
|
// overwrite the current bytes with the new uppercased bytes
|
||||||
|
copy(word[:size], bytes.ToUpper(word[:size]))
|
||||||
|
|
||||||
|
// to get printed bytes/runes need to be encoded in a string
|
||||||
|
fmt.Printf("%s = % [1]x\n", word)
|
||||||
|
}
|
45
19-strings-runes-bytes/05-internals/main.go
Normal file
45
19-strings-runes-bytes/05-internals/main.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// empty := ""
|
||||||
|
// dump(empty)
|
||||||
|
|
||||||
|
hello := "hello"
|
||||||
|
dump(hello)
|
||||||
|
dump("hello")
|
||||||
|
dump("hello!")
|
||||||
|
|
||||||
|
for i := range hello {
|
||||||
|
dump(hello[i : i+1])
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(string([]byte(hello)))
|
||||||
|
dump(string([]byte(hello)))
|
||||||
|
dump(string([]rune(hello)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringHeader is used by a string value
|
||||||
|
// In practice, you should use: reflect.Header
|
||||||
|
type StringHeader struct {
|
||||||
|
// points to a backing array's item
|
||||||
|
pointer uintptr // where it starts
|
||||||
|
length int // where it ends
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump prints the string header of a string value
|
||||||
|
func dump(s string) {
|
||||||
|
ptr := *(*StringHeader)(unsafe.Pointer(&s))
|
||||||
|
fmt.Printf("%q: %+v\n", s, ptr)
|
||||||
|
}
|
54
20-project-spam-masker/01-step-1/main.go
Normal file
54
20-project-spam-masker/01-step-1/main.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
✅ #1- Get and check the input
|
||||||
|
✅ #2- Create a byte buffer and use it as the output
|
||||||
|
✅ #3- Write input to the buffer as it is and print it
|
||||||
|
✅ #4- Detect the link
|
||||||
|
#5- Mask the link
|
||||||
|
#6- Stop masking when whitespace is detected
|
||||||
|
#7- Put a http:// prefix in front of the masked link
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
args := os.Args[1:]
|
||||||
|
if len(args) != 1 {
|
||||||
|
fmt.Println("gimme somethin' to mask!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
link = "http://"
|
||||||
|
nlink = len(link)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
text = args[0]
|
||||||
|
size = len(text)
|
||||||
|
buf = make([]byte, 0, size)
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
buf = append(buf, text[i])
|
||||||
|
|
||||||
|
// slice the input and look for the link pattern
|
||||||
|
// do not slice it when it goes beyond the input text's capacity
|
||||||
|
if len(text[i:]) >= nlink && text[i:i+nlink] == link {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print out the buffer as text (string)
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
}
|
7
20-project-spam-masker/01-step-1/spam.txt
Normal file
7
20-project-spam-masker/01-step-1/spam.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Hi guys,
|
||||||
|
|
||||||
|
Here is my new spammy webpage http://www.mysuperpage.com <-- This is my website!
|
||||||
|
|
||||||
|
Please click on the link now!!!
|
||||||
|
|
||||||
|
When you click, I will be rich, thanks!
|
80
20-project-spam-masker/02-step-2/main.go
Normal file
80
20-project-spam-masker/02-step-2/main.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
✅ #1- Get and check the input
|
||||||
|
✅ #2- Create a byte buffer and use it as the output
|
||||||
|
✅ #3- Write input to the buffer as it is and print it
|
||||||
|
✅ #4- Detect the link
|
||||||
|
✅ #5- Mask the link
|
||||||
|
✅ #6- Stop masking when whitespace is detected
|
||||||
|
✅ #7- Put a http:// prefix in front of the masked link
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
link = "http://"
|
||||||
|
nlink = len(link)
|
||||||
|
mask = '*'
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
args := os.Args[1:]
|
||||||
|
if len(args) != 1 {
|
||||||
|
fmt.Println("gimme somethin' to mask!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
text = args[0]
|
||||||
|
size = len(text)
|
||||||
|
buf = make([]byte, 0, size)
|
||||||
|
|
||||||
|
in bool
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
// slice the input and look for the link pattern
|
||||||
|
// do not slice it when it goes beyond the input text's capacity
|
||||||
|
if len(text[i:]) >= nlink && text[i:i+nlink] == link {
|
||||||
|
// set the flag: we're in a link! -> "http://....."
|
||||||
|
in = true
|
||||||
|
|
||||||
|
// add the "http://" manually
|
||||||
|
buf = append(buf, link...)
|
||||||
|
|
||||||
|
// jump to the next character after "http://"
|
||||||
|
i += nlink
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the current byte from the input
|
||||||
|
c := text[i]
|
||||||
|
|
||||||
|
// disable the link detection flag
|
||||||
|
// this will prevent masking the rest of the bytes
|
||||||
|
switch c {
|
||||||
|
case ' ', '\t', '\n': // try -> unicode.IsSpace
|
||||||
|
in = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're in the link detection mode (inside the link bytes)
|
||||||
|
// then, mask the current character
|
||||||
|
if in {
|
||||||
|
c = mask
|
||||||
|
}
|
||||||
|
buf = append(buf, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// print out the buffer as text (string)
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
}
|
7
20-project-spam-masker/02-step-2/spam.txt
Normal file
7
20-project-spam-masker/02-step-2/spam.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Hi guys,
|
||||||
|
|
||||||
|
Here is my new spammy webpage http://www.mysuperpage.com <-- This is my website!
|
||||||
|
|
||||||
|
Please click on the link now!!!
|
||||||
|
|
||||||
|
When you click, I will be rich, thanks!
|
68
20-project-spam-masker/03-step-2-no-append/main.go
Normal file
68
20-project-spam-masker/03-step-2-no-append/main.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
✅ #1- Get and check the input
|
||||||
|
✅ #2- Create a byte buffer and use it as the output
|
||||||
|
✅ #3- Write input to the buffer as it is and print it
|
||||||
|
✅ #4- Detect the link
|
||||||
|
✅ #5- Mask the link
|
||||||
|
✅ #6- Stop masking when whitespace is detected
|
||||||
|
✅ #7- Put a http:// prefix in front of the masked link
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
link = "http://"
|
||||||
|
nlink = len(link)
|
||||||
|
mask = '*'
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
args := os.Args[1:]
|
||||||
|
if len(args) != 1 {
|
||||||
|
fmt.Println("gimme somethin' to mask!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
text = args[0]
|
||||||
|
size = len(text)
|
||||||
|
|
||||||
|
// create a byte buffer directly from the string (text)
|
||||||
|
buf = []byte(text)
|
||||||
|
|
||||||
|
in bool
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
// no need to add an artificial http:// prefix
|
||||||
|
// it's already there
|
||||||
|
if len(text[i:]) >= nlink && text[i:i+nlink] == link {
|
||||||
|
in = true
|
||||||
|
i += nlink
|
||||||
|
}
|
||||||
|
|
||||||
|
switch text[i] {
|
||||||
|
case ' ', '\t', '\n': // try -> unicode.IsSpace
|
||||||
|
in = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// when censoring mode: on
|
||||||
|
// directly manipulate the bytes on the buffer
|
||||||
|
if in {
|
||||||
|
buf[i] = mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
}
|
7
20-project-spam-masker/03-step-2-no-append/spam.txt
Normal file
7
20-project-spam-masker/03-step-2-no-append/spam.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Hi guys,
|
||||||
|
|
||||||
|
Here is my new spammy webpage http://www.mysuperpage.com <-- This is my website!
|
||||||
|
|
||||||
|
Please click on the link now!!!
|
||||||
|
|
||||||
|
When you click, I will be rich, thanks!
|
60
20-project-spam-masker/README.md
Normal file
60
20-project-spam-masker/README.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Spam Masker Challenge Tips
|
||||||
|
|
||||||
|
## Rules:
|
||||||
|
|
||||||
|
* You shouldn't use a standard library function.
|
||||||
|
|
||||||
|
* You should only solve the challenge by manipulating the bytes directly.
|
||||||
|
|
||||||
|
* Manipulate the bytes of a string using indexing, slicing, appending etc.
|
||||||
|
|
||||||
|
* Be efficient: Do not use string concat (+ operator).
|
||||||
|
* Instead, create a new byte slice as a buffer from the given string argument.
|
||||||
|
* Then, manipulate it during your program.
|
||||||
|
* And, for once, print that buffer.
|
||||||
|
|
||||||
|
* Mask only links starting with `http://`
|
||||||
|
|
||||||
|
* Don't check for uppercase/lowercase letters
|
||||||
|
|
||||||
|
* The goal is learning how to manipulate bytes in strings, it's not about creating the perfect masker.
|
||||||
|
|
||||||
|
* For example: A spammer can prevent the masker like this (for now this is OK):
|
||||||
|
|
||||||
|
```
|
||||||
|
"Here's my spammy page: hTTp://youth-elixir.com"
|
||||||
|
^^
|
||||||
|
```
|
||||||
|
|
||||||
|
* But, you should catch this:
|
||||||
|
|
||||||
|
```
|
||||||
|
INPUT:
|
||||||
|
Here's my spammy page: http://hehefouls.netHAHAHA see you.
|
||||||
|
|
||||||
|
OUTPUT:
|
||||||
|
Here's my spammy page: http://******************* see you.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Steps:
|
||||||
|
|
||||||
|
1. Check whether there's a command line argument or not. If not, quit from the program with a message.
|
||||||
|
|
||||||
|
2. Create a byte buffer as big as the argument.
|
||||||
|
|
||||||
|
3. Loop and detect the `http://` patterns
|
||||||
|
|
||||||
|
4. Copy the input character by character to the buffer
|
||||||
|
|
||||||
|
5. If you detect `http://` pattern, copy the `http://` first, then copy the `*`s instead of the original link until you see whitespace character.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
INPUT:
|
||||||
|
Here: http://www.mylink.com Click!
|
||||||
|
|
||||||
|
OUTPUT:
|
||||||
|
Here: http://************** Click!
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Print the buffer as a string
|
18
21-project-text-wrapper/README.md
Normal file
18
21-project-text-wrapper/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Text Wrapper Challenge Guideline
|
||||||
|
|
||||||
|
In this project your goal is to mimic the soft text wrapping feature of text editors. For example, when there are 100 characters on a line and if the soft-wrapping is set to 40, the editors cut each line that goes beyond 40 characters and display the rest of the line in the next line instead.
|
||||||
|
|
||||||
|
## EXAMPLE
|
||||||
|
|
||||||
|
Wrap the text for 40 characters in a line. For example, for the following input, the program should print the following output.
|
||||||
|
|
||||||
|
**INPUT:**
|
||||||
|
Hello world, how is it going? It is ok. The weather is beautiful.
|
||||||
|
|
||||||
|
**OUTPUT:**
|
||||||
|
Hello world, how is it going? It is ok.
|
||||||
|
The weather is beautiful.
|
||||||
|
|
||||||
|
## RULES
|
||||||
|
|
||||||
|
* The program should also work with Unicode text. You can find a unicode story in [story.txt](story.txt) file in the current folder. Please use the text in the file and soft-wrap it to 40 characters.
|
38
21-project-text-wrapper/main.go
Normal file
38
21-project-text-wrapper/main.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// For more tutorials: https://blog.learngoprogramming.com
|
||||||
|
//
|
||||||
|
// Copyright © 2018 Inanc Gumus
|
||||||
|
// Learn Go Programming Course
|
||||||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
const text = `Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.
|
||||||
|
|
||||||
|
Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
|
||||||
|
|
||||||
|
Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.`
|
||||||
|
|
||||||
|
const maxWidth = 40
|
||||||
|
|
||||||
|
var lw int // line width
|
||||||
|
|
||||||
|
for _, r := range text {
|
||||||
|
fmt.Printf("%c", r)
|
||||||
|
|
||||||
|
switch lw++; {
|
||||||
|
case lw > maxWidth && r != '\n' && unicode.IsSpace(r):
|
||||||
|
fmt.Println()
|
||||||
|
fallthrough
|
||||||
|
case r == '\n':
|
||||||
|
lw = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
5
21-project-text-wrapper/story.txt
Normal file
5
21-project-text-wrapper/story.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.
|
||||||
|
|
||||||
|
Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
|
||||||
|
|
||||||
|
Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.
|
Reference in New Issue
Block a user