add: strings and projects

This commit is contained in:
Inanc Gumus
2019-04-03 19:33:36 +03:00
parent 6e931e503b
commit 453774b601
17 changed files with 733 additions and 0 deletions

View 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)
}

View File

@ -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
*/

View File

@ -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]}) // ü
}

View 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()
}

View File

@ -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))
}

View 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)
}

View 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)
}

View 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))
}

View 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!

View 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))
}

View 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!

View 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))
}

View 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!

View 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

View 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.

View 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()
}

View 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.