diff --git a/14-arrays/01-whats-an-array/main.go b/14-arrays/01-whats-an-array/main.go new file mode 100644 index 0000000..91d6b49 --- /dev/null +++ b/14-arrays/01-whats-an-array/main.go @@ -0,0 +1,25 @@ +package main + +import "fmt" + +func main() { + var ( + myAge byte + herAge byte + + // uncomment the code below and observe the error + // wrongDeclaration [-1]byte + + zero [0]byte + ages [2]byte + agesExp [2 + 1]byte + + tags [5]string + ) + + fmt.Printf("%d %d\n", myAge, herAge) + fmt.Printf("%#v\n", zero) + fmt.Printf("%#v\n", ages) + fmt.Printf("%#v\n", agesExp) + fmt.Printf("%#v\n", tags) +} diff --git a/14-arrays/02-examples-1-hipsters-love-bookstore/main.go b/14-arrays/02-examples-1-hipsters-love-bookstore/main.go new file mode 100644 index 0000000..64dbc70 --- /dev/null +++ b/14-arrays/02-examples-1-hipsters-love-bookstore/main.go @@ -0,0 +1,33 @@ +package main + +// STORY: +// Hipster's Love store publishes limited books +// twice a year. +// +// The number of books they publish is fixed at 4. + +// So, let's create a 4 elements string array for the books. + +const ( + winter = 1 + summer = 3 + yearly = winter + summer +) + +func main() { + // var books [4]string + // var books [1 + 3]string + var books [yearly]string + + books[0] = "Kafka's Revenge" + books[1] = "Stay Golden" + books[2] = "Everythingship" + books[3] += books[0] + " 2nd Edition" + + // Go compiler can catch indexing errors when constant is used + // books[4] = "Neverland" + + // Go compiler cannot catch indexing errors when non-constant is used + // i := 4 + // books[i] = "Neverland" +} diff --git a/14-arrays/03-examples-2-hipsters-love-bookstore/main.go b/14-arrays/03-examples-2-hipsters-love-bookstore/main.go new file mode 100644 index 0000000..2a39ad1 --- /dev/null +++ b/14-arrays/03-examples-2-hipsters-love-bookstore/main.go @@ -0,0 +1,74 @@ +package main + +import "fmt" + +// STORY: +// Hipster's Love store publishes limited books +// twice a year. +// +// The number of books they publish is fixed at 4. + +// So, let's create a 4 elements string array for the books. + +const ( + winter = 1 + summer = 3 + yearly = winter + summer +) + +func main() { + var books [yearly]string + + books[0] = "Kafka's Revenge" + books[1] = "Stay Golden" + books[2] = "Everythingship" + books[3] += books[0] + " 2nd Edition" + fmt.Printf("books : %#v\n", books) + + // ------------------------------------ + // SEASONAL BOOKS + // ------------------------------------ + + var ( + wBooks [winter]string + sBooks [summer]string + ) + + // assign the first book as the wBook's first book + wBooks[0] = books[0] + + // assign all the books starting from the 2nd book + // to sBooks array + + // sBooks[0] = books[1] + // sBooks[1] = books[2] + // sBooks[2] = books[3] + + // for i := 0; i < len(sBooks); i++ { + // sBooks[i] = books[i+1] + // } + + for i := range sBooks { + sBooks[i] = books[i+1] + } + + fmt.Printf("\nwinter : %#v\n", wBooks) + fmt.Printf("\nsummer : %#v\n", sBooks) + + // ------------------------------------ + // Let's print the published books + // ------------------------------------ + + // equal to: [4]bool + var published [len(books)]bool + + published[0] = true + published[len(books)-1] = true + + fmt.Println("\nPublished Books:") + for i, ok := range published { + if ok { + fmt.Printf("+ %s\n", books[i]) + } + } +} diff --git a/14-arrays/04-array-literal/main.go b/14-arrays/04-array-literal/main.go new file mode 100644 index 0000000..85bffad --- /dev/null +++ b/14-arrays/04-array-literal/main.go @@ -0,0 +1,57 @@ +package main + +import "fmt" + +// STORY: +// Hipster's Love store publishes limited books +// twice a year. +// +// The number of books they publish is fixed at 4. + +// So, let's create a 4 elements string array for the books. + +const ( + winter = 1 + summer = 3 + yearly = winter + summer +) + +func main() { + // ALTERNATIVE: + // Use this only when you don't know about the elements beforehand + // var books [yearly]string + + books := [yearly]string{ + "Kafka's Revenge", + "Stay Golden", + "Everythingship", + "Kafka's Revenge 2nd Edition", + } + fmt.Printf("books : %#v\n", books) + + // var ( + // wBooks [winter]string + // sBooks [summer]string + // ) + + // wBooks[0] = books[0] + + // for i := range sBooks { + // sBooks[i] = books[i+1] + // } + + // fmt.Printf("\nwinter : %#v\n", wBooks) + // fmt.Printf("\nsummer : %#v\n", sBooks) + + // var published [len(books)]bool + + // published[0] = true + // published[len(books)-1] = true + + // fmt.Println("\nPublished Books:") + // for i, ok := range published { + // if ok { + // fmt.Printf("+ %s\n", books[i]) + // } + // } +} diff --git a/14-arrays/05-compare/main.go b/14-arrays/05-compare/main.go new file mode 100644 index 0000000..b905e0a --- /dev/null +++ b/14-arrays/05-compare/main.go @@ -0,0 +1,42 @@ +package main + +import "fmt" + +// STORY: +// You want to compare two bookcases, +// whether they're equal or not. + +func main() { + // When comparing two arrays, + // Their types should be identical + + var ( + // equal (types + elements are identical):: + blue = [3]int{6, 9, 3} + red = [3]int{6, 9, 3} + + // equal (types + elements are identical): + // blue = [...]int{6, 9, 3} + // red = [3]int{6, 9, 3} + + // not equal (element ordering are different): + // blue = [3]int{6, 9, 3} + // red = [3]int{3, 9, 6} + + // not equal (the last elements are not equal): + // blue = [3]int{6, 9} + // red = [3]int{6, 9, 3} + + // not comparable (type mismatch: length): + // blue = [3]int{6, 9, 3} + // red = [5]int{6, 9, 3} + + // not comparable (type mismatch: element type): + // blue = [3]int64{6, 9, 3} + // red = [3]int{6, 9, 3} + ) + fmt.Printf("blue bookcase : %v\n", blue) + fmt.Printf("red bookcase : %v\n", red) + + fmt.Println("Are they equal?", blue == red) +} diff --git a/14-arrays/06-compare-unnamed/main.go b/14-arrays/06-compare-unnamed/main.go new file mode 100644 index 0000000..5722aa4 --- /dev/null +++ b/14-arrays/06-compare-unnamed/main.go @@ -0,0 +1,28 @@ +package main + +import "fmt" + +// STORY: +// You want to compare two bookcases, +// whether they're equal or not. + +func main() { + type ( + bookcase [5]int + cabinet [5]int + ) + + blue := bookcase{6, 9, 3, 2, 1} + red := cabinet{6, 9, 3, 2, 1} + + fmt.Print("Are they equal? ") + + if cabinet(blue) == red { + fmt.Println("✅") + } else { + fmt.Println("❌") + } + + fmt.Printf("blue: %#v\n", blue) + fmt.Printf("red : %#v\n", bookcase(red)) +} diff --git a/14-arrays/README.md b/14-arrays/README.md deleted file mode 100644 index 58094c8..0000000 --- a/14-arrays/README.md +++ /dev/null @@ -1 +0,0 @@ -This section is in progress. I'm working hard to update the course all the time. Hold on! \ No newline at end of file diff --git a/14-arrays/_experimental/11-avg/main.go b/14-arrays/_experimental/11-avg/main.go new file mode 100644 index 0000000..f322a8e --- /dev/null +++ b/14-arrays/_experimental/11-avg/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + args := os.Args[1:] + + var ( + sum float64 + nums [5]float64 + ) + + for i, v := range args { + n, err := strconv.ParseFloat(v, 64) + if err != nil { + continue + } + + nums[i] = n + sum += n + } + + fmt.Println("Your numbers :", nums) + fmt.Println("Average :", sum/float64(len(nums))) +} + +// EXERCISE +// Average calculator has a flaw. +// It divides the numbers by the length of the array. +// This results in wrong calculatio. +// +// For example: +// +// When you run it like this: +// go run main.go 1 5 +// It tells you that the average number is: +// 1.2 +// Whereas, actually, it should be 3. +// +// Fix this error. +// So that, it will output 3 instead of 1.2 +// +// Do not change the length of the array. diff --git a/14-arrays/_experimental/11-avg/solution-slices/main.go b/14-arrays/_experimental/11-avg/solution-slices/main.go new file mode 100644 index 0000000..4bf06b7 --- /dev/null +++ b/14-arrays/_experimental/11-avg/solution-slices/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + args := os.Args[1:] + + var ( + sum float64 + nums []float64 + ) + + for _, v := range args { + n, err := strconv.ParseFloat(v, 64) + if err != nil { + continue + } + + nums = append(nums, n) + sum += n + } + + fmt.Println("Your numbers:", nums) + fmt.Println("Average:", sum/float64(len(nums))) +} diff --git a/14-arrays/_experimental/11-avg/solution/main.go b/14-arrays/_experimental/11-avg/solution/main.go new file mode 100644 index 0000000..8fde9d0 --- /dev/null +++ b/14-arrays/_experimental/11-avg/solution/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + args := os.Args[1:] + + var ( + sum float64 + nums [5]float64 + total float64 + ) + + for i, v := range args { + n, err := strconv.ParseFloat(v, 64) + if err != nil { + continue + } + + total++ + nums[i] = n + sum += n + } + + fmt.Println("Your numbers:", nums) + fmt.Printf("(Only %g of them were valid)\n", total) + fmt.Println("Average:", sum/total) +} diff --git a/14-arrays/_experimental/11-sort/main.go b/14-arrays/_experimental/11-sort/main.go new file mode 100644 index 0000000..5c34e31 --- /dev/null +++ b/14-arrays/_experimental/11-sort/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +const usage = `Sorry. Go arrays are fixed. +So, for now, I'm only supporting sorting %d numbers... +` + +func main() { + args := os.Args[1:] + + var nums [5]float64 + + if len(args) > 5 { + fmt.Printf(usage, len(nums)) + return + } + + for i, v := range args { + n, err := strconv.ParseFloat(v, 64) + if err != nil { + continue + } + + nums[i] = n + } + + for range nums { + for i, v := range nums { + if i < len(nums)-1 && v > nums[i+1] { + nums[i], nums[i+1] = nums[i+1], nums[i] + } + } + } + + fmt.Println(nums) +} diff --git a/14-arrays/_experimental/11-word-finder/main.go b/14-arrays/_experimental/11-word-finder/main.go new file mode 100644 index 0000000..ec6c0b3 --- /dev/null +++ b/14-arrays/_experimental/11-word-finder/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "os" + "strings" +) + +const corpus = `lazy cat jumps again and again and again... +since she is very excited and happy.` + +func main() { + query := os.Args[1:] + words := strings.Fields(corpus) + + filter := [...]string{ + "and", "or", "the", "is", "since", "very", + } + +queries: + for _, q := range query { + for _, v := range filter { + if q == v { + continue queries + } + } + + for i, w := range words { + if q == w { + fmt.Printf("#%-2d: %q\n", i+1, w) + } + } + } +} diff --git a/14-arrays/_experimental/_14-arrays/01-what/01-without-arrays/main.go b/14-arrays/_experimental/_14-arrays/01-what/01-without-arrays/main.go new file mode 100644 index 0000000..971b653 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/01-what/01-without-arrays/main.go @@ -0,0 +1,28 @@ +// 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() { + jake := "jake" + joe := "joe" + lee := "lee" + lina := "lina" + + fmt.Println(jake) + fmt.Println(joe) + fmt.Println(lee) + fmt.Println(lina) + + // for each name + // you need to declare a variable + // and then you need to print it + // + // but by using an array, you don't need to do that +} diff --git a/14-arrays/_experimental/_14-arrays/01-what/02-with-arrays/main.go b/14-arrays/_experimental/_14-arrays/01-what/02-with-arrays/main.go new file mode 100644 index 0000000..cc79c94 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/01-what/02-with-arrays/main.go @@ -0,0 +1,27 @@ +// 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() { + // instead of storing the names in variables, + // you can use an array to store all of the names + // in a single variable + + // names := [3]string{"jake", "joe", "lee"} + names := [4]string{"jake", "joe", "lee", "lina"} + + // doing so allows you to loop over the names + // and print each one of them + // + // you can't do this without arrays + for _, name := range names { + fmt.Println(name) + } +} diff --git a/14-arrays/_experimental/_14-arrays/02-array-literals/01/main.go b/14-arrays/_experimental/_14-arrays/02-array-literals/01/main.go new file mode 100644 index 0000000..e613271 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/02-array-literals/01/main.go @@ -0,0 +1,18 @@ +// 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() { + ages := [3]int{15, 30, 25} + + for _, age := range ages { + fmt.Println(age) + } +} diff --git a/14-arrays/_experimental/_14-arrays/02-array-literals/02-fixed-size/main.go b/14-arrays/_experimental/_14-arrays/02-array-literals/02-fixed-size/main.go new file mode 100644 index 0000000..6187189 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/02-array-literals/02-fixed-size/main.go @@ -0,0 +1,18 @@ +// 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 + +func main() { + // uncomment the code below to observe the error + + // ages := [3]int{15, 30, 25, 44} + + // for _, age := range ages { + // fmt.Println(age) + // } +} diff --git a/14-arrays/_experimental/_14-arrays/02-array-literals/03-constant-expressions/main.go b/14-arrays/_experimental/_14-arrays/02-array-literals/03-constant-expressions/main.go new file mode 100644 index 0000000..520de38 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/02-array-literals/03-constant-expressions/main.go @@ -0,0 +1,39 @@ +// 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() { + // you cannot use variables + // when setting the length of an array + + // length := 3 + + // but, you can use constants and constant expressions + const length = 3 * 2 + + ages := [3 * 2]int{15, 30, 25} + + for _, age := range ages { + fmt.Println(age) + } +} + +// EXERCISE: +// Try to put the `length` constant +// in place of `3 * 2` above. + +// EXERCISE: +// Try to put the `length` variable +// in place of `3 * 2` above. +// +// And observe the error. +// +// To do that, you need comment-out +// the length constant first. diff --git a/14-arrays/_experimental/_14-arrays/02-array-literals/04-element-type/main.go b/14-arrays/_experimental/_14-arrays/02-array-literals/04-element-type/main.go new file mode 100644 index 0000000..3b008ba --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/02-array-literals/04-element-type/main.go @@ -0,0 +1,51 @@ +// 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 + +func main() { + // ----- + // you cannot use incompatible values + // than the array's element type + // + // uncomment the code parts below one by one + // then observe the errors + // ----- + + // for example you can't use a string + // ages := [3]int{15, 30, "hi"} + + // ----- + + // or a float64, etc... + // ages := [3]int{15, 30, 5.5} + + // ----- + + // of course this is valid, since it's untyped + // 5. becomes 5 (int) + // ages := [3]int{15, 30, 5.} + + // ----- + + // for _, age := range ages { + // fmt.Println(age) + // } +} + +// EXERCISE: +// Try to put the `length` constant +// in place of `3 * 2` above. + +// EXERCISE: +// Try to put the `length` variable +// in place of `3 * 2` above. +// +// And observe the error. +// +// To do that, you need comment-out +// the length constant first. diff --git a/14-arrays/_experimental/_14-arrays/02-array-literals/05-ellipsis/main.go b/14-arrays/_experimental/_14-arrays/02-array-literals/05-ellipsis/main.go new file mode 100644 index 0000000..c12af56 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/02-array-literals/05-ellipsis/main.go @@ -0,0 +1,20 @@ +// 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() { + ages := [...]int{15, 30, 25} + // equals to: + // ages := [3]int{15, 30, 25} + + for _, age := range ages { + fmt.Println(age) + } +} diff --git a/14-arrays/_experimental/_14-arrays/03-array-type/main.go b/14-arrays/_experimental/_14-arrays/03-array-type/main.go new file mode 100644 index 0000000..06ec9ff --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/03-array-type/main.go @@ -0,0 +1,22 @@ +// 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() { + ages := [3]int{15, 30, 25} + + fmt.Printf("%T\n", ages) // [3]int + fmt.Printf("%T\n", [...]int{15, 30, 25}) // [3]int + + fmt.Printf("%T\n", [2]int{15, 30}) // [2]int + + fmt.Printf("%T\n", [1]string{"hi"}) // [1]string + fmt.Printf("%T\n", [...]float64{3.14, 6.28}) // [2]float64 +} diff --git a/14-arrays/_experimental/_14-arrays/04-zero-values/01-uninitialized-array/main.go b/14-arrays/_experimental/_14-arrays/04-zero-values/01-uninitialized-array/main.go new file mode 100644 index 0000000..6d3fabb --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/04-zero-values/01-uninitialized-array/main.go @@ -0,0 +1,16 @@ +// 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() { + var ages [3]int + + fmt.Println(ages) +} diff --git a/14-arrays/_experimental/_14-arrays/04-zero-values/02-partially-initialized-array/main.go b/14-arrays/_experimental/_14-arrays/04-zero-values/02-partially-initialized-array/main.go new file mode 100644 index 0000000..e35abbe --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/04-zero-values/02-partially-initialized-array/main.go @@ -0,0 +1,16 @@ +// 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() { + ages := [3]int{1} + + fmt.Println(ages) +} diff --git a/14-arrays/_experimental/_14-arrays/04-zero-values/03-ellipsis/main.go b/14-arrays/_experimental/_14-arrays/04-zero-values/03-ellipsis/main.go new file mode 100644 index 0000000..1a1a500 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/04-zero-values/03-ellipsis/main.go @@ -0,0 +1,18 @@ +// 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() { + names := [...]string{ + "lina", "bob", "jane", + } + + fmt.Printf("%#v\n", names) +} diff --git a/14-arrays/_experimental/_14-arrays/04-zero-values/04-without-ellipsis/main.go b/14-arrays/_experimental/_14-arrays/04-zero-values/04-without-ellipsis/main.go new file mode 100644 index 0000000..2b62719 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/04-zero-values/04-without-ellipsis/main.go @@ -0,0 +1,18 @@ +// 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() { + names := [5]string{ + "lina", "bob", "jane", + } + + fmt.Printf("%#v\n", names) +} diff --git a/14-arrays/_experimental/_14-arrays/04-zero-values/05-more-examples/main.go b/14-arrays/_experimental/_14-arrays/04-zero-values/05-more-examples/main.go new file mode 100644 index 0000000..11a0ce3 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/04-zero-values/05-more-examples/main.go @@ -0,0 +1,21 @@ +// 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() { + names := [5]string{ + "lina", "bob", "jane", + } + + fmt.Printf("%#v\n", names) + + temperatures := [10]float64{1.5, 2.5} + fmt.Printf("%#v\n", temperatures) +} diff --git a/14-arrays/_experimental/_14-arrays/05-array-operations/01-getting-length/main.go b/14-arrays/_experimental/_14-arrays/05-array-operations/01-getting-length/main.go new file mode 100644 index 0000000..94e87ce --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/05-array-operations/01-getting-length/main.go @@ -0,0 +1,35 @@ +// 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() { + ages := [2]int{15, 20} + + // i can directly use `len` + fmt.Println(len(ages)) // 2 + + // i can also assign its result to a variable + l := len(ages) + fmt.Println(l) // 2 + + // let's print the length of a few arrays + l = len([1]bool{true}) // 1 + fmt.Println(l) + + l = len([3]string{"lina", "james", "joe"}) // 3 + fmt.Println(l) + + // this array doesn't initialize any elements + // but its length is still 5 + // whether the elements are initialized or not + l = len([5]int{}) + fmt.Println(l) // 5 + fmt.Println([5]int{}) +} diff --git a/14-arrays/_experimental/_14-arrays/05-array-operations/02-getting-elements/main.go b/14-arrays/_experimental/_14-arrays/05-array-operations/02-getting-elements/main.go new file mode 100644 index 0000000..84673b2 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/05-array-operations/02-getting-elements/main.go @@ -0,0 +1,32 @@ +// 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() { + ages := [2]int{15, 20} + + // WRONG (try it): + // fmt.Println(ages[-1]) + + fmt.Println("1st item:", ages[0]) + fmt.Println("2nd item:", ages[1]) + + // fmt.Println("2nd item:", ages[2]) + + // fmt.Println(ages[len(ages)]) + // here, `len(ages) - 1` equals to 1 + fmt.Println("last item:", ages[len(ages)-1]) + + // let's display the indexes and the items + // of the array + for i, v := range ages { + fmt.Printf("index: %d, value: %d\n", i, v) + } +} diff --git a/14-arrays/_experimental/_14-arrays/05-array-operations/03-getting-elements/main.go b/14-arrays/_experimental/_14-arrays/05-array-operations/03-getting-elements/main.go new file mode 100644 index 0000000..f3a69c1 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/05-array-operations/03-getting-elements/main.go @@ -0,0 +1,49 @@ +// 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() { + ages := [2]int{15, 20} + + ages[0] = 6 + ages[1] *= 3 + + fmt.Println(ages) + + // increase the last element by 1 + ages[1]++ + ages[len(ages)-1]++ + + fmt.Println(ages) + + // v is a copy + for _, v := range ages { + // it's like: + // v = ages[0] + // v++ + + // and: + // v = ages[1] + // v++ + + v++ + } + + fmt.Println(ages) + + // you don't need to use blank-identifier for the value + // for i, _ := range ages { + + for i := range ages { + ages[i]++ + } + + fmt.Println(ages) +} diff --git a/14-arrays/_experimental/_14-arrays/06-comparing-arrays/01-equal-arrays/main.go b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/01-equal-arrays/main.go new file mode 100644 index 0000000..440d2fe --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/01-equal-arrays/main.go @@ -0,0 +1,30 @@ +// 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() { + a := [3]int{6, 9, 3} + b := [3]int{6, 9, 3} + + if a == b { + fmt.Println("they're equal!") + + // they're comparable + // since their types are identical + fmt.Printf("1st array's type is %T\n", a) + fmt.Printf("2nd array's type is %T\n", b) + + // go compares arrays like this + // it compares the elements one by one + fmt.Println(a[0] == b[0]) + fmt.Println(a[1] == b[1]) + fmt.Println(a[2] == b[2]) + } +} diff --git a/14-arrays/_experimental/_14-arrays/06-comparing-arrays/02-not-equal-arrays/main.go b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/02-not-equal-arrays/main.go new file mode 100644 index 0000000..d88a685 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/02-not-equal-arrays/main.go @@ -0,0 +1,39 @@ +// 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() { + a := [3]int{6, 9, 3} + b := [3]int{3, 9, 6} + + if a == b { + fmt.Println("they're equal!") + } else { + fmt.Println("they're not equal! a==b?", a == b) + + // but, they're comparable + // since their types are identical + fmt.Printf("1st array's type is %T\n", a) + fmt.Printf("2nd array's type is %T\n", b) + + // go compares arrays like this + // it compares the elements one by one + fmt.Println(a[0] == b[0]) // false + fmt.Println(a[1] == b[1]) // true + fmt.Println(a[2] == b[2]) // false + + // actually Go will quit comparing these arrays + // once it sees unequal items + // + // so, it will stop the comparison (short-circuit) + // when it sees the first item is false + // and it will return false + } +} diff --git a/14-arrays/_experimental/_14-arrays/06-comparing-arrays/03-comparability/main.go b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/03-comparability/main.go new file mode 100644 index 0000000..b243337 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/03-comparability/main.go @@ -0,0 +1,24 @@ +// 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 + +func main() { + // these two arrays not comparable + // their types are different + + // uncomment all the code below and observe the error + + // a := [3]int{6, 9, 3} + // b := [2]int{6, 9} + + // you can't ask this question + + // if a == b { + // fmt.Println("they're equal!") + // } +} diff --git a/14-arrays/_experimental/_14-arrays/06-comparing-arrays/04-example/main.go b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/04-example/main.go new file mode 100644 index 0000000..dd197a9 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/06-comparing-arrays/04-example/main.go @@ -0,0 +1,26 @@ +// 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() { + a := [2]string{"jane", "lina"} + b := [2]string{"jane", "lina"} + c := [2]string{"mike", "joe"} + + fmt.Println("a==b?", a == b) // equal + fmt.Println("a==c?", a == c) // not equal + + // cannot compare + d := [3]string{"jane", "lina"} + // fmt.Println("c==d?", c == d) + + fmt.Printf("type of c is %T\n", c) + fmt.Printf("type of d is %T\n", d) +} diff --git a/14-arrays/_experimental/_14-arrays/07-unnamed-vs-named-types/main.go b/14-arrays/_experimental/_14-arrays/07-unnamed-vs-named-types/main.go new file mode 100644 index 0000000..a030fe1 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/07-unnamed-vs-named-types/main.go @@ -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" + +func main() { + type ( + A [3]int + B [3]int + ) + + x := A{1, 2, 3} + y := B{1, 2, 3} + z := [3]int{1, 2, 3} + + fmt.Printf("x's type: %T\n", x) // named type : main.A + fmt.Printf("y's type: %T\n", y) // named type : main.B + fmt.Printf("z's type: %T\n", z) // unnamed type: [3]int + + // cannot compare different named types + // fmt.Println("x==y?", x == y) + + // can convert between identical types + fmt.Println("x==y?", x == A(y)) + fmt.Println("x==y?", B(x) == y) + + fmt.Printf("x's type : %T\n", x) + fmt.Printf("A(y)'s type: %T\n", A(y)) + + // can compare to unnamed types + fmt.Println("x==z?", x == z) +} diff --git a/14-arrays/_experimental/_14-arrays/08-assigning-arrays/01-assigning-arrays/main.go b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/01-assigning-arrays/main.go new file mode 100644 index 0000000..b28c83b --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/01-assigning-arrays/main.go @@ -0,0 +1,24 @@ +// 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() { + a := [3]int{5, 4, 7} + + // this assignment will create a new array value + // and then it will be stored in the b variable + b := a + + fmt.Println("a =>", a) + fmt.Println("b =>", b) + + // they're equal, they're clones + fmt.Println("a==b?", a == b) +} diff --git a/14-arrays/_experimental/_14-arrays/08-assigning-arrays/02-arrays-are-value-types/main.go b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/02-arrays-are-value-types/main.go new file mode 100644 index 0000000..aa36f54 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/02-arrays-are-value-types/main.go @@ -0,0 +1,27 @@ +// 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() { + a := [3]int{5, 4, 7} + b := a + + // this will only change the 'a' array + a[0] = 10 + + fmt.Println("a =>", a) + fmt.Println("b =>", b) + + // this will only change the 'b' array + b[1] = 20 + + fmt.Println("a =>", a) + fmt.Println("b =>", b) +} diff --git a/14-arrays/_experimental/_14-arrays/08-assigning-arrays/03-assigning-arrays2/main.go b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/03-assigning-arrays2/main.go new file mode 100644 index 0000000..e558aa7 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/03-assigning-arrays2/main.go @@ -0,0 +1,23 @@ +// 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() { + a := [3]int{5, 4, 7} + b := [3]int{6, 9, 3} + + b = a + + fmt.Println("b =>", b) + + b[0] = 100 + fmt.Println("a =>", a) + fmt.Println("b =>", b) +} diff --git a/14-arrays/_experimental/_14-arrays/08-assigning-arrays/04-cannot-assign-arrays/main.go b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/04-cannot-assign-arrays/main.go new file mode 100644 index 0000000..20c3a03 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/04-cannot-assign-arrays/main.go @@ -0,0 +1,23 @@ +// 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 + +func main() { + // you can't assign the array 'a' to the array 'b' + // a's type is [2]int whereas b's type is [3]int + + // when two values are not comparable, + // then they're not assignable either + + // uncomment and observe the error + + // a := [2]int{5, 4} + // b := [3]int{6, 9, 3} + + // b = a +} diff --git a/14-arrays/_experimental/_14-arrays/08-assigning-arrays/05-passing-to-funcs/main.go b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/05-passing-to-funcs/main.go new file mode 100644 index 0000000..7ed609e --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/08-assigning-arrays/05-passing-to-funcs/main.go @@ -0,0 +1,31 @@ +// 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() { + a := [3]int{10, 4, 7} + + // like the assignment passing an array to a function + // creates a copy of the array + fmt.Println("a (before) =>", a) + incr(a) + fmt.Println("a (after) =>", a) +} + +// inside the function +// the passed array 'a' is a new copy (a clone) +// it's not the original one +func incr(a [3]int) { + // this only changes the copy of the passed array + a[1]++ + + // this prints the copied array not the original one + fmt.Println("a (inside) =>", a) +} diff --git a/14-arrays/_experimental/_14-arrays/09-multi-dimensional-arrays/main.go b/14-arrays/_experimental/_14-arrays/09-multi-dimensional-arrays/main.go new file mode 100644 index 0000000..108dc0f --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/09-multi-dimensional-arrays/main.go @@ -0,0 +1,49 @@ +// 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() { + // [LENGTH]TYPE { + // ELEMENTS + // } + + // LENGTH=2 and TYPE=[2]int + + // nums := [2][2]int{ + // [2]int{2, 4}, + // [2]int{1, 3}, + // } + + // code below is the same as the code above + nums := [2][2]int{ + {2, 4}, + {1, 3}, + } + + fmt.Println("nums =", nums) + fmt.Println("nums[0] =", nums[0]) + fmt.Println("nums[1] =", nums[1]) + + fmt.Println("nums[0][0] =", nums[0][0]) + fmt.Println("nums[0][1] =", nums[0][1]) + fmt.Println("nums[1][0] =", nums[1][0]) + fmt.Println("nums[1][1] =", nums[1][1]) + + fmt.Println("len(nums) =", len(nums)) + fmt.Println("len(nums[0]) =", len(nums[0])) + fmt.Println("len(nums[1]) =", len(nums[1])) + + for i, array := range nums { + for j, n := range array { + // nums[i][j] = number + fmt.Printf("nums[%d][%d] = %d\n", i, j, n) + } + } +} diff --git a/14-arrays/_experimental/_14-arrays/10-keyed-elements/01-unkeyed/main.go b/14-arrays/_experimental/_14-arrays/10-keyed-elements/01-unkeyed/main.go new file mode 100644 index 0000000..f04c477 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/10-keyed-elements/01-unkeyed/main.go @@ -0,0 +1,20 @@ +// 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() { + rates := [3]float64{ + 0.5, + 2.5, + 1.5, + } + + fmt.Println(rates) +} diff --git a/14-arrays/_experimental/_14-arrays/10-keyed-elements/02-keyed/main.go b/14-arrays/_experimental/_14-arrays/10-keyed-elements/02-keyed/main.go new file mode 100644 index 0000000..e74f912 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/10-keyed-elements/02-keyed/main.go @@ -0,0 +1,28 @@ +// 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() { + rates := [3]float64{ + 0: 0.5, // index: 0 + 1: 2.5, // index: 1 + 2: 1.5, // index: 2 + } + + fmt.Println(rates) + + // above array literal equals to this: + // + // rates := [3]float64{ + // 0.5, + // 2.5, + // 1.5, + // } +} diff --git a/14-arrays/_experimental/_14-arrays/10-keyed-elements/03-keyed-order/main.go b/14-arrays/_experimental/_14-arrays/10-keyed-elements/03-keyed-order/main.go new file mode 100644 index 0000000..122d389 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/10-keyed-elements/03-keyed-order/main.go @@ -0,0 +1,28 @@ +// 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() { + rates := [3]float64{ + 1: 2.5, // index: 1 + 0: 0.5, // index: 0 + 2: 1.5, // index: 2 + } + + fmt.Println(rates) + + // above array literal equals to this: + // + // rates := [3]float64{ + // 0.5, + // 2.5, + // 1.5, + // } +} diff --git a/14-arrays/_experimental/_14-arrays/10-keyed-elements/04-keyed-auto-initialize/main.go b/14-arrays/_experimental/_14-arrays/10-keyed-elements/04-keyed-auto-initialize/main.go new file mode 100644 index 0000000..5fa9b54 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/10-keyed-elements/04-keyed-auto-initialize/main.go @@ -0,0 +1,28 @@ +// 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() { + rates := [3]float64{ + // index 0 empty + // index 1 empty + 2: 1.5, // index: 2 + } + + fmt.Println(rates) + + // above array literal equals to this: + // + // rates := [3]float64{ + // 0., + // 0., + // 1.5, + // } +} diff --git a/14-arrays/_experimental/_14-arrays/10-keyed-elements/05-keyed-auto-initialize-ellipsis/main.go b/14-arrays/_experimental/_14-arrays/10-keyed-elements/05-keyed-auto-initialize-ellipsis/main.go new file mode 100644 index 0000000..a51b1fc --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/10-keyed-elements/05-keyed-auto-initialize-ellipsis/main.go @@ -0,0 +1,36 @@ +// 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() { + // ellipsis (...) below calculates the length of the + // array automatically + rates := [...]float64{ + // index 0 empty + // index 1 empty + // index 2 empty + // index 3 empty + // index 4 empty + 5: 1.5, // index: 5 + } + + fmt.Println(rates) + + // above array literal equals to this: + // + // rates := [6]float64{ + // 0., + // 0., + // 0., + // 0., + // 0., + // 1.5, + // } +} diff --git a/14-arrays/_experimental/_14-arrays/10-keyed-elements/06-keyed-and-unkeyed/main.go b/14-arrays/_experimental/_14-arrays/10-keyed-elements/06-keyed-and-unkeyed/main.go new file mode 100644 index 0000000..76839a7 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/10-keyed-elements/06-keyed-and-unkeyed/main.go @@ -0,0 +1,34 @@ +// 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() { + rates := [...]float64{ + // index 1 to 4 empty + + 5: 1.5, // index: 5 + 2.5, // index: 6 + 0: 0.5, // index: 0 + } + + fmt.Println(rates) + + // above array literal equals to this: + // + // rates := [7]float64{ + // 0.5, + // 0., + // 0., + // 0., + // 0., + // 1.5, + // 2.5, + // } +} diff --git a/14-arrays/_experimental/_14-arrays/11-project-xratio/01-without-keys/main.go b/14-arrays/_experimental/_14-arrays/11-project-xratio/01-without-keys/main.go new file mode 100644 index 0000000..3b5865a --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/11-project-xratio/01-without-keys/main.go @@ -0,0 +1,21 @@ +// 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() { + rates := [...]float64{ + 25.5, // ethereum + 120.5, // wanchain + } + + // uses magic values - not good + fmt.Printf("1 BTC is %g ETH\n", rates[0]) + fmt.Printf("1 BTC is %g WAN\n", rates[1]) +} diff --git a/14-arrays/_experimental/_14-arrays/11-project-xratio/02-with-keys/main.go b/14-arrays/_experimental/_14-arrays/11-project-xratio/02-with-keys/main.go new file mode 100644 index 0000000..91759e3 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/11-project-xratio/02-with-keys/main.go @@ -0,0 +1,30 @@ +// 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" + +// REFACTORED VERSION +// It uses well-defined names instead of magic numbers. +// Thanks to keyed elements and constants. + +func main() { + const ( + ETH = iota + WAN + ) + + rates := [...]float64{ + ETH: 25.5, + WAN: 120.5, + } + + // uses well-defined names (ETH, WAN, ...) - good + fmt.Printf("1 BTC is %g ETH\n", rates[ETH]) + fmt.Printf("1 BTC is %g WAN\n", rates[WAN]) +} diff --git a/14-arrays/_experimental/_14-arrays/12-random-message/01-1st-version/main.go b/14-arrays/_experimental/_14-arrays/12-random-message/01-1st-version/main.go new file mode 100644 index 0000000..c66cf4d --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/12-random-message/01-1st-version/main.go @@ -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" + "math/rand" + "os" + "time" +) + +func main() { + args := os.Args[1:] + if len(args) != 1 { + fmt.Println("[your name]") + return + } + + name := args[0] + + moods := [...]string{ + "happy 😀", "good 👍", "awesome 😎", + "sad 😞", "bad 👎", "terrible 😩", + } + + rand.Seed(time.Now().UnixNano()) + n := rand.Intn(len(moods)) + + fmt.Printf("%s feels %s\n", name, moods[n]) +} + +// inspired from: +// https://github.com/moby/moby/blob/1fd7e4c28d3a4a21c3540f03a045f96a4190b527/pkg/namesgenerator/names-generator.go diff --git a/14-arrays/_experimental/_14-arrays/12-random-message/02-2nd-version/main.go b/14-arrays/_experimental/_14-arrays/12-random-message/02-2nd-version/main.go new file mode 100644 index 0000000..76b6544 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/12-random-message/02-2nd-version/main.go @@ -0,0 +1,39 @@ +// 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" + "math/rand" + "os" + "time" +) + +func main() { + args := os.Args[1:] + if len(args) != 2 { + fmt.Println("[your name] [positive|negative]") + return + } + + name, mood := args[0], args[1] + + moods := [...][3]string{ + {"happy 😀", "good 👍", "awesome 😎"}, + {"sad 😞", "bad 👎", "terrible 😩"}, + } + + rand.Seed(time.Now().UnixNano()) + n := rand.Intn(len(moods[0])) + + var mi int + if mood != "positive" { + mi = 1 + } + fmt.Printf("%s feels %s\n", name, moods[mi][n]) +} diff --git a/14-arrays/_experimental/_14-arrays/13-refactor-lucky-number-game/main.go b/14-arrays/_experimental/_14-arrays/13-refactor-lucky-number-game/main.go new file mode 100644 index 0000000..d92d041 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/13-refactor-lucky-number-game/main.go @@ -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" + "math/rand" + "os" + "strconv" + "time" +) + +const ( + maxTurns = 5 // less is more difficult + usage = `Welcome to the Lucky Number Game! + +The program will pick %d random numbers. +Your mission is to guess one of those numbers. + +The greater your number is, harder it gets. + +Wanna play? +` +) + +func main() { + rand.Seed(time.Now().UnixNano()) + + args := os.Args[1:] + + if len(args) != 1 { + fmt.Printf(usage, maxTurns) + return + } + + guess, err := strconv.Atoi(args[0]) + if err != nil { + fmt.Println("Not a number.") + return + } + + if guess < 0 { + fmt.Println("Please pick a positive number.") + return + } + + // This array will store the generated random numbers + var pickeds [maxTurns]int + + for turn := 0; turn < maxTurns; turn++ { + n := rand.Intn(guess + 1) + + pickeds[turn] = n + + if n == guess { + fmt.Println("🎉 YOU WIN!") + goto pickeds + } + } + + fmt.Println("☠️ YOU LOST... Try again?") + +pickeds: + fmt.Println("Computer has picked these:", pickeds) + + // after this line the program automatically exits +} diff --git a/14-arrays/_experimental/_14-arrays/exercises/00/main.go b/14-arrays/_experimental/_14-arrays/exercises/00/main.go new file mode 100644 index 0000000..1bace58 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/exercises/00/main.go @@ -0,0 +1,22 @@ +// 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 + +// --------------------------------------------------------- +// EXERCISE +// ? +// +// NOTE +// ? +// +// EXPECTED OUTPUT +// ? +// --------------------------------------------------------- + +func main() { +} diff --git a/14-arrays/_experimental/_14-arrays/exercises/00/solution/main.go b/14-arrays/_experimental/_14-arrays/exercises/00/solution/main.go new file mode 100644 index 0000000..b5e729e --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/exercises/00/solution/main.go @@ -0,0 +1,11 @@ +// 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 + +func main() { +} diff --git a/14-arrays/_experimental/_14-arrays/exercises/xxx-lucky-number-unique-picker/main.go b/14-arrays/_experimental/_14-arrays/exercises/xxx-lucky-number-unique-picker/main.go new file mode 100644 index 0000000..44beb17 --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/exercises/xxx-lucky-number-unique-picker/main.go @@ -0,0 +1,82 @@ +// 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" + "math/rand" + "os" + "strconv" + "time" +) + +const ( + maxTurns = 5 // less is more difficult + usage = `Welcome to the Lucky Number Game! + +The program will pick %d random numbers. +Your mission is to guess one of those numbers. + +The greater your number is, harder it gets. + +Wanna play? +` +) + +func main() { + rand.Seed(time.Now().UnixNano()) + + args := os.Args[1:] + + if len(args) != 1 { + fmt.Printf(usage, maxTurns) + return + } + + guess, err := strconv.Atoi(args[0]) + if err != nil { + fmt.Println("Not a number.") + return + } + + if guess < 0 { + fmt.Println("Please pick a positive number.") + return + } + + // This array will store the generated random numbers + var pickeds [maxTurns]int + + for turn := 0; turn < maxTurns; turn++ { + var n int + pick: + for { + n = rand.Intn(guess + 1) + for _, v := range pickeds { + if n == v { + continue pick + } + } + break + } + + pickeds[turn] = n + + if n == guess { + fmt.Println("🎉 YOU WIN!") + goto pickeds + } + } + + fmt.Println("☠️ YOU LOST... Try again?") + +pickeds: + fmt.Println("Computer has picked these:", pickeds) + + // after this line the program automatically exits +} diff --git a/14-arrays/_experimental/_14-arrays/questions/questions.md b/14-arrays/_experimental/_14-arrays/questions/questions.md new file mode 100644 index 0000000..cac63ae --- /dev/null +++ b/14-arrays/_experimental/_14-arrays/questions/questions.md @@ -0,0 +1,3 @@ +## ? +* text *CORRECT* +* text diff --git a/14-arrays/_experimental/__main.go b/14-arrays/_experimental/__main.go new file mode 100644 index 0000000..7d05c98 --- /dev/null +++ b/14-arrays/_experimental/__main.go @@ -0,0 +1,16 @@ +const ( + Mon Weekday = iota + Tue + Wed + Thu + Fri + Sat + Sun +) + +var names = [...]string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"} + + +for d := Mon; d <= Sun; d++ { + fmt.Println(names[d]) +} \ No newline at end of file diff --git a/14-arrays/_experimental/addr/main.go b/14-arrays/_experimental/addr/main.go new file mode 100644 index 0000000..c260f81 --- /dev/null +++ b/14-arrays/_experimental/addr/main.go @@ -0,0 +1,19 @@ +package main + +import "fmt" + +func main() { + age1 := getAge(15) + age2 := getAge(25) + age3 := getAge(35) + + fmt.Printf("age1 lives in %p\n", age1) + fmt.Printf("age2 lives in %p\n", age2) + fmt.Printf("age3 lives in %p\n", age3) +} + +func getAge(n byte) *byte { + m := new(byte) + *m = n + return m +} diff --git a/14-arrays/_experimental/csv-writer-slices/main.go b/14-arrays/_experimental/csv-writer-slices/main.go new file mode 100644 index 0000000..68ea314 --- /dev/null +++ b/14-arrays/_experimental/csv-writer-slices/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "encoding/csv" + "log" + "os" +) + +func main() { + records := [...][3]string{ + {"first_name", "last_name", "username"}, + {"Rob", "Pike", "rob"}, + {"Ken", "Thompson", "ken"}, + {"Robert", "Griesemer", "gri"}, + } + + w := csv.NewWriter(os.Stdout) + + for _, record := range records { + if err := w.Write(record[:]); err != nil { + log.Fatalln("error writing record to csv:", err) + } + } + + // Write any buffered data to the underlying writer (standard output). + w.Flush() + + if err := w.Error(); err != nil { + log.Fatal(err) + } + // Output: + // first_name,last_name,username + // Rob,Pike,rob + // Ken,Thompson,ken + // Robert,Griesemer,gri +} diff --git a/14-arrays/_experimental/notes.md b/14-arrays/_experimental/notes.md new file mode 100644 index 0000000..66d5cbc --- /dev/null +++ b/14-arrays/_experimental/notes.md @@ -0,0 +1,10 @@ +# Array + +## Summary + +* An array can store any type of values as long as they've the same type + +* Fixed Length and Type +* Stores the same type of values + +* Array stores its values contagiously \ No newline at end of file diff --git a/14-arrays/_experimental/wall-clock/main.go b/14-arrays/_experimental/wall-clock/main.go new file mode 100644 index 0000000..3f1c58f --- /dev/null +++ b/14-arrays/_experimental/wall-clock/main.go @@ -0,0 +1,191 @@ +package main + +import ( + "fmt" + "time" +) + +// NOTE: We're going to refactor this code in the functions section. + +const ( + charDefault = "█" + charColon = "░" + charEmpty = " " + charSeparator = " " + + // clears the screen + // + // only works on bash command prompts + // \033 is a control code: [2J clears the screen + // + // For Go Playground, use: "\f" + charClear = "\033[H\033[2J" +) + +func main() { + // for keeping things easy to read and type-safe + type placeholder [5][3]byte + + // we're using arrays because: + // - the pattern of a placeholder is constant (it doesn't change) + // - the placeholders in the clock is constant (which is 8) + // + // so, whenever values are precomputed or constant, use an array. + // + // you can always convert it to a slice easily. you'll learn + // how to do so in the slices section. + digits := [10]placeholder{ + // 0 + { + {1, 1, 1}, + {1, 0, 1}, + {1, 0, 1}, + {1, 0, 1}, + {1, 1, 1}, + }, + + // 1 + { + {1, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 1, 1}, + }, + + // 2 + { + {1, 1, 1}, + {0, 0, 1}, + {1, 1, 1}, + {1, 0, 0}, + {1, 1, 1}, + }, + + // 3 + { + {1, 1, 1}, + {0, 0, 1}, + {1, 1, 1}, + {0, 0, 1}, + {1, 1, 1}, + }, + + // 4 + { + {1, 0, 1}, + {1, 0, 1}, + {1, 1, 1}, + {0, 0, 1}, + {0, 0, 1}, + }, + + // 5 + { + {1, 1, 1}, + {1, 0, 0}, + {1, 1, 1}, + {0, 0, 1}, + {1, 1, 1}, + }, + + // 6 + { + {1, 1, 1}, + {1, 0, 0}, + {1, 1, 1}, + {1, 0, 1}, + {1, 1, 1}, + }, + + // 7 + { + {1, 1, 1}, + {0, 0, 1}, + {0, 0, 1}, + {0, 0, 1}, + {0, 0, 1}, + }, + + // 8 + { + {1, 1, 1}, + {1, 0, 1}, + {1, 1, 1}, + {1, 0, 1}, + {1, 1, 1}, + }, + + // 9 + { + {1, 1, 1}, + {1, 0, 1}, + {1, 1, 1}, + {0, 0, 1}, + {1, 1, 1}, + }, + } + + colon := placeholder{ + {0, 0, 0}, + {0, 1, 0}, + {0, 0, 0}, + {0, 1, 0}, + {0, 0, 0}, + } + + // For Go Playground: loop 100 steps, for example. + for { + // get the current time: hour, minute, and second + var ( + now = time.Now() + hour, min, sec = now.Hour(), now.Minute(), now.Second() + ) + + // again, an array is used here. + // + // because, the number of placeholders in this clock + // is constant (which is 8 placeholders). + clock := [8]placeholder{ + // separate the digits: 17 becomes, 1 and 7 respectively + digits[hour/10], digits[hour%10], + colon, + digits[min/10], digits[min%10], + colon, + digits[sec/10], digits[sec%10], + } + + fmt.Print(charClear) + + // print the clock + for line := range clock[0] { + + // print a line for each letter + for letter, v := range clock { + // colon blink + char := charDefault + if v == colon { + char = charEmpty + if sec%2 == 0 { + char = charColon + } + } + + // print a line + for _, c := range clock[letter][line] { + if c == 1 { + fmt.Print(char) + } else { + fmt.Print(charEmpty) + } + } + + fmt.Print(charSeparator) + } + fmt.Println() + } + + // wait for 1 second + time.Sleep(time.Second) + } +} diff --git a/14-arrays/exercises/00-name/main.go b/14-arrays/exercises/00-name/main.go new file mode 100644 index 0000000..7dd4f79 --- /dev/null +++ b/14-arrays/exercises/00-name/main.go @@ -0,0 +1,15 @@ +package main + +// --------------------------------------------------------- +// EXERCISE: Name +// ? +// +// NOTE +// ? +// +// EXPECTED OUTPUT +// ? +// --------------------------------------------------------- + +func main() { +} diff --git a/14-arrays/exercises/00-name/solution/main.go b/14-arrays/exercises/00-name/solution/main.go new file mode 100644 index 0000000..da29a2c --- /dev/null +++ b/14-arrays/exercises/00-name/solution/main.go @@ -0,0 +1,4 @@ +package main + +func main() { +} diff --git a/14-arrays/exercises/01-declare-empty/main.go b/14-arrays/exercises/01-declare-empty/main.go new file mode 100644 index 0000000..56b756a --- /dev/null +++ b/14-arrays/exercises/01-declare-empty/main.go @@ -0,0 +1,36 @@ +package main + +// --------------------------------------------------------- +// EXERCISE: Declare empty arrays +// +// 1. Declare and printf the following arrays: +// +// 1. A string array with 4 items +// 2. An int array 5 items +// 3. A byte array with 5 items +// 4. A float64 array with 1 item +// 5. A bool array with 4 items +// 6. A byte array without any items +// +// 2. Print the types of the previous arrays. +// +// NOTE +// You should use printf with #v verb. +// +// EXPECTED OUTPUT +// names : [4]string{"", "", "", ""} +// distances: [5]int{0, 0, 0, 0, 0} +// data : [5]uint8{0x0, 0x0, 0x0, 0x0, 0x0} +// ratios : [1]float64{0} +// switches : [4]bool{false, false, false, false} +// zero : [0]bool{} +// names : [4]string +// distances: [5]int +// data : [5]uint8 +// ratios : [1]float64 +// switches : [4]bool +// zero : [0]bool +// --------------------------------------------------------- + +func main() { +} diff --git a/14-arrays/exercises/01-declare-empty/solution/main.go b/14-arrays/exercises/01-declare-empty/solution/main.go new file mode 100644 index 0000000..338d083 --- /dev/null +++ b/14-arrays/exercises/01-declare-empty/solution/main.go @@ -0,0 +1,36 @@ +package main + +import "fmt" + +func main() { + // 1. Declare and printf the following arrays: + // 1. A string array with 4 items + // 2. An int array 5 items + // 3. A byte array with 5 items + // 4. A float64 array with 1 item + // 5. A bool array with 4 items + // 6. A byte array without any items + var ( + names [4]string + distances [5]int + data [5]byte + ratios [1]float64 + switches [4]bool + zero [0]bool + ) + + fmt.Printf("names : %#v\n", names) + fmt.Printf("distances: %#v\n", distances) + fmt.Printf("data : %#v\n", data) + fmt.Printf("ratios : %#v\n", ratios) + fmt.Printf("switches : %#v\n", switches) + fmt.Printf("zero : %#v\n", zero) + + // 2. Print the types of the previous arrays. + fmt.Printf("names : %T\n", names) + fmt.Printf("distances: %T\n", distances) + fmt.Printf("data : %T\n", data) + fmt.Printf("ratios : %T\n", ratios) + fmt.Printf("switches : %T\n", switches) + fmt.Printf("zero : %T\n", zero) +} diff --git a/14-arrays/exercises/0x-hipsters-love-search/main.go b/14-arrays/exercises/0x-hipsters-love-search/main.go new file mode 100644 index 0000000..f2b2aa4 --- /dev/null +++ b/14-arrays/exercises/0x-hipsters-love-search/main.go @@ -0,0 +1,17 @@ +package main + +// search for books in hipster's love + +// --------------------------------------------------------- +// EXERCISE: Name +// ? +// +// NOTE +// ? +// +// EXPECTED OUTPUT +// ? +// --------------------------------------------------------- + +func main() { +} diff --git a/14-arrays/exercises/0x-hipsters-love-search/solution/main.go b/14-arrays/exercises/0x-hipsters-love-search/solution/main.go new file mode 100644 index 0000000..6542793 --- /dev/null +++ b/14-arrays/exercises/0x-hipsters-love-search/solution/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "os" + "strings" +) + +const yearly = 4 + +func main() { + var books [yearly]string + + books[0] = "Kafka's Revenge" + books[1] = "Stay Golden" + books[2] = "Everythingship" + books[3] += books[0] + " 2nd Edition" + + if len(os.Args) != 2 { + fmt.Println("Tell me a book title") + return + } + query := os.Args[1] + + fmt.Println("Search Results:") + fmt.Println("---------------") + + var found bool + + for _, v := range books { + if strings.Contains(strings.ToLower(v), query) { + fmt.Println("+", v) + found = true + } + } + + if !found { + fmt.Printf("We don't have that book: %q\n", query) + } +} diff --git a/14-arrays/exercises/README.md b/14-arrays/exercises/README.md new file mode 100644 index 0000000..496ef77 --- /dev/null +++ b/14-arrays/exercises/README.md @@ -0,0 +1,20 @@ +# Array Exercises + +1. **[Declare Empty Arrays](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/01-declare-empty)** + +- get data from command-line + - into a fixed array; see how it blows beyond its len + +- add items +- get items +- check the length +- print the items +- reverse the array +- shuffle the items +- find the first item that contains x +- find the last item that contains y +- find the duplicate items + +1. **[text](https://github.com/inancgumus/learngo/tree/master/)** + + text \ No newline at end of file diff --git a/14-arrays/questions/README.md b/14-arrays/questions/README.md new file mode 100644 index 0000000..de0d04a --- /dev/null +++ b/14-arrays/questions/README.md @@ -0,0 +1,64 @@ +# Arrays + +## Where is the 2nd variable below stored in memory? +```go +// Let's say that first variable below is stored in this memory location: 20th +var ( + first int32 = 100 + second int32 = 150 +) +``` +1. 21 +2. 22 +3. 24 +4. It can be stored anywhere *CORRECT* + +> **4:** That's right. It can be anywhere. Because, there's no guarantee that variables will be stored in contiguous memory locations. + + +## Where is the 3rd element of the following array stored in memory? + +```go +// +// Let's say that: +// nums array is stored in this memory location (cell): 500th +// +// So, this means: nums[0] is stored at 500th location as well. +// +var nums [5]int64 +``` +1. 3 +2. 2 +3. 502 +4. 503 +5. 516 *CORRECT* + +> **2:** Nope, that's the index of an element. +> +> **3, 4:** 500+index? You're getting closer. +> +> **5:** Perfect. Array elements are stored in contiguous memory locations (cells). Here, the array's location is 500, and each element is 8 bytes (int64). So, 1st element: 500th, 2nd element: 508th, 3rd element: 516th, and so on. Formula: 516 = 500 + (8 * (3 - 1)). + + +## How many values the following variable represents? +```go +var gophers [10]string +``` +1. 0 +2. 1 *CORRECT* +3. 2 +4. 10 + +> **2:** That's right! A variable can only store one value. Here, it stores a single array value with all its elements. However, through the gophers variable, you can access to 10 string values individually of that array. +> +> **4:** That's the length of the array. It's not the number of values that the gophers variable represents. + + +## ? +1. text *CORRECT* +2. text + +> **1:** +> + + diff --git a/14-arrays/xx-examples-3-hipsters-love-bookstore/main.go b/14-arrays/xx-examples-3-hipsters-love-bookstore/main.go new file mode 100644 index 0000000..0fc1386 --- /dev/null +++ b/14-arrays/xx-examples-3-hipsters-love-bookstore/main.go @@ -0,0 +1,34 @@ +package main + +import "fmt" + +// STORY: +// Hipster's Love store publishes limited books +// twice a year. +// +// The number of books they publish is fixed at 4. + +// So, let's create a 4 elements string array for the books. + +const ( + winter = 1 + summer = 3 + yearly = winter + summer +) + +func main() { + var books [yearly]string + + books[0] = "Kafka's Revenge" + books[1] = "Stay Golden" + books[2] = "Everythingship" + books[3] += books[0] + " 2nd Edition" + + // won't update the original array + for _, v := range books { + v += " (Sold Out)" + fmt.Println(v) + } + + fmt.Printf("\nbooks: %#v\n", books) +} diff --git a/14-arrays/xx-examples-4-hipsters-love-bookstore/main.go b/14-arrays/xx-examples-4-hipsters-love-bookstore/main.go new file mode 100644 index 0000000..0b8c908 --- /dev/null +++ b/14-arrays/xx-examples-4-hipsters-love-bookstore/main.go @@ -0,0 +1,45 @@ +package main + +import "fmt" + +// STORY: +// Hipster's Love store publishes limited books +// twice a year. +// +// The number of books they publish is fixed at 4. + +// So, let's create a 4 elements string array for the books. + +const ( + winter = 1 + summer = 3 + yearly = winter + summer +) + +func main() { + var ( + prevBooks [yearly]string + books [yearly]string + ) + + books[0] = "Kafka's Revenge" + books[1] = "Stay Golden" + books[2] = "Everythingship" + books[3] += books[0] + " 2nd Edition" + + prevBooks = books + books[0] = "Silver Ages" + books[1] = "Dragon's Fire" + books[2] = "Nothingless" + books[3] = prevBooks[2] + " 2nd Edition" + + fmt.Println("Last Year's Books (Sold Out!):") + for _, v := range prevBooks { + fmt.Println("+", v) + } + + fmt.Println("\nNew Books:") + for _, v := range books { + fmt.Println("+", v) + } +} diff --git a/15-slices/01-intro/01-theory/main.go b/15-slices/01-intro/01-theory/main.go new file mode 100644 index 0000000..e41c332 --- /dev/null +++ b/15-slices/01-intro/01-theory/main.go @@ -0,0 +1,82 @@ +// 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() { + // ----------------------------------------------------- + // COMPLEX LITERALS: + // ----------------------------------------------------- + // array literal : [4]int{1, 2, 3} + // slice literal : []int{1, 2, 3} + // + // You didn't learn about these yet: + // + // map literal : map[int]int{1: 2} + // struct literal: struct{ x, y int }{ 1, 2 } + + // ----------------------------------------------------- + // SLICE LITERAL: + // ----------------------------------------------------- + r := []rune{'h', 'e', 'y'} // 3 items + i := []int{'h', 'e', 'y'} // 3 items + b := []byte{'h', 'e', 'y'} // 3 items + s := []string{"hey"} // 1 item + + fmt.Printf("[]rune type: %T\n", r) + fmt.Printf("[]int type: %T\n", i) + fmt.Printf("[]byte type: %T\n", b) + fmt.Printf("[]string type: %T\n", s) + + // ----------------------------------------------------- + // multi-dimensional slice + // ----------------------------------------------------- + multi := [][]rune{ + {1, 2, 3}, + // each item can have a different length + {4, 5, 6, 7, 8}, + } + fmt.Printf("multi's type : %T\n", multi) + fmt.Printf("multi's length : %d\n", len(multi)) + fmt.Printf("multi[0]'s length: %d\n", len(multi[0])) + fmt.Printf("multi[1]'s length: %d\n", len(multi[1])) + + // ----------------------------------------------------- + // getting and setting elements + // ----------------------------------------------------- + hello := []rune{'h', 'e', 'y'} + fmt.Println(hello[0], hello[1], hello[2]) + + hello[0] = 'y' + hello[1] = 'o' + hello[2] = '!' + fmt.Println(hello[0], hello[1], hello[2]) + + // ----------------------------------------------------- + // empty slice + // ----------------------------------------------------- + e := []rune{} + fmt.Printf("empty slice's length: %d\n", len(e)) + + // ----------------------------------------------------- + // nil slice + // slice's zero value is nil + // ----------------------------------------------------- + var n []rune + fmt.Println("Really nil?", n == nil) + + // you can't get/set elements of a nil slice + // if you run the code below, it will error at runtime + // + // fmt.Println(n[0]) + // fmt.Println(n[1]) + + // but you can get its length + fmt.Printf("nil slice's length: %d\n", len(n)) +} diff --git a/15-slices/01-intro/02-examples/main.go b/15-slices/01-intro/02-examples/main.go new file mode 100644 index 0000000..450fb28 --- /dev/null +++ b/15-slices/01-intro/02-examples/main.go @@ -0,0 +1,61 @@ +// 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" + + s "github.com/inancgumus/prettyslice" +) + +func main() { + basket := []string{"banana", "apple", "coffee"} + s.Show("basket (before)", basket) + + // #1 example: type + fmt.Printf("[]string type: %T\n", basket) + + // #2 example: getting and setting elements + fmt.Println(basket[0], basket[1], basket[2]) + + basket[0] = "pepper" + basket[1] = "water" + basket[2] = "tea" + s.Show("basket (after)", basket) + + // #3 example: empty slice + emptyBasket := []rune{} + s.Show(`emptyBasket := []rune{}`, emptyBasket) + + // #4 example: nil slice + // a slice's zero value is nil + var nilButHappy []rune + + s.Show(`var nilButHappy []rune`, nilButHappy) + + // #5 example: comparing to nil + fmt.Println("nilButHappy == nil", nilButHappy == nil) + fmt.Println("emptyBasket == nil", emptyBasket == nil) + + // you can't compare slices other than nil + // nilButHappy == emptyBasket + + // #6 example: comparing slices + newBasket := []string{"pepper", "water", "tea"} + + equal := true + for i := range basket { + if basket[i] != newBasket[i] { + equal = false + break + } + } + + s.Show("equal?", basket, newBasket) + fmt.Println(equal) +} diff --git a/15-slices/02-append/01-theory/main.go b/15-slices/02-append/01-theory/main.go new file mode 100644 index 0000000..a504d9b --- /dev/null +++ b/15-slices/02-append/01-theory/main.go @@ -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 ( + s "github.com/inancgumus/prettyslice" +) + +func main() { + nums := []int{1, 2, 3} + s.Show("nums := []int{1, 2, 3}", nums) + + // ----------------------------------------------------- + nums = append(nums, 4) + s.Show("append(nums, 4)", nums) + + // ----------------------------------------------------- + nums = append(nums, 9) + s.Show("append(nums, 9)", nums) + + // ----------------------------------------------------- + // let's reset nums + // and let's add multiple elements + nums = []int{1, 2, 3} + s.Show("nums = []int{1, 2, 3}", nums) + + nums = append(nums, 4, 9) + s.Show("append(nums, 4, 9)", nums) + + // ----------------------------------------------------- + // let's reset nums again + // let's add multiple elements using the ellipsis + nums = []int{1, 2, 3} + tens := []int{12, 13} + + s.Show("nums = []int{1, 2, 3}", nums) + s.Show("tens := []int{12, 13}", tens) + + nums = append(nums, tens...) + s.Show("append(nums, tens...)", nums) +} diff --git a/15-slices/02-append/02-examples/main.go b/15-slices/02-append/02-examples/main.go new file mode 100644 index 0000000..9bb0d65 --- /dev/null +++ b/15-slices/02-append/02-examples/main.go @@ -0,0 +1,26 @@ +// 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 ( + s "github.com/inancgumus/prettyslice" +) + +func main() { + var basket []string + + basket = append(basket, "banana") + basket = append(basket, "milk", "apple") + + todo := []string{"tea", "coffee", "salt"} + basket = append(basket, todo...) + + _ = append(basket, "pepper") + + s.Show("my basket", basket) +} diff --git a/15-slices/03-slices-vs-arrays/01-with-arrays/main.go b/15-slices/03-slices-vs-arrays/01-with-arrays/main.go new file mode 100644 index 0000000..a11c321 --- /dev/null +++ b/15-slices/03-slices-vs-arrays/01-with-arrays/main.go @@ -0,0 +1,40 @@ +// 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 ( + "math/rand" + "time" + + s "github.com/inancgumus/prettyslice" +) + +func main() { + rand.Seed(time.Now().UnixNano()) + + const max = 10 + // max, _ := strconv.Atoi(os.Args[1]) + + var uniques [max]int + +loop: + for found := 0; found < max; { + n := rand.Intn(max + 1) + + for _, u := range uniques { + if u == n { + continue loop + } + } + + uniques[found] = n + found++ + } + + s.Show("Uniques", uniques) +} diff --git a/15-slices/03-slices-vs-arrays/02-with-slices/main.go b/15-slices/03-slices-vs-arrays/02-with-slices/main.go new file mode 100644 index 0000000..1d443b1 --- /dev/null +++ b/15-slices/03-slices-vs-arrays/02-with-slices/main.go @@ -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 ( + "math/rand" + "os" + "strconv" + "time" + + s "github.com/inancgumus/prettyslice" +) + +func main() { + rand.Seed(time.Now().UnixNano()) + + max, _ := strconv.Atoi(os.Args[1]) + + // declare an uninitialized nil slice + var uniques []int + +loop: + // you can still use the len function on a nil slice + for len(uniques) < max { + n := rand.Intn(max + 1) + + for _, u := range uniques { + if u == n { + continue loop + } + } + + // let's grow the slice by appending + uniques = append(uniques, n) + } + + s.Show("Uniques", uniques) +} diff --git a/15-slices/04-copy/01-usage/main.go b/15-slices/04-copy/01-usage/main.go new file mode 100644 index 0000000..48455cb --- /dev/null +++ b/15-slices/04-copy/01-usage/main.go @@ -0,0 +1,28 @@ +// 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" + + s "github.com/inancgumus/prettyslice" +) + +func main() { + me := []byte{'m', 'e'} + yo := []byte{'y', 'o', '!'} + + s.Show("me [before]", me) + s.Show("yo [before]", yo) + + N := copy(me, yo) + fmt.Printf("%d element(s) copied.\n", N) + + s.Show("me [after]", me) + s.Show("yo [after]", yo) +} diff --git a/15-slices/04-copy/02-hacker-incident/main.go b/15-slices/04-copy/02-hacker-incident/main.go new file mode 100644 index 0000000..73af75e --- /dev/null +++ b/15-slices/04-copy/02-hacker-incident/main.go @@ -0,0 +1,44 @@ +// 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" + + s "github.com/inancgumus/prettyslice" +) + +func main() { + // we've received the raining probabilities + data := []float64{10, 25, 30, 50} + + s.Show("Probabilities", data) + + fmt.Printf("Is it gonna rain? %.f%% chance.\n", + (data[0]+data[1]+data[2]+data[3])/ + float64(len(data))) + + // ----------------------------------------------------- + // but it turns out that the first two items of the data + // has been corrupted by a hacker. + // + // this time, we've received clean data. + // let's overwrite the invalid data by copying + + copy(data, []float64{80, 90}) + + // why copy? why not just assign and overwrite? + // because: it overwrites the whole slice + // data = []float64{80, 90} + + s.Show("Probabilities", data) + + fmt.Printf("Is it gonna rain? %.f%% chance.\n", + (data[0]+data[1]+data[2]+data[3])/ + float64(len(data))) +} diff --git a/15-slices/05-whats-a-slice-in-real/01-theory/main.go b/15-slices/05-whats-a-slice-in-real/01-theory/main.go new file mode 100644 index 0000000..f6153b0 --- /dev/null +++ b/15-slices/05-whats-a-slice-in-real/01-theory/main.go @@ -0,0 +1,78 @@ +// 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" + + s "github.com/inancgumus/prettyslice" +) + +/* +If you find this code hard to understand, please comment +some parts of it and run it again. +*/ + +func main() { + // example #1 + slice := []int{5, 6, 7, 8, 9} + s.Show("slice", slice) + + // fmt.Println("slice[0]:", slice[0]) + // fmt.Println("slice[1]:", slice[1]) + // fmt.Println("slice[2]:", slice[2]) + // fmt.Println("slice[3]:", slice[3]) + // fmt.Println("slice[4]:", slice[4]) + + // example #2 + sliced := slice[1:4] + s.Show("slice[1:4]", sliced) + + // fmt.Println("sliced[0]:", sliced[0]) + // fmt.Println("sliced[1]:", sliced[1]) + // fmt.Println("sliced[2]:", sliced[2]) + // fmt.Println("sliced[3]:", sliced[3]) // -> you can't + + // example #3 + // the new slice will also be effected from this change + sliced = append(sliced, 15) + slice[1] = 200 + s.Show("append(sliced, 15)", sliced) + + // example #3b + // the new slice won't be effected anymore + // because, go has created a new array for the `s` + sliced = append(sliced, 3) + slice[1] = 0 + s.Show("slice[1] = 0", slice) + s.Show("sliced", sliced) + + // example #4 + // its pointer will stay the same until 8 elements + sliced = append(sliced, 10, 11, 12) + s.Show("append(sliced, 10, 11, 12)", sliced) + + // now it will change: 13 the wicked number! + sliced = append(sliced, 13) + s.Show("append(sliced, 13)", sliced) + + // example #5 + var ( + // just declaring it will make it nil + nilButHappy []int + + // without any elements will make empty + empty = []int{} + ) + + s.Show("Empty Slice", empty) + s.Show("Nil Slice", nilButHappy) + + fmt.Println("empty == nil?", empty == nil) + fmt.Println("nilButHappy == nil?", nilButHappy == nil) +} diff --git a/15-slices/05-whats-a-slice-in-real/02-example/main.go b/15-slices/05-whats-a-slice-in-real/02-example/main.go new file mode 100644 index 0000000..a3f8a79 --- /dev/null +++ b/15-slices/05-whats-a-slice-in-real/02-example/main.go @@ -0,0 +1,36 @@ +// 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 ( + s "github.com/inancgumus/prettyslice" +) + +// Please uncomment the examples below to see the results + +func main() { + colors := []string{"black", "white"} + + // 1st example + vivid := colors + vivid[0] = "orange" + + // 2nd example + // vivid = nil + + // 3th example + vivid = append(colors, "yellow") + vivid[0] = "gray" + + // 4th example + colors = append(colors, "yellow") + colors[0] = "gray" + + s.Show("colors slice header", colors) + s.Show("vivid slice header", vivid) +} diff --git a/15-slices/06-slice-expressions/01-theory/main.go b/15-slices/06-slice-expressions/01-theory/main.go new file mode 100644 index 0000000..c995721 --- /dev/null +++ b/15-slices/06-slice-expressions/01-theory/main.go @@ -0,0 +1,18 @@ +// 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 s "github.com/inancgumus/prettyslice" + +func main() { + slicable := []byte{'c', 'o', 'l', 'o', 'r'} + s.Show("slicable[0:5]", slicable[0:5]) + s.Show("slicable[0:2]", slicable[0:2]) + s.Show("slicable[3:5]", slicable[3:5]) + s.Show("slicable[1:4]", slicable[1:4]) +} diff --git a/15-slices/06-slice-expressions/02-examples/main.go b/15-slices/06-slice-expressions/02-examples/main.go new file mode 100644 index 0000000..6173596 --- /dev/null +++ b/15-slices/06-slice-expressions/02-examples/main.go @@ -0,0 +1,56 @@ +// 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" + + s "github.com/inancgumus/prettyslice" +) + +func main() { + // 1. slicing creates a new slice + nums := []int{1, 3, 5, 2, 4, 8} + odds := nums[:3] + evens := nums[3:] + + // 2. backing array is shared + nums[1], nums[3] = 9, 6 + s.Show("nums", nums) + s.Show("odds : nums[:3]", odds) + s.Show("evens: nums[3:]", evens) + + // 3. you can create a new slice from an array + heyArr := [3]byte{'h', 'e', 'y'} + hey, he := heyArr[:], heyArr[:2] + + // 4. sliced array will be shared among the slices + heyArr[0] = 'm' + s.Show("hey := heyArr[:]", hey) + s.Show("he := heyArr[:2]", he) + + // 5. index expression returns a value + // while a slice expression returns a slice + s.Show("nums[0]", nums[0]) + s.Show("nums[0:1]", nums[0:1]) + fmt.Printf("nums[0] : %T\n", nums[0]) // just int + fmt.Printf("nums[0:1]: %T\n", nums[0:1]) // []int slice + + // 6. extending a slice up to its capacity + first := nums[0:1] + s.Show("first := nums[0:1]", first) + s.Show("first[0:2]", first[0:2]) + s.Show("first[0:3]", first[0:3]) + s.Show("first[0:4]", first[0:4]) + s.Show("first[0:5]", first[0:5]) + s.Show("first[0:6]", first[0:6]) + // s.Show("first[0:7]", first[0:7]) // <- you can't + + first = append(first[0:6], 9) + s.Show("first: with a new backing array", first) +} diff --git a/15-slices/07-full-slice-expressions/main.go b/15-slices/07-full-slice-expressions/main.go new file mode 100644 index 0000000..c24f63f --- /dev/null +++ b/15-slices/07-full-slice-expressions/main.go @@ -0,0 +1,23 @@ +// 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 s "github.com/inancgumus/prettyslice" + +func main() { + ships := []string{ + "Normandy", "Verrikan", "Nexus", + } + + // frigates := ships[:2] + frigates := ships[:2:2] + frigates = append(frigates, "Warsaw") + + s.Show("Ships", ships) + s.Show("Frigates", frigates) +} diff --git a/15-slices/08-make/main.go b/15-slices/08-make/main.go new file mode 100644 index 0000000..35616c0 --- /dev/null +++ b/15-slices/08-make/main.go @@ -0,0 +1,31 @@ +// 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 s "github.com/inancgumus/prettyslice" + +func main() { + // #1: make preallocates an array + nums := make([]int, 0, 10) + nums = append(nums, 1, 2, 3) + nums = append(nums, 4, 5) + s.Show("nums", nums) + + nums = append(nums, 6) + s.Show("nums: doesn't allocate", nums) + + // #2: prevent overwriting with make + doubles := make([]int, len(nums) /*, 12 */) + + for i := range nums { + doubles[i] = nums[i] * 2 + } + + s.Show("nums: after doubling", nums) + s.Show("doubles", doubles) +} diff --git a/15-slices/09-bouncing-ball-challenge/01-challenge/main.go b/15-slices/09-bouncing-ball-challenge/01-challenge/main.go new file mode 100644 index 0000000..4a78421 --- /dev/null +++ b/15-slices/09-bouncing-ball-challenge/01-challenge/main.go @@ -0,0 +1,181 @@ +// 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 + +// ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ +// Post your solution to twitter with this hashtag: +// #learngoprogramming +// +// Notify me on twitter by adding my account to your tweet: +// @inancgumus +// +// ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + +// ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ +// This document contains what you need to do to create +// the bouncing ball animation. +// +// You're going to learn a great deal of knowledge about +// slices and you'll earn a good experience while doing this. +// +// However, refer to this document only when you get stuck. +// Do not follow it step by step. +// Try to solve the challenge on your own. +// +// This document organized into steps/sections. +// So you can jump to that step/section directly. +// +// Good luck! +// ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + +// ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ +// #1 Declare constants here. +// ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ +// The width and the height of the board. +// You're going to draw your board using these. + +func main() { + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // -> Declare ball positions: X and Y + // Initialize them to 0s. + + // -> Declare ball's velocity: xVelocity and yVelocity + // + // Velocity means: Speed and Direction + // X velocity = 1 // balls moves to the right + // X velocity = -1 // balls moves to the left + // Y velocity = 1 // balls moves down + // Y velocity = -1 // balls moves up + // + // -> On each step, add velocities to ball's position. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 🎾 CREATE THE BOARD + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // + // -> Use the make function to initialize your board. + // Remember: You also need to initialize each sub-slice. + // (in a for loop) + // + // -> You can use [][]bool for your board. + // + // Because, when you set one of the items to true, + // then you know that the ball is in that position. + // + // EXAMPLE: + // false false false false + // false true -+ false false + // false false | false false + // v + // the ball is here + // board[1][1] is true + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 🎾 DRAWING LOOP + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // { + // + // Create a loop. + // + // On each step of the loop, you're going to: + // -> Clear the board + // -> Calculate the next ball position + // -> Draw the board with the balls + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 🎾 CLEAR THE BOARD + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // -> Set all the board elements to false. + // (I mean the sub-slices' elements) + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 🎾 CALCULATE THE NEXT BALL POSITION + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // -> Add the velocities to the ball's current position: + // + // X += xVelocity + // Y += yVelocity + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 👉 When ball hits the borders change its direction. + // + // -> Multiply the velocity by -1 to change its X direction. + // -> Do the same for the Y velocity as well. + + // 👉 Set the ball's position in the board. + // + // -> You will use this information when drawing the board. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 🎾 DRAW THE BOARD + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // -> Make a large enough []rune `buffer`. + // + // HINT: width * height will give you a large enough buffer. + // TIP : You could also use string but it would be inefficient. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 👉 FILL YOUR BUFFER: + // + // + It's better to use buffers for these kind of things. + // + It's worst to call the Print functions all the time. + // + // 1. Loop for the height of the board. + // 2. Then in a nested loop, loop for the width of the board. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 👉 NESTEP LOOP (WIDTH LOOP): + // + // In each step of the nested loop, do this: + // + // 1. Check whether the ball is in the x, y positions. + // You need to check for it using your board slice. + // + // 2. If so, append this tennis ball '🎾' to the buf slice. + // 3. If not, append this pool ball '🎱' to the buf slice. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 👉 HEIGHT LOOP: + // + // After the nested loop (but in the height loop): + // + // 1. Append the newline character to the buf: '\n' + // This will allow you to print the next row to the + // next line. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 🎾 PRINT THE BOARD + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // After the loop print this to clear the screen. + // + // fmt.Print("\033[2J") + // + // Note : This will only work in Linux and Mac. + // For Windows: Just install Ubuntu bash on Windows, it's easy now! + // It isn't a virtual machine. + // https://docs.microsoft.com/en-us/windows/wsl/install-win10 + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 👉 PRINT YOUR BOARD (USING THE BUFFER): + // + // -> Do not forget converting it to string. + // Because your buffer is []rune. + // + // fmt.Print(string(buf)) + // + // You'll learn the details about rune and strings later. + + // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ + // 👉 SLOW DOWN THE SPEED + // And lastly, call the time.Sleep function to slow down + // the speed of the loop, so you can see the ball :) + // + // time.Sleep(time.Millisecond * 60) + + // } DRAWING LOOP ENDS HERE 👈 +} diff --git a/15-slices/09-bouncing-ball-challenge/02-solution-draw-the-board/main.go b/15-slices/09-bouncing-ball-challenge/02-solution-draw-the-board/main.go new file mode 100644 index 0000000..8e2897b --- /dev/null +++ b/15-slices/09-bouncing-ball-challenge/02-solution-draw-the-board/main.go @@ -0,0 +1,47 @@ +// 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" +) + +const ( + width = 25 + height = 8 +) + +func main() { + // ------------------------------------------------- + // CREATE THE BOARD + // ------------------------------------------------- + board := make([][]bool, width) + for row := range board { + board[row] = make([]bool, height) + } + + // ------------------------------------------------- + // DRAW THE BOARD + // ------------------------------------------------- + var ( + buf = make([]rune, 0, width*height) + ball rune + ) + + for y := range board[0] { + for x := range board { + ball = '🎱' + if board[x][y] { + ball = '🎾' + } + buf = append(buf, ball, ' ') + } + buf = append(buf, '\n') + } + fmt.Print(string(buf)) +} diff --git a/15-slices/09-bouncing-ball-challenge/03-solution-drawing-loop/main.go b/15-slices/09-bouncing-ball-challenge/03-solution-drawing-loop/main.go new file mode 100644 index 0000000..b90b16e --- /dev/null +++ b/15-slices/09-bouncing-ball-challenge/03-solution-drawing-loop/main.go @@ -0,0 +1,64 @@ +// 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" + "time" +) + +const ( + width = 25 + height = 8 + + maxFrames = 1200 +) + +func main() { + // ------------------------------------------------- + // CREATE THE BOARD + // ------------------------------------------------- + board := make([][]bool, width) + for row := range board { + board[row] = make([]bool, height) + } + + var X, Y int // ball positions + + for i := 0; i < maxFrames; i++ { + // draw after a while: slows down the animation + time.Sleep(time.Second / 20) + + // ------------------------------------------------- + // PUT THE BALL + // ------------------------------------------------- + board[X][Y] = true + + // ------------------------------------------------- + // DRAW THE BOARD + // ------------------------------------------------- + var ( + buf = make([]rune, 0, width*height) + ball rune + ) + + for y := range board[0] { + for x := range board { + ball = '🎱' + if board[x][y] { + ball = '🎾' + } + buf = append(buf, ball, ' ') + } + buf = append(buf, '\n') + } + + // clear the screen and draw the board + fmt.Print("\033[2J", string(buf)) + } +} diff --git a/15-slices/09-bouncing-ball-challenge/04-solution-final/main.go b/15-slices/09-bouncing-ball-challenge/04-solution-final/main.go new file mode 100644 index 0000000..dfa0834 --- /dev/null +++ b/15-slices/09-bouncing-ball-challenge/04-solution-final/main.go @@ -0,0 +1,87 @@ +// 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" + "time" +) + +const ( + width = 25 + height = 8 + + maxFrames = 1200 +) + +func main() { + // ------------------------------------------------- + // CREATE THE BOARD + // ------------------------------------------------- + board := make([][]bool, width) + for row := range board { + board[row] = make([]bool, height) + } + + var ( + X, Y int // ball positions + xVel, yVel = 1, 1 // velocities + ) + + for i := 0; i < maxFrames; i++ { + // draw after a while: slows down the animation + time.Sleep(time.Second / 20) + + // ------------------------------------------------- + // CALCULATE THE NEXT BALL POSITION + // ------------------------------------------------- + X += xVel + Y += yVel + + // when the ball hits the borders change its direction + // by changing its velocity + if X <= 0 || X >= width-1 { + xVel *= -1 + } + if Y <= 0 || Y >= height-1 { + yVel *= -1 + } + + // ------------------------------------------------- + // CLEAR THE BOARD AND PUT THE BALL + // ------------------------------------------------- + for y := range board[0] { + for x := range board { + board[x][y] = false + } + } + board[X][Y] = true + + // ------------------------------------------------- + // DRAW THE BOARD + // ------------------------------------------------- + var ( + buf = make([]rune, 0, width*height) + ball rune + ) + + for y := range board[0] { + for x := range board { + ball = '🎱' + if board[x][y] { + ball = '🎾' + } + buf = append(buf, ball, ' ') + } + buf = append(buf, '\n') + } + + // clear the screen and draw the board + fmt.Print("\x0c", string(buf)) + } +} diff --git a/15-slices/README-WARNING.md b/15-slices/README-WARNING.md new file mode 100644 index 0000000..58abcdc --- /dev/null +++ b/15-slices/README-WARNING.md @@ -0,0 +1,8 @@ +# WARNING + +For the code in this section, you should install my prettyslice library. + +## STEPS +1. Open your command-line +2. Type: `go get github.com/inancgumus/prettyslice` +3. That's all. \ No newline at end of file diff --git a/15-slices/README.md b/15-slices/README.md deleted file mode 100644 index 58094c8..0000000 --- a/15-slices/README.md +++ /dev/null @@ -1 +0,0 @@ -This section is in progress. I'm working hard to update the course all the time. Hold on! \ No newline at end of file diff --git a/16-strings-revisited/01-byte/main.go b/16-strings-revisited/01-byte/main.go new file mode 100644 index 0000000..4f1232b --- /dev/null +++ b/16-strings-revisited/01-byte/main.go @@ -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" + +func main() { + var g, o rune + + g, o = 'g', 'o' + g, o = 103, 111 + g, o = 0x67, 0x6f + g, o = '\U00000067', '\U0000006f' + g, o = '\u0067', '\u006f' + g, o = '\x67', '\x6f' + + fmt.Println("codepoints") + fmt.Printf(" dec : %d %d\n", g, o) + fmt.Printf(" hex : %x %x\n", g, o) + fmt.Printf(" unicode : %U %U\n", g, o) + fmt.Printf(" chars : %c %c\n", g, o) + + // g++ + // o -= 6 + + g -= 'a' - 'A' + o -= 'a' - 'A' + + fmt.Println("codepoints") + fmt.Printf(" dec : %d %d\n", g, o) + fmt.Printf(" hex : %x %x\n", g, o) + fmt.Printf(" unicode : %U %U\n", g, o) + fmt.Printf(" chars : %c %c\n", g, o) + + // string representations + // fmt.Print("string() : ", string(g), string(o), "\n") + // fmt.Print("hex 1 byte : \x67\x6f \n") + // fmt.Print("hex 2 bytes : \u0067\u006f \n") + // fmt.Print("hex 4 bytes : \U00000067\U0000006f \n") +} diff --git a/16-strings-revisited/02-string-byte-slice/main.go b/16-strings-revisited/02-string-byte-slice/main.go new file mode 100644 index 0000000..198762c --- /dev/null +++ b/16-strings-revisited/02-string-byte-slice/main.go @@ -0,0 +1,28 @@ +// 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() { + msg := "WONDERFUL!" + bytes := []byte(msg) + + fmt.Println("msg :", msg) + fmt.Println("bytes :", bytes) + fmt.Println("string(bytes) :", string(bytes)) + fmt.Println("string(87) :", string(87)) + + fmt.Println() + + for i, v := range msg { + fmt.Printf( + "msg[%d] : %d = %[2]q\n", + i, v) + } +} diff --git a/16-strings-revisited/03-string-indexing-slicing/main.go b/16-strings-revisited/03-string-indexing-slicing/main.go new file mode 100644 index 0000000..c0c8d77 --- /dev/null +++ b/16-strings-revisited/03-string-indexing-slicing/main.go @@ -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() { + // GOALS: + // 1- String value is immutable + // 2- Indexing vs Slicing + // 3- Using bytes for manipulating strings + + mood := "wonder" + + // 1- a string value is immutable (read-only) + // mood[1] = 'a' + + // 2- Indexing vs Slicing + + // "wonder" + // ^ ^^^^ + // | |||| + // "wandering" + + // "w" + "a" + "nder" + "ing" + + // wandering := mood[0] + "a" + mood[2:] + "ing" + // fmt.Printf("mood[0] : %T - %[1]v\n", mood[0]) // byte + // fmt.Printf("mood[0:1] : %T - %[1]v\n", mood[0:1]) // string + + // wandering := mood[:1] + "a" + mood[2:] + "ing" + fmt.Println(mood) + // fmt.Println(wandering) + + // 3- converting creates a new byte slice (allocation) + b := []byte(mood) + b[1] = 'a' + + // b = append(b, 'i', 'n', 'g') + // b = append(b, []byte{'i', 'n', 'g'}) + b = append(b, "ing"...) + + // starts copying from the first element + copy(b, "listen") + + // starts copying from the "7th" element + copy(b[6:], "ed.") + + fmt.Println(string(b)) +} diff --git a/16-strings-revisited/04-masker-challenge/main.go b/16-strings-revisited/04-masker-challenge/main.go new file mode 100644 index 0000000..14ca092 --- /dev/null +++ b/16-strings-revisited/04-masker-challenge/main.go @@ -0,0 +1,77 @@ +// 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/ +// + +/* +------------------------------------------------------------ +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. + +------------------------------------------------------------ +STEPS +------------------------------------------------------------ + +* Mask only links starting with http:// + +* Don't check for uppercase/lowercase letters + * The goal is to learn manipulating bytes in strings + * It's not about creating a 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: + + "Here's my spammy page: http://hehefouls.netHAHAHA see you." + "Here's my spammy page: http://******************* see you." +*/ +package main + +func main() { + // --------------------------------------------------------------- + // #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 + // --------------------------------------------------------------- + // 1- Loop and detect the http:// patterns + // 2- Copy the input character by character to the buffer + // 3- If you detect http:// pattern, copy the http:// first, + // then copy the *s instead of the original link until + // you see a whitespace character. + // + // Here: http://www.mylink.com Click! + // -> Here: http://************** Click! + // + + // --------------------------------------------------------------- + // #4 + // --------------------------------------------------------------- + // Print the buffer as a string +} diff --git a/16-strings-revisited/04-masker-challenge/spam.txt b/16-strings-revisited/04-masker-challenge/spam.txt new file mode 100644 index 0000000..6ad043d --- /dev/null +++ b/16-strings-revisited/04-masker-challenge/spam.txt @@ -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! \ No newline at end of file diff --git a/16-strings-revisited/05-masker-solution/main.go b/16-strings-revisited/05-masker-solution/main.go new file mode 100644 index 0000000..e3399fd --- /dev/null +++ b/16-strings-revisited/05-masker-solution/main.go @@ -0,0 +1,88 @@ +// 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 buffer with a sufficient size +#3- Write input to the buffer as it is and print it +#4- Detect the link +#5- Mask the link +#6- Detect white spaces and disable the masking +#7- Write http:// to the buffer, just before the link +*/ + +package main + +import ( + "fmt" + "os" +) + +const ( + link = "http://" + mask = '*' +) + +func main() { + args := os.Args[1:] + if len(args) != 1 { + fmt.Println("gimme somethin' to censor!") + return + } + + var ( + text = args[0] + size = len(text) + + // create a sufficient buffer for the output + // + // and adjust its slice pointer to the first element + // of the backing array! -> make(..., 0, ...) + buf = make([]byte, 0, size) + + in bool + ) + + for i := 0; i < size; i++ { + nlink := len(link) + + // 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 { + // jump to the next character after "http://" + i += nlink + + // set the flag: we're in a link! -> "http://....." + in = true + + // add the "http://" manually + buf = append(buf, link...) + } + + // 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 + } + + // add the current character to the buffer + buf = append(buf, c) + } + + // print out the buffer as text (string) + fmt.Println(string(buf)) +} diff --git a/16-strings-revisited/05-masker-solution/spam.txt b/16-strings-revisited/05-masker-solution/spam.txt new file mode 100644 index 0000000..6ad043d --- /dev/null +++ b/16-strings-revisited/05-masker-solution/spam.txt @@ -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! \ No newline at end of file diff --git a/16-strings-revisited/06-encoding/main.go b/16-strings-revisited/06-encoding/main.go new file mode 100644 index 0000000..3a6bb64 --- /dev/null +++ b/16-strings-revisited/06-encoding/main.go @@ -0,0 +1,144 @@ +// 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" +) + +// Please run this code and experiment with it +// Observe the results + +// USELESS-NOTE : "Öykü" means "Story" in Turkish! + +func main() { + fmt.Println("-----------------------------------") + fmt.Println("ASCII Codepoints") + fmt.Println("-----------------------------------") + + var ( + a, z byte = 'a', 'z' + A, Z byte = 'A', 'Z' + d0, d9 byte = '0', '9' + ) + + for _, c := range []byte{a, z, A, Z, d0, d9} { + fmt.Printf("%c - 1 byte - %[1]U - %[1]d\n", c) + } + + fmt.Println("\n-----------------------------------") + fmt.Println("Unicode Codepoints") + fmt.Println("-----------------------------------") + + var ( + Ö = 'Ö' + 栗 = '栗' + monkey = '🙉' + ) + for _, c := range []rune{rune(A), Ö, 栗, monkey} { + fmt.Printf("%c - %d bytes - %[1]U - %[1]d\n", c, cptb(c)) + } + + fmt.Println("\n-----------------------------------") + fmt.Println("UTF-8 Encoded") + fmt.Println("-----------------------------------") + + // utf8.RuneLen finds the number of bytes necessary for + // encoding a codepoint to utf8 + for _, c := range []rune{rune(A), Ö, 栗, monkey} { + fmt.Printf("%c - %d bytes - %[1]U - %[1]d\n", c, + utf8.RuneLen(c)) + } + + fmt.Println("\n-----------------------------------") + fmt.Println("Example: Unicode Codepoints") + fmt.Println("-----------------------------------") + + var ( + ö = 'ö' + y = 'y' + k = 'k' + ü = 'ü' + ) + + var ( + oykuRunes = []rune{ö, y, k, ü} + total int + ) + + for _, c := range oykuRunes { + fmt.Printf("%c - %d bytes - %[1]U - %[1]d\n", c, cptb(c)) + + // unsafe.Sizeof finds the memory size of simple values + // don't use it in production-level code -> it's unsafe! + total += int(unsafe.Sizeof(c)) + } + fmt.Printf("TOTAL: %d bytes.\n", total) + + fmt.Println("\n-----------------------------------") + fmt.Println("Example: Indexing") + fmt.Println("-----------------------------------") + + fmt.Printf("%c%c%c%c\n", + oykuRunes[0], oykuRunes[1], oykuRunes[2], + oykuRunes[len(oykuRunes)-1]) + + // string to []rune + oykuRunes = []rune("öykü") + fmt.Printf("%c%c%c%c\n", + oykuRunes[0], oykuRunes[1], oykuRunes[2], + oykuRunes[len(oykuRunes)-1]) + + fmt.Println("\n-----------------------------------") + fmt.Println("Example: UTF-8 Encoding") + fmt.Println("-----------------------------------") + + // this is also ok + // oykuString := string(oykuRunes) + + oykuString := "öykü" + + fmt.Printf("TOTAL bytes in oykuRunes : %d\n", total) + fmt.Printf("TOTAL bytes in oykuString: %d\n", len(oykuString)) + fmt.Printf("TOTAL runes in oykuString: %d\n", + utf8.RuneCountInString(oykuString)) + + fmt.Printf("Runes of oykuString : %s\n", oykuString) + fmt.Printf("Bytes of oykuString : % x\n", oykuString) + + fmt.Println() + for i := 0; i < len(oykuString); i++ { + fmt.Printf("oykuString[%d]: %c\n", i, oykuString[i]) + } + + // slicing returns a slice with the type of the sliced value + // so, the sliced value is a string, then a string is returned + // + // example: + // oykuString[0:2] is a string + fmt.Println() + fmt.Printf("oykuString[0:2]: %q\n", oykuString[0:2]) + fmt.Printf("oykuString[4:6]: %q\n", oykuString[4:6]) +} + +// ------------------------------------------------------------------- +// cptb finds how many bytes are necessary to represent a codepoint +// cptb means codepoint to bytes +func cptb(r rune) int { + switch { + case r <= 0xFF: // 255 + return 1 + case r <= 0xFFFF: // 65,535 + return 2 + case r <= 0xFFFFF: // 16,777,215 + return 3 + } + return 4 +} diff --git a/16-strings-revisited/07-encoding-examples/main.go b/16-strings-revisited/07-encoding-examples/main.go new file mode 100644 index 0000000..a61ab66 --- /dev/null +++ b/16-strings-revisited/07-encoding-examples/main.go @@ -0,0 +1,60 @@ +// 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() { + // try yourself: try other runes! + // you can find more here: https://unicode-table.com + // r := '🙉' + + // r := '\u011e' + r := 'Ğ' + + // only codepoint (can't be printed) + fmt.Printf("before encoding: %d\n", r) + fmt.Printf(" bits : %016b\n", r) + fmt.Printf(" bytes: % x\n", r) + + // utf-8 encoded string + encoded := string(r) + encodedBytes := []byte(encoded) + + fmt.Println() + fmt.Printf("after encoding: %q\n", encoded) + fmt.Printf(" bits : %8b\n", encodedBytes) + fmt.Printf(" bytes: % x\n", encodedBytes) + + // utf-8 string efficient to store and transmit + // but, it's harder to use. + // + // rune slice is inefficient. + // but, it's easy to use. + fmt.Println() + fmt.Println("string (utf-8) vs []rune (unicode)") + + s := "hava çok güzel 😳" + fmt.Printf("%q\n", s) + fmt.Printf(" size : %d bytes\n", len(s)) + fmt.Printf(" len : %d chars\n", utf8.RuneCountInString(s)) + fmt.Printf(" s[5] : %q\n", s[5]) + fmt.Printf(" s[5:7] : %q\n", s[5:7]) + + runes := []rune(s) + size := int(unsafe.Sizeof(runes[0])) * len(runes) + + fmt.Printf("\n%q\n", runes) + fmt.Printf(" size : %d bytes\n", size) + fmt.Printf(" len : %d chars\n", len(runes)) + fmt.Printf(" runes[5] : %q\n", runes[5]) +} diff --git a/16-strings-revisited/08-wrapper-example/main.go b/16-strings-revisited/08-wrapper-example/main.go new file mode 100644 index 0000000..d79344b --- /dev/null +++ b/16-strings-revisited/08-wrapper-example/main.go @@ -0,0 +1,66 @@ +// 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" + "unicode/utf8" +) + +const lineWidth = 40 + +func main() { + 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.` + + var lw int // line width + + for _, r := range text { + fmt.Printf("%c", r) + + switch lw++; { + case lw > lineWidth && r != '\n' && unicode.IsSpace(r): + fmt.Println() + fallthrough + case r == '\n': + lw = 0 + } + } + fmt.Println() +} + +// call it like: runeHandler(text) +func runeHandler(text string) { + for i := 0; i < len(text); { + r := rune(text[i]) + + size := 1 + if r > utf8.RuneSelf { + r, size = utf8.DecodeRuneInString(text[i:]) + // check out the other functions as well, play with them! + // + // for example (type these into the command-line): + // go doc utf8 + // go doc utf8 EncodeRune + } + i += size + + fmt.Printf("%c", r) + } +} + +// call it like: byteHandler(text) +func byteHandler(text string) { + for i := 0; i < len(text); i++ { + fmt.Printf("%c", text[i]) + } +} diff --git a/16-strings-revisited/09-internals/main.go b/16-strings-revisited/09-internals/main.go new file mode 100644 index 0000000..e5cfce7 --- /dev/null +++ b/16-strings-revisited/09-internals/main.go @@ -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) +} diff --git a/16-strings-revisited/README.md b/16-strings-revisited/README.md deleted file mode 100644 index 58094c8..0000000 --- a/16-strings-revisited/README.md +++ /dev/null @@ -1 +0,0 @@ -This section is in progress. I'm working hard to update the course all the time. Hold on! \ No newline at end of file diff --git a/16-strings-revisited/charset-table/main.go b/16-strings-revisited/charset-table/main.go new file mode 100644 index 0000000..eead3fb --- /dev/null +++ b/16-strings-revisited/charset-table/main.go @@ -0,0 +1,83 @@ +// 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" +) + +const ( + asciiStart = '\u0001' // 1 + asciiStop = '\u007f' // 127 + + cols = 1 +) + +func main() { + // DETERMINE START - STOP POSITIONS + 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 = asciiStart, asciiStop + } + + // PRINT HEADER + for i := 0; i < cols; i++ { + fmt.Printf("| %-6s %-8s %-8s %-14s", "rune", "dec", "code", "bytes") + } + fmt.Print("\n", strings.Repeat("-", 40*cols), "\n") + + // PRINT TABLE + for n, l := start, 0; n <= stop; n++ { + // draw the line + fmt.Printf("| %-6q %-8d %-8U % -14x", n, n, n, string(n)) + + // go to next line if columns are consumed + if l++; l%cols == 0 { + fmt.Println() + continue + } + } + fmt.Println() +} + +/* +EXAMPLE BLOCKS + +1 byte +------------------------------------------------------------ +asciiStart = '\u0001' -> 32 +asciiStop = '\u007f' -> 127 + +2 bytes +------------------------------------------------------------ +latin1Start = '\u0080' -> 128 +latin1Stop = '\u00ff' -> 255 + +3 bytes +------------------------------------------------------------ +dingbatStart = '\u2700' -> 9984 +dingbatStop = '\u27bf' -> 10175 + +4 bytes +------------------------------------------------------------ +emojiStart = '\U0001f600' -> 128512 +emojiStop = '\U0001f64f' -> 128591 +transportStart = '\U0001F680' -> 128640 +transportStop = '\U0001f6ff' -> 128767 + +BIG THANK YOU! -> https://unicode-table.com/ +*/ diff --git a/16-strings-revisited/notes.md b/16-strings-revisited/notes.md new file mode 100644 index 0000000..ebc6419 --- /dev/null +++ b/16-strings-revisited/notes.md @@ -0,0 +1,233 @@ +# Strings Revisited + +## Bytes +* ASCII +* Immutable + +## Runes +* Unicode +* vs ASCII +* UTF-8 +* Made up of bytes + +## Slicing +* String: Read-Only Byte Slice +* Slicing -> String +* Index -> Byte + +--- + +## Read-only byte slice +* A string is a read-only slice +* You can't change its data +* Indexable: Returns you a byte +* Slicable: Returns you a string + +## Slicing +* Strings can be sliced just like a slice +* After slicing Go returns you a new string slice +* WARNING: Indexing expression returns you a byte + * s := "hey" + * s[0] + s[1] + s[2] != "hey" + * s[0:3] == "hey + +## Underlying array +* Underlying array is a string array +* There's no capacity this time: Only length and pointer. + +* Sliced string will refer to that array +* String slicing is cheap — They share the same array + +## Unicode +* At the beginning there was only ASCII code standard + * It was using 7-bits to represents 128 characters + * Only English characters + * Each code corresponding to a character + +* After Internet nothing couldn't stay the same +* There was a need to introduce more languages +* 127 characters aren't enough for the entire world + +* So: Unicode is born +* It collects all of the characters in world's languages +* Unicode can represent every character in every imaginable language system. + +* Assigns each character to a codepoint or a rune (in Go) +* Unicode assigns each character a unique number, or code point. + +* Codepoint is a numeric number which represents a character in general +* U+2700 -> hex +* Unicode defines codepoints for 1m+ characters +* It includes the ASCII codes too + + A chinese character: 汉 + Its unicode value: U+6C49 + convert 6C49 to binary: 01101100 01001001 + embed 6C49 as UTF-8: 11100110 10110001 10001001 + + +## Unicode and Runes +* Rune is a 4-bytes type for storing unicode codepoints + +* Rune data type and rune codepoints are different things! + +* There's UTF-32 standard which assigns 4 bytes to each codepoint +* But, that's inefficient, so, instead Go uses a variable encoding standard called UTF-8. It assigns different number of bytes to codepoints. +* UTF-8 has been invented by Rob Pike and Ken Thompson (two of the creators of Go) + +* So, a rune is 1-4 bytes. Uses 1 byte for ASCII (english). +* 2-3 bytes for most of the characters. + +* A string can contain runes +* Each rune can span to multiple bytes +* WARNING: Getting one byte of a string may give you corrupt data + * If you're getting one part of a rune inside the string! + +* In a string with runes, you can't easily index the characters + * You need to use unicode and utf8 packages + * Or you need to convert the string into a rune slice + * unicode: letters vs nums, to uppercase, ... + * utf8 : working w/bytes and runes + +* RuneCountInString(s) == len([]rune(s)) +* DecodeRuneInString(s) returns the first rune + +## Ranging over strings +* You can range over a string like a slice +* It will jump over the runes inside the string +* The index variable will be the starting position of each rune + * And the value will be the rune itself + +## Representing bytes +* Unicode characters can be hard to type in code +* So, we can use \x and \u in a string to represent bytes and runes + +* A string literal is always utf-8 but a string value is not + +## Convenience +* It's easy to work with runes in code: []rune +* However, it will consume more memory: Each char is 4 bytes + +* "inanç"[4] = gibberish + +* r := []rune("inanç") -> five elements rune slice + * r[4] = 'ç' + * string(r) + * // inanç: automatically concatenates the runes to form a string + +* string(105) // i -> interprets 105 as a rune value; 'i' not 105 +* string(351) // ş -> "" + +* printf: %q -> 'ç' %c -> ç %d -> 231 + +## Bytes +* major libs: + * strings, bytes (have corresponding funcs) + * strconv, unicode + * bytes.Buffer + +* []byte can be modified whereas string is immutable + * if you do a lot of string manipulations you can use []byte + +* []byte <-> string convertable + * but, each conversion copies the data + * compiler optimizes it mostly + + * however, do not blindly convert; use bytes pkg + * it's like the string pkg + + * s := "inanc" + * b := []byte(s) + * s := string(b) + +## Sprintf +* Just like printf but instead of printing it returns a string + +## Builders +* bytes.Buffer +* strings.Builder + +* Use WriteRune when adding rune + + +## Terminology: +Summary: Unicode is a large table mapping characters to numbers and the different UTF encodings specify how these numbers are encoded as bits. + +* **ASCII** First character set that maps characters to codepoints or character codes. In terms of alphabets, it only supports basic latin alphabet: English. 2^7=127 + + * The center of the computer industry was in the USA at that time. As a consequence, they didn't need to support accents or other marks such as á, ü, ç, ñ, etc. + + * Once upon a time, computer memory and storage was very expensive. And all of the computers in the world (for practical purposes) were in the hands of English-speaking countries. + + * Single byte encoding only using the bottom 7 bits. Basic Latin. (Unicode code points 0-127.) No accents etc. + +* **Unicode** is a coded character set. A set of characters and a mapping between the characters and integer code points representing them. Unicode is a superset of ASCII. + + * You cannot save text to your hard drive as "Unicode". Unicode is an abstract representation of the text. You need to "encode" this abstract representation. That's where an encoding comes into play. + + * Unicode first and foremost defines a table of code points for characters. That's a fancy way of saying "65 stands for A, 66 stands for B and 9,731 stands for ☃" (seriously, it does). How these code points are actually encoded into bits is a different topic. + +* **UTF-8** is a character encoding - a way of converting from sequences of bytes to sequences of characters and vice versa. It covers the whole of the Unicode character set. + + * UTF-8 uses the ASCII set for the first 128 characters. That's handy because it means ASCII text is also valid in UTF-8. + +* **Character Set:** A character set is a list of characters with unique numbers (these numbers are sometimes referred to as “code points”). For example, in the Unicode character set, the number for A is 41. + +* **Codepoint:** Characters are referred to by their "Unicode code point". + + * Written in hexadecimal (to keep the numbers shorter). + + * Preceded by a "U+" (that's just what they do, it has no other meaning than "this is a Unicode code point"). + + * Unicode itself is a mapping, it defines codepoints and a codepoint is a number, associated with usually a character. + + * Code: a system of words, letters, figures, or other symbols substituted for other words, letters, etc. + +* **Encoding:** Converting data into a coded form. An encoding on the other hand, is an algorithm that translates a list of numbers to binary so it can be stored on disk. For example UTF-8 would translate the number sequence 1, 2, 3, 4 like this: `00000001 00000010 00000011 00000100`. Our data is now translated into binary and can now be saved to disk. + + * To encode means to use something to represent something else. An encoding is the set of rules with which to convert something from one representation to another. + + * To represent 1,114,112 different values, two bytes aren't enough. Three bytes are, but three bytes are often awkward to work with, so four bytes would be the comfortable minimum. But, unless you're actually using Chinese or some of the other characters with big numbers that take a lot of bits to encode, you're never going to use a huge chunk of those four bytes. + + * If the letter "A" was always encoded to 00000000 00000000 00000000 01000001, "B" always to 00000000 00000000 00000000 01000010 and so on, any document would bloat to four times the necessary size. + + * To optimize this, there are several ways to encode Unicode code points into bits. UTF-8 is one of them. + + character encoding bits + A UTF-8 01000001 + A UTF-16 00000000 01000001 + A UTF-32 00000000 00000000 00000000 01000001 + + U+0000 to U+007F are (correctly) encoded with one byte + U+0080 to U+07FF are encoded with 2 bytes + U+0800 to U+FFFF are encoded with 3 bytes + U+010000 to U+10FFFF are encoded with 4 bytes + + * There is NO string or text, without an accompanying encoding standard. + +## REFS: +https://unicode-table.com/en/ + +What's the difference between ASCII and Unicode? +https://stackoverflow.com/a/41198513/115363 + +https://stackoverflow.com/questions/643694/what-is-the-difference-between-utf-8-and-unicode + +https://stackoverflow.com/questions/3951722/whats-the-difference-between-unicode-and-utf-8 + +https://stackoverflow.com/questions/1543613/how-does-utf-8-variable-width-encoding-work + +http://kunststube.net/encoding/ +(detailed and simple) + +http://www.joelonsoftware.com/articles/Unicode.html + +Unicode codepoint to UTF-8 encoding answer: https://stackoverflow.com/a/27939161/115363 + +http://www.polylab.dk/utf8-vs-unicode.html + +Characters, Symbols and the Unicode Miracle - Computerphile +https://www.youtube.com/watch?v=MijmeoH9LT4 + +The history of UTF-8 as told by Rob Pike +http://doc.cat-v.org/bell_labs/utf-8_history \ No newline at end of file