This commit is contained in:
2021-10-09 20:23:02 +02:00
parent 4031ad1831
commit bd4e76b246
11 changed files with 980 additions and 9 deletions

View File

@ -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)
}