feat: Demo-Examples (Python/Rust/Go/C) mit Protokoll-Templates und Restore-Skript
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fb4e96919a
commit
64c2b7f0fd
21 changed files with 614 additions and 0 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -1,3 +1,10 @@
|
|||
*.bak
|
||||
node_modules/
|
||||
.DS_Store
|
||||
|
||||
# Build-Artefakte (Examples)
|
||||
examples/rust-wordcount/target/
|
||||
examples/**/__pycache__/
|
||||
examples/**/.pytest_cache/
|
||||
examples/**/Cargo.lock
|
||||
examples/**/ll_demo
|
||||
|
|
|
|||
74
examples/README.md
Normal file
74
examples/README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# pi-coder Beispielprojekte
|
||||
|
||||
Vier kleine, eigenständige Projekte als Demonstrationsgrundlage für die pi-coder-Features.
|
||||
Jedes Projekt startet bewusst unvollständig — genau der Ausgangspunkt, für den pi-coder gebaut ist.
|
||||
|
||||
## Übersicht
|
||||
|
||||
| Verzeichnis | Sprache | Demonstriert |
|
||||
|---|---|---|
|
||||
| `python-calculator/` | Python | `/optimize` mit `--test-cmd pytest` |
|
||||
| `rust-wordcount/` | Rust | `/optimize` mit `--test-cmd "cargo test"` + `/version` |
|
||||
| `go-fibonacci/` | Go | `/optimize --interactive` + `/continue` + `/shipit` |
|
||||
| `c-linkedlist/` | C | `/quick_check` + `/fix` + `/patch` |
|
||||
|
||||
## Demo-Workflow
|
||||
|
||||
### Schritt 1 — Vorbereitung: Sub-Repos anlegen
|
||||
|
||||
Jedes Example braucht ein eigenes git-Repo, damit pi-coder commit-basierte
|
||||
Features nutzen kann (Loop-Erkennung, Diff-Anzeige, `/version`):
|
||||
|
||||
```bash
|
||||
for dir in python-calculator rust-wordcount go-fibonacci c-linkedlist; do
|
||||
cd examples/$dir
|
||||
git init && git add -A && git commit -m "feat: initial $dir"
|
||||
cd ../..
|
||||
done
|
||||
```
|
||||
|
||||
Für `/version` im rust-wordcount-Beispiel zusätzlich:
|
||||
|
||||
```bash
|
||||
cd examples/rust-wordcount && git tag v0.1.0
|
||||
```
|
||||
|
||||
### Schritt 2 — Demo ausführen
|
||||
|
||||
In pi das jeweilige Unterverzeichnis als Arbeitsverzeichnis öffnen.
|
||||
Die genauen Befehle stehen im README.md des jeweiligen Examples.
|
||||
Zeitmessung: Systemuhr notieren oder Terminal-Kommando `time` nutzen.
|
||||
|
||||
### Schritt 3 — Protokoll ausfüllen
|
||||
|
||||
Jedes Example enthält eine `PROTOKOLL.md`.
|
||||
Startzeit, Endzeit, Rundenanzahl und Endergebnis eintragen.
|
||||
|
||||
### Schritt 4 — Ausgangszustand wiederherstellen
|
||||
|
||||
```bash
|
||||
bash examples/restore-all.sh
|
||||
```
|
||||
|
||||
Das Skript löscht Sub-Repos, restauriert alle Quelldateien aus dem Haupt-Repo
|
||||
und bereinigt Build-Artefakte (`target/`, `__pycache__` etc.).
|
||||
|
||||
---
|
||||
|
||||
## Empfohlene Demo-Reihenfolge
|
||||
|
||||
| # | Beispiel | Geschätzte Dauer | Highlights |
|
||||
|---|---|---|---|
|
||||
| 1 | `python-calculator` | ~5–10 min | Einstieg, Test-Loop |
|
||||
| 2 | `c-linkedlist` | ~5 min | `/quick_check` + `/fix`, kein Loop |
|
||||
| 3 | `rust-wordcount` | ~10–15 min | Loop + `/version` |
|
||||
| 4 | `go-fibonacci` | ~15–20 min | `--interactive` + `/shipit` |
|
||||
|
||||
---
|
||||
|
||||
## Weitere Details
|
||||
|
||||
[python-calculator](python-calculator/README.md) ·
|
||||
[rust-wordcount](rust-wordcount/README.md) ·
|
||||
[go-fibonacci](go-fibonacci/README.md) ·
|
||||
[c-linkedlist](c-linkedlist/README.md)
|
||||
35
examples/c-linkedlist/PROTOKOLL.md
Normal file
35
examples/c-linkedlist/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Demo-Protokoll: c-linkedlist
|
||||
|
||||
## Lauf 1
|
||||
|
||||
**Datum:**
|
||||
|
||||
**Befehl /quick_check:**
|
||||
```
|
||||
/quick_check "Gibt es Speicherlecks oder sonstige Probleme in diesem C-Projekt?"
|
||||
```
|
||||
**Startzeit:**
|
||||
**Endzeit:**
|
||||
**Dauer (min):**
|
||||
**Ergebnis:** OK / PROBLEM (Kurzbeschreibung):
|
||||
|
||||
**Befehl /fix:**
|
||||
```
|
||||
/fix "Implementiere list_free() korrekt, sodass valgrind --leak-check=full sauber ist."
|
||||
```
|
||||
**Startzeit:**
|
||||
**Endzeit:**
|
||||
**Dauer (min):**
|
||||
**Ergebnis:** erledigt / fehlgeschlagen
|
||||
|
||||
**Befehl /patch (optional):**
|
||||
```
|
||||
/patch "Ergänze list_search(head, value) in Header und Implementierung.
|
||||
Gibt den ersten Node* mit dem gesuchten Wert zurück, oder NULL."
|
||||
```
|
||||
**Startzeit:**
|
||||
**Endzeit:**
|
||||
**Dauer (min):**
|
||||
**Besonderheiten / Beobachtungen:**
|
||||
|
||||
---
|
||||
48
examples/c-linkedlist/README.md
Normal file
48
examples/c-linkedlist/README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# C Linked List
|
||||
|
||||
Vollständige einfach-verkettete Liste — bis auf `list_free()`, das als leerer Stub vorliegt.
|
||||
Jeder Programmlauf leckt den gesamten Listen-Speicher.
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
```
|
||||
linked_list.h Interface: node_new, list_prepend, list_append, list_print, list_free, list_length
|
||||
linked_list.c Alles implementiert — außer list_free() (Stub, tut nichts)
|
||||
main.c Baut Liste 1–5, gibt sie aus, ruft list_free() auf (ohne Wirkung)
|
||||
```
|
||||
|
||||
## Demo 1: `/quick_check` als Diagnose
|
||||
|
||||
```
|
||||
/quick_check "Gibt es Speicherlecks oder sonstige Probleme in diesem C-Projekt?"
|
||||
```
|
||||
|
||||
Der Judge analysiert den Code und identifiziert das leere `list_free()` als Speicherleck-Quelle.
|
||||
|
||||
## Demo 2: `/fix` für gezieltes Nacharbeiten
|
||||
|
||||
```
|
||||
/fix "Implementiere list_free() korrekt, sodass valgrind --leak-check=full sauber ist."
|
||||
```
|
||||
|
||||
Coder implementiert die Funktion, committet. Kein vollständiger Judge-Loop —
|
||||
ideal für kleine, klar abgegrenzte Fixes.
|
||||
|
||||
## Demo 3: `/patch` für Minimal-Erweiterungen
|
||||
|
||||
```
|
||||
/patch "Ergänze list_search(head, value) in Header und Implementierung.
|
||||
Gibt den ersten Node* mit dem gesuchten Wert zurück, oder NULL."
|
||||
```
|
||||
|
||||
pi-coder wendet einen unified diff an (`apply_patch`-Tool), ohne den vollständigen Loop.
|
||||
|
||||
## Manueller Build
|
||||
|
||||
```bash
|
||||
gcc -Wall -Wextra -o ll_demo linked_list.c main.c
|
||||
./ll_demo
|
||||
|
||||
# Mit Leak-Check:
|
||||
valgrind --leak-check=full ./ll_demo
|
||||
```
|
||||
43
examples/c-linkedlist/linked_list.c
Normal file
43
examples/c-linkedlist/linked_list.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "linked_list.h"
|
||||
|
||||
Node *node_new(int value) {
|
||||
Node *n = malloc(sizeof(Node));
|
||||
n->value = value;
|
||||
n->next = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
Node *list_prepend(Node *head, int value) {
|
||||
Node *n = node_new(value);
|
||||
n->next = head;
|
||||
return n;
|
||||
}
|
||||
|
||||
Node *list_append(Node *head, int value) {
|
||||
Node *n = node_new(value);
|
||||
if (!head) return n;
|
||||
Node *cur = head;
|
||||
while (cur->next) cur = cur->next;
|
||||
cur->next = n;
|
||||
return head;
|
||||
}
|
||||
|
||||
void list_print(const Node *head) {
|
||||
for (const Node *cur = head; cur; cur = cur->next)
|
||||
printf("%d ", cur->value);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* BUG: Speicher wird nicht freigegeben — valgrind meldet Leaks. */
|
||||
void list_free(Node *head) {
|
||||
(void)head; /* TODO: implementieren */
|
||||
}
|
||||
|
||||
int list_length(const Node *head) {
|
||||
int len = 0;
|
||||
for (const Node *cur = head; cur; cur = cur->next)
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
16
examples/c-linkedlist/linked_list.h
Normal file
16
examples/c-linkedlist/linked_list.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef LINKED_LIST_H
|
||||
#define LINKED_LIST_H
|
||||
|
||||
typedef struct Node {
|
||||
int value;
|
||||
struct Node *next;
|
||||
} Node;
|
||||
|
||||
Node *node_new(int value);
|
||||
Node *list_prepend(Node *head, int value);
|
||||
Node *list_append(Node *head, int value);
|
||||
void list_print(const Node *head);
|
||||
void list_free(Node *head);
|
||||
int list_length(const Node *head);
|
||||
|
||||
#endif
|
||||
16
examples/c-linkedlist/main.c
Normal file
16
examples/c-linkedlist/main.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
#include "linked_list.h"
|
||||
|
||||
int main(void) {
|
||||
Node *list = NULL;
|
||||
|
||||
for (int i = 1; i <= 5; i++)
|
||||
list = list_append(list, i);
|
||||
|
||||
printf("Liste: ");
|
||||
list_print(list);
|
||||
printf("Länge: %d\n", list_length(list));
|
||||
|
||||
list_free(list); /* leckt wegen unvollständigem TODO */
|
||||
return 0;
|
||||
}
|
||||
37
examples/go-fibonacci/PROTOKOLL.md
Normal file
37
examples/go-fibonacci/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Demo-Protokoll: go-fibonacci
|
||||
|
||||
## Lauf 1
|
||||
|
||||
**Datum:**
|
||||
**Befehl:**
|
||||
```
|
||||
/optimize "Ersetze die naive Rekursion durch Memoization.
|
||||
fib(50) soll in unter 1ms abgeschlossen sein.
|
||||
Bestehende Tests müssen weiterhin grün bleiben." \
|
||||
--test-cmd "go test ./..." --interactive
|
||||
```
|
||||
**Startzeit:**
|
||||
**Ende Loop (PASS):**
|
||||
**Dauer Loop (min):**
|
||||
**Runden:**
|
||||
**Endergebnis Loop:** PASS / PASS WITH CONCERNS
|
||||
|
||||
**Befehl im --interactive-Checkpoint:**
|
||||
```
|
||||
/continue "Gib zusätzlich die Berechnungszeit in Mikrosekunden aus."
|
||||
```
|
||||
*(oder: `/continue` ohne Zusatzauftrag)*
|
||||
|
||||
**Startzeit /continue:**
|
||||
**Ende /continue:**
|
||||
|
||||
**Befehl /shipit:**
|
||||
```
|
||||
/shipit
|
||||
```
|
||||
**Startzeit /shipit:**
|
||||
**Endzeit /shipit:**
|
||||
**Endergebnis /shipit:** SHIP / NO-SHIP
|
||||
**Besonderheiten / Beobachtungen:**
|
||||
|
||||
---
|
||||
48
examples/go-fibonacci/README.md
Normal file
48
examples/go-fibonacci/README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Go Fibonacci
|
||||
|
||||
Naive rekursive Fibonacci-Implementierung — korrekt, aber exponentiell langsam.
|
||||
`fib(45)` dauert mehrere Sekunden; `fib(50)` läuft praktisch nicht durch.
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
```
|
||||
main.go fib(n) — rekursiv, O(2^n)
|
||||
main_test.go TestFib mit 5 Tabellen-Tests (alle grün)
|
||||
```
|
||||
|
||||
## Demo 1: `/optimize --interactive`
|
||||
|
||||
```
|
||||
/optimize "Ersetze die naive Rekursion durch Memoization.
|
||||
fib(50) soll in unter 1ms abgeschlossen sein.
|
||||
Bestehende Tests müssen weiterhin grün bleiben." \
|
||||
--test-cmd "go test ./..." --interactive
|
||||
```
|
||||
|
||||
Nach dem ersten PASS hält pi-coder im **interaktiven Checkpoint** an.
|
||||
Hier kann ein Zusatzauftrag erteilt werden:
|
||||
|
||||
```
|
||||
/continue "Gib zusätzlich die Berechnungszeit in Mikrosekunden aus."
|
||||
```
|
||||
|
||||
Oder einfach bestätigen:
|
||||
|
||||
```
|
||||
/continue
|
||||
```
|
||||
|
||||
## Demo 2: Abschluss mit `/shipit`
|
||||
|
||||
```
|
||||
/shipit
|
||||
```
|
||||
|
||||
Der Judge prüft nochmals explizit auf Produktionsreife und gibt SHIP oder NO-SHIP zurück.
|
||||
|
||||
## Manueller Test
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
go run main.go
|
||||
```
|
||||
3
examples/go-fibonacci/go.mod
Normal file
3
examples/go-fibonacci/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module fibonacci
|
||||
|
||||
go 1.21
|
||||
18
examples/go-fibonacci/main.go
Normal file
18
examples/go-fibonacci/main.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// fib berechnet die n-te Fibonacci-Zahl rekursiv.
|
||||
// Korrekt, aber für n > 40 sehr langsam (exponentiell).
|
||||
func fib(n int) int {
|
||||
if n <= 1 {
|
||||
return n
|
||||
}
|
||||
return fib(n-1) + fib(n-2)
|
||||
}
|
||||
|
||||
func main() {
|
||||
for i := 0; i <= 10; i++ {
|
||||
fmt.Printf("fib(%2d) = %d\n", i, fib(i))
|
||||
}
|
||||
}
|
||||
20
examples/go-fibonacci/main_test.go
Normal file
20
examples/go-fibonacci/main_test.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFib(t *testing.T) {
|
||||
cases := []struct {
|
||||
n, want int
|
||||
}{
|
||||
{0, 0},
|
||||
{1, 1},
|
||||
{2, 1},
|
||||
{5, 5},
|
||||
{10, 55},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := fib(c.n); got != c.want {
|
||||
t.Errorf("fib(%d) = %d, want %d", c.n, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
19
examples/python-calculator/PROTOKOLL.md
Normal file
19
examples/python-calculator/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Demo-Protokoll: python-calculator
|
||||
|
||||
## Lauf 1
|
||||
|
||||
**Datum:**
|
||||
**Befehl:**
|
||||
```
|
||||
/optimize "Ergänze multiply, divide (wirft ZeroDivisionError bei 0) und power.
|
||||
Schreibe pytest-Tests für alle neuen Funktionen." \
|
||||
--test-cmd "pytest test_calculator.py -v"
|
||||
```
|
||||
**Startzeit:**
|
||||
**Endzeit:**
|
||||
**Dauer (min):**
|
||||
**Runden:**
|
||||
**Endergebnis:** PASS / PASS WITH CONCERNS / SHIP / NO-SHIP
|
||||
**Besonderheiten / Beobachtungen:**
|
||||
|
||||
---
|
||||
51
examples/python-calculator/README.md
Normal file
51
examples/python-calculator/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Python Calculator
|
||||
|
||||
Einfacher Taschenrechner mit `add()` und `subtract()`.
|
||||
Multiply, divide, power und Fehlerbehandlung fehlen noch.
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
```
|
||||
calculator.py add(), subtract()
|
||||
test_calculator.py 5 pytest-Tests (alle grün)
|
||||
```
|
||||
|
||||
## Demo: `/optimize` mit Test-Integration
|
||||
|
||||
```
|
||||
/optimize "Ergänze multiply, divide (wirft ZeroDivisionError bei 0) und power.
|
||||
Schreibe pytest-Tests für alle neuen Funktionen." \
|
||||
--test-cmd "pytest test_calculator.py -v"
|
||||
```
|
||||
|
||||
**Was pi-coder hier zeigt:**
|
||||
- Coder implementiert, committet
|
||||
- Extension führt `pytest` aus und übergibt das Ergebnis an den Judge
|
||||
- Judge bewertet Korrektheit anhand der Testergebnisse
|
||||
- Bei FAIL: Coder fixt, nächste Runde
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
```bash
|
||||
pip install pytest
|
||||
```
|
||||
|
||||
## Weitere Demo-Befehle nach dem `/optimize`-Lauf
|
||||
|
||||
```
|
||||
/quick_check "Sind alle Randfälle (negative Zahlen, floats) korrekt behandelt?"
|
||||
```
|
||||
Schnelle Einzel-Beurteilung ohne neuen Fix-Loop.
|
||||
|
||||
```
|
||||
/update_doku
|
||||
```
|
||||
Lässt den Coder Code-Kommentare ergänzen, README aktualisieren und eine
|
||||
Bedienungsanleitung erzeugen.
|
||||
|
||||
## Manueller Test
|
||||
|
||||
```bash
|
||||
pytest test_calculator.py -v
|
||||
python calculator.py
|
||||
```
|
||||
11
examples/python-calculator/calculator.py
Normal file
11
examples/python-calculator/calculator.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
def add(a, b):
|
||||
return a + b
|
||||
|
||||
|
||||
def subtract(a, b):
|
||||
return a - b
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(add(3, 4)) # 7
|
||||
print(subtract(10, 3)) # 7
|
||||
18
examples/python-calculator/test_calculator.py
Normal file
18
examples/python-calculator/test_calculator.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import pytest
|
||||
from calculator import add, subtract
|
||||
|
||||
|
||||
def test_add_positive():
|
||||
assert add(2, 3) == 5
|
||||
|
||||
def test_add_negative():
|
||||
assert add(-1, 1) == 0
|
||||
|
||||
def test_add_zero():
|
||||
assert add(0, 0) == 0
|
||||
|
||||
def test_subtract_basic():
|
||||
assert subtract(5, 3) == 2
|
||||
|
||||
def test_subtract_negative_result():
|
||||
assert subtract(3, 5) == -2
|
||||
31
examples/restore-all.sh
Executable file
31
examples/restore-all.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
# Stellt den Ausgangszustand aller Examples wieder her.
|
||||
# Löscht erzeugte Sub-Repos, restauriert Quelldateien aus dem Haupt-Repo
|
||||
# und bereinigt Build-Artefakte.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(git -C "$(dirname "$0")" rev-parse --show-toplevel)"
|
||||
EXAMPLES="$ROOT/examples"
|
||||
|
||||
echo "Stelle Examples-Ausgangszustand wieder her..."
|
||||
|
||||
for dir in python-calculator rust-wordcount go-fibonacci c-linkedlist; do
|
||||
path="$EXAMPLES/$dir"
|
||||
if [ -d "$path/.git" ]; then
|
||||
rm -rf "$path/.git"
|
||||
echo " ✓ Sub-Repo entfernt: $dir"
|
||||
fi
|
||||
git -C "$ROOT" checkout -- "examples/$dir/"
|
||||
echo " ✓ Dateien restauriert: $dir"
|
||||
done
|
||||
|
||||
# Build-Artefakte bereinigen
|
||||
rm -rf "$EXAMPLES/rust-wordcount/target"
|
||||
find "$EXAMPLES" -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$EXAMPLES" -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$EXAMPLES" -name "ll_demo" -delete 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "Fertig. Alle Examples sind im Ausgangszustand."
|
||||
echo "git status zeigt examples/ als clean (wenn kein PROTOKOLL.md verändert wurde)."
|
||||
4
examples/rust-wordcount/Cargo.toml
Normal file
4
examples/rust-wordcount/Cargo.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[package]
|
||||
name = "wordcount"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
29
examples/rust-wordcount/PROTOKOLL.md
Normal file
29
examples/rust-wordcount/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Demo-Protokoll: rust-wordcount
|
||||
|
||||
## Lauf 1
|
||||
|
||||
**Datum:**
|
||||
**Befehl:**
|
||||
```
|
||||
/optimize "Ergänze --lines (Zeilenzählung) und --chars (Zeichenzählung) als CLI-Flags.
|
||||
Ohne Flag: Standardausgabe wie bisher (Wörter).
|
||||
Schreibe Tests für alle drei Modi." \
|
||||
--test-cmd "cargo test"
|
||||
```
|
||||
**Startzeit:**
|
||||
**Endzeit:**
|
||||
**Dauer /optimize (min):**
|
||||
**Runden:**
|
||||
**Endergebnis /optimize:** PASS / PASS WITH CONCERNS / SHIP / NO-SHIP
|
||||
|
||||
**Befehl /version:**
|
||||
```
|
||||
/version
|
||||
```
|
||||
**Startzeit /version:**
|
||||
**Endzeit /version:**
|
||||
**Gewählter Bump:** patch / minor / major
|
||||
**Gesetzter Tag:**
|
||||
**Besonderheiten / Beobachtungen:**
|
||||
|
||||
---
|
||||
50
examples/rust-wordcount/README.md
Normal file
50
examples/rust-wordcount/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Rust Word Counter
|
||||
|
||||
Liest stdin und gibt die Anzahl der Wörter aus.
|
||||
Zeilen- und Zeichenzählung sowie CLI-Flags fehlen noch.
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
```
|
||||
src/main.rs count_words() — nur Wortzählung, kein Argument-Parsing
|
||||
Cargo.toml Version 0.1.0
|
||||
```
|
||||
|
||||
## Demo 1: `/optimize` mit Cargo-Test-Integration
|
||||
|
||||
```
|
||||
/optimize "Ergänze --lines (Zeilenzählung) und --chars (Zeichenzählung) als CLI-Flags.
|
||||
Ohne Flag: Standardausgabe wie bisher (Wörter).
|
||||
Schreibe Tests für alle drei Modi." \
|
||||
--test-cmd "cargo test"
|
||||
```
|
||||
|
||||
**Was pi-coder hier zeigt:**
|
||||
- Rust-Toolchain wird automatisch erkannt
|
||||
- `cargo test`-Output geht an den Judge
|
||||
- Mehrere Compile-Test-Fix-Zyklen möglich
|
||||
|
||||
## Demo 2: `/version` nach dem Feature
|
||||
|
||||
**Voraussetzung:** Das Verzeichnis muss ein git-Repo mit mindestens einem Commit sein.
|
||||
Falls noch kein Repo existiert, vorher einmalig:
|
||||
|
||||
```bash
|
||||
git init && git add -A && git commit -m "feat: initial wordcount"
|
||||
git tag v0.1.0
|
||||
```
|
||||
|
||||
```
|
||||
/version
|
||||
```
|
||||
|
||||
Analysiert die Commits seit `v0.1.0`, erkennt `feat:`-Commits → schlägt `minor`-Bump vor
|
||||
und setzt den Git-Tag `v0.2.0`.
|
||||
|
||||
## Manueller Test
|
||||
|
||||
```bash
|
||||
cargo test
|
||||
echo "Hallo Welt" | cargo run
|
||||
echo -e "Zeile 1\nZeile 2" | cargo run -- --lines
|
||||
```
|
||||
36
examples/rust-wordcount/src/main.rs
Normal file
36
examples/rust-wordcount/src/main.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use std::io::{self, Read};
|
||||
|
||||
fn count_words(text: &str) -> usize {
|
||||
text.split_whitespace().count()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input).unwrap();
|
||||
println!("{} words", count_words(&input));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_empty_input() {
|
||||
assert_eq!(count_words(""), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_word() {
|
||||
assert_eq!(count_words("hallo"), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_words() {
|
||||
assert_eq!(count_words("eins zwei drei"), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extra_whitespace() {
|
||||
assert_eq!(count_words(" a b "), 2);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue