Created
April 27, 2011 23:27
-
-
Save martenlienen/945463 to your computer and use it in GitHub Desktop.
BwInf Runde 2 Aufgabe 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Ein Logger fuer die Kranbewegungen | |
*/ | |
class logger | |
{ | |
/** | |
* Lognachrichten | |
* | |
* @var array | |
*/ | |
protected $messages = array(); | |
/** | |
* Anzahl der Bewegungen | |
* | |
* @var int | |
*/ | |
protected $movements = 0; | |
/** | |
* Loggt eine Bewegung | |
* | |
* @param bool $forward Vorwaerts oder rueckwaerts | |
* @return void | |
*/ | |
public function logMove ($forward) | |
{ | |
$this->movements++; | |
if ($forward === true) | |
{ | |
$this->log('1 Schritt vorwaerts'); | |
} | |
else | |
{ | |
$this->log('1 Schritt rueckwaerts'); | |
} | |
} | |
/** | |
* Loggt eine Nachricht | |
* | |
* @param string $msg Nachricht | |
* @return void | |
*/ | |
public function log ($msg) | |
{ | |
$this->messages[] = (string)$msg; | |
} | |
/** | |
* Gibt die geloggten Informationen auf der Standardausgabe aus | |
* | |
* @return void | |
*/ | |
public function dump () | |
{ | |
foreach ($this->messages as $message) | |
{ | |
echo $message . "\n"; | |
} | |
echo "\nAnzahl der Bewegungen: " . $this->getNumberOfMovements() . "\n"; | |
} | |
/** | |
* Gibt die Anzahl der geloggten Bewegungen zurueck | |
* | |
* @return int | |
*/ | |
public function getNumberOfMovements () | |
{ | |
return $this->movements; | |
} | |
} | |
/** | |
* Das Dock mit den Containern | |
*/ | |
class dock | |
{ | |
/** | |
* Anzahl der Container | |
* | |
* @var int | |
*/ | |
protected $numberOfContainers = 0; | |
/** | |
* Positionen der Container | |
* | |
* @var array | |
*/ | |
protected $positions = array(); | |
/** | |
* Position des Krans | |
* | |
* @var int | |
*/ | |
protected $position = 0; | |
/** | |
* | |
* | |
* @var int | |
*/ | |
protected $container = -1; | |
/** | |
* Der Logger | |
* | |
* @var logger | |
*/ | |
protected $logger = null; | |
/** | |
* Erzeugt eine zufällige Reihenfolge der Container | |
* | |
* @param int $numberOfContainers Anzahl der Container | |
* @param logger $logger Logger | |
*/ | |
public function __construct ($numberOfContainers, logger $logger) | |
{ | |
$this->logger = $logger; | |
$numberOfContainers = (int)$numberOfContainers; | |
if ($numberOfContainers < 1) | |
{ | |
throw new Exception(); | |
} | |
$this->numberOfContainers = $numberOfContainers; | |
$containers = range(0, $numberOfContainers - 1); | |
shuffle($containers); | |
for ($i = 0; $i < $numberOfContainers; $i++) | |
{ | |
$this->positions[] = array(-1, array_pop($containers)); | |
} | |
} | |
public function getThisShitStarted () | |
{ | |
$this->solve(); | |
} | |
/** | |
* Verteilt die Container auf den Zug | |
* | |
* @return void | |
*/ | |
protected function solve () | |
{ | |
try | |
{ | |
$nextBorder = $this->getNextSubsystemBorder( | |
$this->positions, | |
$this->position | |
); | |
} | |
catch (Exception $e) | |
{ | |
$nextBorder = false; | |
} | |
$start = $this->position; | |
do | |
{ | |
// Wenn man sich an einer Grenze befindet | |
if ($nextBorder !== false | |
&& $this->position + 1 === $nextBorder) | |
{ | |
$this->dropOnTrain(); | |
$this->moveForward(); | |
$this->solve(); | |
$nextBorder = false; | |
$this->moveBack(); | |
} | |
$this->handleContainers(); | |
$this->move(); | |
if ($this->position === $start) | |
{ | |
$this->handleContainers(); | |
} | |
} | |
while ($this->position !== $start); | |
} | |
/** | |
* Bewegt den Kran vorwaerts | |
* | |
* @return void | |
*/ | |
protected function moveForward () | |
{ | |
$this->logger->logMove(true); | |
$this->position++; | |
} | |
/** | |
* Bewegt den Kran vorwaerts | |
* | |
* @return void | |
*/ | |
protected function moveBack () | |
{ | |
$this->logger->logMove(false); | |
$this->position--; | |
} | |
/** | |
* Bewegt den Kran so, dass der geladene Container naeher an sein Ziel kommt | |
* | |
* @return void | |
*/ | |
protected function move () | |
{ | |
if ($this->isCraneLoaded() === false) | |
{ | |
return; | |
} | |
else if ($this->container - $this->position > 0) | |
{ | |
$this->moveForward(); | |
} | |
else | |
{ | |
$this->moveBack(); | |
} | |
} | |
/** | |
* Behandelt die Container an der aktuellen Stelle | |
* | |
* @return void | |
*/ | |
protected function handleContainers () | |
{ | |
if (!$this->isCraneLoaded()) | |
{ | |
$this->pickFromStore(); | |
} | |
// Wenn der geladene Container an seinem Ziel angekommen ist | |
if ($this->container - $this->position === 0) | |
{ | |
$this->dropOnTrain(); | |
if (!$this->isStoreEmpty()) | |
{ | |
$this->pickFromStore(); | |
} | |
} | |
// Wenn der Container im Lager seinem Ziel direkt gegenueber liegt | |
else if ($this->positions[$this->position][1] - $this->position === 0) | |
{ | |
$this->dropOnTrain(); | |
$this->switchTrainAndStore(); | |
$this->pickFromStore(); | |
} | |
else | |
{ | |
// Wenn der Container im Lager noch eine weitere Strecke in die | |
// gleiche Richtung zuruecklegen muss als der aktuell geladene | |
if ($this->positions[$this->position][1] > $this->container) | |
{ | |
$this->dropOnTrain(); | |
$this->pickFromStore(); | |
} | |
// Wenn der Container auf dem Zug noch eine weitere Strecke "nach | |
// rechts" zuruecklegen muss als der aktuell geladene und der | |
// Container auf dem Zug nicht schon an seinem Bestimmungsort | |
// angekommen ist | |
else if ($this->positions[$this->position][0] > $this->container | |
&& $this->positions[$this->position][0] - $this->position !== 0) | |
{ | |
$this->dropInStore(); | |
$this->pickFromTrain(); | |
} | |
} | |
} | |
/** | |
* Hebt den Container aus dem Lager | |
* | |
* @return void | |
* @throws Exception wenn der Kran schon beladen ist | |
*/ | |
protected function pickFromStore () | |
{ | |
if ($this->container !== -1) | |
{ | |
throw new Exception( | |
'Crane is already loaded and is therefore not able to pick from store' | |
); | |
} | |
if ($this->positions[$this->position][1] === -1) | |
{ | |
return; | |
} | |
$this->logger->log('Nimm aus dem Lager'); | |
$this->container = $this->positions[$this->position][1]; | |
$this->positions[$this->position][1] = -1; | |
} | |
/** | |
* Hebt den Container vom Zug | |
* | |
* @return void | |
* @throws Exception wenn der Kran schon beladen ist | |
*/ | |
protected function pickFromTrain () | |
{ | |
if ($this->isCraneLoaded()) | |
{ | |
throw new Exception( | |
'Crane is already loaded and is therefore not able to pick from train' | |
); | |
} | |
if ($this->positions[$this->position][0] === -1) | |
{ | |
return; | |
} | |
$this->logger->log('Nimm von dem Zug'); | |
$this->container = $this->positions[$this->position][0]; | |
$this->positions[$this->position][0] = -1; | |
} | |
/** | |
* Laedt den geladenen Container auf dem Zug ab | |
* | |
* Wenn nicht direkt abgeladen werden kann, wird versucht den Container ins | |
* Lager zu legen und dann Lager und Zug zu vertauschen. | |
* | |
* @return void | |
*/ | |
protected function dropOnTrain () | |
{ | |
if (!$this->isTrainEmpty()) | |
{ | |
$this->dropInStore(); | |
$this->switchTrainAndStore(); | |
} | |
else | |
{ | |
if ($this->isCraneLoaded() === false) | |
{ | |
return; | |
} | |
$this->logger->log('Lege auf den Zug'); | |
$this->positions[$this->position][0] = $this->container; | |
$this->container = -1; | |
} | |
} | |
/** | |
* Laedt den geladenen Container im Lager ab | |
* | |
* @return void | |
* @throws Exception wenn das Lager nicht leer ist | |
*/ | |
protected function dropInStore () | |
{ | |
if ($this->isStoreEmpty() === false) | |
{ | |
throw new Exception('Store is not empty'); | |
} | |
if ($this->isCraneLoaded() === false) | |
{ | |
return; | |
} | |
$this->logger->log('Lege ins Lager'); | |
$this->positions[$this->position][1] = $this->container; | |
$this->container = -1; | |
} | |
/** | |
* Vertauscht den Inhalt von Lager und Zug an der aktuellen Position | |
* | |
* @return void | |
* @throws Exception wenn der Kran nicht leer ist | |
*/ | |
protected function switchTrainAndStore () | |
{ | |
if ($this->isCraneLoaded()) | |
{ | |
throw new Exception( | |
'Crane has to be unloaded to switch train and store' | |
); | |
} | |
$this->logger->log('Vertausche die Container in Lager und Zug'); | |
$tmp = $this->positions[$this->position][1]; | |
$this->positions[$this->position][1] = $this->positions[$this->position][0]; | |
$this->positions[$this->position][0] = $tmp; | |
} | |
/** | |
* Checkt, ob der Zug an der aktuellen Position leer ist | |
* | |
* @return bool | |
*/ | |
protected function isTrainEmpty () | |
{ | |
if ($this->positions[$this->position][0] === -1) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Checkt, ob das Lager an der aktuellen Position leer ist | |
* | |
* @return bool | |
*/ | |
protected function isStoreEmpty () | |
{ | |
if ($this->positions[$this->position][1] === -1) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Checkt, ob der Kran beladen ist | |
* | |
* @return bool | |
*/ | |
protected function isCraneLoaded () | |
{ | |
if ($this->container !== -1) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Gibt die Position des ersten Containers des naechsten Subsystems zurueck | |
* | |
* @param array $positions | |
* @param int $start | |
* @throws Exception wenn es keine weitere Grenze gibt | |
* @return int | |
*/ | |
protected function getNextSubsystemBorder (array $positions, $start) | |
{ | |
$lastContainer = count($positions) - 1; | |
$maxContainer = $positions[$start][1]; | |
for ($i = $start; $i <= $lastContainer; $i++) | |
{ | |
if ($maxContainer < $positions[$i][1]) | |
{ | |
$maxContainer = $positions[$i][1]; | |
} | |
if ($maxContainer === $i) | |
{ | |
break; | |
} | |
} | |
if ($i === $lastContainer) | |
{ | |
throw new Exception('There are no more subsystems'); | |
} | |
$i++; | |
return $i; | |
} | |
/** | |
* Gibt den Zug und das Lager aus | |
* | |
* @return void | |
*/ | |
public function dumpContainers () | |
{ | |
for ($i = 0; $i < count($this->positions); $i++) | |
{ | |
echo $i . ': ' . $this->positions[$i][0] . ', ' . $this->positions[$i][1] . "\n"; | |
} | |
echo "\n"; | |
} | |
} | |
try | |
{ | |
$logger = new logger(); | |
$dock = new Dock($_SERVER['argv'][1], $logger); | |
$dock->dumpContainers(); | |
$dock->getThisShitStarted(); | |
$logger->dump(); | |
} | |
catch (Exception $e) | |
{ | |
?> | |
Das Programm erwartet als ersten Parameter eine Zahl, die die Anzahl der Container angibt. | |
<?php | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment