gabrielleeyj
Navigate back to the homepage
About Me

Tests and more Go

Gabriel Lee
September 22nd, 2020 · 4 min read

Tests (DDMG)

Finally the end of the 3rd semester of my first year, for the past 2 weeks its been a roller coaster ride of emotions. First up it was my Database Design and Modelling (DDMG) Module exams, the questions covered the entire syllabus right from the start where there were questions about what Joins were Inner Joins, Outer Joins. Data dependency, Database Management Systems (DBMS) and Data Models. Focusing quite abit of questions on interpreting E-R Diagrams. First Normal Form (1NF), Second Normal Form (2NF) and Third Normal Form (3NF) how to normalize/denormalize data. The types of Entities and Relationships and what supertypes/subtypes, Software Development Lifecycle (SDLC) and Rapid Application Development (RAD) comparing the differences between the 2 development cycles.

It also covered MySQL commands on the DDL and DML aspects. Clauses, Queries, Keys and Operators. How you create a TABLE and link the key to another primary key of another table. Overall the exam was quite comprehensive as it covered most of the important points in a typical database.

Though the practical aspect of this module had only 8 contact hours of lab exercises. We managed to practice enough to understand how the MySQL commands worked. Creating tables, populating values into columns and setting the primary/foreign keys via command line instead of using the GUI.

Tests 2 (ISOG)

Next up it will be my Introduction to Systems Organisation test in another 2 days. In my opinion, the topics is really a very general overview of Computer Architecture. I probably will only know the results next month as this lecturer don’t seem to take responsibility to tell how well or bad you did on the tests / assignments. So its hard to gauge how well I will be doing for this module.

Go Go - Go Advanced

GoSchool started on the 10th to 16th, for Go Advanced we took a deeper dive into Golang. The first day was just an introduction for us to learn about what Algorithms are and what Data Structures are used for and its relation to Space-Time Complexity and Big-O Notation.

We covered:

  1. Data Structures
  2. Packages
  3. Error Handling
  4. Concurrency

Data Structures - Linked List

The very basics of a linked list. You have a Node which stores your data and a next which points to the next item on the linkedlist, and a Head which references to the Node. This was the solution we were tasked to create for practice, what I like about Golang is that you can determine how you want to structure your data easily. Because you can put a map into a struct value or a slice to a struct and just manipulate it easily.

1package main
2
3import "fmt"
4
5// Initialize the Node and create the linkedList
6type Node struct {
7 item string
8 next *Node*
9}
10
11type linkedList struct {
12 head *Node*
13 size int
14}
15
16
17func (p *linkedList) addNode(name string) error {
18 newNode := &Node{
19 item: name,
20 next: nil,
21 }
22 if p.head == nil {
23 p.head = newNode
24 } else {
25 currentNode := p.head
26 for currentNode.next != nil {
27 currentNode = currentNode.next
28 }
29 currentNode.next = newNode
30 }
31 p.size++
32 return nil
33}
34
35func (p *linkedList) printAllNodes() error {
36 currentNode := p.head
37 // Check if list is not empty, if empty return empty.
38 if currentNode == nil {
39 fmt.Println("Linked list is empty.")
40 return nil
41 }
42 fmt.Printf("%+v\n", currentNode.item)
43 for currentNode.next != nil {
44 currentNode = currentNode.next
45 fmt.Printf("%+v\n", currentNode.item)
46 }
47
48 return nil
49}
50
51// Remove Node
52func (p *linkedList) Remove(item string) error {
53 currentNode := p.head
54 // Check if currentNode exists
55 for currentNode != nil {
56 if currentNode.next.item == item {
57 currentNode.next = currentNode.next.next
58 return nil
59 }
60 currentNode = currentNode.next
61 }
62 return nil
63}
64
65// add at Position
66func (p *linkedList) addPos(item string, position int) error {
67 // Check if Position is valid if not return error.
68 if position < 0 || position > p.size {
69 return fmt.Errorf("Index out of bounds")
70 }
71
72 // Initialize variable addNode to Node Struct
73 addNode := Node{item, nil}
74
75 // Check whether existing Node with value exists if not take the first position 0
76 if position == 0 {
77 addNode.next = p.head
78 p.head = &addNode
79 return nil
80 }
81 node := p.head
82 j := 0
83 for j < position-2 {
84 j++
85 node = node.next
86 }
87 addNode.next = node.next
88 node.next = &addNode
89 p.size++
90 return nil
91}
92
93// get function
94func (p *linkedList) get(index int) (string, error) {
95 currentNode := p.head
96 if p.head == nil {
97 return "", fmt.Errorf("Empty Linked list")
98 }
99 if index > 0 && index <= p.size {
100 for i := 1; i <= index-1; i++ {
101 currentNode = currentNode.next
102 }
103 item := currentNode.item
104 return item, nil
105 }
106 return "", fmt.Errorf("Invalid index")
107}
108
109func main() {
110 myList := &linkedList{nil, 0}
111 fmt.Println("Created Linked List")
112 fmt.Println()
113
114 fmt.Print("Adding nodes to the linked list...\n\n")
115 myList.addNode("Mary")
116 myList.addNode("Jaina")
117 myList.addNode("Gabriel")
118 myList.addNode("Rabbya")
119 fmt.Println("Showing all nodes in the linked list...")
120 myList.printAllNodes()
121 fmt.Printf("There are %+v elements in the list in total. \n", myList.size)
122 fmt.Println()
123
124 fmt.Println("Removing Nodes...")
125 myList.Remove("Gabriel")
126 fmt.Println()
127 myList.printAllNodes()
128
129 fmt.Println("Add Node at Position..")
130 myList.addPos("Gabriel", 2)
131 fmt.Println()
132 myList.printAllNodes()
133}

