basic a2
This commit is contained in:
124
a1-Schiebeparkplatz/Aufgabe1.md
Normal file
124
a1-Schiebeparkplatz/Aufgabe1.md
Normal file
@ -0,0 +1,124 @@
|
||||
# Schiebeparkplatz
|
||||
|
||||
## Lösungsidee
|
||||
|
||||
Für jede normale Textdatei wird ASCII encoding verwendet bzw. ein Encoding
|
||||
Standart welcher auf ASCII basiert und zusätzliche Sonderzeichen enthält,
|
||||
wobei die Werte die bereits in ASCII enthalten übernommen wurden.
|
||||
Die ASCII codes für die Buchstaben sind entsprechend des Alphabets
|
||||
hintereinander angeordnet. Dies ist sehr nützlich, da somit eine Liste der
|
||||
Buchstaben und deren Position im Alphabet nicht benötigt wird.<br>
|
||||
Zur Lösung des Parkplatzproblems werden die Autos wenn möglich nach links bzw.
|
||||
rechts verschoben bis die Parklücke frei ist. Je nachdem in welche Richtung
|
||||
weniger Autos verschoben werden müssen, wird die Verschiebungsrichtung gewählt.
|
||||
|
||||
## Umsetzung
|
||||
|
||||
Da die Lösung des Problem keine besondere Library benötigt wird und die Anforderungen
|
||||
an die Ausführungsgeschwindigkeit gering sind, hätte man fast jede Progmiersprache
|
||||
wählen können. Ich habe mich für Go entschieden.<br>
|
||||
Das Programm akzeptiert als Argumente eine beliebige Anzahl an Pfaden zu Parkplatzdatein.
|
||||
Für das Iterieren über die Argumente wird eine for-Schleife benutzt.
|
||||
Innerhalb der Schleife wird die Eingabedatei ausgelesen. Anhand des ersten und letzten
|
||||
Buchstaben der Autos auf den normalen Parkplätzen wird die die Anzahl an Parkplätzen
|
||||
bestimmt. Anschließend wird eine Slice (ein dynamisch vergrößerbares Array in Go)
|
||||
mit den Buchstaben der quer parkenden Autos befüllt an den Indexen an denen sie die
|
||||
normalen Parkplätze blockieren.<br>
|
||||
In einer for-Schleife wird die "move"-Funktion je Index der Parkplätze doppelt
|
||||
für beide Verschiebungsrichtungen aufgerufen.
|
||||
In der "move"-Funktion wird ein Auto verschoben, wenn nicht das Ende des
|
||||
Parkplatzes erreicht ist. Die Funktion ruft sich recursive auf um weitere Autos zu
|
||||
verschieben. Je nachdem in welche Richtung weniger Autos verschoben werden müssen
|
||||
oder, wenn es gleich viele sind, wo die Anzahl der verschobenen Plätze aller Autos
|
||||
geringer ist, wird sich für das Verschieben in diese Richtung entschieden.
|
||||
|
||||
## Beispiele
|
||||
|
||||
```
|
||||
parkplatz0.txt:
|
||||
A:
|
||||
B:
|
||||
C: H 1 rechts
|
||||
D: H 1 links
|
||||
E:
|
||||
F: H 1 links, I 2 links
|
||||
G: I 1 links
|
||||
parkplatz1.txt:
|
||||
A:
|
||||
B: O 1 rechts, P 1 rechts
|
||||
C: O 1 links
|
||||
D: P 1 rechts
|
||||
E: O 1 links, P 1 links
|
||||
F:
|
||||
G: Q 1 rechts
|
||||
H: Q 1 links
|
||||
I:
|
||||
J:
|
||||
K: R 1 rechts
|
||||
L: R 1 links
|
||||
M:
|
||||
N:
|
||||
parkplatz2.txt:
|
||||
A:
|
||||
B:
|
||||
C: O 1 rechts
|
||||
D: O 1 links
|
||||
E:
|
||||
F: O 1 links, P 2 links
|
||||
G: P 1 links
|
||||
H: Q 1 rechts, R 1 rechts
|
||||
I: P 1 links, Q 1 links
|
||||
J: R 1 rechts
|
||||
K: P 1 links, Q 1 links, R 1 links
|
||||
L:
|
||||
M: P 1 links, Q 1 links, R 1 links, S 2 links
|
||||
N: S 1 links
|
||||
parkplatz3.txt:
|
||||
A:
|
||||
B: O 1 rechts
|
||||
C: O 1 links
|
||||
D:
|
||||
E: P 1 rechts
|
||||
F: P 1 links
|
||||
G:
|
||||
H:
|
||||
I: Q 2 links
|
||||
J: Q 1 links
|
||||
K: Q 2 links, R 2 links
|
||||
L: Q 1 links, R 1 links
|
||||
M: Q 2 links, R 2 links, S 2 links
|
||||
N: Q 1 links, R 1 links, S 1 links
|
||||
parkplatz4.txt:
|
||||
A: Q 1 rechts, R 1 rechts
|
||||
B: Q 2 rechts, R 2 rechts
|
||||
C: R 1 rechts
|
||||
D: R 2 rechts
|
||||
E:
|
||||
F:
|
||||
G: S 1 rechts
|
||||
H: S 1 links
|
||||
I:
|
||||
J:
|
||||
K: T 1 rechts
|
||||
L: T 1 links
|
||||
M:
|
||||
N: U 1 rechts
|
||||
O: U 1 links
|
||||
P:
|
||||
parkplatz5.txt:
|
||||
A:
|
||||
B:
|
||||
C: P 2 links
|
||||
D: P 1 links
|
||||
E: Q 1 rechts
|
||||
F: Q 2 rechts
|
||||
G:
|
||||
H:
|
||||
I: R 1 rechts
|
||||
J: R 1 links
|
||||
K:
|
||||
L:
|
||||
M: S 1 rechts
|
||||
N: S 1 links
|
||||
O:
|
||||
```
|
||||
@ -5,7 +5,6 @@ import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"strconv"
|
||||
"math"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
@ -18,39 +17,62 @@ type movedCar struct {
|
||||
var querAutos []byte
|
||||
|
||||
func main() {
|
||||
// Dem Programm können beliebig viele Eingabedatein übergeben werden.
|
||||
for _, filepath := range os.Args[1:] {
|
||||
fmt.Printf("%s: \n", filepath)
|
||||
rawFile, err := ioutil.ReadFile(filepath)
|
||||
// ausgeben des Dateipfades, um Zuordnung der Lösung zu der entsprechenden Eingabedatei zu ermöglichen
|
||||
fmt.Printf("%s:\n", filepath)
|
||||
|
||||
rawFile, err := ioutil.ReadFile(filepath) // lesen der Eingabedatei
|
||||
throw(err)
|
||||
input := string(rawFile)
|
||||
firstChar := input[0]
|
||||
|
||||
firstChar := input[0] // firstChar ist der Buchstabe mit dem das erste Auto gekennzeichnet wird.
|
||||
|
||||
/* querAutos ist ein Array bzw. slice, wie dynamisch vergrößerbare Arrays in Go benannt werden,
|
||||
welches die Autos, die quer auf dem Parkplatz parken, enthält. input[2] ist der Buchstabe vom letztem Auto.
|
||||
Die Größe der slice bzw. die Anzahl der senkrecht parkenden Autos wird durch die Differenz der ASCII Codes
|
||||
berechnet. */
|
||||
querAutos = make([]byte, input[2] - firstChar + 1)
|
||||
// teilt den Text in Zeilen auf und iteriert über die Zeilen ab Zeile 3
|
||||
for _, line := range strings.Split(input, "\n")[2:] {
|
||||
// auf Unix Systemen enden die Textdatei auf einem newline Zeichen. Deshalb hat unsere letzte "Zeile" die Länge 0 und wird übersprungen.
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
// Die Position des des quer stehenden Autos beginnt ab dem 3. Zeichen (Index 2) bis zum Ende der Zeile.
|
||||
i, err := strconv.Atoi(line[2:])
|
||||
throw(err)
|
||||
// Jedes quer stehende Auto blockiert zwei Parkplätze. Deshalb belegt es auch zwei Plätze in unserer Slice.
|
||||
querAutos[i], querAutos[i + 1] = line[0], line[0]
|
||||
}
|
||||
for i := range querAutos {
|
||||
var currentMoves []movedCar
|
||||
var carLeastSteps uint32 = math.MaxUint32
|
||||
for _, direction := range []int{-1, 1} {
|
||||
var currentMoves []movedCar // enthält die Verschiebungen der Autos in die Richtung in der weniger Autos verschoben werden müssen
|
||||
var carLeastSteps uint32
|
||||
for _, direction := range []int{-1, 1} { // -1 steht für links und 1 für rechts
|
||||
movedCars, steps, success := move(i, direction, []movedCar{}, 0, 0)
|
||||
|
||||
/* Wenn das Verschieben der Autos in der jeweiligen Richtung erfolgreich ist und noch keine
|
||||
Verschiebungen abgespeichert wurden, d. h. gerade die Verschiebungen für links berechnet
|
||||
wurden oder das Verschieben nach links nicht erfolgreich war, da das Ende das Parkplatzes
|
||||
erreicht wurde, dann werden die Verschiebungen abgespeichert.
|
||||
Sollten allerdings bereits Verschiebungen für links vorhanden sein, wird das Verschieben nach
|
||||
rechts bevorzugt, wenn weniger Autos verschoben werden mussten oder die Autos weniger Plätze
|
||||
verschoben werden mussten. */
|
||||
if success && (currentMoves == nil || len(movedCars) < len(currentMoves) || len(movedCars) == len(currentMoves) && steps < carLeastSteps) {
|
||||
currentMoves = movedCars
|
||||
carLeastSteps = steps
|
||||
}
|
||||
}
|
||||
// sortiert die verschoben Autos alphabetisch
|
||||
sort.Slice(currentMoves, func(i, j int) bool {
|
||||
return currentMoves[i].id < currentMoves[j].id
|
||||
})
|
||||
fmt.Printf("%s: ", string(firstChar + byte(i)))
|
||||
fmt.Printf("%s: ", string(firstChar + byte(i))) // gibt den Buchstaben für das jeweilige Auto auf den normalen Parkplatz aus.
|
||||
for j, car := range currentMoves {
|
||||
if(j != 0) {
|
||||
fmt.Print(", ")
|
||||
}
|
||||
// gibt aus welches Auto wie viele Plätze in welche Richtung verschoben wurde.
|
||||
fmt.Printf("%s %d ", string(car.id), car.steps)
|
||||
if car.direction == 1 {
|
||||
fmt.Print("rechts")
|
||||
@ -63,34 +85,52 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Funktion um im Falle eines Fehlers, den Fehler auszugeben und das Programm zu beenden.
|
||||
func throw(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Funktion zur Berechung der Autos, die für einen Parkplatz verschoben werden müssen.
|
||||
func move(i, direction int, movedCars []movedCar, lastMoved byte, totalSteps uint32) ([]movedCar, uint32, bool) {
|
||||
querAuto := querAutos[i]
|
||||
|
||||
/* Wenn querAuto gleich 0 ist, ist kein Auto vor dem Parkplatz.
|
||||
Wenn es das gleiche Auto ist wie das zuletzt verschobene, ist auch das Verschieben beendet,
|
||||
da dieses Auto bereits ausreichend verschoben wurde. */
|
||||
if querAuto == 0 || querAuto == lastMoved {
|
||||
return movedCars, totalSteps, true
|
||||
}
|
||||
|
||||
/* Wenn neben unserem Auto in der jeweiligen Richtung kein Parkplatz mehr ist,
|
||||
dann können auch keine Autos in diese Richtung verschoben werden. */
|
||||
if outOfBounds(querAutos, i + direction) {
|
||||
return movedCars, totalSteps, false
|
||||
}
|
||||
var steps int
|
||||
/* Wenn sich eins nach der Verschiebungsrichtung auch unserer quer parkendes Auto befindet,
|
||||
muss es nur um einen Platz verschoben werden, ansonsten um zwei. */
|
||||
if querAutos[i + direction] == querAuto {
|
||||
steps = 1
|
||||
} else {
|
||||
steps = 2
|
||||
}
|
||||
endCar := i + direction * 2
|
||||
endCar := i + direction * 2 // ist das Ende des verschobenen Autos, das realtiv zur verschobenen Richtung, vorne ist.
|
||||
|
||||
/* müsste das Auto ausserhalb des Parkplatzes geschoben werden,
|
||||
damit unser normale Parkplatz frei wird, ist das Verschieben in diese Richtung nicht möglich. */
|
||||
if outOfBounds(querAutos, endCar) {
|
||||
return movedCars, totalSteps, false
|
||||
}
|
||||
// fügt das gerade verschobene Auto der Slice mit den verschobenen Autos hinzu.
|
||||
movedCars = append(movedCars, movedCar{querAuto, steps, direction})
|
||||
/* ruft die Funktion recursive auf, mit dem Index des Parkplatzes an dem
|
||||
noch ein quer stehendes Auto stehen könnte, das verschoben werden müsste. */
|
||||
return move(endCar, direction, movedCars, querAuto, totalSteps + uint32(steps))
|
||||
}
|
||||
|
||||
// Funktion um zu überprüfen, ob ein Index innerhalb einer Slice liegt.
|
||||
func outOfBounds(slice []byte, i int) bool {
|
||||
return i < 0 || i >= len(slice)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user