. * * To disable strict typing, comment out the directive below. */ declare(strict_types=1); class ProteinError { protected string $msg; public function __construct(string $msg) { $this->msg = $msg; } public function Error(): string { return $this->msg; } } const STOP = "STOP"; const ErrStop = new ProteinError(STOP); const ErrInvalidCodon = new ProteinError("Invalid codon"); class ProteinTranslation { public function getProteins(string $rna) { return $this->FromRNA($rna); } private function FromRNA(string $rna): array|ProteinError { $names = []; for ($i = 0; $i < strlen($rna); $i += 3) { $codon = substr($rna, $i, 3); $nameOrError = $this->FromCodon($codon); if (is_string($nameOrError)) { $names[] = $nameOrError; continue; } if ($nameOrError == ErrStop) { return $names; } throw new InvalidArgumentException($nameOrError->Error()); } return $names; } private function FromCodon(string $codon): string|ProteinError { $names = [ "AUG" => "Methionine", "UUU" => "Phenylalanine", "UUC" => "Phenylalanine", "UUA" => "Leucine", "UUG" => "Leucine", "UCU" => "Serine", "UCC" => "Serine", "UCA" => "Serine", "UCG" => "Serine", "UAU" => "Tyrosine", "UAC" => "Tyrosine", "UGU" => "Cysteine", "UGC" => "Cysteine", "UGG" => "Tryptophan", "UAA" => STOP, "UAG" => STOP, "UGA" => STOP, ]; @$name = $names[$codon]; if (empty($name)) { return ErrInvalidCodon; } if ($name == STOP) { return ErrStop; } return $name; } }