So back to Linked Lists, they are a very versatile data structure but the complexity is Big-O of O(n). The more data there is the longer it will take. But then you can solve this by creating a sorting algorithm perhaps by sorting it alphabetically and query using any of the sorting algorithm depending on the query. Theoretically it should improve right? I’m not sure as I’m one of those non-Comp Sci students in this course and I don’t really fully understand how data structures work.

Data Structures - Stack

For a stack, its a data structure that is similar to how you stack boxes or books? First-In-Last-Out is what I can remember of it. Basically the first think that you put is at the top, the second thing you put becomes the new top and vice versa.

This was the solution that was half-complete. I couldn’t figure out how to create a function to check for parentheses. Logically you need to check the stack for an open and a closing parentheses. But I struggled with it so this is my partial answer, the rest of my classmates were definitely better as some of them are fresh out of Uni and/or have been developing in a different type of language previously.

I feel so inferior right now heh…

1package main
2
3import (
4 "errors"
5 "fmt"
6)
7
8// Node struct
9type Node struct {
10 item string
11 next *Node
12}
13
14type stack struct {
15 top *Node
16 size int
17}
18
19func (p *stack) push(name string) error {
20 newNode := &Node{
21 item: name,
22 next: nil,
23 }
24 if p.top == nil {
25 p.top = newNode
26 } else {
27 newNode.next = p.top
28 p.top = newNode
29 }
30 p.size++
31 return nil
32}
33
34func (p *stack) pop() (string, error) {
35 var item string
36
37 if p.top == nil {
38 return "", errors.New("Empty Stack")
39 }
40
41 item = p.top.item
42 if p.size == 1 {
43 p.top = nil
44 } else {
45 p.top = p.top.next
46 }
47 p.size--
48 return item, nil
49}
50
51func (p *stack) printAllNodes() error {
52 currentNode := p.top
53 if currentNode == nil {
54 fmt.Println("Stack is empty.")
55 return nil
56 }
57 fmt.Printf("%+v\n", currentNode.item)
58 for currentNode.next != nil {
59 currentNode = currentNode.next
60 fmt.Printf("%+v\n", currentNode.item)
61 }
62 return nil
63}
64
65var (
66 parentheses = map[string]string{
67 "(": ")",
68 "{": "}",
69 "[": "]",
70 }
71 openParentheses = "({["
72 closeParentheses = ")}]"
73)
74
75func main() {
76 myStack := &stack{nil, 0}
77 fmt.Println("Initializing Stack")
78 fmt.Println()
79
80 fmt.Println("Add in Stacks....")
81 myStack.push("Gabriel")
82 myStack.push("Ada")
83 myStack.push("Kai")
84 myStack.push("Rawr!")
85 fmt.Println("Stacks added...")
86 fmt.Println()
87
88 fmt.Println("Printing all Nodes...")
89 myStack.printAllNodes()
90 fmt.Println()
91
92 fmt.Println("Popping Top Node...")
93 myStack.pop()
94
95 fmt.Println("Printing all Nodes...")
96 myStack.printAllNodes()
97 fmt.Println()
98
99 fmt.Println("Printing Stack without function")
100
101 currentNode := myStack.top
102 if currentNode == nil {
103 fmt.Println("Stack is empty.")
104 } else {
105 fmt.Printf("%+v\n", currentNode.item)
106 for currentNode.next != nil {
107 currentNode = currentNode.next
108 fmt.Printf("%+v\n", currentNode.item)
109 }
110
111 }
112}

