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