forked from steger/pr3-sose2026
Merge branch 'go' of https://gitty.informatik.th-mannheim.de/steger/pr3-code
commit
827232a5b4
20
README.md
20
README.md
|
|
@ -0,0 +1,20 @@
|
|||
# PR3 Code Repository
|
||||
|
||||
This repository contains all code of the PR3 lecture. This includes assignments. Solutions and code produced during the lecture is added incrementally during the semester.
|
||||
|
||||
## Usage
|
||||
|
||||
The code for each programming language is located in a dedicated subfolder. The individual development environment is defined by a [Development Container](https://containers.dev/) which ensures a uniform easy to set up coding experience on all platforms (Windows/MacOS/Linux). The following tools shall be available on the developer's machine:
|
||||
|
||||
- A [container runtime](https://en.wikipedia.org/wiki/OS-level_virtualization) such as [docker](https://www.docker.com/) or [podman](https://podman.io/). Windows users should install [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) beforehand.
|
||||
|
||||
- [Visual Studio Code](https://code.visualstudio.com/) along with the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
|
||||
|
||||
Follow these steps to get started:
|
||||
|
||||
1. Clone this repository into a local folder of your choice. Use a WSL folder on Windows.
|
||||
2. Navigate to the subfolder of the desired programming language (e.g. `cd pr3-xyz/go`).
|
||||
3. Open Visual Studio Code in that folder by executing `code .`
|
||||
4. Click on *Reopen in Container* in the popup that appears on the bottom right corner: 
|
||||
|
||||
This will open the folder in the dedicated *Development Container* that contains all required tools. Furthermore, programming language specific Visual Studio Code extensions are automatically installed inside the *Development Container* without affecting the host system.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
FROM golang:1.26-bookworm
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y build-essential \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG USERNAME=developer
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=$USER_UID
|
||||
RUN groupadd --gid $USER_GID $USERNAME && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "Go Dev Container",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"postCreateCommand": "go install github.com/go-delve/delve/cmd/dlv@latest && go install github.com/cweill/gotests/gotests@v1.9.0 && go install golang.org/x/tools/gopls@latest && go install golang.org/x/tools/cmd/goimports@latest && go install honnef.co/go/tools/cmd/staticcheck@latest",
|
||||
"customizations": {
|
||||
"vscode": { "extensions": [
|
||||
"golang.go",
|
||||
"gruntfuggly.todo-tree",
|
||||
"-github.copilot"
|
||||
]}
|
||||
},
|
||||
"remoteUser": "developer",
|
||||
"updateRemoteUserUID": true
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"chat.disableAIFeatures": true,
|
||||
"terminal.integrated.env.linux": {
|
||||
"EDITOR": "code --wait"
|
||||
},
|
||||
"terminal.integrated.profiles.linux": {
|
||||
"bash": {
|
||||
"path": "bash",
|
||||
"icon": "terminal-bash"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Hello World
|
||||
|
||||
## Run
|
||||
`go run hello-world.go`
|
||||
|
||||
## Build
|
||||
`go build hello-world.go`
|
||||
|
||||
## Formatting
|
||||
`go fmt hello-world.go`
|
||||
|
||||
## Linting
|
||||
`go vet hello-world.go`
|
||||
|
||||
### Examples
|
||||
1. `fmt.Printf("hello world, %s\n")`
|
||||
2. `a := 7` (already caught by the compiler)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
module gitty.informatik.th-mannheim.de/steger/pr3-sose2026/go/00-hello-world/hello-world
|
||||
|
||||
go 1.26.0
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("hello world")
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
# Go By Example
|
||||
<https://gobyexample.com/>
|
||||
|
||||
|
||||
# Assignment 1 - Simple Calculator
|
||||
|
||||
## Objective
|
||||
Write a Go program that performs basic mathematical operations (addition, subtraction, multiplication, and division) based on user input.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Define constants for valid operations (*add*,*subtract*,*multiply*,*divide*).
|
||||
2. Use variables to store user inputs and computed results.
|
||||
3. Use a loop to allow the user to perform multiple calculations until they choose to exit.
|
||||
4. Validate inputs using statements (e.g., handle division by zero).
|
||||
5. Use a statement to perform the selected mathematical operation.
|
||||
|
||||
## Example Output
|
||||
```
|
||||
Enter operation (add, subtract, multiply, divide, exit): add
|
||||
Enter the first number: 5
|
||||
Enter the second number: 3
|
||||
Result: 8
|
||||
|
||||
Enter operation (add, subtract, multiply, divide, exit): divide
|
||||
Enter the first number: 10
|
||||
Enter the second number: 0
|
||||
Error: Division by zero is not allowed!
|
||||
|
||||
Enter operation (add, subtract, multiply, divide, exit): exit
|
||||
Goodbye!
|
||||
```
|
||||
|
||||
## Hint
|
||||
The program can use the `fmt.Scan` function to accept user input.
|
||||
|
||||
# Assignment 2 - Inventory Management System
|
||||
|
||||
## Objective
|
||||
Create a program that simulates an inventory management system for a store.
|
||||
|
||||
## Steps
|
||||
1. Define product categories (e.g., Electronics, Groceries, Clothes) using `const` and `iota`.
|
||||
2. Store a fixed list of initial product names in an **array**.
|
||||
3. Convert the array into a **slice** so the inventory can grow or shrink dynamically.
|
||||
4. Use a **map** to associate product names with details like quantity, price, and category.
|
||||
5. Implement the following **functions**:
|
||||
- *AddProduct*: Add a new product to the inventory.
|
||||
- *RemoveProduct*: Remove a product from the inventory.
|
||||
- *DisplayInventory*: Display all products with their details.
|
||||
- *UpdateQuantity*: Update the quantity of a product.
|
||||
|
||||
## Example Output
|
||||
```
|
||||
Welcome to the Inventory Manager!
|
||||
|
||||
Initial Inventory:
|
||||
1. Laptop - Electronics (Price: $1000, Quantity: 5)
|
||||
2. Apples - Groceries (Price: $2, Quantity: 50)
|
||||
3. T-shirt - Clothes (Price: $10, Quantity: 20)
|
||||
|
||||
Adding a new product: Phone (Electronics, Price: $800, Quantity: 10)
|
||||
|
||||
Updated Inventory:
|
||||
1. Laptop - Electronics (Price: $1000, Quantity: 5)
|
||||
2. Apples - Groceries (Price: $2, Quantity: 50)
|
||||
3. T-shirt - Clothes (Price: $10, Quantity: 20)
|
||||
4. Phone - Electronics (Price: $800, Quantity: 10)
|
||||
|
||||
Updating quantity for Apples: New Quantity = 30
|
||||
|
||||
Removing product: T-shirt
|
||||
|
||||
Final Inventory:
|
||||
1. Laptop - Electronics (Price: $1000, Quantity: 5)
|
||||
2. Apples - Groceries (Price: $2, Quantity: 30)
|
||||
3. Phone - Electronics (Price: $800, Quantity: 10)
|
||||
```
|
||||
|
||||
- Use **arrays** to store initial product information.
|
||||
- Use **slices** to dynamically manage items in the inventory.
|
||||
- Use **maps** to track product details (e.g., quantity or price).
|
||||
- Define **functions** for adding, removing, and displaying products.
|
||||
- Use **enums** (via constants) to represent product categories.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
//TODO: implement according to README.md
|
||||
|
||||
//the following code just demonstrates how to use fmt.Scan
|
||||
|
||||
var str string
|
||||
fmt.Print("Please enter a string: ")
|
||||
fmt.Scan(&str)
|
||||
|
||||
var x float64
|
||||
fmt.Print("Please enter a float: ")
|
||||
fmt.Scan(&x)
|
||||
|
||||
fmt.Printf("You entered '%s' and %f\n", str, x)
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package main
|
||||
|
||||
type Product struct {
|
||||
Name string
|
||||
Price float64
|
||||
Quantity int
|
||||
Category string //TODO: use enum instead
|
||||
}
|
||||
|
||||
func addProduct(inventory *[]Product, name string, price float64, quantity int, category string) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
func removeProduct(inventory *[]Product, name string) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
func updateQuantity(inventory *[]Product, name string, newQuantity int) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
func displayInventory(inventory []Product) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
func main() {
|
||||
inventory := []Product{
|
||||
{Name: "Laptop", Price: 1000, Quantity: 5, Category: "Electronics"},
|
||||
{Name: "Apples", Price: 2, Quantity: 50, Category: "Groceries"},
|
||||
{Name: "T-shirt", Price: 10, Quantity: 20, Category: "Clothes"},
|
||||
}
|
||||
|
||||
// Display initial inventory
|
||||
displayInventory(inventory)
|
||||
|
||||
// Add a new product
|
||||
addProduct(&inventory, "Phone", 800, 10, "Electronics")
|
||||
|
||||
// Display updated inventory
|
||||
displayInventory(inventory)
|
||||
|
||||
// Update the quantity of an existing product
|
||||
updateQuantity(&inventory, "Apples", 30)
|
||||
|
||||
// Remove a product
|
||||
removeProduct(&inventory, "T-shirt")
|
||||
|
||||
// Display final inventory
|
||||
displayInventory(inventory)
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func SlicesIndex[S []E, E int](s []string, v string) int {
|
||||
for i := range s {
|
||||
if v == s[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
type List struct {
|
||||
head, tail *element
|
||||
}
|
||||
|
||||
type element struct {
|
||||
next *element
|
||||
val int
|
||||
}
|
||||
|
||||
func (lst *List) Push(v int) {
|
||||
if lst.tail == nil {
|
||||
lst.head = &element{val: v}
|
||||
lst.tail = lst.head
|
||||
} else {
|
||||
lst.tail.next = &element{val: v}
|
||||
lst.tail = lst.tail.next
|
||||
}
|
||||
}
|
||||
|
||||
func (lst *List) AllElements() []int {
|
||||
var elems []int
|
||||
for e := lst.head; e != nil; e = e.next {
|
||||
elems = append(elems, e.val)
|
||||
}
|
||||
return elems
|
||||
}
|
||||
|
||||
func main() {
|
||||
var s = []string{"foo", "bar", "zoo"}
|
||||
|
||||
fmt.Println("index of zoo:", SlicesIndex(s, "zoo"))
|
||||
|
||||
lst := List{}
|
||||
lst.Push(10)
|
||||
lst.Push(13)
|
||||
lst.Push(23)
|
||||
fmt.Println("list:", lst.AllElements())
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
f := createFile("/tmp/defer.txt")
|
||||
writeFile(f)
|
||||
closeFile(f)
|
||||
}
|
||||
|
||||
func createFile(p string) *os.File {
|
||||
fmt.Println("creating")
|
||||
f, err := os.Create(p)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func writeFile(f *os.File) {
|
||||
fmt.Println("writing")
|
||||
fmt.Fprintln(f, "data")
|
||||
}
|
||||
|
||||
func closeFile(f *os.File) {
|
||||
fmt.Println("closing")
|
||||
err := f.Close()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Assignment
|
||||
|
||||
Implement an arbitrary [design pattern](https://refactoring.guru/design-patterns/catalog) in Go.
|
||||
|
||||
1. Create a package named `patterns` in the `04-design-patterns` folder
|
||||
2. Implement the design pattern in that package
|
||||
3. Implement a corresponding unit test
|
||||
4. Create an example application that uses the design pattern in the file `04-design-patterns/main.go`
|
||||
5. Zip the source code and upload
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package main
|
||||
|
||||
func print(ci <-chan int) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
c := make(chan int)
|
||||
|
||||
c <- 1
|
||||
c <- 2
|
||||
c <- 3
|
||||
close(c)
|
||||
|
||||
print(c)
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mergeSortSequential(data []float64) {
|
||||
if len(data) <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
mid := len(data) / 2
|
||||
left := data[:mid]
|
||||
right := data[mid:]
|
||||
|
||||
mergeSortSequential(left)
|
||||
mergeSortSequential(right)
|
||||
|
||||
copy(data, merge(left, right))
|
||||
}
|
||||
|
||||
func merge(left, right []float64) []float64 {
|
||||
result := make([]float64, 0, len(left)+len(right))
|
||||
i, j := 0, 0
|
||||
|
||||
for i < len(left) && j < len(right) {
|
||||
if left[i] < right[j] {
|
||||
result = append(result, left[i])
|
||||
i++
|
||||
} else {
|
||||
result = append(result, right[j])
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, left[i:]...)
|
||||
result = append(result, right[j:]...)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
//1. DATA CREATION
|
||||
data := make([]float64, 1000*1000*20)
|
||||
|
||||
for i := range data {
|
||||
data[i] = rand.Float64() * 100 // Random floats between 0 and 100
|
||||
}
|
||||
|
||||
expected := make([]float64, len(data))
|
||||
copy(expected, data)
|
||||
sort.Float64s(expected)
|
||||
|
||||
//2. SORTING
|
||||
start := time.Now()
|
||||
|
||||
mergeSortSequential(data)
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("MergeSort took %s\n", elapsed)
|
||||
|
||||
//3. VERIFICATION
|
||||
if sort.Float64sAreSorted(data) {
|
||||
fmt.Println("Data is sorted correctly")
|
||||
} else {
|
||||
fmt.Println("Data is NOT sorted correctly")
|
||||
}
|
||||
|
||||
if len(data) != len(expected) {
|
||||
fmt.Println("Data and expected slices have different lengths")
|
||||
return
|
||||
}
|
||||
|
||||
for i := range data {
|
||||
if data[i] != expected[i] {
|
||||
fmt.Println("Data and expected slices do not match")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Data and expected slices match")
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
ch1 := make(chan string)
|
||||
|
||||
go func() {
|
||||
time.Sleep(time.Duration(rand.Intn(5)+1) * time.Second)
|
||||
ch1 <- "Message from channel 1"
|
||||
}()
|
||||
|
||||
msg1 := <-ch1
|
||||
println("Received:", msg1)
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
Loading…
Reference in New Issue