Data Structures - Queue

On Day 2 we were taught what a Queue was, basically its the reverse of a Stack. Since a Stack is First-In-Last-Out, a Queue is First-In-First-Out. Like what it says a Queue is a “queue”, like you queue for food and you are first in line. You get to choose first. All Singaporeans love to queue. No pun intended.

Here is the solution which is still not complete. In the assignment we were supposed to use the Queue data structure to check whether a word is a palindrome. A palindrome, is “A word, phrase, or sequence that reads the same backwards as forwards.”

Its getting harder by the day… I need more help!

1package main
2
3import (
4 "errors"
5 "fmt"
6)
7
8// Node Struct - Local
9type Node struct {
10 item string
11 next *Node
12}
13
14// Queue Struct Global
15type Queue struct {
16 front *Node
17 back *Node
18 size int
19}
20
21func (p *Queue) enqueue(name string) error {
22 newNode := &Node{
23 item: name,
24 next: nil,
25 }
26 if p.front == nil {
27 p.front = newNode
28
29 } else {
30 p.back.next = newNode
31
32 }
33 p.back = newNode
34 p.size++
35 return nil
36}
37
38func (p *Queue) dequeue() (string, error) {
39 var item string
40
41 if p.front == nil {
42 return "", errors.New("empty queue")
43 }
44
45 item = p.front.item
46 if p.size == 1 {
47 p.front = nil
48 p.back = nil
49 } else {
50 p.front = p.front.next
51 }
52 p.size--
53 return item, nil
54}
55
56func (p *Queue) printAllNodes() error {
57 currentNode := p.front
58 if currentNode == nil {
59 fmt.Println("Queue is empty.")
60 return nil
61 }
62 fmt.Printf("%+v\n", currentNode.item)
63 for currentNode.next != nil {
64 currentNode = currentNode.next
65 fmt.Printf("%+v\n", currentNode.item)
66 }
67
68 return nil
69}
70
71func (p *Queue) isEmpty() bool {
72 return p.size == 0
73}
74
75func createQueue() *Queue {
76 myQueue := &Queue{}
77 myQueue.enqueue("Gabriel")
78 myQueue.enqueue("Ada")
79 myQueue.enqueue("Jaina")
80 myQueue.enqueue("Proudmoore")
81 return myQueue
82}
83
84func printContent(p *Queue) {
85 p.printAllNodes()
86}
87
88func main() {
89 myQueueT := createQueue()
90
91 printContent(myQueueT)
92 fmt.Println()
93
94 myQueueT.dequeue()
95 myQueueT.printAllNodes()
96}

Data Structures - Binary Search Tree

On the third day, we learnt about Binary Search Tree (BST). I think its mainly used for robotics, automation and natural language processing. So we learnt the different types of traversal, InOrder, PreOrder, PostOrder and Level Order. A typical BST has a left, right, root. Depending on the type of traversal you get different results. Because the sequence will be different.

It was pretty fun and quite easy to understand the concept. But the implementation and getting the right results were tough.

1package main
2
3import "fmt"
4
5type bstnode struct {
6 name string
7 left *bstnode
8 right *bstnode
9}
10
11type bst struct {
12 root *bstnode
13}
14
15func (b *bst) reset() {
16 b.root = nil
17}
18
19func (b *bst) insert(name string) {
20 b.insertRec(b.root, name)
21}
22
23func (b *bst) insertRec(node *bstnode, name string) *bstnode {
24 if b.root == nil {
25 b.root = &bstnode{
26 name: name,
27 }
28 return b.root
29 }
30 if node == nil {
31 return &bstnode{name: name}
32 }
33 if name <= node.name {
34 node.left = b.insertRec(node.left, name)
35 }
36 if name > node.name {
37 node.right = b.insertRec(node.right, name)
38 }
39 return node
40}
41
42func (b *bst) find(name string) error {
43 node := b.findRec(b.root, name)
44 if node == nil {
45 return fmt.Errorf("Name: %s not found in tree", name)
46 }
47 fmt.Printf("%s is found in tree\n", name)
48 return nil
49}
50
51func (b *bst) findRec(node *bstnode, name string) *bstnode {
52 if node == nil {
53 return nil
54 }
55 if node.name == name {
56 return b.root
57 }
58 if name < node.name {
59 return b.findRec(node.left, name)
60 }
61 return b.findRec(node.right, name)
62}
63
64func (b *bst) inorder() {
65 b.inorderRec(b.root)
66}
67
68func (b *bst) inorderRec(node *bstnode) {
69 if node != nil {
70 b.inorderRec(node.left)
71 fmt.Println(node.name)
72 b.inorderRec(node.right)
73 }
74}
75
76func (b *bst) preorder() {
77 b.preorderRec(b.root)
78}
79
80func (b *bst) preorderRec(node *bstnode) {
81 if node != nil {
82 fmt.Println(node.name)
83 b.inorderRec(node.left)
84 b.inorderRec(node.right)
85 }
86}
87
88// Min returns the Item with min value stored in the tree
89func (b *bst) Min() *bstnode {
90 n := b.root
91 if n == nil {
92 return nil
93 }
94 for {
95 if n.left == nil {
96 return b.root
97 }
98 n = n.left
99 }
100}
101
102func main() {
103 bst := &bst{}
104 eg := []string{"John", "Wick", "Mary", "Jane", "Michael", "Angelo", "Tom", "Paul", "Jaina"}
105 for _, name := range eg {
106 bst.insert(name)
107 }
108
109 fmt.Printf("Printing Inorder:\n")
110 bst.inorder()
111 fmt.Println()
112
113 fmt.Printf("\nPrinting Preorder:\n")
114 bst.preorder()
115 fmt.Println()
116
117 fmt.Printf("\nFinding Values:\n")
118 ex := []string{"Mages", "Wick", "Freud", "Jane", "Michael", "Splinter", "Tom", "Jerry", "Jaina"}
119 for _, name := range ex {
120 bst.find(name)
121 }
122
123 fmt.Printf("\nFinding Min:\n")
124 bst.Min()
125
126}

Data Structures - More?

Yes to my understanding there are more data structures! Theres a doubly linked list, a heap, hash, graph. Though we didnt cover any of it. But its good to know perhaps.

Error Handling & Panics + Concurrency

So the entire course was a build-up to these topics. The main focus being Concurrency which is the whole idea why Golang is so efficient. Basically, Errors are just what you return to inform what went wrong in your program. Its always good to know why your program is not working right?

Errors can be used for tests and debugging. And you can use Panic, Defer, to control when it happens too! Thats amazing. The only major problem I had was understanding concurrency and the channels thingy. After reading online I basically get an understanding that you use channels via wg.Add() and then using go to print out concurrently the results. Of course you can see it in parallel because the command line prints line by line. But logically it will be run side by side?

1package main
2
3import (
4 "fmt"
5 "runtime"
6 "sync"
7)
8
9// initialize variable for Goroutine
10
11var wg sync.WaitGroup
12
13func main() {
14 runtime.GOMAXPROCS(1)
15
16 // Add a count of two, one for each goroutine.
17 wg.Add(2)
18 // Create two goroutines.
19 fmt.Println("Create Goroutines")
20 go printPrime("A")
21 go printPrime("B")
22
23 // Wait for the goroutines to finish.
24 fmt.Println("Waiting To Finish")
25 wg.Wait()
26 fmt.Println("Terminating Program")
27}
28
29// printPrime displays prime numbers for first 5000 numbers.
30func printPrime(prefix string) {
31
32 // call to Done to inform main
33
34 defer wg.Done()
35 next:
36 for outer := 2; outer < 5000; outer++ {
37 for inner := 2; inner < outer; inner++ {
38 if outer%inner == 0 {
39 continue
40 next
41 }
42 }
43 fmt.Printf("%s:%d\n", prefix, outer)
44 }
45 fmt.Println("Completed", prefix)
46}

For now I’m still learning and reading more about Golang from the stack of books i borrowed from the library. But none of it covers anything close to data structures which is what I worry about. Of course Google is your best friend, but it probably won’t help me in a technical interview right. Really worried if I could even secure a job at all in this situation. Will the topics get more complex? Perhaps. But I hope that I can pull through this successfully and get start afresh in this attempt to career switch.

More articles from gabrielleeyj

Go Go Gopher

It's been a pretty hectic month, there were many things to do. Tough decisions to make and ultimately a family to consider. Golang…

September 1st, 2020 · 2 min read

Basic Search Algorithms

What is an Algorithm? My understanding, its just mathematics. In its earliest form, its a set of equations derived to solve problems. In…

July 7th, 2020 · 2 min read
© 2020 gabrielleeyj
Link to $mailto:hello@gabrielleeyj.comLink to $https://github.com/kayigeLink to $https://www.linkedin.com/in/gabrielleeyj/Link to $https://www.instagram.com/gabrielleeyjLink to $https://www.facebook.com/melchsee